|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00018 00028 defined('MOODLE_INTERNAL') || die(); 00029 00030 require_once($CFG->libdir.'/dml/pdo_moodle_database.php'); 00031 00035 class sqlite3_pdo_moodle_database extends pdo_moodle_database { 00036 protected $database_file_extension = '.sq3.php'; 00042 public function driver_installed() { 00043 if (!extension_loaded('pdo_sqlite') || !extension_loaded('pdo')){ 00044 return get_string('sqliteextensionisnotpresentinphp', 'install'); 00045 } 00046 return true; 00047 } 00048 00054 public function get_dbfamily() { 00055 return 'sqlite'; 00056 } 00057 00063 protected function get_dbtype() { 00064 return 'sqlite3'; 00065 } 00066 00067 protected function configure_dbconnection() { 00068 // try to protect database file against web access; 00069 // this is required in case that the moodledata folder is web accessible and 00070 // .htaccess is not in place; requires that the database file extension is php 00071 $this->pdb->exec('CREATE TABLE IF NOT EXISTS "<?php die?>" (id int)'); 00072 $this->pdb->exec('PRAGMA synchronous=OFF'); 00073 $this->pdb->exec('PRAGMA short_column_names=1'); 00074 $this->pdb->exec('PRAGMA encoding="UTF-8"'); 00075 $this->pdb->exec('PRAGMA case_sensitive_like=0'); 00076 $this->pdb->exec('PRAGMA locking_mode=NORMAL'); 00077 } 00078 00088 public function create_database($dbhost, $dbuser, $dbpass, $dbname, array $dboptions=null) { 00089 $this->dbhost = $dbhost; 00090 $this->dbuser = $dbuser; 00091 $this->dbpass = $dbpass; 00092 $this->dbname = $dbname; 00093 $filepath = $this->get_dbfilepath(); 00094 $dirpath = dirname($filepath); 00095 @mkdir($dirpath); 00096 return touch($filepath); 00097 } 00098 00104 protected function get_dsn() { 00105 return 'sqlite:'.$this->get_dbfilepath(); 00106 } 00107 00116 public function get_dbfilepath() { 00117 global $CFG; 00118 if (!empty($this->dboptions['file'])) { 00119 return $this->dboptions['file']; 00120 } 00121 if ($this->dbhost && $this->dbhost != 'localhost') { 00122 $path = $this->dbhost; 00123 } else { 00124 $path = $CFG->dataroot; 00125 } 00126 $path = rtrim($path, '\\/').'/'; 00127 if (!empty($this->dbuser)) { 00128 $path .= $this->dbuser.'_'; 00129 } 00130 $path .= $this->dbname.'_'.md5($this->dbpass).$this->database_file_extension; 00131 return $path; 00132 } 00133 00138 public function get_tables($usecache=true) { 00139 $tables = array(); 00140 00141 $sql = 'SELECT name FROM sqlite_master WHERE type="table" UNION ALL SELECT name FROM sqlite_temp_master WHERE type="table" ORDER BY name'; 00142 if ($this->debug) { 00143 $this->debug_query($sql); 00144 } 00145 $rstables = $this->pdb->query($sql); 00146 foreach ($rstables as $table) { 00147 $table = $table['name']; 00148 $table = strtolower($table); 00149 if (empty($this->prefix) || strpos($table, $this->prefix) === 0) { 00150 $table = substr($table, strlen($this->prefix)); 00151 $tables[$table] = $table; 00152 } 00153 } 00154 return $tables; 00155 } 00156 00161 public function get_indexes($table) { 00162 $indexes = array(); 00163 $sql = 'PRAGMA index_list('.$this->prefix.$table.')'; 00164 if ($this->debug) { 00165 $this->debug_query($sql); 00166 } 00167 $rsindexes = $this->pdb->query($sql); 00168 foreach($rsindexes as $index) { 00169 $unique = (boolean)$index['unique']; 00170 $index = $index['name']; 00171 $sql = 'PRAGMA index_info("'.$index.'")'; 00172 if ($this->debug) { 00173 $this->debug_query($sql); 00174 } 00175 $rscolumns = $this->pdb->query($sql); 00176 $columns = array(); 00177 foreach($rscolumns as $row) { 00178 $columns[] = strtolower($row['name']); 00179 } 00180 $index = strtolower($index); 00181 $indexes[$index]['unique'] = $unique; 00182 $indexes[$index]['columns'] = $columns; 00183 } 00184 return $indexes; 00185 } 00186 00193 public function get_columns($table, $usecache=true) { 00194 if ($usecache and isset($this->columns[$table])) { 00195 return $this->columns[$table]; 00196 } 00197 // get table's CREATE TABLE command (we'll need it for autoincrement fields) 00198 $sql = 'SELECT sql FROM sqlite_master WHERE type="table" AND tbl_name="'.$this->prefix.$table.'"'; 00199 if ($this->debug) { 00200 $this->debug_query($sql); 00201 } 00202 $createsql = $this->pdb->query($sql)->fetch(); 00203 if (!$createsql) { 00204 return false; 00205 } 00206 $createsql = $createsql['sql']; 00207 00208 $columns = array(); 00209 $sql = 'PRAGMA table_info("'. $this->prefix.$table.'")'; 00210 if ($this->debug) { 00211 $this->debug_query($sql); 00212 } 00213 $rscolumns = $this->pdb->query($sql); 00214 foreach ($rscolumns as $row) { 00215 $columninfo = array( 00216 'name' => strtolower($row['name']), // colum names must be lowercase 00217 'not_null' =>(boolean)$row['notnull'], 00218 'primary_key' => (boolean)$row['pk'], 00219 'has_default' => !is_null($row['dflt_value']), 00220 'default_value' => $row['dflt_value'], 00221 'auto_increment' => false, 00222 'binary' => false, 00223 //'unsigned' => false, 00224 ); 00225 $type = explode('(', $row['type']); 00226 $columninfo['type'] = strtolower($type[0]); 00227 if (count($type) > 1) { 00228 $size = explode(',', trim($type[1], ')')); 00229 $columninfo['max_length'] = $size[0]; 00230 if (count($size) > 1) { 00231 $columninfo['scale'] = $size[1]; 00232 } 00233 } 00234 // SQLite does not have a fixed set of datatypes (ie. it accepts any string as 00235 // datatype in the CREATE TABLE command. We try to guess which type is used here 00236 switch(substr($columninfo['type'], 0, 3)) { 00237 case 'int': // int integer 00238 if ($columninfo['primary_key'] && preg_match('/'.$columninfo['name'].'\W+integer\W+primary\W+key\W+autoincrement/im', $createsql)) { 00239 $columninfo['meta_type'] = 'R'; 00240 $columninfo['auto_increment'] = true; 00241 } else { 00242 $columninfo['meta_type'] = 'I'; 00243 } 00244 break; 00245 case 'num': // number numeric 00246 case 'rea': // real 00247 case 'dou': // double 00248 case 'flo': // float 00249 $columninfo['meta_type'] = 'N'; 00250 break; 00251 case 'var': // varchar 00252 case 'cha': // char 00253 $columninfo['meta_type'] = 'C'; 00254 break; 00255 case 'enu': // enums 00256 if (preg_match('|'.$columninfo['name'].'\W+in\W+\(/\*liststart\*/(.*?)/\*listend\*/\)|im', $createsql, $tmp)) { 00257 $tmp = explode(',', $tmp[1]); 00258 foreach($tmp as $value) { 00259 $columninfo['enums'][] = trim($value, '\'"'); 00260 } 00261 unset($tmp); 00262 } 00263 $columninfo['meta_type'] = 'C'; 00264 break; 00265 case 'tex': // text 00266 case 'clo': // clob 00267 $columninfo['meta_type'] = 'X'; 00268 break; 00269 case 'blo': // blob 00270 case 'non': // none 00271 $columninfo['meta_type'] = 'B'; 00272 $columninfo['binary'] = true; 00273 break; 00274 case 'boo': // boolean 00275 case 'bit': // bit 00276 case 'log': // logical 00277 $columninfo['meta_type'] = 'L'; 00278 $columninfo['max_length'] = 1; 00279 break; 00280 case 'tim': // timestamp 00281 $columninfo['meta_type'] = 'T'; 00282 break; 00283 case 'dat': // date datetime 00284 $columninfo['meta_type'] = 'D'; 00285 break; 00286 } 00287 if ($columninfo['has_default'] && ($columninfo['meta_type'] == 'X' || $columninfo['meta_type']== 'C')) { 00288 // trim extra quotes from text default values 00289 $columninfo['default_value'] = substr($columninfo['default_value'], 1, -1); 00290 } 00291 $columns[$columninfo['name']] = new database_column_info($columninfo); 00292 } 00293 00294 $this->columns[$table] = $columns; 00295 return $columns; 00296 } 00297 00305 protected function normalise_value($column, $value) { 00306 return $value; 00307 } 00308 00316 protected function get_limit_clauses($sql, $limitfrom=0, $limitnum=0) { 00317 if ($limitnum) { 00318 $sql .= ' LIMIT '.$limitnum; 00319 if ($limitfrom) { 00320 $sql .= ' OFFSET '.$limitfrom; 00321 } 00322 } 00323 return $sql; 00324 } 00325 00334 public function delete_records($table, array $conditions=null) { 00335 if (is_null($conditions)) { 00336 return $this->execute("DELETE FROM {{$table}}"); 00337 } 00338 list($select, $params) = $this->where_clause($table, $conditions); 00339 return $this->delete_records_select($table, $select, $params); 00340 } 00341 00349 public function sql_concat() { 00350 $elements = func_get_args(); 00351 return implode('||', $elements); 00352 } 00353 00362 public function sql_concat_join($separator="' '", $elements=array()) { 00363 // Intersperse $elements in the array. 00364 // Add items to the array on the fly, walking it 00365 // _backwards_ splicing the elements in. The loop definition 00366 // should skip first and last positions. 00367 for ($n=count($elements)-1; $n > 0; $n--) { 00368 array_splice($elements, $n, 0, $separator); 00369 } 00370 return implode('||', $elements); 00371 } 00372 00381 public function sql_bitxor($int1, $int2) { 00382 return '( ~' . $this->sql_bitand($int1, $int2) . ' & ' . $this->sql_bitor($int1, $int2) . ')'; 00383 } 00384 }