PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.36.0
MailPoet – Newsletters, Email Marketing, and Automation v5.36.0
5.36.0 5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor-prefixed / doctrine / dbal / src / Platforms / AbstractMySQLPlatform.php
mailpoet / vendor-prefixed / doctrine / dbal / src / Platforms Last commit date
Keywords 9 months ago MySQL 2 years ago AbstractMySQLPlatform.php 9 months ago AbstractPlatform.php 9 months ago DateIntervalUnit.php 2 years ago MariaDBPlatform.php 2 years ago MariaDb1010Platform.php 9 months ago MariaDb1027Platform.php 2 years ago MariaDb1043Platform.php 2 years ago MariaDb1052Platform.php 2 years ago MariaDb1060Platform.php 2 years ago MariaDb110700Platform.php 9 months ago MySQL57Platform.php 2 years ago MySQL80Platform.php 2 years ago MySQL84Platform.php 9 months ago MySQLPlatform.php 2 years ago PostgreSQL120Platform.php 9 months ago TrimMode.php 2 years ago index.php 2 years ago
AbstractMySQLPlatform.php
779 lines
1 <?php
2 namespace MailPoetVendor\Doctrine\DBAL\Platforms;
3 if (!defined('ABSPATH')) exit;
4 use MailPoetVendor\Doctrine\DBAL\Connection;
5 use MailPoetVendor\Doctrine\DBAL\Exception;
6 use MailPoetVendor\Doctrine\DBAL\Schema\AbstractAsset;
7 use MailPoetVendor\Doctrine\DBAL\Schema\ForeignKeyConstraint;
8 use MailPoetVendor\Doctrine\DBAL\Schema\Identifier;
9 use MailPoetVendor\Doctrine\DBAL\Schema\Index;
10 use MailPoetVendor\Doctrine\DBAL\Schema\MySQLSchemaManager;
11 use MailPoetVendor\Doctrine\DBAL\Schema\Table;
12 use MailPoetVendor\Doctrine\DBAL\Schema\TableDiff;
13 use MailPoetVendor\Doctrine\DBAL\SQL\Builder\DefaultSelectSQLBuilder;
14 use MailPoetVendor\Doctrine\DBAL\SQL\Builder\SelectSQLBuilder;
15 use MailPoetVendor\Doctrine\DBAL\TransactionIsolationLevel;
16 use MailPoetVendor\Doctrine\DBAL\Types\BlobType;
17 use MailPoetVendor\Doctrine\DBAL\Types\TextType;
18 use MailPoetVendor\Doctrine\DBAL\Types\Types;
19 use MailPoetVendor\Doctrine\Deprecations\Deprecation;
20 use InvalidArgumentException;
21 use function array_diff_key;
22 use function array_merge;
23 use function array_unique;
24 use function array_values;
25 use function count;
26 use function func_get_arg;
27 use function func_get_args;
28 use function func_num_args;
29 use function implode;
30 use function in_array;
31 use function is_numeric;
32 use function is_string;
33 use function sprintf;
34 use function str_replace;
35 use function strcasecmp;
36 use function strtolower;
37 use function strtoupper;
38 use function trim;
39 abstract class AbstractMySQLPlatform extends AbstractPlatform
40 {
41 public const LENGTH_LIMIT_TINYTEXT = 255;
42 public const LENGTH_LIMIT_TEXT = 65535;
43 public const LENGTH_LIMIT_MEDIUMTEXT = 16777215;
44 public const LENGTH_LIMIT_TINYBLOB = 255;
45 public const LENGTH_LIMIT_BLOB = 65535;
46 public const LENGTH_LIMIT_MEDIUMBLOB = 16777215;
47 protected function doModifyLimitQuery($query, $limit, $offset)
48 {
49 if ($limit !== null) {
50 $query .= sprintf(' LIMIT %d', $limit);
51 if ($offset > 0) {
52 $query .= sprintf(' OFFSET %d', $offset);
53 }
54 } elseif ($offset > 0) {
55 // 2^64-1 is the maximum of unsigned BIGINT, the biggest limit possible
56 $query .= sprintf(' LIMIT 18446744073709551615 OFFSET %d', $offset);
57 }
58 return $query;
59 }
60 public function getIdentifierQuoteCharacter()
61 {
62 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/5388', 'AbstractMySQLPlatform::getIdentifierQuoteCharacter() is deprecated. Use quoteIdentifier() instead.');
63 return '`';
64 }
65 public function getRegexpExpression()
66 {
67 return 'RLIKE';
68 }
69 public function getLocateExpression($str, $substr, $startPos = \false)
70 {
71 if ($startPos === \false) {
72 return 'LOCATE(' . $substr . ', ' . $str . ')';
73 }
74 return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')';
75 }
76 public function getConcatExpression()
77 {
78 return sprintf('CONCAT(%s)', implode(', ', func_get_args()));
79 }
80 protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
81 {
82 $function = $operator === '+' ? 'DATE_ADD' : 'DATE_SUB';
83 return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')';
84 }
85 public function getDateDiffExpression($date1, $date2)
86 {
87 return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')';
88 }
89 public function getCurrentDatabaseExpression() : string
90 {
91 return 'DATABASE()';
92 }
93 public function getLengthExpression($column)
94 {
95 return 'CHAR_LENGTH(' . $column . ')';
96 }
97 public function getListDatabasesSQL()
98 {
99 return 'SHOW DATABASES';
100 }
101 public function getListTableConstraintsSQL($table)
102 {
103 return 'SHOW INDEX FROM ' . $table;
104 }
105 public function getListTableIndexesSQL($table, $database = null)
106 {
107 if ($database !== null) {
108 return 'SELECT NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, COLUMN_NAME AS Column_Name,' . ' SUB_PART AS Sub_Part, INDEX_TYPE AS Index_Type' . ' FROM information_schema.STATISTICS WHERE TABLE_NAME = ' . $this->quoteStringLiteral($table) . ' AND TABLE_SCHEMA = ' . $this->quoteStringLiteral($database) . ' ORDER BY SEQ_IN_INDEX ASC';
109 }
110 return 'SHOW INDEX FROM ' . $table;
111 }
112 public function getListViewsSQL($database)
113 {
114 return 'SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = ' . $this->quoteStringLiteral($database);
115 }
116 public function getListTableForeignKeysSQL($table, $database = null)
117 {
118 // The schema name is passed multiple times as a literal in the WHERE clause instead of using a JOIN condition
119 // in order to avoid performance issues on MySQL older than 8.0 and the corresponding MariaDB versions
120 // caused by https://bugs.mysql.com/bug.php?id=81347
121 return 'SELECT k.CONSTRAINT_NAME, k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, ' . 'k.REFERENCED_COLUMN_NAME /*!50116 , c.UPDATE_RULE, c.DELETE_RULE */ ' . 'FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k /*!50116 ' . 'INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c ON ' . 'c.CONSTRAINT_NAME = k.CONSTRAINT_NAME AND ' . 'c.TABLE_NAME = k.TABLE_NAME */ ' . 'WHERE k.TABLE_NAME = ' . $this->quoteStringLiteral($table) . ' ' . 'AND k.TABLE_SCHEMA = ' . $this->getDatabaseNameSQL($database) . ' /*!50116 ' . 'AND c.CONSTRAINT_SCHEMA = ' . $this->getDatabaseNameSQL($database) . ' */' . 'ORDER BY k.ORDINAL_POSITION';
122 }
123 protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
124 {
125 if ($length <= 0 || func_num_args() > 2 && func_get_arg(2)) {
126 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/3263', 'Relying on the default string column length on MySQL is deprecated' . ', specify the length explicitly.');
127 }
128 return $fixed ? $length > 0 ? 'CHAR(' . $length . ')' : 'CHAR(255)' : ($length > 0 ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
129 }
130 protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
131 {
132 if ($length <= 0 || func_num_args() > 2 && func_get_arg(2)) {
133 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/3263', 'Relying on the default binary column length on MySQL is deprecated' . ', specify the length explicitly.');
134 }
135 return $fixed ? 'BINARY(' . ($length > 0 ? $length : 255) . ')' : 'VARBINARY(' . ($length > 0 ? $length : 255) . ')';
136 }
137 public function getClobTypeDeclarationSQL(array $column)
138 {
139 if (!empty($column['length']) && is_numeric($column['length'])) {
140 $length = $column['length'];
141 if ($length <= static::LENGTH_LIMIT_TINYTEXT) {
142 return 'TINYTEXT';
143 }
144 if ($length <= static::LENGTH_LIMIT_TEXT) {
145 return 'TEXT';
146 }
147 if ($length <= static::LENGTH_LIMIT_MEDIUMTEXT) {
148 return 'MEDIUMTEXT';
149 }
150 }
151 return 'LONGTEXT';
152 }
153 public function getDateTimeTypeDeclarationSQL(array $column)
154 {
155 if (isset($column['version']) && $column['version'] === \true) {
156 return 'TIMESTAMP';
157 }
158 return 'DATETIME';
159 }
160 public function getDateTypeDeclarationSQL(array $column)
161 {
162 return 'DATE';
163 }
164 public function getTimeTypeDeclarationSQL(array $column)
165 {
166 return 'TIME';
167 }
168 public function getBooleanTypeDeclarationSQL(array $column)
169 {
170 return 'TINYINT(1)';
171 }
172 public function prefersIdentityColumns()
173 {
174 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/1519', 'AbstractMySQLPlatform::prefersIdentityColumns() is deprecated.');
175 return \true;
176 }
177 public function supportsIdentityColumns()
178 {
179 return \true;
180 }
181 public function supportsInlineColumnComments()
182 {
183 return \true;
184 }
185 public function supportsColumnCollation()
186 {
187 return \true;
188 }
189 public function getListTablesSQL()
190 {
191 return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
192 }
193 public function getListTableColumnsSQL($table, $database = null)
194 {
195 return 'SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ' . 'COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, ' . 'CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ' . 'FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ' . $this->getDatabaseNameSQL($database) . ' AND TABLE_NAME = ' . $this->quoteStringLiteral($table) . ' ORDER BY ORDINAL_POSITION ASC';
196 }
197 public function getColumnTypeSQLSnippets(string $tableAlias = 'c') : array
198 {
199 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/6202', 'AbstractMySQLPlatform::getColumnTypeSQLSnippets() is deprecated. ' . 'Use AbstractMySQLPlatform::getColumnTypeSQLSnippet() instead.');
200 return [$this->getColumnTypeSQLSnippet(...func_get_args()), ''];
201 }
202 public function getColumnTypeSQLSnippet(string $tableAlias = 'c', ?string $databaseName = null) : string
203 {
204 return $tableAlias . '.COLUMN_TYPE';
205 }
206 public function getListTableMetadataSQL(string $table, ?string $database = null) : string
207 {
208 return sprintf(<<<'SQL'
209 SELECT t.ENGINE,
210 t.AUTO_INCREMENT,
211 t.TABLE_COMMENT,
212 t.CREATE_OPTIONS,
213 t.TABLE_COLLATION,
214 ccsa.CHARACTER_SET_NAME
215 FROM information_schema.TABLES t
216 INNER JOIN information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` ccsa
217 ON ccsa.COLLATION_NAME = t.TABLE_COLLATION
218 WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = %s AND TABLE_NAME = %s
219 SQL
220 , $this->getDatabaseNameSQL($database), $this->quoteStringLiteral($table));
221 }
222 public function getCreateTablesSQL(array $tables) : array
223 {
224 $sql = [];
225 foreach ($tables as $table) {
226 $sql = array_merge($sql, $this->getCreateTableWithoutForeignKeysSQL($table));
227 }
228 foreach ($tables as $table) {
229 if (!$table->hasOption('engine') || $this->engineSupportsForeignKeys($table->getOption('engine'))) {
230 foreach ($table->getForeignKeys() as $foreignKey) {
231 $sql[] = $this->getCreateForeignKeySQL($foreignKey, $table->getQuotedName($this));
232 }
233 } elseif (count($table->getForeignKeys()) > 0) {
234 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/5414', 'Relying on the DBAL not generating DDL for foreign keys on MySQL engines' . ' other than InnoDB is deprecated.' . ' Define foreign key constraints only if they are necessary.');
235 }
236 }
237 return $sql;
238 }
239 protected function _getCreateTableSQL($name, array $columns, array $options = [])
240 {
241 $queryFields = $this->getColumnDeclarationListSQL($columns);
242 if (isset($options['uniqueConstraints']) && !empty($options['uniqueConstraints'])) {
243 foreach ($options['uniqueConstraints'] as $constraintName => $definition) {
244 $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($constraintName, $definition);
245 }
246 }
247 // add all indexes
248 if (isset($options['indexes']) && !empty($options['indexes'])) {
249 foreach ($options['indexes'] as $indexName => $definition) {
250 $queryFields .= ', ' . $this->getIndexDeclarationSQL($indexName, $definition);
251 }
252 }
253 // attach all primary keys
254 if (isset($options['primary']) && !empty($options['primary'])) {
255 $keyColumns = array_unique(array_values($options['primary']));
256 $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
257 }
258 $query = 'CREATE ';
259 if (!empty($options['temporary'])) {
260 $query .= 'TEMPORARY ';
261 }
262 $query .= 'TABLE ' . $name . ' (' . $queryFields . ') ';
263 $query .= $this->buildTableOptions($options);
264 $query .= $this->buildPartitionOptions($options);
265 $sql = [$query];
266 // Propagate foreign key constraints only for InnoDB.
267 if (isset($options['foreignKeys'])) {
268 if (!isset($options['engine']) || $this->engineSupportsForeignKeys($options['engine'])) {
269 foreach ($options['foreignKeys'] as $definition) {
270 $sql[] = $this->getCreateForeignKeySQL($definition, $name);
271 }
272 } elseif (count($options['foreignKeys']) > 0) {
273 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/5414', 'Relying on the DBAL not generating DDL for foreign keys on MySQL engines' . ' other than InnoDB is deprecated.' . ' Define foreign key constraints only if they are necessary.');
274 }
275 }
276 return $sql;
277 }
278 public function createSelectSQLBuilder() : SelectSQLBuilder
279 {
280 return new DefaultSelectSQLBuilder($this, 'FOR UPDATE', null);
281 }
282 public function getDefaultValueDeclarationSQL($column)
283 {
284 // Unset the default value if the given column definition does not allow default values.
285 if ($column['type'] instanceof TextType || $column['type'] instanceof BlobType) {
286 $column['default'] = null;
287 }
288 return parent::getDefaultValueDeclarationSQL($column);
289 }
290 private function buildTableOptions(array $options) : string
291 {
292 if (isset($options['table_options'])) {
293 return $options['table_options'];
294 }
295 $tableOptions = [];
296 // Charset
297 if (!isset($options['charset'])) {
298 $options['charset'] = 'utf8';
299 }
300 $tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']);
301 if (isset($options['collate'])) {
302 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/5214', 'The "collate" option is deprecated in favor of "collation" and will be removed in 4.0.');
303 $options['collation'] = $options['collate'];
304 }
305 // Collation
306 if (!isset($options['collation'])) {
307 $options['collation'] = $options['charset'] . '_unicode_ci';
308 }
309 $tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collation']);
310 // Engine
311 if (!isset($options['engine'])) {
312 $options['engine'] = 'InnoDB';
313 }
314 $tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
315 // Auto increment
316 if (isset($options['auto_increment'])) {
317 $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
318 }
319 // Comment
320 if (isset($options['comment'])) {
321 $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($options['comment']));
322 }
323 // Row format
324 if (isset($options['row_format'])) {
325 $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']);
326 }
327 return implode(' ', $tableOptions);
328 }
329 private function buildPartitionOptions(array $options) : string
330 {
331 return isset($options['partition_options']) ? ' ' . $options['partition_options'] : '';
332 }
333 private function engineSupportsForeignKeys(string $engine) : bool
334 {
335 return strcasecmp(trim($engine), 'InnoDB') === 0;
336 }
337 public function getAlterTableSQL(TableDiff $diff)
338 {
339 $columnSql = [];
340 $queryParts = [];
341 $newName = $diff->getNewName();
342 if ($newName !== \false) {
343 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/5663', 'Generation of SQL that renames a table using %s is deprecated. Use getRenameTableSQL() instead.', __METHOD__);
344 $queryParts[] = 'RENAME TO ' . $newName->getQuotedName($this);
345 }
346 foreach ($diff->getAddedColumns() as $column) {
347 if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
348 continue;
349 }
350 $columnProperties = array_merge($column->toArray(), ['comment' => $this->getColumnComment($column)]);
351 $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnProperties);
352 }
353 foreach ($diff->getDroppedColumns() as $column) {
354 if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
355 continue;
356 }
357 $queryParts[] = 'DROP ' . $column->getQuotedName($this);
358 }
359 foreach ($diff->getModifiedColumns() as $columnDiff) {
360 if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
361 continue;
362 }
363 $newColumn = $columnDiff->getNewColumn();
364 $newColumnProperties = array_merge($newColumn->toArray(), ['comment' => $this->getColumnComment($newColumn)]);
365 $oldColumn = $columnDiff->getOldColumn() ?? $columnDiff->getOldColumnName();
366 $queryParts[] = 'CHANGE ' . $oldColumn->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($newColumn->getQuotedName($this), $newColumnProperties);
367 }
368 foreach ($diff->getRenamedColumns() as $oldColumnName => $column) {
369 if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
370 continue;
371 }
372 $oldColumnName = new Identifier($oldColumnName);
373 $columnProperties = array_merge($column->toArray(), ['comment' => $this->getColumnComment($column)]);
374 $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnProperties);
375 }
376 $addedIndexes = $this->indexAssetsByLowerCaseName($diff->getAddedIndexes());
377 $modifiedIndexes = $this->indexAssetsByLowerCaseName($diff->getModifiedIndexes());
378 $diffModified = \false;
379 if (isset($addedIndexes['primary'])) {
380 $keyColumns = array_unique(array_values($addedIndexes['primary']->getColumns()));
381 $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')';
382 unset($addedIndexes['primary']);
383 $diffModified = \true;
384 } elseif (isset($modifiedIndexes['primary'])) {
385 $addedColumns = $this->indexAssetsByLowerCaseName($diff->getAddedColumns());
386 // Necessary in case the new primary key includes a new auto_increment column
387 foreach ($modifiedIndexes['primary']->getColumns() as $columnName) {
388 if (isset($addedColumns[$columnName]) && $addedColumns[$columnName]->getAutoincrement()) {
389 $keyColumns = array_unique(array_values($modifiedIndexes['primary']->getColumns()));
390 $queryParts[] = 'DROP PRIMARY KEY';
391 $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')';
392 unset($modifiedIndexes['primary']);
393 $diffModified = \true;
394 break;
395 }
396 }
397 }
398 if ($diffModified) {
399 $diff = new TableDiff($diff->name, $diff->getAddedColumns(), $diff->getModifiedColumns(), $diff->getDroppedColumns(), array_values($addedIndexes), array_values($modifiedIndexes), $diff->getDroppedIndexes(), $diff->getOldTable(), $diff->getAddedForeignKeys(), $diff->getModifiedForeignKeys(), $diff->getDroppedForeignKeys(), $diff->getRenamedColumns(), $diff->getRenamedIndexes());
400 }
401 $sql = [];
402 $tableSql = [];
403 if (!$this->onSchemaAlterTable($diff, $tableSql)) {
404 if (count($queryParts) > 0) {
405 $sql[] = 'ALTER TABLE ' . ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this) . ' ' . implode(', ', $queryParts);
406 }
407 $sql = array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff));
408 }
409 return array_merge($sql, $tableSql, $columnSql);
410 }
411 protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
412 {
413 $sql = [];
414 $tableNameSQL = ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this);
415 foreach ($diff->getModifiedIndexes() as $changedIndex) {
416 $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $changedIndex));
417 }
418 foreach ($diff->getDroppedIndexes() as $droppedIndex) {
419 $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $droppedIndex));
420 foreach ($diff->getAddedIndexes() as $addedIndex) {
421 if ($droppedIndex->getColumns() !== $addedIndex->getColumns()) {
422 continue;
423 }
424 $indexClause = 'INDEX ' . $addedIndex->getName();
425 if ($addedIndex->isPrimary()) {
426 $indexClause = 'PRIMARY KEY';
427 } elseif ($addedIndex->isUnique()) {
428 $indexClause = 'UNIQUE INDEX ' . $addedIndex->getName();
429 }
430 $query = 'ALTER TABLE ' . $tableNameSQL . ' DROP INDEX ' . $droppedIndex->getName() . ', ';
431 $query .= 'ADD ' . $indexClause;
432 $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addedIndex) . ')';
433 $sql[] = $query;
434 $diff->unsetAddedIndex($addedIndex);
435 $diff->unsetDroppedIndex($droppedIndex);
436 break;
437 }
438 }
439 $engine = 'INNODB';
440 $table = $diff->getOldTable();
441 if ($table !== null && $table->hasOption('engine')) {
442 $engine = strtoupper(trim($table->getOption('engine')));
443 }
444 // Suppress foreign key constraint propagation on non-supporting engines.
445 if ($engine !== 'INNODB') {
446 $diff->addedForeignKeys = [];
447 $diff->changedForeignKeys = [];
448 $diff->removedForeignKeys = [];
449 }
450 $sql = array_merge($sql, $this->getPreAlterTableAlterIndexForeignKeySQL($diff), parent::getPreAlterTableIndexForeignKeySQL($diff), $this->getPreAlterTableRenameIndexForeignKeySQL($diff));
451 return $sql;
452 }
453 private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $index) : array
454 {
455 if (!$index->isPrimary()) {
456 return [];
457 }
458 $table = $diff->getOldTable();
459 if ($table === null) {
460 return [];
461 }
462 $sql = [];
463 $tableNameSQL = ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this);
464 // Dropping primary keys requires to unset autoincrement attribute on the particular column first.
465 foreach ($index->getColumns() as $columnName) {
466 if (!$table->hasColumn($columnName)) {
467 continue;
468 }
469 $column = $table->getColumn($columnName);
470 if ($column->getAutoincrement() !== \true) {
471 continue;
472 }
473 $column->setAutoincrement(\false);
474 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
475 // original autoincrement information might be needed later on by other parts of the table alteration
476 $column->setAutoincrement(\true);
477 }
478 return $sql;
479 }
480 private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff) : array
481 {
482 $table = $diff->getOldTable();
483 if ($table === null) {
484 return [];
485 }
486 $primaryKey = $table->getPrimaryKey();
487 if ($primaryKey === null) {
488 return [];
489 }
490 $primaryKeyColumns = [];
491 foreach ($primaryKey->getColumns() as $columnName) {
492 if (!$table->hasColumn($columnName)) {
493 continue;
494 }
495 $primaryKeyColumns[] = $table->getColumn($columnName);
496 }
497 if (count($primaryKeyColumns) === 0) {
498 return [];
499 }
500 $sql = [];
501 $tableNameSQL = $table->getQuotedName($this);
502 foreach ($diff->getModifiedIndexes() as $changedIndex) {
503 // Changed primary key
504 if (!$changedIndex->isPrimary()) {
505 continue;
506 }
507 foreach ($primaryKeyColumns as $column) {
508 // Check if an autoincrement column was dropped from the primary key.
509 if (!$column->getAutoincrement() || in_array($column->getName(), $changedIndex->getColumns(), \true)) {
510 continue;
511 }
512 // The autoincrement attribute needs to be removed from the dropped column
513 // before we can drop and recreate the primary key.
514 $column->setAutoincrement(\false);
515 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
516 // Restore the autoincrement attribute as it might be needed later on
517 // by other parts of the table alteration.
518 $column->setAutoincrement(\true);
519 }
520 }
521 return $sql;
522 }
523 protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff)
524 {
525 $sql = [];
526 $tableNameSQL = ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this);
527 foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) {
528 if (in_array($foreignKey, $diff->getModifiedForeignKeys(), \true)) {
529 continue;
530 }
531 $sql[] = $this->getDropForeignKeySQL($foreignKey->getQuotedName($this), $tableNameSQL);
532 }
533 return $sql;
534 }
535 private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff) : array
536 {
537 if (count($diff->getRenamedIndexes()) === 0) {
538 return [];
539 }
540 $table = $diff->getOldTable();
541 if ($table === null) {
542 return [];
543 }
544 $foreignKeys = [];
545 $remainingForeignKeys = array_diff_key($table->getForeignKeys(), $diff->getDroppedForeignKeys());
546 foreach ($remainingForeignKeys as $foreignKey) {
547 foreach ($diff->getRenamedIndexes() as $index) {
548 if ($foreignKey->intersectsIndexColumns($index)) {
549 $foreignKeys[] = $foreignKey;
550 break;
551 }
552 }
553 }
554 return $foreignKeys;
555 }
556 protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
557 {
558 return array_merge(parent::getPostAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableRenameIndexForeignKeySQL($diff));
559 }
560 protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff)
561 {
562 $sql = [];
563 $newName = $diff->getNewName();
564 if ($newName !== \false) {
565 $tableNameSQL = $newName->getQuotedName($this);
566 } else {
567 $tableNameSQL = ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this);
568 }
569 foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) {
570 if (in_array($foreignKey, $diff->getModifiedForeignKeys(), \true)) {
571 continue;
572 }
573 $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableNameSQL);
574 }
575 return $sql;
576 }
577 protected function getCreateIndexSQLFlags(Index $index)
578 {
579 $type = '';
580 if ($index->isUnique()) {
581 $type .= 'UNIQUE ';
582 } elseif ($index->hasFlag('fulltext')) {
583 $type .= 'FULLTEXT ';
584 } elseif ($index->hasFlag('spatial')) {
585 $type .= 'SPATIAL ';
586 }
587 return $type;
588 }
589 public function getIntegerTypeDeclarationSQL(array $column)
590 {
591 return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($column);
592 }
593 public function getBigIntTypeDeclarationSQL(array $column)
594 {
595 return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($column);
596 }
597 public function getSmallIntTypeDeclarationSQL(array $column)
598 {
599 return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($column);
600 }
601 public function getFloatDeclarationSQL(array $column)
602 {
603 return 'DOUBLE PRECISION' . $this->getUnsignedDeclaration($column);
604 }
605 public function getDecimalTypeDeclarationSQL(array $column)
606 {
607 return parent::getDecimalTypeDeclarationSQL($column) . $this->getUnsignedDeclaration($column);
608 }
609 private function getUnsignedDeclaration(array $columnDef) : string
610 {
611 return !empty($columnDef['unsigned']) ? ' UNSIGNED' : '';
612 }
613 protected function _getCommonIntegerTypeDeclarationSQL(array $column)
614 {
615 $autoinc = '';
616 if (!empty($column['autoincrement'])) {
617 $autoinc = ' AUTO_INCREMENT';
618 }
619 return $this->getUnsignedDeclaration($column) . $autoinc;
620 }
621 public function getColumnCharsetDeclarationSQL($charset)
622 {
623 return 'CHARACTER SET ' . $charset;
624 }
625 public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
626 {
627 $query = '';
628 if ($foreignKey->hasOption('match')) {
629 $query .= ' MATCH ' . $foreignKey->getOption('match');
630 }
631 $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
632 return $query;
633 }
634 public function getDropIndexSQL($index, $table = null)
635 {
636 if ($index instanceof Index) {
637 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/4798', 'Passing $index as an Index object to %s is deprecated. Pass it as a quoted name instead.', __METHOD__);
638 $indexName = $index->getQuotedName($this);
639 } elseif (is_string($index)) {
640 $indexName = $index;
641 } else {
642 throw new InvalidArgumentException(__METHOD__ . '() expects $index parameter to be string or ' . Index::class . '.');
643 }
644 if ($table instanceof Table) {
645 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/4798', 'Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.', __METHOD__);
646 $table = $table->getQuotedName($this);
647 } elseif (!is_string($table)) {
648 throw new InvalidArgumentException(__METHOD__ . '() expects $table parameter to be string or ' . Table::class . '.');
649 }
650 if ($index instanceof Index && $index->isPrimary()) {
651 // MySQL primary keys are always named "PRIMARY",
652 // so we cannot use them in statements because of them being keyword.
653 return $this->getDropPrimaryKeySQL($table);
654 }
655 return 'DROP INDEX ' . $indexName . ' ON ' . $table;
656 }
657 protected function getDropPrimaryKeySQL($table)
658 {
659 return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
660 }
661 public function getDropUniqueConstraintSQL(string $name, string $tableName) : string
662 {
663 return $this->getDropIndexSQL($name, $tableName);
664 }
665 public function getSetTransactionIsolationSQL($level)
666 {
667 return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
668 }
669 public function getName()
670 {
671 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/4749', 'AbstractMySQLPlatform::getName() is deprecated. Identify platforms by their class.');
672 return 'mysql';
673 }
674 public function getReadLockSQL()
675 {
676 return 'LOCK IN SHARE MODE';
677 }
678 protected function initializeDoctrineTypeMappings()
679 {
680 $this->doctrineTypeMapping = ['bigint' => Types::BIGINT, 'binary' => Types::BINARY, 'blob' => Types::BLOB, 'char' => Types::STRING, 'date' => Types::DATE_MUTABLE, 'datetime' => Types::DATETIME_MUTABLE, 'decimal' => Types::DECIMAL, 'double' => Types::FLOAT, 'float' => Types::FLOAT, 'int' => Types::INTEGER, 'integer' => Types::INTEGER, 'longblob' => Types::BLOB, 'longtext' => Types::TEXT, 'mediumblob' => Types::BLOB, 'mediumint' => Types::INTEGER, 'mediumtext' => Types::TEXT, 'numeric' => Types::DECIMAL, 'real' => Types::FLOAT, 'set' => Types::SIMPLE_ARRAY, 'smallint' => Types::SMALLINT, 'string' => Types::STRING, 'text' => Types::TEXT, 'time' => Types::TIME_MUTABLE, 'timestamp' => Types::DATETIME_MUTABLE, 'tinyblob' => Types::BLOB, 'tinyint' => Types::BOOLEAN, 'tinytext' => Types::TEXT, 'varbinary' => Types::BINARY, 'varchar' => Types::STRING, 'year' => Types::DATE_MUTABLE];
681 }
682 public function getVarcharMaxLength()
683 {
684 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/3263', 'AbstractMySQLPlatform::getVarcharMaxLength() is deprecated.');
685 return 65535;
686 }
687 public function getBinaryMaxLength()
688 {
689 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/3263', 'AbstractMySQLPlatform::getBinaryMaxLength() is deprecated.');
690 return 65535;
691 }
692 protected function getReservedKeywordsClass()
693 {
694 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/4510', 'AbstractMySQLPlatform::getReservedKeywordsClass() is deprecated,' . ' use AbstractMySQLPlatform::createReservedKeywordsList() instead.');
695 return Keywords\MySQLKeywords::class;
696 }
697 public function getDropTemporaryTableSQL($table)
698 {
699 if ($table instanceof Table) {
700 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/dbal/issues/4798', 'Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.', __METHOD__);
701 $table = $table->getQuotedName($this);
702 } elseif (!is_string($table)) {
703 throw new InvalidArgumentException(__METHOD__ . '() expects $table parameter to be string or ' . Table::class . '.');
704 }
705 return 'DROP TEMPORARY TABLE ' . $table;
706 }
707 public function getBlobTypeDeclarationSQL(array $column)
708 {
709 if (!empty($column['length']) && is_numeric($column['length'])) {
710 $length = $column['length'];
711 if ($length <= static::LENGTH_LIMIT_TINYBLOB) {
712 return 'TINYBLOB';
713 }
714 if ($length <= static::LENGTH_LIMIT_BLOB) {
715 return 'BLOB';
716 }
717 if ($length <= static::LENGTH_LIMIT_MEDIUMBLOB) {
718 return 'MEDIUMBLOB';
719 }
720 }
721 return 'LONGBLOB';
722 }
723 public function quoteStringLiteral($str)
724 {
725 $str = str_replace('\\', '\\\\', $str);
726 // MySQL requires backslashes to be escaped
727 return parent::quoteStringLiteral($str);
728 }
729 public function getDefaultTransactionIsolationLevel()
730 {
731 return TransactionIsolationLevel::REPEATABLE_READ;
732 }
733 public function supportsColumnLengthIndexes() : bool
734 {
735 return \true;
736 }
737 protected function getDatabaseNameSQL(?string $databaseName) : string
738 {
739 Deprecation::triggerIfCalledFromOutside('doctrine/dbal', 'https://github.com/doctrine/dbal/pull/6215', '%s is deprecated without replacement.', __METHOD__);
740 if ($databaseName !== null) {
741 return $this->quoteStringLiteral($databaseName);
742 }
743 return $this->getCurrentDatabaseExpression();
744 }
745 public function createSchemaManager(Connection $connection) : MySQLSchemaManager
746 {
747 return new MySQLSchemaManager($connection, $this);
748 }
749 private function indexAssetsByLowerCaseName(array $assets) : array
750 {
751 $result = [];
752 foreach ($assets as $asset) {
753 $result[strtolower($asset->getName())] = $asset;
754 }
755 return $result;
756 }
757 public function fetchTableOptionsByTable(bool $includeTableName) : string
758 {
759 $sql = <<<'SQL'
760 SELECT t.TABLE_NAME,
761 t.ENGINE,
762 t.AUTO_INCREMENT,
763 t.TABLE_COMMENT,
764 t.CREATE_OPTIONS,
765 t.TABLE_COLLATION,
766 ccsa.CHARACTER_SET_NAME
767 FROM information_schema.TABLES t
768 INNER JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY ccsa
769 ON ccsa.COLLATION_NAME = t.TABLE_COLLATION
770 SQL;
771 $conditions = ['t.TABLE_SCHEMA = ?'];
772 if ($includeTableName) {
773 $conditions[] = 't.TABLE_NAME = ?';
774 }
775 $conditions[] = "t.TABLE_TYPE = 'BASE TABLE'";
776 return $sql . ' WHERE ' . implode(' AND ', $conditions);
777 }
778 }
779