Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/ddl/sql_generator.php
Go to the documentation of this file.
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 
00033 defined('MOODLE_INTERNAL') || die();
00034 
00038 abstract class sql_generator {
00039 
00044 
00045     public $quote_string = '"';   // String used to quote names
00046 
00047     public $statement_end = ';'; // String to be automatically added at the end of each statement
00048 
00049     public $quote_all    = false; // To decide if we want to quote all the names or only the reserved ones
00050 
00051     public $integer_to_number = false;  // To create all the integers as NUMBER(x) (also called DECIMAL, NUMERIC...)
00052     public $float_to_number   = false;  // To create all the floats as NUMBER(x) (also called DECIMAL, NUMERIC...)
00053 
00054     public $number_type = 'NUMERIC';    // Proper type for NUMBER(x) in this DB
00055 
00056     public $unsigned_allowed = true;    // To define in the generator must handle unsigned information
00057     public $default_for_char = null;      // To define the default to set for NOT NULLs CHARs without default (null=do nothing)
00058 
00059     public $drop_default_value_required = false; //To specify if the generator must use some DEFAULT clause to drop defaults
00060     public $drop_default_value = ''; //The DEFAULT clause required to drop defaults
00061 
00062     public $default_after_null = true;  //To decide if the default clause of each field must go after the null clause
00063 
00064     public $specify_nulls = false;  //To force the generator if NULL clauses must be specified. It shouldn't be necessary
00065                                  //but some mssql drivers require them or everything is created as NOT NULL :-(
00066 
00067     public $primary_key_name = null; //To force primary key names to one string (null=no force)
00068 
00069     public $primary_keys = true;  // Does the generator build primary keys
00070     public $unique_keys = false;  // Does the generator build unique keys
00071     public $foreign_keys = false; // Does the generator build foreign keys
00072 
00073     public $drop_primary_key = 'ALTER TABLE TABLENAME DROP CONSTRAINT KEYNAME'; // Template to drop PKs
00074                                // with automatic replace for TABLENAME and KEYNAME
00075 
00076     public $drop_unique_key = 'ALTER TABLE TABLENAME DROP CONSTRAINT KEYNAME'; // Template to drop UKs
00077                                // with automatic replace for TABLENAME and KEYNAME
00078 
00079     public $drop_foreign_key = 'ALTER TABLE TABLENAME DROP CONSTRAINT KEYNAME'; // Template to drop FKs
00080                                // with automatic replace for TABLENAME and KEYNAME
00081 
00082     public $sequence_extra_code = true; //Does the generator need to add extra code to generate the sequence fields
00083     public $sequence_name = 'auto_increment'; //Particular name for inline sequences in this generator
00084     public $sequence_name_small = false; //Different name for small (4byte) sequences or false if same
00085     public $sequence_only = false; //To avoid to output the rest of the field specs, leaving only the name and the sequence_name publiciable
00086 
00087     public $add_table_comments  = true;  // Does the generator need to add code for table comments
00088 
00089     public $add_after_clause = false; // Does the generator need to add the after clause for fields
00090 
00091     public $prefix_on_names = true; //Does the generator need to prepend the prefix to all the key/index/sequence/trigger/check names
00092 
00093     public $names_max_length = 30; //Max length for key/index/sequence/trigger/check names (keep 30 for all!)
00094 
00095     public $concat_character = '||'; //Characters to be used as concatenation operator. If not defined
00096                                   //MySQL CONCAT function will be used
00097 
00098     public $rename_table_sql = 'ALTER TABLE OLDNAME RENAME TO NEWNAME'; //SQL sentence to rename one table, both
00099                                   //OLDNAME and NEWNAME are dynamically replaced
00100 
00101     public $drop_table_sql = 'DROP TABLE TABLENAME'; //SQL sentence to drop one table
00102                                   //TABLENAME is dynamically replaced
00103 
00104     public $alter_column_sql = 'ALTER TABLE TABLENAME ALTER COLUMN COLUMNSPECS'; //The SQL template to alter columns
00105 
00106     public $alter_column_skip_default = false; //The generator will skip the default clause on alter columns
00107 
00108     public $alter_column_skip_type = false; //The generator will skip the type clause on alter columns
00109 
00110     public $alter_column_skip_notnull = false; //The generator will skip the null/notnull clause on alter columns
00111 
00112     public $rename_column_sql = 'ALTER TABLE TABLENAME RENAME COLUMN OLDFIELDNAME TO NEWFIELDNAME';
00114 
00115     public $drop_index_sql = 'DROP INDEX INDEXNAME'; //SQL sentence to drop one index
00116                                   //TABLENAME, INDEXNAME are dynamically replaced
00117 
00118     public $rename_index_sql = 'ALTER INDEX OLDINDEXNAME RENAME TO NEWINDEXNAME'; //SQL sentence to rename one index
00119                                   //TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dynamically replaced
00120 
00121     public $rename_key_sql = 'ALTER TABLE TABLENAME CONSTRAINT OLDKEYNAME RENAME TO NEWKEYNAME'; //SQL sentence to rename one key
00122                                   //TABLENAME, OLDKEYNAME, NEWKEYNAME are dynamically replaced
00123 
00124     public $prefix;         // Prefix to be used for all the DB objects
00125 
00126     public $reserved_words; // List of reserved words (in order to quote them properly)
00127 
00128     public $mdb;
00129 
00130     protected $temptables; // Control existing temptables
00131 
00136     public function __construct($mdb, $temptables = null) {
00137         $this->prefix         = $mdb->get_prefix();
00138         $this->reserved_words = $this->getReservedWords();
00139         $this->mdb            = $mdb; // this creates circular reference - the other link must be unset when closing db
00140         $this->temptables     = $temptables;
00141     }
00142 
00146     public function dispose() {
00147         $this->mdb = null;
00148     }
00149 
00153     public function getEndedStatements($input) {
00154 
00155         if (is_array($input)) {
00156             foreach ($input as $key=>$content) {
00157                 $input[$key] = $this->getEndedStatements($content);
00158             }
00159             return $input;
00160         } else {
00161             $input = trim($input).$this->statement_end;
00162             return $input;
00163         }
00164     }
00165 
00172     public function table_exists($table) {
00173         if (is_string($table)) {
00174             $tablename = $table;
00175         } else {
00177             $tablename = $table->getName();
00178         }
00179 
00181         $tables = $this->mdb->get_tables();
00182         $exists = in_array($tablename, $tables);
00183 
00184         return $exists;
00185     }
00186 
00190     public function getCreateStructureSQL($xmldb_structure) {
00191         $results = array();
00192 
00193         if ($tables = $xmldb_structure->getTables()) {
00194             foreach ($tables as $table) {
00195                 $results = array_merge($results, $this->getCreateTableSQL($table));
00196             }
00197         }
00198 
00199         return $results;
00200     }
00201 
00209     public function getTableName(xmldb_table $xmldb_table, $quoted=true) {
00211         $tablename = $this->prefix.$xmldb_table->getName();
00212 
00214         if ($quoted) {
00215             $tablename = $this->getEncQuoted($tablename);
00216         }
00217 
00218         return $tablename;
00219     }
00220 
00225     public function getCreateTableSQL($xmldb_table) {
00226 
00227         $results = array();  //Array where all the sentences will be stored
00228 
00230         $table = 'CREATE TABLE ' . $this->getTableName($xmldb_table) . ' (';
00231 
00232         if (!$xmldb_fields = $xmldb_table->getFields()) {
00233             return $results;
00234         }
00235 
00236         $sequencefield = null;
00237 
00239         foreach ($xmldb_fields as $xmldb_field) {
00240             if ($xmldb_field->getSequence()) {
00241                 $sequencefield = $xmldb_field->getName();
00242             }
00243             $table .= "\n    " . $this->getFieldSQL($xmldb_table, $xmldb_field);
00244             $table .= ',';
00245         }
00247         if ($xmldb_keys = $xmldb_table->getKeys()) {
00248             foreach ($xmldb_keys as $xmldb_key) {
00249                 if ($keytext = $this->getKeySQL($xmldb_table, $xmldb_key)) {
00250                     $table .= "\nCONSTRAINT " . $keytext . ',';
00251                 }
00253                 if ($xmldb_key->getType() == XMLDB_KEY_FOREIGN_UNIQUE) {
00255                     $xmldb_key->setType(XMLDB_KEY_UNIQUE);
00256                     if ($keytext = $this->getKeySQL($xmldb_table, $xmldb_key)) {
00257                         $table .= "\nCONSTRAINT " . $keytext . ',';
00258                     }
00259                 }
00261                 if ($sequencefield and $xmldb_key->getType() == XMLDB_KEY_PRIMARY) {
00262                     $field = reset($xmldb_key->getFields());
00263                     if ($sequencefield === $field) {
00264                         $sequencefield = null;
00265                     }
00266                 }
00267             }
00268         }
00270         if ($sequencefield) {
00271             throw new ddl_exception('ddsequenceerror', $xmldb_table->getName());
00272         }
00273 
00275         $table = trim($table,',');
00276         $table .= "\n)";
00277 
00279         $results[] = $table;
00280 
00282         if ($this->add_table_comments && $xmldb_table->getComment()) {
00283             $comment = $this->getCommentSQL($xmldb_table);
00285             $results = array_merge($results, $comment);
00286         }
00287 
00289         if ($xmldb_indexes = $xmldb_table->getIndexes()) {
00290             foreach ($xmldb_indexes as $xmldb_index) {
00292                 if ($indextext = $this->getCreateIndexSQL($xmldb_table, $xmldb_index)) {
00293                     $results = array_merge($results, $indextext);
00294                 }
00295             }
00296         }
00297 
00299         if ($xmldb_keys = $xmldb_table->getKeys()) {
00300             foreach ($xmldb_keys as $xmldb_key) {
00303                 if (!$this->getKeySQL($xmldb_table, $xmldb_key) || $xmldb_key->getType() == XMLDB_KEY_FOREIGN) {
00305                     $index = new xmldb_index('anyname');
00306                     $index->setFields($xmldb_key->getFields());
00308                     $createindex = false; //By default
00309                     switch ($xmldb_key->getType()) {
00310                         case XMLDB_KEY_UNIQUE:
00311                         case XMLDB_KEY_FOREIGN_UNIQUE:
00312                             $index->setUnique(true);
00313                             $createindex = true;
00314                             break;
00315                         case XMLDB_KEY_FOREIGN:
00316                             $index->setUnique(false);
00317                             $createindex = true;
00318                             break;
00319                     }
00320                     if ($createindex) {
00321                         if ($indextext = $this->getCreateIndexSQL($xmldb_table, $index)) {
00323                             $results = array_merge($results, $indextext);
00324                         }
00325                     }
00326                 }
00327             }
00328         }
00329 
00331         if ($this->sequence_extra_code) {
00333             foreach ($xmldb_fields as $xmldb_field) {
00334                 if ($xmldb_field->getSequence()) {
00336                     $sequence_sentences = $this->getCreateSequenceSQL($xmldb_table, $xmldb_field);
00338                     $results = array_merge($results, $sequence_sentences);
00339                 }
00340             }
00341         }
00342 
00343         return $results;
00344     }
00345 
00350     public function getCreateIndexSQL($xmldb_table, $xmldb_index) {
00351         if ($error = $xmldb_index->validateDefinition($xmldb_table)) {
00352             throw new coding_exception($error);
00353         }
00354 
00355         $unique = '';
00356         $suffix = 'ix';
00357         if ($xmldb_index->getUnique()) {
00358             $unique = ' UNIQUE';
00359             $suffix = 'uix';
00360         }
00361 
00362         $index = 'CREATE' . $unique . ' INDEX ';
00363         $index .= $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_index->getFields()), $suffix);
00364         $index .= ' ON ' . $this->getTableName($xmldb_table);
00365         $index .= ' (' . implode(', ', $this->getEncQuoted($xmldb_index->getFields())) . ')';
00366 
00367         return array($index);
00368     }
00369 
00373     public function getFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL, $specify_nulls_clause = NULL, $specify_field_name = true)  {
00374         if ($error = $xmldb_field->validateDefinition($xmldb_table)) {
00375             throw new coding_exception($error);
00376         }
00377 
00378         $skip_type_clause = is_null($skip_type_clause) ? $this->alter_column_skip_type : $skip_type_clause;
00379         $skip_default_clause = is_null($skip_default_clause) ? $this->alter_column_skip_default : $skip_default_clause;
00380         $skip_notnull_clause = is_null($skip_notnull_clause) ? $this->alter_column_skip_notnull : $skip_notnull_clause;
00381         $specify_nulls_clause = is_null($specify_nulls_clause) ? $this->specify_nulls : $specify_nulls_clause;
00382 
00384         if ($this->integer_to_number) {
00385             if ($xmldb_field->getType() == XMLDB_TYPE_INTEGER) {
00386                 $xmldb_field->setType(XMLDB_TYPE_NUMBER);
00387             }
00388         }
00390         if ($this->float_to_number) {
00391             if ($xmldb_field->getType() == XMLDB_TYPE_FLOAT) {
00392                 $xmldb_field->setType(XMLDB_TYPE_NUMBER);
00393             }
00394         }
00395 
00396         $field = ''; // Let's accumulate the whole expression based on params and settings
00398         if ($specify_field_name) {
00399             $field .= $this->getEncQuoted($xmldb_field->getName());
00400         }
00402         if (!$skip_type_clause) {
00404             $field .= ' ' . $this->getTypeSQL($xmldb_field->getType(), $xmldb_field->getLength(), $xmldb_field->getDecimals());
00405         }
00407         if ($this->unsigned_allowed && ($xmldb_field->getType() == XMLDB_TYPE_INTEGER ||
00408                                       $xmldb_field->getType() == XMLDB_TYPE_NUMBER ||
00409                                       $xmldb_field->getType() == XMLDB_TYPE_FLOAT)) {
00410             if ($xmldb_field->getUnsigned()) {
00411                 $field .= ' unsigned';
00412             }
00413         }
00415         $notnull = '';
00417         if (!$skip_notnull_clause) {
00418             if ($xmldb_field->getNotNull()) {
00419                 $notnull = ' NOT NULL';
00420             } else {
00421                 if ($specify_nulls_clause) {
00422                     $notnull = ' NULL';
00423                 }
00424             }
00425         }
00427         $default_clause = '';
00428         if (!$skip_default_clause) { //Only if we don't want to skip it
00429             $default_clause = $this->getDefaultClause($xmldb_field);
00430         }
00432         if ($this->default_after_null) {
00433             $field .= $notnull . $default_clause;
00434         } else {
00435             $field .= $default_clause . $notnull;
00436         }
00438         if ($xmldb_field->getSequence()) {
00439             if($xmldb_field->getLength()<=9 && $this->sequence_name_small) {
00440                 $sequencename=$this->sequence_name_small;
00441             } else {
00442                 $sequencename=$this->sequence_name;
00443             }
00444             $field .= ' ' . $sequencename;
00445             if ($this->sequence_only) {
00448                 $sql = $this->getEncQuoted($xmldb_field->getName()) . ' ' . $sequencename;
00449                 return $sql;
00450             }
00451         }
00452         return $field;
00453     }
00454 
00458     public function getKeySQL($xmldb_table, $xmldb_key) {
00459 
00460         $key = '';
00461 
00462         switch ($xmldb_key->getType()) {
00463             case XMLDB_KEY_PRIMARY:
00464                 if ($this->primary_keys) {
00465                     if ($this->primary_key_name !== null) {
00466                         $key = $this->getEncQuoted($this->primary_key_name);
00467                     } else {
00468                         $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'pk');
00469                     }
00470                     $key .= ' PRIMARY KEY (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')';
00471                 }
00472                 break;
00473             case XMLDB_KEY_UNIQUE:
00474                 if ($this->unique_keys) {
00475                     $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'uk');
00476                     $key .= ' UNIQUE (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')';
00477                 }
00478                 break;
00479             case XMLDB_KEY_FOREIGN:
00480             case XMLDB_KEY_FOREIGN_UNIQUE:
00481                 if ($this->foreign_keys) {
00482                     $key = $this->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), 'fk');
00483                     $key .= ' FOREIGN KEY (' . implode(', ', $this->getEncQuoted($xmldb_key->getFields())) . ')';
00484                     $key .= ' REFERENCES ' . $this->getEncQuoted($this->prefix . $xmldb_key->getRefTable());
00485                     $key .= ' (' . implode(', ', $this->getEncQuoted($xmldb_key->getRefFields())) . ')';
00486                 }
00487                 break;
00488         }
00489 
00490         return $key;
00491     }
00492 
00496     public function getDefaultValue($xmldb_field) {
00497 
00498         $default = null;
00499 
00500         if ($xmldb_field->getDefault() !== NULL) {
00501             if ($xmldb_field->getType() == XMLDB_TYPE_CHAR ||
00502                 $xmldb_field->getType() == XMLDB_TYPE_TEXT) {
00503                     if ($xmldb_field->getDefault() === '') { // If passing empty default, use the $default_for_char one instead
00504                         $default = "'" . $this->default_for_char . "'";
00505                     } else {
00506                         $default = "'" . $this->addslashes($xmldb_field->getDefault()) . "'";
00507                     }
00508             } else {
00509                 $default = $xmldb_field->getDefault();
00510             }
00511         } else {
00514             if ($this->default_for_char !== NULL &&
00515                 $xmldb_field->getType() == XMLDB_TYPE_CHAR &&
00516                 $xmldb_field->getNotNull()) {
00517                 $default = "'" . $this->default_for_char . "'";
00518             } else {
00521                 if ($this->drop_default_value_required &&
00522                     $xmldb_field->getType() != XMLDB_TYPE_TEXT &&
00523                     $xmldb_field->getType() != XMLDB_TYPE_BINARY && !$xmldb_field->getNotNull()) {
00524                     $default = $this->drop_default_value;
00525                 }
00526             }
00527         }
00528         return $default;
00529     }
00530 
00534     public function getDefaultClause($xmldb_field) {
00535 
00536         $defaultvalue = $this->getDefaultValue ($xmldb_field);
00537 
00538         if ($defaultvalue !== null) {
00539             return ' DEFAULT ' . $defaultvalue;
00540         } else {
00541             return null;
00542         }
00543     }
00544 
00549     public function getRenameTableSQL($xmldb_table, $newname) {
00550 
00551         $results = array();  //Array where all the sentences will be stored
00552 
00553         $newt = new xmldb_table($newname); //Temporal table for name calculations
00554 
00555         $rename = str_replace('OLDNAME', $this->getTableName($xmldb_table), $this->rename_table_sql);
00556         $rename = str_replace('NEWNAME', $this->getTableName($newt), $rename);
00557 
00558         $results[] = $rename;
00559 
00561         $extra_sentences = $this->getRenameTableExtraSQL($xmldb_table, $newname);
00562         $results = array_merge($results, $extra_sentences);
00563 
00564         return $results;
00565     }
00566 
00571     public function getDropTableSQL($xmldb_table) {
00572 
00573         $results = array();  //Array where all the sentences will be stored
00574 
00575         $drop = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->drop_table_sql);
00576 
00577         $results[] = $drop;
00578 
00580         $extra_sentences = $this->getDropTableExtraSQL($xmldb_table);
00581         $results = array_merge($results, $extra_sentences);
00582 
00583         return $results;
00584     }
00585 
00589     public function getAddFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL) {
00590 
00591         $skip_type_clause = is_null($skip_type_clause) ? $this->alter_column_skip_type : $skip_type_clause;
00592         $skip_default_clause = is_null($skip_default_clause) ? $this->alter_column_skip_default : $skip_default_clause;
00593         $skip_notnull_clause = is_null($skip_notnull_clause) ? $this->alter_column_skip_notnull : $skip_notnull_clause;
00594 
00595         $results = array();
00596 
00598         $tablename = $this->getTableName($xmldb_table);
00599 
00601         $sql = $this->getFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause,
00602                                   $skip_default_clause,
00603                                   $skip_notnull_clause);
00604         $altertable = 'ALTER TABLE ' . $tablename . ' ADD ' . $sql;
00606         if ($this->add_after_clause && $xmldb_field->getPrevious()) {
00607             $altertable .= ' AFTER ' . $this->getEncQuoted($xmldb_field->getPrevious());
00608         }
00609         $results[] = $altertable;
00610 
00611         return $results;
00612     }
00613 
00617     public function getDropFieldSQL($xmldb_table, $xmldb_field) {
00618 
00619         $results = array();
00620 
00622         $tablename = $this->getTableName($xmldb_table);
00623         $fieldname = $this->getEncQuoted($xmldb_field->getName());
00624 
00626         $results[] = 'ALTER TABLE ' . $tablename . ' DROP COLUMN ' . $fieldname;
00627 
00628         return $results;
00629     }
00630 
00634     public function getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL) {
00635 
00636         $skip_type_clause = is_null($skip_type_clause) ? $this->alter_column_skip_type : $skip_type_clause;
00637         $skip_default_clause = is_null($skip_default_clause) ? $this->alter_column_skip_default : $skip_default_clause;
00638         $skip_notnull_clause = is_null($skip_notnull_clause) ? $this->alter_column_skip_notnull : $skip_notnull_clause;
00639 
00640         $results = array();
00641 
00643         $tablename = $this->getTableName($xmldb_table);
00644         $fieldname = $this->getEncQuoted($xmldb_field->getName());
00645 
00647         $alter = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->alter_column_sql);
00648         $colspec = $this->getFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause,
00649                                       $skip_default_clause,
00650                                       $skip_notnull_clause,
00651                                       true);
00652         $alter = str_replace('COLUMNSPECS', $colspec, $alter);
00653 
00655         if ($this->add_after_clause && $xmldb_field->getPrevious()) {
00656             $alter .= ' after ' . $this->getEncQuoted($xmldb_field->getPrevious());
00657         }
00658 
00660         $results[] = $alter;
00661 
00662         return $results;
00663     }
00664 
00668     public function getModifyDefaultSQL($xmldb_table, $xmldb_field) {
00669 
00670         $results = array();
00671 
00673         $tablename = $this->getTableName($xmldb_table);
00674         $fieldname = $this->getEncQuoted($xmldb_field->getName());
00675 
00677         if ($xmldb_field->getDefault() === null) {
00678             $results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); //Drop
00679         } else {
00680             $results = $this->getCreateDefaultSQL($xmldb_table, $xmldb_field); //Create/modify
00681         }
00682 
00683         return $results;
00684     }
00685 
00690     public function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) {
00691 
00692         $results = array();  //Array where all the sentences will be stored
00693 
00701         if ($xmldb_field->getName() == 'id') {
00702             return array();
00703         }
00704 
00705         $rename = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->rename_column_sql);
00706         $rename = str_replace('OLDFIELDNAME', $this->getEncQuoted($xmldb_field->getName()), $rename);
00707         $rename = str_replace('NEWFIELDNAME', $this->getEncQuoted($newname), $rename);
00708 
00709         $results[] = $rename;
00710 
00712         $extra_sentences = $this->getRenameFieldExtraSQL($xmldb_table, $xmldb_field, $newname);
00713         $results = array_merge($results, $extra_sentences);
00714 
00715         return $results;
00716     }
00717 
00722     public function getAddKeySQL($xmldb_table, $xmldb_key) {
00723 
00724         $results = array();
00725 
00727         if ($keyclause = $this->getKeySQL($xmldb_table, $xmldb_key)) {
00728             $key = 'ALTER TABLE ' . $this->getTableName($xmldb_table) .
00729                ' ADD CONSTRAINT ' . $keyclause;
00730             $results[] = $key;
00731         }
00732 
00735         if (!$keyclause || $xmldb_key->getType() == XMLDB_KEY_FOREIGN) {
00737             if ($xmldb_key->getType() == XMLDB_KEY_FOREIGN) {  
00738                 $indextype = XMLDB_INDEX_NOTUNIQUE;
00739             } else {
00740                 $indextype = XMLDB_INDEX_UNIQUE;
00741             }
00742             $xmldb_index = new xmldb_index('anyname', $indextype, $xmldb_key->getFields());
00743             if (!$this->mdb->get_manager()->index_exists($xmldb_table, $xmldb_index)) {
00744                 $results = array_merge($results, $this->getAddIndexSQL($xmldb_table, $xmldb_index));
00745             }
00746         }
00747 
00749         if ($xmldb_key->getType() == XMLDB_KEY_FOREIGN_UNIQUE && $this->unique_keys) {
00751             $xmldb_key->setType(XMLDB_KEY_UNIQUE);
00752             $results = array_merge($results, $this->getAddKeySQL($xmldb_table, $xmldb_key));
00753         }
00754 
00756         return $results;
00757     }
00758 
00762     public function getDropKeySQL($xmldb_table, $xmldb_key) {
00763 
00764         $results = array();
00765 
00771         $dbkeyname = $this->mdb->get_manager()->find_key_name($xmldb_table, $xmldb_key);
00772 
00774         $dropkey = false;
00775         switch ($xmldb_key->getType()) {
00776             case XMLDB_KEY_PRIMARY:
00777                 if ($this->primary_keys) {
00778                     $template = $this->drop_primary_key;
00779                     $dropkey = true;
00780                 }
00781                 break;
00782             case XMLDB_KEY_UNIQUE:
00783                 if ($this->unique_keys) {
00784                     $template = $this->drop_unique_key;
00785                     $dropkey = true;
00786                 }
00787                 break;
00788             case XMLDB_KEY_FOREIGN_UNIQUE:
00789             case XMLDB_KEY_FOREIGN:
00790                 if ($this->foreign_keys) {
00791                     $template = $this->drop_foreign_key;
00792                     $dropkey = true;
00793                 }
00794                 break;
00795         }
00797         if ($dropkey) {
00799             $dropsql = str_replace('TABLENAME', $this->getTableName($xmldb_table), $template);
00800             $dropsql = str_replace('KEYNAME', $dbkeyname, $dropsql);
00801 
00802             $results[] = $dropsql;
00803         }
00804 
00807         if (!$dropkey || $xmldb_key->getType() == XMLDB_KEY_FOREIGN) {
00809             $xmldb_index = new xmldb_index('anyname', XMLDB_INDEX_UNIQUE, $xmldb_key->getFields());
00810             if ($this->mdb->get_manager()->index_exists($xmldb_table, $xmldb_index)) {
00811                 $results = array_merge($results, $this->getDropIndexSQL($xmldb_table, $xmldb_index));
00812             }
00813         }
00814 
00816         if ($xmldb_key->getType() == XMLDB_KEY_FOREIGN_UNIQUE && $this->unique_keys) {
00818             $xmldb_key->setType(XMLDB_KEY_UNIQUE);
00819             $results = array_merge($results, $this->getDropKeySQL($xmldb_table, $xmldb_key));
00820         }
00821 
00823         return $results;
00824     }
00825 
00831     public function getRenameKeySQL($xmldb_table, $xmldb_key, $newname) {
00832 
00833         $results = array();
00834 
00836         $dbkeyname = $this->mdb->get_manager()->find_key_name($xmldb_table, $xmldb_key);
00837 
00839         if (($xmldb_key->getType() == XMLDB_KEY_PRIMARY && !$this->primary_keys) ||
00840             ($xmldb_key->getType() == XMLDB_KEY_UNIQUE && !$this->unique_keys) ||
00841             ($xmldb_key->getType() == XMLDB_KEY_FOREIGN && !$this->foreign_keys) ||
00842             ($xmldb_key->getType() == XMLDB_KEY_FOREIGN_UNIQUE && !$this->unique_keys && !$this->foreign_keys)) {
00844             $xmldb_index = new xmldb_index($xmldb_key->getName());
00845             $xmldb_index->setFields($xmldb_key->getFields());
00846             return $this->getRenameIndexSQL($xmldb_table, $xmldb_index, $newname);
00847         }
00848 
00851         $renamesql = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->rename_key_sql);
00852         $renamesql = str_replace('OLDKEYNAME', $dbkeyname, $renamesql);
00853         $renamesql = str_replace('NEWKEYNAME', $newname, $renamesql);
00854 
00856         if ($renamesql) {
00857             $results[] = $renamesql;
00858         }
00859 
00860         return $results;
00861     }
00862 
00866     public function getAddIndexSQL($xmldb_table, $xmldb_index) {
00867 
00869         return $this->getCreateIndexSQL($xmldb_table, $xmldb_index);
00870     }
00871 
00875     public function getDropIndexSQL($xmldb_table, $xmldb_index) {
00876 
00877         $results = array();
00878 
00880         $dbindexname = $this->mdb->get_manager()->find_index_name($xmldb_table, $xmldb_index);
00881 
00883         $dropsql = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->drop_index_sql);
00884         $dropsql = str_replace('INDEXNAME', $this->getEncQuoted($dbindexname), $dropsql);
00885 
00886         $results[] = $dropsql;
00887 
00888         return $results;
00889     }
00890 
00895     function getRenameIndexSQL($xmldb_table, $xmldb_index, $newname) {
00897         if (empty($this->rename_index_sql)) {
00898             return array();
00899         }
00900 
00902         $dbindexname = $this->mdb->get_manager()->find_index_name($xmldb_table, $xmldb_index);
00904         $renamesql = str_replace('TABLENAME', $this->getTableName($xmldb_table), $this->rename_index_sql);
00905         $renamesql = str_replace('OLDINDEXNAME', $this->getEncQuoted($dbindexname), $renamesql);
00906         $renamesql = str_replace('NEWINDEXNAME', $this->getEncQuoted($newname), $renamesql);
00907 
00908         return array($renamesql);
00909     }
00910 
00918     public function getNameForObject($tablename, $fields, $suffix='') {
00919 
00920         $name = '';
00921 
00927         static $used_names = array();
00928 
00930         $tablearr = explode ('_', $tablename);
00931         foreach ($tablearr as $table) {
00932             $name .= substr(trim($table),0,4);
00933         }
00934         $name .= '_';
00935         $fieldsarr = explode (',', $fields);
00936         foreach ($fieldsarr as $field) {
00937             $name .= substr(trim($field),0,3);
00938         }
00940         $name = $this->prefix . $name;
00941 
00942         $name = substr(trim($name), 0, $this->names_max_length - 1 - strlen($suffix)); //Max names_max_length
00943 
00945         $namewithsuffix = $name;
00946         if ($suffix) {
00947             $namewithsuffix = $namewithsuffix . '_' . $suffix;
00948         }
00949 
00951         if (in_array($namewithsuffix, $used_names) || $this->isNameInUse($namewithsuffix, $suffix, $tablename)) {
00952             $counter = 2;
00954             if (strlen($namewithsuffix) < $this->names_max_length) {
00955                 $newname = $name . $counter;
00957             } else {
00958                 $newname = substr($name, 0, strlen($name)-1) . $counter;
00959             }
00960             $newnamewithsuffix = $newname;
00961             if ($suffix) {
00962                 $newnamewithsuffix = $newnamewithsuffix . '_' . $suffix;
00963             }
00965             while (in_array($newnamewithsuffix, $used_names) || $this->isNameInUse($newnamewithsuffix, $suffix, $tablename)) {
00966                 $counter++;
00967                 $newname = substr($name, 0, strlen($newname)-1) . $counter;
00968                 $newnamewithsuffix = $newname;
00969                 if ($suffix) {
00970                     $newnamewithsuffix = $newnamewithsuffix . '_' . $suffix;
00971                 }
00972             }
00973             $namewithsuffix = $newnamewithsuffix;
00974         }
00975 
00977         $used_names[] = $namewithsuffix;
00978 
00980         $namewithsuffix = $this->getEncQuoted($namewithsuffix);
00981 
00982         return $namewithsuffix;
00983     }
00984 
00989     public function getEncQuoted($input) {
00990 
00991         if (is_array($input)) {
00992             foreach ($input as $key=>$content) {
00993                 $input[$key] = $this->getEncQuoted($content);
00994             }
00995             return $input;
00996         } else {
00998             $input = strtolower($input);
01000             if ($this->quote_all || in_array($input, $this->reserved_words) || strpos($input, '-') !== false) {
01001                 $input = $this->quote_string . $input . $this->quote_string;
01002             }
01003             return $input;
01004         }
01005     }
01006 
01010     function getExecuteInsertSQL($statement) {
01011 
01012          $results = array();  //Array where all the sentences will be stored
01013 
01014          if ($sentences = $statement->getSentences()) {
01015              foreach ($sentences as $sentence) {
01017                  $fields = $statement->getFieldsFromInsertSentence($sentence);
01019                  $values = $statement->getValuesFromInsertSentence($sentence);
01021                  foreach($values as $key => $value) {
01023                      $value = trim($value,"'");
01024                      if (stristr($value, 'CONCAT') !== false){
01026                          preg_match("/CONCAT\s*\((.*)\)$/is", trim($value), $matches);
01027                          if (isset($matches[1])) {
01028                              $part = $matches[1];
01030                              $arr = xmldb_object::comma2array($part);
01031                              if ($arr) {
01032                                  $value = $this->getConcatSQL($arr);
01033                              }
01034                          }
01035                      }
01037                      $value = $this->addslashes($value);
01039                      $value = "'" . $value . "'";
01041                      $values[$key] = $value;
01042                  }
01043 
01045                  foreach($fields as $key => $field) {
01046                      $fields[$key] = $this->getEncQuoted($field);
01047                  }
01049              $sql = 'INSERT INTO ' . $this->getEncQuoted($this->prefix . $statement->getTable()) .
01050                          '(' . implode(', ', $fields) . ') ' .
01051                          'VALUES (' . implode(', ', $values) . ')';
01052                  $results[] = $sql;
01053              }
01054 
01055          }
01056          return $results;
01057     }
01058 
01064     public function getConcatSQL($elements) {
01065 
01067         foreach($elements as $key => $element) {
01068             $element = trim($element);
01069             if (substr($element, 0, 1) == '"' &&
01070                 substr($element, -1, 1) == '"') {
01071                     $elements[$key] = "'" . trim($element, '"') . "'";
01072             }
01073         }
01074 
01076         return call_user_func_array(array($this->mdb, 'sql_concat'), $elements);
01077     }
01078 
01083     public function getSequenceFromDB($xmldb_table) {
01084         return false;
01085     }
01086 
01094     public function isNameInUse($object_name, $type, $table_name) {
01095         return false; //For generators not implementing introspection,
01096                       //we always return with the name being free to be used
01097     }
01098 
01099 
01101 
01107     public abstract function getResetSequenceSQL($tablename);
01108 
01113     abstract public function getCreateTempTableSQL($xmldb_table);
01114 
01119     abstract public function getDropTempTableSQL($xmldb_table);
01120 
01124     public abstract function getTypeSQL($xmldb_type, $xmldb_length=null, $xmldb_decimals=null);
01125 
01129     public function getRenameFieldExtraSQL($xmldb_table, $xmldb_field) {
01130         return array();
01131     }
01132 
01137     public function getCreateSequenceSQL($xmldb_table, $xmldb_field) {
01138         return array();
01139     }
01140 
01144     public abstract function getCommentSQL($xmldb_table);
01145 
01149     public function getRenameTableExtraSQL($xmldb_table, $newname) {
01150         return array();
01151     }
01152 
01156     public function getDropTableExtraSQL($xmldb_table) {
01157         return array();
01158     }
01159 
01166     public abstract function getDropEnumSQL($xmldb_table, $xmldb_field);
01167 
01174     public abstract function getDropDefaultSQL($xmldb_table, $xmldb_field);
01175 
01183     public abstract function getCheckConstraintsFromDB($xmldb_table, $xmldb_field=null);
01184 
01189     public abstract function getCreateDefaultSQL($xmldb_table, $xmldb_field);
01190 
01196     public static function getReservedWords() {
01197         throw new coding_exception('getReservedWords() method needs to be overridden in each subclass of sql_generator');
01198     }
01199 
01205     public static function getAllReservedWords() {
01206         global $CFG;
01207 
01208         $generators = array('mysql', 'postgres', 'oracle', 'mssql');
01209         $reserved_words = array();
01210 
01211         foreach($generators as $generator) {
01212             $class = $generator . '_sql_generator';
01213             require_once("$CFG->libdir/ddl/$class.php");
01214             foreach (call_user_func(array($class, 'getReservedWords')) as $word) {
01215                 $reserved_words[$word][] = $generator;
01216             }
01217         }
01218         ksort($reserved_words);
01219         return $reserved_words;
01220     }
01221 
01222     public function addslashes($s) {
01223         // do not use php addslashes() because it depends on PHP quote settings!
01224         $s = str_replace('\\','\\\\',$s);
01225         $s = str_replace("\0","\\\0", $s);
01226         $s = str_replace("'",  "\\'", $s);
01227         return $s;
01228     }
01229 }
 All Data Structures Namespaces Files Functions Variables Enumerations