|
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 00029 defined('MOODLE_INTERNAL') || die(); 00030 00031 require_once($CFG->libdir.'/ddl/sql_generator.php'); 00032 00036 00037 class mysql_sql_generator extends sql_generator { 00038 00040 00041 public $quote_string = '`'; // String used to quote names 00042 00043 public $default_for_char = ''; // To define the default to set for NOT NULLs CHARs without default (null=do nothing) 00044 00045 public $drop_default_value_required = true; //To specify if the generator must use some DEFAULT clause to drop defaults 00046 public $drop_default_value = NULL; //The DEFAULT clause required to drop defaults 00047 00048 public $primary_key_name = ''; //To force primary key names to one string (null=no force) 00049 00050 public $drop_primary_key = 'ALTER TABLE TABLENAME DROP PRIMARY KEY'; // Template to drop PKs 00051 // with automatic replace for TABLENAME and KEYNAME 00052 00053 public $drop_unique_key = 'ALTER TABLE TABLENAME DROP KEY KEYNAME'; // Template to drop UKs 00054 // with automatic replace for TABLENAME and KEYNAME 00055 00056 public $drop_foreign_key = 'ALTER TABLE TABLENAME DROP FOREIGN KEY KEYNAME'; // Template to drop FKs 00057 // with automatic replace for TABLENAME and KEYNAME 00058 00059 public $sequence_extra_code = false; //Does the generator need to add extra code to generate the sequence fields 00060 public $sequence_name = 'auto_increment'; //Particular name for inline sequences in this generator 00061 00062 public $enum_extra_code = false; //Does the generator need to add extra code to generate code for the enums in the table 00063 00064 public $add_after_clause = true; // Does the generator need to add the after clause for fields 00065 00066 public $concat_character = null; //Characters to be used as concatenation operator. If not defined 00067 //MySQL CONCAT function will be use 00068 00069 public $alter_column_sql = 'ALTER TABLE TABLENAME MODIFY COLUMN COLUMNSPECS'; //The SQL template to alter columns 00070 00071 public $drop_index_sql = 'ALTER TABLE TABLENAME DROP INDEX INDEXNAME'; //SQL sentence to drop one index 00072 //TABLENAME, INDEXNAME are dynamically replaced 00073 00074 public $rename_index_sql = null; //SQL sentence to rename one index (MySQL doesn't support this!) 00075 //TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dynamically replaced 00076 00077 public $rename_key_sql = null; //SQL sentence to rename one key (MySQL doesn't support this!) 00078 //TABLENAME, OLDKEYNAME, NEWKEYNAME are dynamically replaced 00079 00085 public function getResetSequenceSQL($table) { 00086 00087 if ($table instanceof xmldb_table) { 00088 $tablename = $table->getName(); 00089 } else { 00090 $tablename = $table; 00091 } 00092 00093 // From http://dev.mysql.com/doc/refman/5.0/en/alter-table.html 00094 $value = (int)$this->mdb->get_field_sql('SELECT MAX(id) FROM {'.$tablename.'}'); 00095 $value++; 00096 return array("ALTER TABLE $this->prefix$tablename AUTO_INCREMENT = $value"); 00097 } 00098 00103 public function getCreateTableSQL($xmldb_table) { 00104 // first find out if want some special db engine 00105 $engine = null; 00106 if (method_exists($this->mdb, 'get_dbengine')) { 00107 $engine = $this->mdb->get_dbengine(); 00108 } 00109 00110 $sqlarr = parent::getCreateTableSQL($xmldb_table); 00111 00112 if (!$engine) { 00113 // we rely on database defaults 00114 return $sqlarr; 00115 } 00116 00117 // let's inject the engine into SQL 00118 foreach ($sqlarr as $i=>$sql) { 00119 if (strpos($sql, 'CREATE TABLE ') === 0) { 00120 $sqlarr[$i] .= " ENGINE = $engine"; 00121 } 00122 } 00123 00124 return $sqlarr; 00125 } 00126 00131 public function getCreateTempTableSQL($xmldb_table) { 00132 $this->temptables->add_temptable($xmldb_table->getName()); 00133 $sqlarr = parent::getCreateTableSQL($xmldb_table); // we do not want the engine hack included in create table SQL 00134 $sqlarr = preg_replace('/^CREATE TABLE (.*)/s', 'CREATE TEMPORARY TABLE $1', $sqlarr); 00135 return $sqlarr; 00136 } 00137 00142 public function getDropTempTableSQL($xmldb_table) { 00143 $sqlarr = $this->getDropTableSQL($xmldb_table); 00144 $sqlarr = preg_replace('/^DROP TABLE/', "DROP TEMPORARY TABLE", $sqlarr); 00145 $this->temptables->delete_temptable($xmldb_table->getName()); 00146 return $sqlarr; 00147 } 00148 00152 public function getTypeSQL($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) { 00153 00154 switch ($xmldb_type) { 00155 case XMLDB_TYPE_INTEGER: // From http://mysql.com/doc/refman/5.0/en/numeric-types.html! 00156 if (empty($xmldb_length)) { 00157 $xmldb_length = 10; 00158 } 00159 if ($xmldb_length > 9) { 00160 $dbtype = 'BIGINT'; 00161 } else if ($xmldb_length > 6) { 00162 $dbtype = 'INT'; 00163 } else if ($xmldb_length > 4) { 00164 $dbtype = 'MEDIUMINT'; 00165 } else if ($xmldb_length > 2) { 00166 $dbtype = 'SMALLINT'; 00167 } else { 00168 $dbtype = 'TINYINT'; 00169 } 00170 $dbtype .= '(' . $xmldb_length . ')'; 00171 break; 00172 case XMLDB_TYPE_NUMBER: 00173 $dbtype = $this->number_type; 00174 if (!empty($xmldb_length)) { 00175 $dbtype .= '(' . $xmldb_length; 00176 if (!empty($xmldb_decimals)) { 00177 $dbtype .= ',' . $xmldb_decimals; 00178 } 00179 $dbtype .= ')'; 00180 } 00181 break; 00182 case XMLDB_TYPE_FLOAT: 00183 $dbtype = 'DOUBLE'; 00184 if (!empty($xmldb_decimals)) { 00185 if ($xmldb_decimals < 6) { 00186 $dbtype = 'FLOAT'; 00187 } 00188 } 00189 if (!empty($xmldb_length)) { 00190 $dbtype .= '(' . $xmldb_length; 00191 if (!empty($xmldb_decimals)) { 00192 $dbtype .= ',' . $xmldb_decimals; 00193 } else { 00194 $dbtype .= ', 0'; // In MySQL, if length is specified, decimals are mandatory for FLOATs 00195 } 00196 $dbtype .= ')'; 00197 } 00198 break; 00199 case XMLDB_TYPE_CHAR: 00200 $dbtype = 'VARCHAR'; 00201 if (empty($xmldb_length)) { 00202 $xmldb_length='255'; 00203 } 00204 $dbtype .= '(' . $xmldb_length . ')'; 00205 break; 00206 case XMLDB_TYPE_TEXT: 00207 if (empty($xmldb_length)) { 00208 $xmldb_length = 'small'; 00209 } 00210 if ($xmldb_length == 'small') { 00211 $dbtype = 'TEXT'; 00212 } else if ($xmldb_length == 'medium') { 00213 $dbtype = 'MEDIUMTEXT'; 00214 } else { 00215 $dbtype = 'LONGTEXT'; 00216 } 00217 break; 00218 case XMLDB_TYPE_BINARY: 00219 if (empty($xmldb_length)) { 00220 $xmldb_length = 'small'; 00221 } 00222 if ($xmldb_length == 'small') { 00223 $dbtype = 'BLOB'; 00224 } else if ($xmldb_length == 'medium') { 00225 $dbtype = 'MEDIUMBLOB'; 00226 } else { 00227 $dbtype = 'LONGBLOB'; 00228 } 00229 break; 00230 case XMLDB_TYPE_DATETIME: 00231 $dbtype = 'DATETIME'; 00232 } 00233 return $dbtype; 00234 } 00235 00240 public function getCreateEnumSQL($xmldb_table, $xmldb_field) { 00242 return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); 00243 } 00244 00251 public function getDropEnumSQL($xmldb_table, $xmldb_field) { 00253 if ($check_constraints = $this->getCheckConstraintsFromDB($xmldb_table, $xmldb_field)) { 00255 return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); 00256 } else { 00257 return array(); 00258 } 00259 } 00260 00265 public function getCreateDefaultSQL($xmldb_table, $xmldb_field) { 00268 return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); 00269 } 00270 00276 public function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) { 00277 00279 $xmldb_field_clone = clone($xmldb_field); 00280 00282 $xmldb_field_clone->setName($xmldb_field_clone->getName() . ' ' . $newname); 00283 00284 $fieldsql = $this->getFieldSQL($xmldb_table, $xmldb_field_clone); 00285 00286 $sql = 'ALTER TABLE ' . $this->getTableName($xmldb_table) . ' CHANGE ' . $fieldsql; 00287 00288 return array($sql); 00289 } 00290 00295 public function getDropDefaultSQL($xmldb_table, $xmldb_field) { 00298 return $this->getAlterFieldSQL($xmldb_table, $xmldb_field); 00299 } 00300 00304 function getCommentSQL ($xmldb_table) { 00305 $comment = ''; 00306 00307 if ($xmldb_table->getComment()) { 00308 $comment .= 'ALTER TABLE ' . $this->getTableName($xmldb_table); 00309 $comment .= " COMMENT='" . $this->addslashes(substr($xmldb_table->getComment(), 0, 60)) . "'"; 00310 } 00311 return array($comment); 00312 } 00313 00326 public function getCheckConstraintsFromDB($xmldb_table, $xmldb_field = null) { 00327 00328 $tablename = $xmldb_table->getName($xmldb_table); 00329 00331 if (!$columns = $this->mdb->get_columns($tablename)) { 00332 return array(); 00333 } 00334 00336 if ($xmldb_field) { 00337 $filter = $xmldb_field->getName(); 00338 if (!isset($columns[$filter])) { 00339 return array(); 00340 } 00341 $column = ($columns[$filter]); 00342 if (!empty($column->enums)) { 00343 $result = new stdClass(); 00344 $result->name = $filter; 00345 $result->description = implode(', ', $column->enums); 00346 return array($result); 00347 } else { 00348 return array(); 00349 } 00350 00351 } else { 00352 $results = array(); 00354 foreach ($columns as $key => $column) { 00356 if (!empty($column->enums)) { 00357 $result = new stdClass(); 00358 $result->name = $key; 00359 $result->description = implode(', ', $column->enums); 00360 $results[$key] = $result; 00361 } 00362 } 00363 return $results; 00364 } 00365 } 00366 00372 public function isNameInUse($object_name, $type, $table_name) { 00373 00375 $xmldb_table = new xmldb_table($table_name); 00376 $tname = $this->getTableName($xmldb_table); 00377 00378 switch($type) { 00379 case 'ix': 00380 case 'uix': 00382 $metatables = $this->mdb->get_tables(); 00383 if (isset($metatables[$tname])) { 00385 if ($indexes = $this->mdb->get_indexes($tname)) { 00387 if (isset($indexes[$object_name])) { 00388 return true; 00389 } 00390 } 00391 } 00392 break; 00393 } 00394 return false; //No name in use found 00395 } 00396 00397 00401 public static function getReservedWords() { 00404 $reserved_words = array ( 00405 'accessible', 'add', 'all', 'alter', 'analyze', 'and', 'as', 'asc', 00406 'asensitive', 'before', 'between', 'bigint', 'binary', 00407 'blob', 'both', 'by', 'call', 'cascade', 'case', 'change', 00408 'char', 'character', 'check', 'collate', 'column', 00409 'condition', 'connection', 'constraint', 'continue', 00410 'convert', 'create', 'cross', 'current_date', 'current_time', 00411 'current_timestamp', 'current_user', 'cursor', 'database', 00412 'databases', 'day_hour', 'day_microsecond', 00413 'day_minute', 'day_second', 'dec', 'decimal', 'declare', 00414 'default', 'delayed', 'delete', 'desc', 'describe', 00415 'deterministic', 'distinct', 'distinctrow', 'div', 'double', 00416 'drop', 'dual', 'each', 'else', 'elseif', 'enclosed', 'escaped', 00417 'exists', 'exit', 'explain', 'false', 'fetch', 'float', 'float4', 00418 'float8', 'for', 'force', 'foreign', 'from', 'fulltext', 'grant', 00419 'group', 'having', 'high_priority', 'hour_microsecond', 00420 'hour_minute', 'hour_second', 'if', 'ignore', 'in', 'index', 00421 'infile', 'inner', 'inout', 'insensitive', 'insert', 'int', 'int1', 00422 'int2', 'int3', 'int4', 'int8', 'integer', 'interval', 'into', 'is', 00423 'iterate', 'join', 'key', 'keys', 'kill', 'leading', 'leave', 'left', 00424 'like', 'limit', 'linear', 'lines', 'load', 'localtime', 'localtimestamp', 00425 'lock', 'long', 'longblob', 'longtext', 'loop', 'low_priority', 'master_heartbeat_period', 00426 'master_ssl_verify_server_cert', 'match', 'mediumblob', 'mediumint', 'mediumtext', 00427 'middleint', 'minute_microsecond', 'minute_second', 00428 'mod', 'modifies', 'natural', 'not', 'no_write_to_binlog', 00429 'null', 'numeric', 'on', 'optimize', 'option', 'optionally', 00430 'or', 'order', 'out', 'outer', 'outfile', 'overwrite', 'precision', 'primary', 00431 'procedure', 'purge', 'raid0', 'range', 'read', 'read_only', 'read_write', 'reads', 'real', 00432 'references', 'regexp', 'release', 'rename', 'repeat', 'replace', 00433 'require', 'restrict', 'return', 'revoke', 'right', 'rlike', 'schema', 00434 'schemas', 'second_microsecond', 'select', 'sensitive', 00435 'separator', 'set', 'show', 'smallint', 'soname', 'spatial', 00436 'specific', 'sql', 'sqlexception', 'sqlstate', 'sqlwarning', 00437 'sql_big_result', 'sql_calc_found_rows', 'sql_small_result', 00438 'ssl', 'starting', 'straight_join', 'table', 'terminated', 'then', 00439 'tinyblob', 'tinyint', 'tinytext', 'to', 'trailing', 'trigger', 'true', 00440 'undo', 'union', 'unique', 'unlock', 'unsigned', 'update', 00441 'upgrade', 'usage', 'use', 'using', 'utc_date', 'utc_time', 00442 'utc_timestamp', 'values', 'varbinary', 'varchar', 'varcharacter', 00443 'varying', 'when', 'where', 'while', 'with', 'write', 'x509', 00444 'xor', 'year_month', 'zerofill' 00445 ); 00446 return $reserved_words; 00447 } 00448 }