Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Mysql specific SQL code generator.
19
 *
20
 * @package    core_ddl
21
 * @copyright  1999 onwards Martin Dougiamas     http://dougiamas.com
22
 *             2001-3001 Eloy Lafuente (stronk7) http://contiento.com
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
require_once($CFG->libdir.'/ddl/sql_generator.php');
29
 
30
/**
31
 * This class generate SQL code to be used against MySQL
32
 * It extends XMLDBgenerator so everything can be
33
 * overridden as needed to generate correct SQL.
34
 *
35
 * @property mysqli_native_moodle_database $mdb
36
 *
37
 * @package    core_ddl
38
 * @copyright  1999 onwards Martin Dougiamas     http://dougiamas.com
39
 *             2001-3001 Eloy Lafuente (stronk7) http://contiento.com
40
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
 */
42
class mysql_sql_generator extends sql_generator {
43
 
44
    // Only set values that are different from the defaults present in XMLDBgenerator
45
 
46
    /** @var string Used to quote names. */
47
    public $quote_string = '`';
48
 
49
    /** @var string To define the default to set for NOT NULLs CHARs without default (null=do nothing).*/
50
    public $default_for_char = '';
51
 
52
    /** @var bool To specify if the generator must use some DEFAULT clause to drop defaults.*/
53
    public $drop_default_value_required = true;
54
 
55
    /** @var string The DEFAULT clause required to drop defaults.*/
56
    public $drop_default_value = null;
57
 
58
    /** @var string To force primary key names to one string (null=no force).*/
59
    public $primary_key_name = '';
60
 
61
    /** @var string Template to drop PKs. 'TABLENAME' and 'KEYNAME' will be replaced from this template.*/
62
    public $drop_primary_key = 'ALTER TABLE TABLENAME DROP PRIMARY KEY';
63
 
64
    /** @var string Template to drop UKs. 'TABLENAME' and 'KEYNAME' will be replaced from this template.*/
65
    public $drop_unique_key = 'ALTER TABLE TABLENAME DROP KEY KEYNAME';
66
 
67
    /** @var string Template to drop FKs. 'TABLENAME' and 'KEYNAME' will be replaced from this template.*/
68
    public $drop_foreign_key = 'ALTER TABLE TABLENAME DROP FOREIGN KEY KEYNAME';
69
 
70
    /** @var bool True if the generator needs to add extra code to generate the sequence fields.*/
71
    public $sequence_extra_code = false;
72
 
73
    /** @var string The particular name for inline sequences in this generator.*/
74
    public $sequence_name = 'auto_increment';
75
 
76
    public $add_after_clause = true; // Does the generator need to add the after clause for fields
77
 
78
    /** @var string Characters to be used as concatenation operator.*/
79
    public $concat_character = null;
80
 
81
    /** @var string The SQL template to alter columns where the 'TABLENAME' and 'COLUMNSPECS' keywords are dynamically replaced.*/
82
    public $alter_column_sql = 'ALTER TABLE TABLENAME MODIFY COLUMN COLUMNSPECS';
83
 
84
    /** @var string SQL sentence to drop one index where 'TABLENAME', 'INDEXNAME' keywords are dynamically replaced.*/
85
    public $drop_index_sql = 'ALTER TABLE TABLENAME DROP INDEX INDEXNAME';
86
 
87
    /** @var string SQL sentence to rename one index where 'TABLENAME', 'OLDINDEXNAME' and 'NEWINDEXNAME' are dynamically replaced.*/
88
    public $rename_index_sql = null;
89
 
90
    /** @var string SQL sentence to rename one key 'TABLENAME', 'OLDKEYNAME' and 'NEWKEYNAME' are dynamically replaced.*/
91
    public $rename_key_sql = null;
92
 
93
    /** Maximum size of InnoDB row in Antelope file format */
94
    const ANTELOPE_MAX_ROW_SIZE = 8126;
95
 
96
    /**
97
     * Reset a sequence to the id field of a table.
98
     *
99
     * @param xmldb_table|string $table name of table or the table object.
100
     * @return array of sql statements
101
     */
102
    public function getResetSequenceSQL($table) {
103
 
104
        if ($table instanceof xmldb_table) {
105
            $tablename = $table->getName();
106
        } else {
107
            $tablename = $table;
108
        }
109
 
110
        // From http://dev.mysql.com/doc/refman/5.0/en/alter-table.html
111
        $value = (int)$this->mdb->get_field_sql('SELECT MAX(id) FROM {'.$tablename.'}');
112
        $value++;
113
        return array("ALTER TABLE $this->prefix$tablename AUTO_INCREMENT = $value");
114
    }
115
 
116
    /**
117
     * Calculate proximate row size when using InnoDB tables in Antelope row format.
118
     *
119
     * Note: the returned value is a bit higher to compensate for errors and changes of column data types.
120
     *
121
     * @param xmldb_field[]|database_column_info[] $columns
122
     * @return int approximate row size in bytes
123
     */
124
    public function guess_antelope_row_size(array $columns) {
125
 
126
        if (empty($columns)) {
127
            return 0;
128
        }
129
 
130
        $size = 0;
131
        $first = reset($columns);
132
 
133
        if (count($columns) > 1) {
134
            // Do not start with zero because we need to cover changes of field types and
135
            // this calculation is most probably not be accurate.
136
            $size += 1000;
137
        }
138
 
139
        if ($first instanceof xmldb_field) {
140
            foreach ($columns as $field) {
141
                switch ($field->getType()) {
142
                    case XMLDB_TYPE_TEXT:
143
                        $size += 768;
144
                        break;
145
                    case XMLDB_TYPE_BINARY:
146
                        $size += 768;
147
                        break;
148
                    case XMLDB_TYPE_CHAR:
149
                        $bytes = $field->getLength() * 3;
150
                        if ($bytes > 768) {
151
                            $bytes = 768;
152
                        }
153
                        $size += $bytes;
154
                        break;
155
                    default:
156
                        // Anything else is usually maximum 8 bytes.
157
                        $size += 8;
158
                }
159
            }
160
 
161
        } else if ($first instanceof database_column_info) {
162
            foreach ($columns as $column) {
163
                switch ($column->meta_type) {
164
                    case 'X':
165
                        $size += 768;
166
                        break;
167
                    case 'B':
168
                        $size += 768;
169
                        break;
170
                    case 'C':
171
                        $bytes = $column->max_length * 3;
172
                        if ($bytes > 768) {
173
                            $bytes = 768;
174
                        }
175
                        $size += $bytes;
176
                        break;
177
                    default:
178
                        // Anything else is usually maximum 8 bytes.
179
                        $size += 8;
180
                }
181
            }
182
        }
183
 
184
        return $size;
185
    }
186
 
187
    /**
188
     * Given one correct xmldb_table, returns the SQL statements
189
     * to create it (inside one array).
190
     *
191
     * @param xmldb_table $xmldb_table An xmldb_table instance.
192
     * @return array An array of SQL statements, starting with the table creation SQL followed
193
     * by any of its comments, indexes and sequence creation SQL statements.
194
     */
195
    public function getCreateTableSQL($xmldb_table) {
196
        // First find out if want some special db engine.
197
        $engine = $this->mdb->get_dbengine();
198
        // Do we know collation?
199
        $collation = $this->mdb->get_dbcollation();
200
 
201
        // Do we need to use compressed format for rows?
202
        $rowformat = "";
203
        $size = $this->guess_antelope_row_size($xmldb_table->getFields());
204
        if ($size > self::ANTELOPE_MAX_ROW_SIZE) {
205
            if ($this->mdb->is_compressed_row_format_supported()) {
206
                $rowformat = "\n ROW_FORMAT=Compressed";
207
            }
208
        }
209
 
210
        $utf8mb4rowformat = $this->mdb->get_row_format_sql($engine, $collation);
211
        $rowformat = ($utf8mb4rowformat == '') ? $rowformat : $utf8mb4rowformat;
212
 
213
        $sqlarr = parent::getCreateTableSQL($xmldb_table);
214
 
215
        // This is a very nasty hack that tries to use just one query per created table
216
        // because MySQL is stupidly slow when modifying empty tables.
217
        // Note: it is safer to inject everything on new lines because there might be some trailing -- comments.
218
        $sqls = array();
219
        $prevcreate = null;
220
        $matches = null;
221
        foreach ($sqlarr as $sql) {
222
            if (preg_match('/^CREATE TABLE ([^ ]+)/', $sql, $matches)) {
223
                $prevcreate = $matches[1];
224
                $sql = preg_replace('/\s*\)\s*$/s', '/*keyblock*/)', $sql);
225
                // Let's inject the extra MySQL tweaks here.
226
                if ($engine) {
227
                    $sql .= "\n ENGINE = $engine";
228
                }
229
                if ($collation) {
230
                    if (strpos($collation, 'utf8_') === 0) {
231
                        $sql .= "\n DEFAULT CHARACTER SET utf8";
232
                    }
233
                    $sql .= "\n DEFAULT COLLATE = $collation ";
234
                }
235
                if ($rowformat) {
236
                    $sql .= $rowformat;
237
                }
238
                $sqls[] = $sql;
239
                continue;
240
            }
241
            if ($prevcreate) {
242
                if (preg_match('/^ALTER TABLE '.$prevcreate.' COMMENT=(.*)$/s', $sql, $matches)) {
243
                    $prev = array_pop($sqls);
244
                    $prev .= "\n COMMENT=$matches[1]";
245
                    $sqls[] = $prev;
246
                    continue;
247
                }
248
                if (preg_match('/^CREATE INDEX ([^ ]+) ON '.$prevcreate.' (.*)$/s', $sql, $matches)) {
249
                    $prev = array_pop($sqls);
250
                    if (strpos($prev, '/*keyblock*/')) {
251
                        $prev = str_replace('/*keyblock*/', "\n, KEY $matches[1] $matches[2]/*keyblock*/", $prev);
252
                        $sqls[] = $prev;
253
                        continue;
254
                    } else {
255
                        $sqls[] = $prev;
256
                    }
257
                }
258
                if (preg_match('/^CREATE UNIQUE INDEX ([^ ]+) ON '.$prevcreate.' (.*)$/s', $sql, $matches)) {
259
                    $prev = array_pop($sqls);
260
                    if (strpos($prev, '/*keyblock*/')) {
261
                        $prev = str_replace('/*keyblock*/', "\n, UNIQUE KEY $matches[1] $matches[2]/*keyblock*/", $prev);
262
                        $sqls[] = $prev;
263
                        continue;
264
                    } else {
265
                        $sqls[] = $prev;
266
                    }
267
                }
268
            }
269
            $prevcreate = null;
270
            $sqls[] = $sql;
271
        }
272
 
273
        foreach ($sqls as $key => $sql) {
274
            $sqls[$key] = str_replace('/*keyblock*/', "\n", $sql);
275
        }
276
 
277
        return $sqls;
278
    }
279
 
280
    /**
281
     * Given one xmldb_table and one xmldb_field, return the SQL statements needed to add the field to the table.
282
     *
283
     * @param xmldb_table $xmldb_table The table related to $xmldb_field.
284
     * @param xmldb_field $xmldb_field The instance of xmldb_field to create the SQL from.
285
     * @param string $skip_type_clause The type clause on alter columns, NULL by default.
286
     * @param string $skip_default_clause The default clause on alter columns, NULL by default.
287
     * @param string $skip_notnull_clause The null/notnull clause on alter columns, NULL by default.
288
     * @return array The SQL statement for adding a field to the table.
289
     */
290
    public function getAddFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL) {
291
        $sqls = parent::getAddFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause, $skip_default_clause, $skip_notnull_clause);
292
 
293
        if ($this->table_exists($xmldb_table)) {
294
            $tablename = $xmldb_table->getName();
295
 
296
            $size = $this->guess_antelope_row_size($this->mdb->get_columns($tablename));
297
            $size += $this->guess_antelope_row_size(array($xmldb_field));
298
 
299
            if ($size > self::ANTELOPE_MAX_ROW_SIZE) {
300
                if ($this->mdb->is_compressed_row_format_supported()) {
301
                    $format = strtolower($this->mdb->get_row_format($tablename));
302
                    if ($format === 'compact' or $format === 'redundant') {
303
                        // Change the format before conversion so that we do not run out of space.
304
                        array_unshift($sqls, "ALTER TABLE {$this->prefix}$tablename ROW_FORMAT=Compressed");
305
                    }
306
                }
307
            }
308
        }
309
 
310
        return $sqls;
311
    }
312
 
313
    public function getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL)
314
    {
315
        $tablename = $xmldb_table->getName();
316
        $dbcolumnsinfo = $this->mdb->get_columns($tablename);
317
 
318
        if (($this->mdb->has_breaking_change_sqlmode()) &&
319
            ($dbcolumnsinfo[$xmldb_field->getName()]->meta_type == 'X') &&
320
            ($xmldb_field->getType() == XMLDB_TYPE_INTEGER)) {
321
            // Ignore 1292 ER_TRUNCATED_WRONG_VALUE Truncated incorrect INTEGER value: '%s'.
322
            $altercolumnsqlorig = $this->alter_column_sql;
323
            $this->alter_column_sql = str_replace('ALTER TABLE', 'ALTER IGNORE TABLE', $this->alter_column_sql);
324
            $result = parent::getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause, $skip_default_clause, $skip_notnull_clause);
325
            // Restore the original ALTER SQL statement pattern.
326
            $this->alter_column_sql = $altercolumnsqlorig;
327
 
328
            return $result;
329
        }
330
 
331
        return parent::getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause, $skip_default_clause, $skip_notnull_clause);
332
    }
333
 
334
    /**
335
     * Given one correct xmldb_table, returns the SQL statements
336
     * to create temporary table (inside one array).
337
     *
338
     * @param xmldb_table $xmldb_table The xmldb_table object instance.
339
     * @return array of sql statements
340
     */
341
    public function getCreateTempTableSQL($xmldb_table) {
342
        // Do we know collation?
343
        $collation = $this->mdb->get_dbcollation();
344
        $this->temptables->add_temptable($xmldb_table->getName());
345
 
346
        $sqlarr = parent::getCreateTableSQL($xmldb_table);
347
 
348
        // Let's inject the extra MySQL tweaks.
349
        foreach ($sqlarr as $i=>$sql) {
350
            if (strpos($sql, 'CREATE TABLE ') === 0) {
351
                // We do not want the engine hack included in create table SQL.
352
                $sqlarr[$i] = preg_replace('/^CREATE TABLE (.*)/s', 'CREATE TEMPORARY TABLE $1', $sql);
353
                if ($collation) {
354
                    if (strpos($collation, 'utf8_') === 0) {
355
                        $sqlarr[$i] .= " DEFAULT CHARACTER SET utf8";
356
                    }
357
                    $sqlarr[$i] .= " DEFAULT COLLATE $collation ROW_FORMAT=DYNAMIC";
358
                }
359
            }
360
        }
361
 
362
        return $sqlarr;
363
    }
364
 
365
    /**
366
     * Given one correct xmldb_table, returns the SQL statements
367
     * to drop it (inside one array).
368
     *
369
     * @param xmldb_table $xmldb_table The table to drop.
370
     * @return array SQL statement(s) for dropping the specified table.
371
     */
372
    public function getDropTableSQL($xmldb_table) {
373
        $sqlarr = parent::getDropTableSQL($xmldb_table);
374
        if ($this->temptables->is_temptable($xmldb_table->getName())) {
375
            $sqlarr = preg_replace('/^DROP TABLE/', "DROP TEMPORARY TABLE", $sqlarr);
376
        }
377
        return $sqlarr;
378
    }
379
 
380
    /**
381
     * Given one XMLDB Type, length and decimals, returns the DB proper SQL type.
382
     *
383
     * @param int $xmldb_type The xmldb_type defined constant. XMLDB_TYPE_INTEGER and other XMLDB_TYPE_* constants.
384
     * @param int $xmldb_length The length of that data type.
385
     * @param int $xmldb_decimals The decimal places of precision of the data type.
386
     * @return string The DB defined data type.
387
     */
388
    public function getTypeSQL($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) {
389
 
390
        switch ($xmldb_type) {
391
            case XMLDB_TYPE_INTEGER:    // From http://mysql.com/doc/refman/5.0/en/numeric-types.html!
392
                if (empty($xmldb_length)) {
393
                    $xmldb_length = 10;
394
                }
395
                if ($xmldb_length > 9) {
396
                    $dbtype = 'BIGINT';
397
                } else if ($xmldb_length > 6) {
398
                    $dbtype = 'INT';
399
                } else if ($xmldb_length > 4) {
400
                    $dbtype = 'MEDIUMINT';
401
                } else if ($xmldb_length > 2) {
402
                    $dbtype = 'SMALLINT';
403
                } else {
404
                    $dbtype = 'TINYINT';
405
                }
406
                $dbtype .= '(' . $xmldb_length . ')';
407
                break;
408
            case XMLDB_TYPE_NUMBER:
409
                $dbtype = $this->number_type;
410
                if (!empty($xmldb_length)) {
411
                    $dbtype .= '(' . $xmldb_length;
412
                    if (!empty($xmldb_decimals)) {
413
                        $dbtype .= ',' . $xmldb_decimals;
414
                    }
415
                    $dbtype .= ')';
416
                }
417
                break;
418
            case XMLDB_TYPE_FLOAT:
419
                $dbtype = 'DOUBLE';
420
                if (!empty($xmldb_decimals)) {
421
                    if ($xmldb_decimals < 6) {
422
                        $dbtype = 'FLOAT';
423
                    }
424
                }
425
                if (!empty($xmldb_length)) {
426
                    $dbtype .= '(' . $xmldb_length;
427
                    if (!empty($xmldb_decimals)) {
428
                        $dbtype .= ',' . $xmldb_decimals;
429
                    } else {
430
                        $dbtype .= ', 0'; // In MySQL, if length is specified, decimals are mandatory for FLOATs
431
                    }
432
                    $dbtype .= ')';
433
                }
434
                break;
435
            case XMLDB_TYPE_CHAR:
436
                $dbtype = 'VARCHAR';
437
                if (empty($xmldb_length)) {
438
                    $xmldb_length='255';
439
                }
440
                $dbtype .= '(' . $xmldb_length . ')';
441
                if ($collation = $this->mdb->get_dbcollation()) {
442
                    if (strpos($collation, 'utf8_') === 0) {
443
                        $dbtype .= " CHARACTER SET utf8";
444
                    }
445
                    $dbtype .= " COLLATE $collation";
446
                }
447
                break;
448
            case XMLDB_TYPE_TEXT:
449
                $dbtype = 'LONGTEXT';
450
                if ($collation = $this->mdb->get_dbcollation()) {
451
                    if (strpos($collation, 'utf8_') === 0) {
452
                        $dbtype .= " CHARACTER SET utf8";
453
                    }
454
                    $dbtype .= " COLLATE $collation";
455
                }
456
                break;
457
            case XMLDB_TYPE_BINARY:
458
                $dbtype = 'LONGBLOB';
459
                break;
460
            case XMLDB_TYPE_DATETIME:
461
                $dbtype = 'DATETIME';
462
        }
463
        return $dbtype;
464
    }
465
 
466
    /**
467
     * Given one xmldb_table and one xmldb_field, return the SQL statements needed to add its default
468
     * (usually invoked from getModifyDefaultSQL()
469
     *
470
     * @param xmldb_table $xmldb_table The xmldb_table object instance.
471
     * @param xmldb_field $xmldb_field The xmldb_field object instance.
472
     * @return array Array of SQL statements to create a field's default.
473
     */
474
    public function getCreateDefaultSQL($xmldb_table, $xmldb_field) {
475
        // Just a wrapper over the getAlterFieldSQL() function for MySQL that
476
        // is capable of handling defaults
477
        return $this->getAlterFieldSQL($xmldb_table, $xmldb_field);
478
    }
479
 
480
    /**
481
     * Given one correct xmldb_field and the new name, returns the SQL statements
482
     * to rename it (inside one array).
483
     *
484
     * @param xmldb_table $xmldb_table The table related to $xmldb_field.
485
     * @param xmldb_field $xmldb_field The instance of xmldb_field to get the renamed field from.
486
     * @param string $newname The new name to rename the field to.
487
     * @return array The SQL statements for renaming the field.
488
     */
489
    public function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) {
490
        // NOTE: MySQL is pretty different from the standard to justify this overloading.
491
 
492
        // Need a clone of xmldb_field to perform the change leaving original unmodified
493
        $xmldb_field_clone = clone($xmldb_field);
494
 
495
        // Change the name of the field to perform the change
496
        $xmldb_field_clone->setName($newname);
497
 
498
        $fieldsql = $this->getFieldSQL($xmldb_table, $xmldb_field_clone);
499
 
500
        $sql = 'ALTER TABLE ' . $this->getTableName($xmldb_table) . ' CHANGE ' .
501
               $this->getEncQuoted($xmldb_field->getName()) . ' ' . $fieldsql;
502
 
503
        return array($sql);
504
    }
505
 
506
    /**
507
     * Given one xmldb_table and one xmldb_field, return the SQL statements needed to drop its default
508
     * (usually invoked from getModifyDefaultSQL()
509
     *
510
     * Note that this method may be dropped in future.
511
     *
512
     * @param xmldb_table $xmldb_table The xmldb_table object instance.
513
     * @param xmldb_field $xmldb_field The xmldb_field object instance.
514
     * @return array Array of SQL statements to create a field's default.
515
     *
516
     * @todo MDL-31147 Moodle 2.1 - Drop getDropDefaultSQL()
517
     */
518
    public function getDropDefaultSQL($xmldb_table, $xmldb_field) {
519
        // Just a wrapper over the getAlterFieldSQL() function for MySQL that
520
        // is capable of handling defaults
521
        return $this->getAlterFieldSQL($xmldb_table, $xmldb_field);
522
    }
523
 
524
    /**
525
     * Returns the code (array of statements) needed to add one comment to the table.
526
     *
527
     * @param xmldb_table $xmldb_table The xmldb_table object instance.
528
     * @return array Array of SQL statements to add one comment to the table.
529
     */
530
    function getCommentSQL($xmldb_table) {
531
        $comment = '';
532
 
533
        if ($xmldb_table->getComment()) {
534
            $comment .= 'ALTER TABLE ' . $this->getTableName($xmldb_table);
535
            $comment .= " COMMENT='" . $this->addslashes(substr($xmldb_table->getComment(), 0, 60)) . "'";
536
        }
537
        return array($comment);
538
    }
539
 
540
    /**
541
     * Given one object name and it's type (pk, uk, fk, ck, ix, uix, seq, trg).
542
     *
543
     * (MySQL requires the whole xmldb_table object to be specified, so we add it always)
544
     *
545
     * This is invoked from getNameForObject().
546
     * Only some DB have this implemented.
547
     *
548
     * @param string $object_name The object's name to check for.
549
     * @param string $type The object's type (pk, uk, fk, ck, ix, uix, seq, trg).
550
     * @param string $table_name The table's name to check in
551
     * @return bool If such name is currently in use (true) or no (false)
552
     */
553
    public function isNameInUse($object_name, $type, $table_name) {
554
 
555
        switch($type) {
556
            case 'ix':
557
            case 'uix':
558
                // First of all, check table exists
559
                $metatables = $this->mdb->get_tables();
560
                if (isset($metatables[$table_name])) {
561
                    // Fetch all the indexes in the table
562
                    if ($indexes = $this->mdb->get_indexes($table_name)) {
563
                        // Look for existing index in array
564
                        if (isset($indexes[$object_name])) {
565
                            return true;
566
                        }
567
                    }
568
                }
569
                break;
570
        }
571
        return false; //No name in use found
572
    }
573
 
574
 
575
    /**
576
     * Returns an array of reserved words (lowercase) for this DB
577
     * @return array An array of database specific reserved words
578
     */
579
    public static function getReservedWords() {
580
        // This file contains the reserved words for MySQL databases.
581
        $reserved_words = array (
582
            // From http://dev.mysql.com/doc/refman/6.0/en/reserved-words.html.
583
            'accessible', 'add', 'all', 'alter', 'analyze', 'and', 'as', 'asc',
584
            'asensitive', 'before', 'between', 'bigint', 'binary',
585
            'blob', 'both', 'by', 'call', 'cascade', 'case', 'change',
586
            'char', 'character', 'check', 'collate', 'column',
587
            'condition', 'connection', 'constraint', 'continue',
588
            'convert', 'create', 'cross', 'current_date', 'current_time',
589
            'current_timestamp', 'current_user', 'cursor', 'database',
590
            'databases', 'day_hour', 'day_microsecond',
591
            'day_minute', 'day_second', 'dec', 'decimal', 'declare',
592
            'default', 'delayed', 'delete', 'desc', 'describe',
593
            'deterministic', 'distinct', 'distinctrow', 'div', 'double',
594
            'drop', 'dual', 'each', 'else', 'elseif', 'enclosed', 'escaped',
595
            'exists', 'exit', 'explain', 'false', 'fetch', 'float', 'float4',
596
            'float8', 'for', 'force', 'foreign', 'from', 'fulltext', 'grant',
597
            'group', 'having', 'high_priority', 'hour_microsecond',
598
            'hour_minute', 'hour_second', 'if', 'ignore', 'in', 'index',
599
            'infile', 'inner', 'inout', 'insensitive', 'insert', 'int', 'int1',
600
            'int2', 'int3', 'int4', 'int8', 'integer', 'interval', 'into', 'is',
601
            'iterate', 'join', 'key', 'keys', 'kill', 'leading', 'leave', 'left',
602
            'like', 'limit', 'linear', 'lines', 'load', 'localtime', 'localtimestamp',
603
            'lock', 'long', 'longblob', 'longtext', 'loop', 'low_priority', 'master_heartbeat_period',
604
            'master_ssl_verify_server_cert', 'match', 'mediumblob', 'mediumint', 'mediumtext',
605
            'middleint', 'minute_microsecond', 'minute_second',
606
            'mod', 'modifies', 'natural', 'not', 'no_write_to_binlog',
607
            'null', 'numeric', 'on', 'optimize', 'option', 'optionally',
608
            'or', 'order', 'out', 'outer', 'outfile', 'overwrite', 'precision', 'primary',
609
            'procedure', 'purge', 'raid0', 'range', 'read', 'read_only', 'read_write', 'reads', 'real',
610
            'references', 'regexp', 'release', 'rename', 'repeat', 'replace',
611
            'require', 'restrict', 'return', 'revoke', 'right', 'rlike', 'schema',
612
            'schemas', 'second_microsecond', 'select', 'sensitive',
613
            'separator', 'set', 'show', 'smallint', 'soname', 'spatial',
614
            'specific', 'sql', 'sqlexception', 'sqlstate', 'sqlwarning',
615
            'sql_big_result', 'sql_calc_found_rows', 'sql_small_result',
616
            'ssl', 'starting', 'straight_join', 'table', 'terminated', 'then',
617
            'tinyblob', 'tinyint', 'tinytext', 'to', 'trailing', 'trigger', 'true',
618
            'undo', 'union', 'unique', 'unlock', 'unsigned', 'update',
619
            'upgrade', 'usage', 'use', 'using', 'utc_date', 'utc_time',
620
            'utc_timestamp', 'values', 'varbinary', 'varchar', 'varcharacter',
621
            'varying', 'when', 'where', 'while', 'with', 'write', 'x509',
622
            'xor', 'year_month', 'zerofill',
623
            // Added in MySQL 8.0, compared to MySQL 5.7:
624
            // https://dev.mysql.com/doc/refman/8.0/en/keywords.html#keywords-new-in-current-series.
625
            '_filename', 'admin', 'cume_dist', 'dense_rank', 'empty', 'except', 'first_value', 'grouping', 'groups',
626
            'json_table', 'lag', 'last_value', 'lead', 'nth_value', 'ntile',
627
            'of', 'over', 'percent_rank', 'persist', 'persist_only', 'rank', 'recursive', 'row_number',
628
            'system', 'window',
629
            // Added in Amazon Aurora MySQL version 3.06.0:
630
            // https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.3060.html .
631
            'accept', 'aws_bedrock_invoke_model', 'aws_sagemaker_invoke_endpoint', 'content_type', 'timeout_ms',
1441 ariadna 632
            // Added in MySQL 8.4:
633
            // https://dev.mysql.com/doc/refman/8.4/en/mysql-nutshell.html.
634
            'auto', 'bernoulli', 'gtids', 'log', 'manual', 'parallel', 'parse_tree', 'qualify', 's3', 'tablesample',
1 efrain 635
        );
636
        return $reserved_words;
637
    }
638
}