|
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.'/ddl/sql_generator.php'); 00031 00035 00036 class sqlite_sql_generator extends sql_generator { 00037 00039 00040 public $drop_default_value_required = true; //To specify if the generator must use some DEFAULT clause to drop defaults 00041 public $drop_default_value = NULL; //The DEFAULT clause required to drop defaults 00042 00043 public $drop_primary_key = 'ALTER TABLE TABLENAME DROP PRIMARY KEY'; // Template to drop PKs 00044 // with automatic replace for TABLENAME and KEYNAME 00045 00046 public $drop_unique_key = 'ALTER TABLE TABLENAME DROP KEY KEYNAME'; // Template to drop UKs 00047 // with automatic replace for TABLENAME and KEYNAME 00048 00049 public $drop_foreign_key = 'ALTER TABLE TABLENAME DROP FOREIGN KEY KEYNAME'; // Template to drop FKs 00050 // with automatic replace for TABLENAME and KEYNAME 00051 public $default_for_char = ''; // To define the default to set for NOT NULLs CHARs without default (null=do nothing) 00052 00053 public $sequence_only = true; //To avoid to output the rest of the field specs, leaving only the name and the sequence_name publiciable 00054 public $sequence_extra_code = false; //Does the generator need to add extra code to generate the sequence fields 00055 public $sequence_name = 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'; //Particular name for inline sequences in this generator 00056 public $unsigned_allowed = false; // To define in the generator must handle unsigned information 00057 00058 public $enum_inline_code = true; //Does the generator need to add inline code in the column definition 00059 public $enum_extra_code = false; //Does the generator need to add extra code to generate code for the enums in the table 00060 00061 public $drop_index_sql = 'ALTER TABLE TABLENAME DROP INDEX INDEXNAME'; //SQL sentence to drop one index 00062 //TABLENAME, INDEXNAME are dynamically replaced 00063 00064 public $rename_index_sql = null; //SQL sentence to rename one index (MySQL doesn't support this!) 00065 //TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dynamically replaced 00066 00067 public $rename_key_sql = null; //SQL sentence to rename one key (MySQL doesn't support this!) 00068 //TABLENAME, OLDKEYNAME, NEWKEYNAME are dynamically replaced 00069 00073 public function __construct($mdb) { 00074 parent::__construct($mdb); 00075 } 00076 00082 public function getResetSequenceSQL($table) { 00083 00084 if ($table instanceof xmldb_table) { 00085 $table = $table->getName(); 00086 } 00087 00088 // From http://sqlite.org/autoinc.html 00089 $value = (int)$this->mdb->get_field_sql('SELECT MAX(id) FROM {'.$table.'}'); 00090 return array("UPDATE sqlite_sequence SET seq=$value WHERE name='{$this->prefix}{$table}'"); 00091 } 00092 00096 public function getKeySQL($xmldb_table, $xmldb_key) { 00097 00098 $key = ''; 00099 00100 switch ($xmldb_key->getType()) { 00101 case XMLDB_KEY_PRIMARY: 00102 if ($this->primary_keys && count($xmldb_key->getFields())>1) { 00103 if ($this->primary_key_name !== null) { 00104 $key = $this->getEncQuoted($this->primary_key_name); 00105 } else { 00106 $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'pk'); 00107 } 00108 $key .= ' PRIMARY KEY (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')'; 00109 } 00110 break; 00111 case XMLDB_KEY_UNIQUE: 00112 if ($this->unique_keys) { 00113 $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'uk'); 00114 $key .= ' UNIQUE (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')'; 00115 } 00116 break; 00117 case XMLDB_KEY_FOREIGN: 00118 case XMLDB_KEY_FOREIGN_UNIQUE: 00119 if ($this->foreign_keys) { 00120 $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'fk'); 00121 $key .= ' FOREIGN KEY (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')'; 00122 $key .= ' REFERENCES ' . $this->getEncQuoted($this->prefix . $xmldb_key->getRefTable()); 00123 $key .= ' (' . implode(', ', $this->getEncQuoted($xmldb_key->getRefFields())) . ')'; 00124 } 00125 break; 00126 } 00127 00128 return $key; 00129 } 00130 00134 public function getTypeSQL($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) { 00135 00136 switch ($xmldb_type) { 00137 case XMLDB_TYPE_INTEGER: // From http://www.sqlite.org/datatype3.html 00138 if (empty($xmldb_length)) { 00139 $xmldb_length = 10; 00140 } 00141 $dbtype = 'INTEGER(' . $xmldb_length . ')'; 00142 break; 00143 case XMLDB_TYPE_NUMBER: 00144 $dbtype = $this->number_type; 00145 if (!empty($xmldb_length)) { 00146 $dbtype .= '(' . $xmldb_length; 00147 if (!empty($xmldb_decimals)) { 00148 $dbtype .= ',' . $xmldb_decimals; 00149 } 00150 $dbtype .= ')'; 00151 } 00152 break; 00153 case XMLDB_TYPE_FLOAT: 00154 $dbtype = 'REAL'; 00155 if (!empty($xmldb_length)) { 00156 $dbtype .= '(' . $xmldb_length; 00157 if (!empty($xmldb_decimals)) { 00158 $dbtype .= ',' . $xmldb_decimals; 00159 } 00160 $dbtype .= ')'; 00161 } 00162 break; 00163 case XMLDB_TYPE_CHAR: 00164 $dbtype = 'VARCHAR'; 00165 if (empty($xmldb_length)) { 00166 $xmldb_length='255'; 00167 } 00168 $dbtype .= '(' . $xmldb_length . ')'; 00169 break; 00170 case XMLDB_TYPE_BINARY: 00171 $dbtype = 'BLOB'; 00172 break; 00173 case XMLDB_TYPE_DATETIME: 00174 $dbtype = 'DATETIME'; 00175 default: 00176 case XMLDB_TYPE_TEXT: 00177 $dbtype = 'TEXT'; 00178 break; 00179 } 00180 return $dbtype; 00181 } 00182 00194 protected function getAlterTableSchema($xmldb_table, $xmldb_add_field=NULL, $xmldb_delete_field=NULL) { 00196 $tablename = $this->getTableName($xmldb_table); 00197 00198 $oldname = $xmldb_delete_field ? $xmldb_delete_field->getName() : NULL; 00199 $newname = $xmldb_add_field ? $xmldb_add_field->getName() : NULL; 00200 if($xmldb_delete_field) { 00201 $xmldb_table->deleteField($oldname); 00202 } 00203 if($xmldb_add_field) { 00204 $xmldb_table->addField($xmldb_add_field); 00205 } 00206 if($oldname) { 00207 // alter indexes 00208 $indexes = $xmldb_table->getIndexes(); 00209 foreach($indexes as $index) { 00210 $fields = $index->getFields(); 00211 $i = array_search($oldname, $fields); 00212 if($i!==FALSE) { 00213 if($newname) { 00214 $fields[$i] = $newname; 00215 } else { 00216 unset($fields[$i]); 00217 } 00218 $xmldb_table->deleteIndex($index->getName()); 00219 if(count($fields)) { 00220 $index->setFields($fields); 00221 $xmldb_table->addIndex($index); 00222 } 00223 } 00224 } 00225 // alter keys 00226 $keys = $xmldb_table->getKeys(); 00227 foreach($keys as $key) { 00228 $fields = $key->getFields(); 00229 $reffields = $key->getRefFields(); 00230 $i = array_search($oldname, $fields); 00231 if($i!==FALSE) { 00232 if($newname) { 00233 $fields[$i] = $newname; 00234 } else { 00235 unset($fields[$i]); 00236 unset($reffields[$i]); 00237 } 00238 $xmldb_table->deleteKey($key->getName()); 00239 if(count($fields)) { 00240 $key->setFields($fields); 00241 $key->setRefFields($fields); 00242 $xmldb_table->addkey($key); 00243 } 00244 } 00245 } 00246 } 00247 // prepare data copy 00248 $fields = $xmldb_table->getFields(); 00249 foreach ($fields as $key => $field) { 00250 $fieldname = $field->getName(); 00251 if($fieldname == $newname && $oldname && $oldname != $newname) { 00252 // field rename operation 00253 $fields[$key] = $this->getEncQuoted($oldname) . ' AS ' . $this->getEncQuoted($newname); 00254 } else { 00255 $fields[$key] = $this->getEncQuoted($field->getName()); 00256 } 00257 } 00258 $fields = implode(',', $fields); 00259 $results[] = 'BEGIN TRANSACTION'; 00260 $results[] = 'CREATE TEMPORARY TABLE temp_data AS SELECT * FROM ' . $tablename; 00261 $results[] = 'DROP TABLE ' . $tablename; 00262 $results = array_merge($results, $this->getCreateTableSQL($xmldb_table)); 00263 $results[] = 'INSERT INTO ' . $tablename . ' SELECT ' . $fields . ' FROM temp_data'; 00264 $results[] = 'DROP TABLE temp_data'; 00265 $results[] = 'COMMIT'; 00266 return $results; 00267 } 00268 00272 public function getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL) { 00273 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $xmldb_field); 00274 } 00275 00280 public function getAddKeySQL($xmldb_table, $xmldb_key) { 00281 $xmldb_table->addKey($xmldb_key); 00282 return $this->getAlterTableSchema($xmldb_table); 00283 } 00284 00289 public function getCreateEnumSQL($xmldb_table, $xmldb_field) { 00290 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $xmldb_field); 00291 } 00292 00297 public function getDropEnumSQL($xmldb_table, $xmldb_field) { 00298 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $xmldb_field); 00299 } 00300 00305 public function getCreateDefaultSQL($xmldb_table, $xmldb_field) { 00306 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $xmldb_field); 00307 } 00308 00314 public function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) { 00315 $oldfield = clone($xmldb_field); 00316 $xmldb_field->setName($newname); 00317 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $oldfield); 00318 } 00319 00323 function getRenameIndexSQL($xmldb_table, $xmldb_index, $newname) { 00325 $dbindexname = $this->mdb->get_manager()->find_index_name($xmldb_table, $xmldb_index); 00326 $xmldb_index->setName($newname); 00327 $results = array('DROP INDEX ' . $dbindexname); 00328 $results = array_merge($results, $this->getCreateIndexSQL($xmldb_table, $xmldb_index)); 00329 return $results; 00330 } 00331 00336 public function getRenameKeySQL($xmldb_table, $xmldb_key, $newname) { 00337 $xmldb_table->deleteKey($xmldb_key->getName()); 00338 $xmldb_key->setName($newname); 00339 $xmldb_table->addkey($xmldb_key); 00340 return $this->getAlterTableSchema($xmldb_table); 00341 } 00342 00346 public function getDropFieldSQL($xmldb_table, $xmldb_field) { 00347 return $this->getAlterTableSchema($xmldb_table, NULL, $xmldb_field); 00348 } 00349 00353 public function getDropIndexSQL($xmldb_table, $xmldb_index) { 00354 $xmldb_table->deleteIndex($xmldb_index->getName()); 00355 return $this->getAlterTableSchema($xmldb_table); 00356 } 00357 00361 public function getDropKeySQL($xmldb_table, $xmldb_key) { 00362 $xmldb_table->deleteKey($xmldb_key->getName()); 00363 return $this->getAlterTableSchema($xmldb_table); 00364 } 00365 00370 public function getDropDefaultSQL($xmldb_table, $xmldb_field) { 00371 return $this->getAlterTableSchema($xmldb_table, $xmldb_field, $xmldb_field); 00372 } 00373 00377 function getCommentSQL ($xmldb_table) { 00378 return array(); 00379 } 00380 00391 public function getCheckConstraintsFromDB($xmldb_table, $xmldb_field = null) { 00392 $tablename = $xmldb_table->getName($xmldb_table); 00393 // Fetch all the columns in the table 00394 if (!$columns = $this->mdb->get_columns($tablename, false)) { 00395 return array(); 00396 } 00397 $results = array(); 00398 $filter = $xmldb_field ? $xmldb_field->getName() : NULL; 00399 // Iterate over columns searching for enums 00400 foreach ($columns as $key => $column) { 00401 // Enum found, let's add it to the constraints list 00402 if (!empty($column->enums) && (!$filter || $column->name == $filter)) { 00403 $result = new stdClass(); 00404 $result->name = $key; 00405 $result->description = implode(', ', $column->enums); 00406 $results[$key] = $result; 00407 } 00408 } 00409 return $results; 00410 } 00411 00417 public function isNameInUse($object_name, $type, $table_name) { 00418 // TODO: add introspection code 00419 return false; //No name in use found 00420 } 00421 00422 00426 public static function getReservedWords() { 00428 $reserved_words = array ( 00429 'add', 'all', 'alter', 'and', 'as', 'autoincrement', 00430 'between', 'by', 00431 'case', 'check', 'collate', 'column', 'commit', 'constraint', 'create', 'cross', 00432 'default', 'deferrable', 'delete', 'distinct', 'drop', 00433 'else', 'escape', 'except', 'exists', 00434 'foreign', 'from', 'full', 00435 'group', 00436 'having', 00437 'in', 'index', 'inner', 'insert', 'intersect', 'into', 'is', 'isnull', 00438 'join', 00439 'left', 'limit', 00440 'natural', 'not', 'notnull', 'null', 00441 'on', 'or', 'order', 'outer', 00442 'primary', 00443 'references', 'regexp', 'right', 'rollback', 00444 'select', 'set', 00445 'table', 'then', 'to', 'transaction', 00446 'union', 'unique', 'update', 'using', 00447 'values', 00448 'when', 'where' 00449 ); 00450 return $reserved_words; 00451 } 00452 00453 public function addslashes($s) { 00454 // do not use php addslashes() because it depends on PHP quote settings! 00455 $s = str_replace("'", "''", $s); 00456 return $s; 00457 } 00458 }