1 | <?php |
||
2 | /* |
||
3 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
4 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
5 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
6 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
7 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
8 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
9 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
10 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
11 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
12 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
13 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
14 | * |
||
15 | * This software consists of voluntary contributions made by many individuals |
||
16 | * and is licensed under the MIT license. For more information, see |
||
17 | * <http://www.doctrine-project.org>. |
||
18 | */ |
||
19 | |||
20 | namespace Doctrine\DBAL\Platforms; |
||
21 | |||
22 | use Doctrine\DBAL\Schema\Column; |
||
23 | use Doctrine\DBAL\Schema\ColumnDiff; |
||
24 | use Doctrine\DBAL\Schema\Identifier; |
||
25 | use Doctrine\DBAL\Schema\Index; |
||
26 | use Doctrine\DBAL\Schema\Sequence; |
||
27 | use Doctrine\DBAL\Schema\TableDiff; |
||
28 | use Doctrine\DBAL\Types\BinaryType; |
||
29 | use Doctrine\DBAL\Types\BlobType; |
||
30 | |||
31 | /** |
||
32 | * PostgreSqlPlatform. |
||
33 | * |
||
34 | * @since 2.0 |
||
35 | * @author Roman Borschel <[email protected]> |
||
36 | * @author Lukas Smith <[email protected]> (PEAR MDB2 library) |
||
37 | * @author Benjamin Eberlei <[email protected]> |
||
38 | * @todo Rename: PostgreSQLPlatform |
||
39 | */ |
||
40 | class PostgreSqlPlatform extends AbstractPlatform |
||
41 | { |
||
42 | /** |
||
43 | * @var bool |
||
44 | */ |
||
45 | private $useBooleanTrueFalseStrings = true; |
||
46 | |||
47 | /** |
||
48 | * @var array PostgreSQL booleans literals |
||
49 | */ |
||
50 | private $booleanLiterals = [ |
||
51 | 'true' => [ |
||
52 | 't', |
||
53 | 'true', |
||
54 | 'y', |
||
55 | 'yes', |
||
56 | 'on', |
||
57 | '1' |
||
58 | ], |
||
59 | 'false' => [ |
||
60 | 'f', |
||
61 | 'false', |
||
62 | 'n', |
||
63 | 'no', |
||
64 | 'off', |
||
65 | '0' |
||
66 | ] |
||
67 | ]; |
||
68 | |||
69 | /** |
||
70 | * PostgreSQL has different behavior with some drivers |
||
71 | * with regard to how booleans have to be handled. |
||
72 | * |
||
73 | * Enables use of 'true'/'false' or otherwise 1 and 0 instead. |
||
74 | * |
||
75 | * @param bool $flag |
||
76 | */ |
||
77 | 8 | public function setUseBooleanTrueFalseStrings($flag) |
|
78 | { |
||
79 | 8 | $this->useBooleanTrueFalseStrings = (bool) $flag; |
|
80 | 8 | } |
|
81 | |||
82 | /** |
||
83 | * {@inheritDoc} |
||
84 | */ |
||
85 | 4 | View Code Duplication | public function getSubstringExpression($value, $from, $length = null) |
86 | { |
||
87 | 4 | if ($length === null) { |
|
88 | 4 | return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; |
|
89 | } |
||
90 | |||
91 | 4 | return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; |
|
92 | } |
||
93 | |||
94 | /** |
||
95 | * {@inheritDoc} |
||
96 | */ |
||
97 | public function getNowExpression() |
||
98 | { |
||
99 | return 'LOCALTIMESTAMP(0)'; |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * {@inheritDoc} |
||
104 | */ |
||
105 | 4 | public function getRegexpExpression() |
|
106 | { |
||
107 | 4 | return 'SIMILAR TO'; |
|
108 | } |
||
109 | |||
110 | /** |
||
111 | * {@inheritDoc} |
||
112 | */ |
||
113 | public function getLocateExpression($str, $substr, $startPos = false) |
||
114 | { |
||
115 | if ($startPos !== false) { |
||
116 | $str = $this->getSubstringExpression($str, $startPos); |
||
117 | |||
118 | return 'CASE WHEN (POSITION('.$substr.' IN '.$str.') = 0) THEN 0 ELSE (POSITION('.$substr.' IN '.$str.') + '.($startPos-1).') END'; |
||
119 | } |
||
120 | |||
121 | return 'POSITION('.$substr.' IN '.$str.')'; |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * {@inheritdoc} |
||
126 | */ |
||
127 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
||
128 | { |
||
129 | if (self::DATE_INTERVAL_UNIT_QUARTER === $unit) { |
||
130 | $interval *= 3; |
||
131 | $unit = self::DATE_INTERVAL_UNIT_MONTH; |
||
132 | } |
||
133 | |||
134 | return "(" . $date ." " . $operator . " (" . $interval . " || ' " . $unit . "')::interval)"; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * {@inheritDoc} |
||
139 | */ |
||
140 | public function getDateDiffExpression($date1, $date2) |
||
141 | { |
||
142 | return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * {@inheritDoc} |
||
147 | */ |
||
148 | 4 | public function supportsSequences() |
|
149 | { |
||
150 | 4 | return true; |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * {@inheritDoc} |
||
155 | */ |
||
156 | public function supportsSchemas() |
||
157 | { |
||
158 | return true; |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * {@inheritdoc} |
||
163 | */ |
||
164 | public function getDefaultSchemaName() |
||
165 | { |
||
166 | return 'public'; |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * {@inheritDoc} |
||
171 | */ |
||
172 | 4 | public function supportsIdentityColumns() |
|
173 | { |
||
174 | 4 | return true; |
|
175 | } |
||
176 | |||
177 | /** |
||
178 | * {@inheritdoc} |
||
179 | */ |
||
180 | 34 | public function supportsPartialIndexes() |
|
181 | { |
||
182 | 34 | return true; |
|
183 | } |
||
184 | |||
185 | /** |
||
186 | * {@inheritdoc} |
||
187 | */ |
||
188 | 4 | public function usesSequenceEmulatedIdentityColumns() |
|
189 | { |
||
190 | 4 | return true; |
|
191 | } |
||
192 | |||
193 | /** |
||
194 | * {@inheritdoc} |
||
195 | */ |
||
196 | 4 | public function getIdentitySequenceName($tableName, $columnName) |
|
197 | { |
||
198 | 4 | return $tableName . '_' . $columnName . '_seq'; |
|
199 | } |
||
200 | |||
201 | /** |
||
202 | * {@inheritDoc} |
||
203 | */ |
||
204 | 44 | public function supportsCommentOnStatement() |
|
205 | { |
||
206 | 44 | return true; |
|
207 | } |
||
208 | |||
209 | /** |
||
210 | * {@inheritDoc} |
||
211 | */ |
||
212 | 4 | public function prefersSequences() |
|
213 | { |
||
214 | 4 | return true; |
|
215 | } |
||
216 | |||
217 | /** |
||
218 | * {@inheritDoc} |
||
219 | */ |
||
220 | 164 | public function hasNativeGuidType() |
|
221 | { |
||
222 | 164 | return true; |
|
223 | } |
||
224 | |||
225 | /** |
||
226 | * {@inheritDoc} |
||
227 | */ |
||
228 | public function getListDatabasesSQL() |
||
229 | { |
||
230 | return 'SELECT datname FROM pg_database'; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * {@inheritDoc} |
||
235 | */ |
||
236 | public function getListNamespacesSQL() |
||
237 | { |
||
238 | return "SELECT schema_name AS nspname |
||
239 | FROM information_schema.schemata |
||
240 | WHERE schema_name NOT LIKE 'pg\_%' |
||
241 | AND schema_name != 'information_schema'"; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * {@inheritDoc} |
||
246 | */ |
||
247 | public function getListSequencesSQL($database) |
||
248 | { |
||
249 | return "SELECT sequence_name AS relname, |
||
250 | sequence_schema AS schemaname |
||
251 | FROM information_schema.sequences |
||
252 | WHERE sequence_schema NOT LIKE 'pg\_%' |
||
253 | AND sequence_schema != 'information_schema'"; |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * {@inheritDoc} |
||
258 | */ |
||
259 | public function getListTablesSQL() |
||
260 | { |
||
261 | return "SELECT quote_ident(table_name) AS table_name, |
||
262 | table_schema AS schema_name |
||
263 | FROM information_schema.tables |
||
264 | WHERE table_schema NOT LIKE 'pg\_%' |
||
265 | AND table_schema != 'information_schema' |
||
266 | AND table_name != 'geometry_columns' |
||
267 | AND table_name != 'spatial_ref_sys' |
||
268 | AND table_type != 'VIEW'"; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * {@inheritDoc} |
||
273 | */ |
||
274 | public function getListViewsSQL($database) |
||
275 | { |
||
276 | return 'SELECT quote_ident(table_name) AS viewname, |
||
277 | table_schema AS schemaname, |
||
278 | view_definition AS definition |
||
279 | FROM information_schema.views |
||
280 | WHERE view_definition IS NOT NULL'; |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * {@inheritDoc} |
||
285 | */ |
||
286 | 8 | public function getListTableForeignKeysSQL($table, $database = null) |
|
287 | { |
||
288 | return "SELECT quote_ident(r.conname) as conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef |
||
289 | FROM pg_catalog.pg_constraint r |
||
290 | WHERE r.conrelid = |
||
291 | ( |
||
292 | SELECT c.oid |
||
293 | FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n |
||
294 | 8 | WHERE " .$this->getTableWhereClause($table) ." AND n.oid = c.relnamespace |
|
295 | ) |
||
296 | AND r.contype = 'f'"; |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * {@inheritDoc} |
||
301 | */ |
||
302 | public function getCreateViewSQL($name, $sql) |
||
303 | { |
||
304 | return 'CREATE VIEW ' . $name . ' AS ' . $sql; |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * {@inheritDoc} |
||
309 | */ |
||
310 | public function getDropViewSQL($name) |
||
311 | { |
||
312 | return 'DROP VIEW '. $name; |
||
313 | } |
||
314 | |||
315 | /** |
||
316 | * {@inheritDoc} |
||
317 | */ |
||
318 | 4 | public function getListTableConstraintsSQL($table) |
|
319 | { |
||
320 | 4 | $table = new Identifier($table); |
|
321 | 4 | $table = $this->quoteStringLiteral($table->getName()); |
|
322 | |||
323 | return "SELECT |
||
324 | quote_ident(relname) as relname |
||
325 | FROM |
||
326 | pg_class |
||
327 | WHERE oid IN ( |
||
328 | SELECT indexrelid |
||
329 | FROM pg_index, pg_class |
||
330 | 4 | WHERE pg_class.relname = $table |
|
331 | AND pg_class.oid = pg_index.indrelid |
||
332 | AND (indisunique = 't' OR indisprimary = 't') |
||
333 | )"; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * {@inheritDoc} |
||
338 | * |
||
339 | * @license New BSD License |
||
340 | * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html |
||
341 | */ |
||
342 | 8 | public function getListTableIndexesSQL($table, $currentDatabase = null) |
|
343 | { |
||
344 | return "SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary, |
||
345 | pg_index.indkey, pg_index.indrelid, |
||
346 | pg_get_expr(indpred, indrelid) AS where |
||
347 | FROM pg_class, pg_index |
||
348 | WHERE oid IN ( |
||
349 | SELECT indexrelid |
||
350 | FROM pg_index si, pg_class sc, pg_namespace sn |
||
351 | 8 | WHERE " . $this->getTableWhereClause($table, 'sc', 'sn')." AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid |
|
352 | ) AND pg_index.indexrelid = oid"; |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * @param string $table |
||
357 | * @param string $classAlias |
||
358 | * @param string $namespaceAlias |
||
359 | * |
||
360 | * @return string |
||
361 | */ |
||
362 | 24 | private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') |
|
363 | { |
||
364 | 24 | $whereClause = $namespaceAlias.".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND "; |
|
365 | 24 | View Code Duplication | if (strpos($table, ".") !== false) { |
366 | 12 | list($schema, $table) = explode(".", $table); |
|
367 | 12 | $schema = $this->quoteStringLiteral($schema); |
|
368 | } else { |
||
369 | 12 | $schema = "ANY(string_to_array((select replace(replace(setting,'\"\$user\"',user),' ','') from pg_catalog.pg_settings where name = 'search_path'),','))"; |
|
370 | } |
||
371 | |||
372 | 24 | $table = new Identifier($table); |
|
373 | 24 | $table = $this->quoteStringLiteral($table->getName()); |
|
374 | 24 | $whereClause .= "$classAlias.relname = " . $table . " AND $namespaceAlias.nspname = $schema"; |
|
375 | |||
376 | 24 | return $whereClause; |
|
377 | } |
||
378 | |||
379 | /** |
||
380 | * {@inheritDoc} |
||
381 | */ |
||
382 | 8 | public function getListTableColumnsSQL($table, $database = null) |
|
383 | { |
||
384 | return "SELECT |
||
385 | a.attnum, |
||
386 | quote_ident(a.attname) AS field, |
||
387 | t.typname AS type, |
||
388 | format_type(a.atttypid, a.atttypmod) AS complete_type, |
||
389 | (SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type, |
||
390 | (SELECT format_type(t2.typbasetype, t2.typtypmod) FROM |
||
391 | pg_catalog.pg_type t2 WHERE t2.typtype = 'd' AND t2.oid = a.atttypid) AS domain_complete_type, |
||
392 | a.attnotnull AS isnotnull, |
||
393 | (SELECT 't' |
||
394 | FROM pg_index |
||
395 | WHERE c.oid = pg_index.indrelid |
||
396 | AND pg_index.indkey[0] = a.attnum |
||
397 | AND pg_index.indisprimary = 't' |
||
398 | ) AS pri, |
||
399 | (SELECT pg_get_expr(adbin, adrelid) |
||
400 | FROM pg_attrdef |
||
401 | WHERE c.oid = pg_attrdef.adrelid |
||
402 | AND pg_attrdef.adnum=a.attnum |
||
403 | ) AS default, |
||
404 | (SELECT pg_description.description |
||
405 | FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid |
||
406 | ) AS comment |
||
407 | FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n |
||
408 | 8 | WHERE ".$this->getTableWhereClause($table, 'c', 'n') ." |
|
409 | AND a.attnum > 0 |
||
410 | AND a.attrelid = c.oid |
||
411 | AND a.atttypid = t.oid |
||
412 | AND n.oid = c.relnamespace |
||
413 | ORDER BY a.attnum"; |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * {@inheritDoc} |
||
418 | */ |
||
419 | 4 | public function getCreateDatabaseSQL($name) |
|
420 | { |
||
421 | 4 | return 'CREATE DATABASE ' . $name; |
|
422 | } |
||
423 | |||
424 | /** |
||
425 | * Returns the SQL statement for disallowing new connections on the given database. |
||
426 | * |
||
427 | * This is useful to force DROP DATABASE operations which could fail because of active connections. |
||
428 | * |
||
429 | * @param string $database The name of the database to disallow new connections for. |
||
430 | * |
||
431 | * @return string |
||
432 | */ |
||
433 | 4 | public function getDisallowDatabaseConnectionsSQL($database) |
|
434 | { |
||
435 | 4 | return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = '$database'"; |
|
436 | } |
||
437 | |||
438 | /** |
||
439 | * Returns the SQL statement for closing currently active connections on the given database. |
||
440 | * |
||
441 | * This is useful to force DROP DATABASE operations which could fail because of active connections. |
||
442 | * |
||
443 | * @param string $database The name of the database to close currently active connections for. |
||
444 | * |
||
445 | * @return string |
||
446 | */ |
||
447 | 4 | public function getCloseActiveDatabaseConnectionsSQL($database) |
|
448 | { |
||
449 | 4 | $database = $this->quoteStringLiteral($database); |
|
450 | |||
451 | 4 | return "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = $database"; |
|
452 | } |
||
453 | |||
454 | /** |
||
455 | * {@inheritDoc} |
||
456 | */ |
||
457 | 20 | public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey) |
|
458 | { |
||
459 | 20 | $query = ''; |
|
460 | |||
461 | 20 | if ($foreignKey->hasOption('match')) { |
|
462 | 4 | $query .= ' MATCH ' . $foreignKey->getOption('match'); |
|
463 | } |
||
464 | |||
465 | 20 | $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); |
|
466 | |||
467 | 20 | if ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) { |
|
468 | 4 | $query .= ' DEFERRABLE'; |
|
469 | } else { |
||
470 | 20 | $query .= ' NOT DEFERRABLE'; |
|
471 | } |
||
472 | |||
473 | 20 | if (($foreignKey->hasOption('feferred') && $foreignKey->getOption('feferred') !== false) |
|
474 | 20 | || ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) |
|
475 | ) { |
||
476 | 4 | $query .= ' INITIALLY DEFERRED'; |
|
477 | } else { |
||
478 | 20 | $query .= ' INITIALLY IMMEDIATE'; |
|
479 | } |
||
480 | |||
481 | 20 | return $query; |
|
482 | } |
||
483 | |||
484 | /** |
||
485 | * {@inheritDoc} |
||
486 | */ |
||
487 | 72 | public function getAlterTableSQL(TableDiff $diff) |
|
488 | { |
||
489 | 72 | $sql = []; |
|
490 | 72 | $commentsSQL = []; |
|
491 | 72 | $columnSql = []; |
|
492 | |||
493 | 72 | foreach ($diff->addedColumns as $column) { |
|
494 | 16 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
|
495 | continue; |
||
496 | } |
||
497 | |||
498 | 16 | $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); |
|
499 | 16 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
500 | |||
501 | 16 | $comment = $this->getColumnComment($column); |
|
502 | |||
503 | 16 | View Code Duplication | if (null !== $comment && '' !== $comment) { |
504 | 4 | $commentsSQL[] = $this->getCommentOnColumnSQL( |
|
505 | 4 | $diff->getName($this)->getQuotedName($this), |
|
506 | 4 | $column->getQuotedName($this), |
|
507 | 16 | $comment |
|
508 | ); |
||
509 | } |
||
510 | } |
||
511 | |||
512 | 72 | foreach ($diff->removedColumns as $column) { |
|
513 | 16 | if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { |
|
514 | continue; |
||
515 | } |
||
516 | |||
517 | 16 | $query = 'DROP ' . $column->getQuotedName($this); |
|
518 | 16 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
519 | } |
||
520 | |||
521 | 72 | foreach ($diff->changedColumns as $columnDiff) { |
|
522 | /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ |
||
523 | 40 | if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { |
|
524 | continue; |
||
525 | } |
||
526 | |||
527 | 40 | if ($this->isUnchangedBinaryColumn($columnDiff)) { |
|
528 | 4 | continue; |
|
529 | } |
||
530 | |||
531 | 36 | $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); |
|
532 | 36 | $column = $columnDiff->column; |
|
533 | |||
534 | 36 | if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('precision') || $columnDiff->hasChanged('scale') || $columnDiff->hasChanged('fixed')) { |
|
535 | 16 | $type = $column->getType(); |
|
536 | |||
537 | // here was a server version check before, but DBAL API does not support this anymore. |
||
538 | 16 | $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSQLDeclaration($column->toArray(), $this); |
|
539 | 16 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
540 | } |
||
541 | |||
542 | 36 | if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) { |
|
543 | 8 | $defaultClause = null === $column->getDefault() |
|
544 | 4 | ? ' DROP DEFAULT' |
|
545 | 8 | : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); |
|
546 | 8 | $query = 'ALTER ' . $oldColumnName . $defaultClause; |
|
547 | 8 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
548 | } |
||
549 | |||
550 | 36 | if ($columnDiff->hasChanged('notnull')) { |
|
551 | 8 | $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotnull() ? 'SET' : 'DROP') . ' NOT NULL'; |
|
552 | 8 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
553 | } |
||
554 | |||
555 | 36 | if ($columnDiff->hasChanged('autoincrement')) { |
|
556 | if ($column->getAutoincrement()) { |
||
557 | // add autoincrement |
||
558 | $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); |
||
559 | |||
560 | $sql[] = "CREATE SEQUENCE " . $seqName; |
||
561 | $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->getName($this)->getQuotedName($this) . "))"; |
||
562 | $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; |
||
563 | $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query; |
||
564 | } else { |
||
565 | // Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have |
||
566 | $query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT"; |
||
567 | $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query; |
||
568 | } |
||
569 | } |
||
570 | |||
571 | 36 | View Code Duplication | if ($columnDiff->hasChanged('comment')) { |
572 | 8 | $commentsSQL[] = $this->getCommentOnColumnSQL( |
|
573 | 8 | $diff->getName($this)->getQuotedName($this), |
|
574 | 8 | $column->getQuotedName($this), |
|
575 | 8 | $this->getColumnComment($column) |
|
576 | ); |
||
577 | } |
||
578 | |||
579 | 36 | if ($columnDiff->hasChanged('length')) { |
|
580 | 4 | $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSQLDeclaration($column->toArray(), $this); |
|
581 | 36 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; |
|
582 | } |
||
583 | } |
||
584 | |||
585 | 72 | View Code Duplication | foreach ($diff->renamedColumns as $oldColumnName => $column) { |
586 | 16 | if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { |
|
587 | continue; |
||
588 | } |
||
589 | |||
590 | 16 | $oldColumnName = new Identifier($oldColumnName); |
|
591 | |||
592 | 16 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . |
|
593 | 16 | ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); |
|
594 | } |
||
595 | |||
596 | 72 | $tableSql = []; |
|
597 | |||
598 | 72 | View Code Duplication | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
599 | 72 | $sql = array_merge($sql, $commentsSQL); |
|
600 | |||
601 | 72 | if ($diff->newName !== false) { |
|
602 | 8 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); |
|
603 | } |
||
604 | |||
605 | 72 | $sql = array_merge( |
|
606 | 72 | $this->getPreAlterTableIndexForeignKeySQL($diff), |
|
607 | 72 | $sql, |
|
608 | 72 | $this->getPostAlterTableIndexForeignKeySQL($diff) |
|
609 | ); |
||
610 | } |
||
611 | |||
612 | 72 | return array_merge($sql, $tableSql, $columnSql); |
|
613 | } |
||
614 | |||
615 | /** |
||
616 | * Checks whether a given column diff is a logically unchanged binary type column. |
||
617 | * |
||
618 | * Used to determine whether a column alteration for a binary type column can be skipped. |
||
619 | * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} |
||
620 | * are mapped to the same database column type on this platform as this platform |
||
621 | * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} |
||
622 | * might detect differences for binary type columns which do not have to be propagated |
||
623 | * to database as there actually is no difference at database level. |
||
624 | * |
||
625 | * @param ColumnDiff $columnDiff The column diff to check against. |
||
626 | * |
||
627 | * @return boolean True if the given column diff is an unchanged binary type column, false otherwise. |
||
628 | */ |
||
629 | 40 | private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) |
|
630 | { |
||
631 | 40 | $columnType = $columnDiff->column->getType(); |
|
632 | |||
633 | 40 | if ( ! $columnType instanceof BinaryType && ! $columnType instanceof BlobType) { |
|
634 | 36 | return false; |
|
635 | } |
||
636 | |||
637 | 4 | $fromColumn = $columnDiff->fromColumn instanceof Column ? $columnDiff->fromColumn : null; |
|
638 | |||
639 | 4 | if ($fromColumn) { |
|
640 | 4 | $fromColumnType = $fromColumn->getType(); |
|
641 | |||
642 | 4 | if ( ! $fromColumnType instanceof BinaryType && ! $fromColumnType instanceof BlobType) { |
|
643 | return false; |
||
644 | } |
||
645 | |||
646 | 4 | return count(array_diff($columnDiff->changedProperties, ['type', 'length', 'fixed'])) === 0; |
|
647 | } |
||
648 | |||
649 | if ($columnDiff->hasChanged('type')) { |
||
650 | return false; |
||
651 | } |
||
652 | |||
653 | return count(array_diff($columnDiff->changedProperties, ['length', 'fixed'])) === 0; |
||
654 | } |
||
655 | |||
656 | /** |
||
657 | * {@inheritdoc} |
||
658 | */ |
||
659 | 20 | View Code Duplication | protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) |
660 | { |
||
661 | 20 | if (strpos($tableName, '.') !== false) { |
|
662 | 8 | list($schema) = explode('.', $tableName); |
|
663 | 8 | $oldIndexName = $schema . '.' . $oldIndexName; |
|
664 | } |
||
665 | |||
666 | 20 | return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)]; |
|
667 | } |
||
668 | |||
669 | /** |
||
670 | * {@inheritdoc} |
||
671 | */ |
||
672 | 32 | View Code Duplication | public function getCommentOnColumnSQL($tableName, $columnName, $comment) |
673 | { |
||
674 | 32 | $tableName = new Identifier($tableName); |
|
675 | 32 | $columnName = new Identifier($columnName); |
|
676 | 32 | $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); |
|
677 | |||
678 | 32 | return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) . |
|
679 | 32 | " IS $comment"; |
|
680 | } |
||
681 | |||
682 | /** |
||
683 | * {@inheritDoc} |
||
684 | */ |
||
685 | 8 | View Code Duplication | public function getCreateSequenceSQL(Sequence $sequence) |
686 | { |
||
687 | 8 | return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . |
|
688 | 8 | ' INCREMENT BY ' . $sequence->getAllocationSize() . |
|
689 | 8 | ' MINVALUE ' . $sequence->getInitialValue() . |
|
690 | 8 | ' START ' . $sequence->getInitialValue() . |
|
691 | 8 | $this->getSequenceCacheSQL($sequence); |
|
692 | } |
||
693 | |||
694 | /** |
||
695 | * {@inheritDoc} |
||
696 | */ |
||
697 | public function getAlterSequenceSQL(Sequence $sequence) |
||
698 | { |
||
699 | return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . |
||
700 | ' INCREMENT BY ' . $sequence->getAllocationSize() . |
||
701 | $this->getSequenceCacheSQL($sequence); |
||
702 | } |
||
703 | |||
704 | /** |
||
705 | * Cache definition for sequences |
||
706 | * |
||
707 | * @param Sequence $sequence |
||
708 | * |
||
709 | * @return string |
||
710 | */ |
||
711 | 8 | private function getSequenceCacheSQL(Sequence $sequence) |
|
712 | { |
||
713 | 8 | if ($sequence->getCache() > 1) { |
|
714 | 4 | return ' CACHE ' . $sequence->getCache(); |
|
715 | } |
||
716 | |||
717 | 4 | return ''; |
|
718 | } |
||
719 | |||
720 | /** |
||
721 | * {@inheritDoc} |
||
722 | */ |
||
723 | 4 | public function getDropSequenceSQL($sequence) |
|
724 | { |
||
725 | 4 | if ($sequence instanceof Sequence) { |
|
726 | $sequence = $sequence->getQuotedName($this); |
||
727 | } |
||
728 | |||
729 | 4 | return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; |
|
730 | } |
||
731 | |||
732 | /** |
||
733 | * {@inheritDoc} |
||
734 | */ |
||
735 | 4 | public function getCreateSchemaSQL($schemaName) |
|
736 | { |
||
737 | 4 | return 'CREATE SCHEMA ' . $schemaName; |
|
738 | } |
||
739 | |||
740 | /** |
||
741 | * {@inheritDoc} |
||
742 | */ |
||
743 | 12 | public function getDropForeignKeySQL($foreignKey, $table) |
|
744 | { |
||
745 | 12 | return $this->getDropConstraintSQL($foreignKey, $table); |
|
746 | } |
||
747 | |||
748 | /** |
||
749 | * {@inheritDoc} |
||
750 | */ |
||
751 | 40 | protected function _getCreateTableSQL($tableName, array $columns, array $options = []) |
|
752 | { |
||
753 | 40 | $queryFields = $this->getColumnDeclarationListSQL($columns); |
|
754 | |||
755 | 40 | View Code Duplication | if (isset($options['primary']) && ! empty($options['primary'])) { |
756 | 16 | $keyColumns = array_unique(array_values($options['primary'])); |
|
757 | 16 | $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; |
|
758 | } |
||
759 | |||
760 | 40 | $query = 'CREATE TABLE ' . $tableName . ' (' . $queryFields . ')'; |
|
761 | |||
762 | 40 | $sql[] = $query; |
|
763 | |||
764 | 40 | View Code Duplication | if (isset($options['indexes']) && ! empty($options['indexes'])) { |
765 | 12 | foreach ($options['indexes'] as $index) { |
|
766 | 12 | $sql[] = $this->getCreateIndexSQL($index, $tableName); |
|
767 | } |
||
768 | } |
||
769 | |||
770 | 40 | View Code Duplication | if (isset($options['foreignKeys'])) { |
771 | 4 | foreach ((array) $options['foreignKeys'] as $definition) { |
|
772 | 4 | $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); |
|
773 | } |
||
774 | } |
||
775 | |||
776 | 40 | return $sql; |
|
777 | } |
||
778 | |||
779 | /** |
||
780 | * Converts a single boolean value. |
||
781 | * |
||
782 | * First converts the value to its native PHP boolean type |
||
783 | * and passes it to the given callback function to be reconverted |
||
784 | * into any custom representation. |
||
785 | * |
||
786 | * @param mixed $value The value to convert. |
||
787 | * @param callable $callback The callback function to use for converting the real boolean value. |
||
788 | * |
||
789 | * @return mixed |
||
790 | * @throws \UnexpectedValueException |
||
791 | */ |
||
792 | 128 | private function convertSingleBooleanValue($value, $callback) |
|
793 | { |
||
794 | 128 | if (null === $value) { |
|
795 | 8 | return $callback(null); |
|
796 | } |
||
797 | |||
798 | 120 | if (is_bool($value) || is_numeric($value)) { |
|
799 | 76 | return $callback($value ? true : false); |
|
800 | } |
||
801 | |||
802 | 44 | if (!is_string($value)) { |
|
803 | return $callback(true); |
||
804 | } |
||
805 | |||
806 | /** |
||
807 | * Better safe than sorry: http://php.net/in_array#106319 |
||
808 | */ |
||
809 | 44 | View Code Duplication | if (in_array(trim(strtolower($value)), $this->booleanLiterals['false'], true)) { |
0 ignored issues
–
show
|
|||
810 | 20 | return $callback(false); |
|
811 | } |
||
812 | |||
813 | 24 | View Code Duplication | if (in_array(trim(strtolower($value)), $this->booleanLiterals['true'], true)) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
814 | 20 | return $callback(true); |
|
815 | } |
||
816 | |||
817 | 4 | throw new \UnexpectedValueException("Unrecognized boolean literal '${value}'"); |
|
818 | } |
||
819 | |||
820 | /** |
||
821 | * Converts one or multiple boolean values. |
||
822 | * |
||
823 | * First converts the value(s) to their native PHP boolean type |
||
824 | * and passes them to the given callback function to be reconverted |
||
825 | * into any custom representation. |
||
826 | * |
||
827 | * @param mixed $item The value(s) to convert. |
||
828 | * @param callable $callback The callback function to use for converting the real boolean value(s). |
||
829 | * |
||
830 | * @return mixed |
||
831 | */ |
||
832 | private function doConvertBooleans($item, $callback) |
||
833 | { |
||
834 | 128 | if (is_array($item)) { |
|
835 | foreach ($item as $key => $value) { |
||
836 | $item[$key] = $this->convertSingleBooleanValue($value, $callback); |
||
837 | } |
||
838 | |||
839 | return $item; |
||
840 | } |
||
841 | |||
842 | 128 | return $this->convertSingleBooleanValue($item, $callback); |
|
843 | } |
||
844 | |||
845 | /** |
||
846 | * {@inheritDoc} |
||
847 | * |
||
848 | * Postgres wants boolean values converted to the strings 'true'/'false'. |
||
849 | */ |
||
850 | public function convertBooleans($item) |
||
851 | { |
||
852 | 72 | if ( ! $this->useBooleanTrueFalseStrings) { |
|
853 | 8 | return parent::convertBooleans($item); |
|
854 | } |
||
855 | |||
856 | 64 | return $this->doConvertBooleans( |
|
857 | 64 | $item, |
|
858 | function ($boolean) { |
||
859 | 64 | if (null === $boolean) { |
|
860 | 4 | return 'NULL'; |
|
861 | } |
||
862 | |||
863 | 60 | return true === $boolean ? 'true' : 'false'; |
|
864 | 64 | } |
|
865 | ); |
||
866 | } |
||
867 | |||
868 | /** |
||
869 | * {@inheritDoc} |
||
870 | */ |
||
871 | public function convertBooleansToDatabaseValue($item) |
||
872 | { |
||
873 | 68 | if ( ! $this->useBooleanTrueFalseStrings) { |
|
874 | 4 | return parent::convertBooleansToDatabaseValue($item); |
|
875 | } |
||
876 | |||
877 | 64 | return $this->doConvertBooleans( |
|
878 | 64 | $item, |
|
879 | function ($boolean) { |
||
880 | 60 | return null === $boolean ? null : (int) $boolean; |
|
881 | 64 | } |
|
882 | ); |
||
883 | } |
||
884 | |||
885 | /** |
||
886 | * {@inheritDoc} |
||
887 | */ |
||
888 | public function convertFromBoolean($item) |
||
889 | { |
||
890 | 60 | if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) { |
|
891 | 24 | return false; |
|
892 | } |
||
893 | |||
894 | 36 | return parent::convertFromBoolean($item); |
|
895 | } |
||
896 | |||
897 | /** |
||
898 | * {@inheritDoc} |
||
899 | */ |
||
900 | public function getSequenceNextValSQL($sequenceName) |
||
901 | { |
||
902 | 4 | return "SELECT NEXTVAL('" . $sequenceName . "')"; |
|
903 | } |
||
904 | |||
905 | /** |
||
906 | * {@inheritDoc} |
||
907 | */ |
||
908 | public function getSetTransactionIsolationSQL($level) |
||
909 | { |
||
910 | return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' |
||
911 | 4 | . $this->_getTransactionIsolationLevelSQL($level); |
|
912 | } |
||
913 | |||
914 | /** |
||
915 | * {@inheritDoc} |
||
916 | */ |
||
917 | public function getBooleanTypeDeclarationSQL(array $field) |
||
918 | { |
||
919 | 4 | return 'BOOLEAN'; |
|
920 | } |
||
921 | |||
922 | /** |
||
923 | * {@inheritDoc} |
||
924 | */ |
||
925 | public function getIntegerTypeDeclarationSQL(array $field) |
||
926 | { |
||
927 | 36 | if ( ! empty($field['autoincrement'])) { |
|
928 | 12 | return 'SERIAL'; |
|
929 | } |
||
930 | |||
931 | 28 | return 'INT'; |
|
932 | } |
||
933 | |||
934 | /** |
||
935 | * {@inheritDoc} |
||
936 | */ |
||
937 | public function getBigIntTypeDeclarationSQL(array $field) |
||
938 | { |
||
939 | if ( ! empty($field['autoincrement'])) { |
||
940 | return 'BIGSERIAL'; |
||
941 | } |
||
942 | |||
943 | return 'BIGINT'; |
||
944 | } |
||
945 | |||
946 | /** |
||
947 | * {@inheritDoc} |
||
948 | */ |
||
949 | public function getSmallIntTypeDeclarationSQL(array $field) |
||
950 | { |
||
951 | 2 | return 'SMALLINT'; |
|
952 | } |
||
953 | |||
954 | /** |
||
955 | * {@inheritDoc} |
||
956 | */ |
||
957 | public function getGuidTypeDeclarationSQL(array $field) |
||
958 | { |
||
959 | 4 | return 'UUID'; |
|
960 | } |
||
961 | |||
962 | /** |
||
963 | * {@inheritDoc} |
||
964 | */ |
||
965 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
966 | { |
||
967 | return 'TIMESTAMP(0) WITHOUT TIME ZONE'; |
||
968 | } |
||
969 | |||
970 | /** |
||
971 | * {@inheritDoc} |
||
972 | */ |
||
973 | public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) |
||
974 | { |
||
975 | return 'TIMESTAMP(0) WITH TIME ZONE'; |
||
976 | } |
||
977 | |||
978 | /** |
||
979 | * {@inheritDoc} |
||
980 | */ |
||
981 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
||
982 | { |
||
983 | return 'DATE'; |
||
984 | } |
||
985 | |||
986 | /** |
||
987 | * {@inheritDoc} |
||
988 | */ |
||
989 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
990 | { |
||
991 | return 'TIME(0) WITHOUT TIME ZONE'; |
||
992 | } |
||
993 | |||
994 | /** |
||
995 | * {@inheritDoc} |
||
996 | */ |
||
997 | public function getGuidExpression() |
||
998 | { |
||
999 | return 'UUID_GENERATE_V4()'; |
||
1000 | } |
||
1001 | |||
1002 | /** |
||
1003 | * {@inheritDoc} |
||
1004 | */ |
||
1005 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
||
1006 | { |
||
1007 | return ''; |
||
1008 | } |
||
1009 | |||
1010 | /** |
||
1011 | * {@inheritDoc} |
||
1012 | */ |
||
1013 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
||
1014 | { |
||
1015 | 48 | return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') |
|
1016 | 48 | : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); |
|
1017 | } |
||
1018 | |||
1019 | /** |
||
1020 | * {@inheritdoc} |
||
1021 | */ |
||
1022 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
||
1023 | { |
||
1024 | 4 | return 'BYTEA'; |
|
1025 | } |
||
1026 | |||
1027 | /** |
||
1028 | * {@inheritDoc} |
||
1029 | */ |
||
1030 | public function getClobTypeDeclarationSQL(array $field) |
||
1031 | { |
||
1032 | 6 | return 'TEXT'; |
|
1033 | } |
||
1034 | |||
1035 | /** |
||
1036 | * {@inheritDoc} |
||
1037 | */ |
||
1038 | public function getName() |
||
1039 | { |
||
1040 | 8 | return 'postgresql'; |
|
1041 | } |
||
1042 | |||
1043 | /** |
||
1044 | * {@inheritDoc} |
||
1045 | * |
||
1046 | * PostgreSQL returns all column names in SQL result sets in lowercase. |
||
1047 | */ |
||
1048 | public function getSQLResultCasing($column) |
||
1049 | { |
||
1050 | return strtolower($column); |
||
1051 | } |
||
1052 | |||
1053 | /** |
||
1054 | * {@inheritDoc} |
||
1055 | */ |
||
1056 | public function getDateTimeTzFormatString() |
||
1057 | { |
||
1058 | return 'Y-m-d H:i:sO'; |
||
1059 | } |
||
1060 | |||
1061 | /** |
||
1062 | * {@inheritDoc} |
||
1063 | */ |
||
1064 | public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) |
||
1065 | { |
||
1066 | return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; |
||
1067 | } |
||
1068 | |||
1069 | /** |
||
1070 | * {@inheritDoc} |
||
1071 | */ |
||
1072 | public function getTruncateTableSQL($tableName, $cascade = false) |
||
1073 | { |
||
1074 | 4 | $tableIdentifier = new Identifier($tableName); |
|
1075 | 4 | $sql = 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); |
|
1076 | |||
1077 | 4 | if ($cascade) { |
|
1078 | $sql .= ' CASCADE'; |
||
1079 | } |
||
1080 | |||
1081 | 4 | return $sql; |
|
1082 | } |
||
1083 | |||
1084 | /** |
||
1085 | * {@inheritDoc} |
||
1086 | */ |
||
1087 | public function getReadLockSQL() |
||
1088 | { |
||
1089 | return 'FOR SHARE'; |
||
1090 | } |
||
1091 | |||
1092 | /** |
||
1093 | * {@inheritDoc} |
||
1094 | */ |
||
1095 | View Code Duplication | protected function initializeDoctrineTypeMappings() |
|
1096 | { |
||
1097 | 22 | $this->doctrineTypeMapping = [ |
|
1098 | 'smallint' => 'smallint', |
||
1099 | 'int2' => 'smallint', |
||
1100 | 'serial' => 'integer', |
||
1101 | 'serial4' => 'integer', |
||
1102 | 'int' => 'integer', |
||
1103 | 'int4' => 'integer', |
||
1104 | 'integer' => 'integer', |
||
1105 | 'bigserial' => 'bigint', |
||
1106 | 'serial8' => 'bigint', |
||
1107 | 'bigint' => 'bigint', |
||
1108 | 'int8' => 'bigint', |
||
1109 | 'bool' => 'boolean', |
||
1110 | 'boolean' => 'boolean', |
||
1111 | 'text' => 'text', |
||
1112 | 'tsvector' => 'text', |
||
1113 | 'varchar' => 'string', |
||
1114 | 'interval' => 'string', |
||
1115 | '_varchar' => 'string', |
||
1116 | 'char' => 'string', |
||
1117 | 'bpchar' => 'string', |
||
1118 | 'inet' => 'string', |
||
1119 | 'date' => 'date', |
||
1120 | 'datetime' => 'datetime', |
||
1121 | 'timestamp' => 'datetime', |
||
1122 | 'timestamptz' => 'datetimetz', |
||
1123 | 'time' => 'time', |
||
1124 | 'timetz' => 'time', |
||
1125 | 'float' => 'float', |
||
1126 | 'float4' => 'float', |
||
1127 | 'float8' => 'float', |
||
1128 | 'double' => 'float', |
||
1129 | 'double precision' => 'float', |
||
1130 | 'real' => 'float', |
||
1131 | 'decimal' => 'decimal', |
||
1132 | 'money' => 'decimal', |
||
1133 | 'numeric' => 'decimal', |
||
1134 | 'year' => 'date', |
||
1135 | 'uuid' => 'guid', |
||
1136 | 'bytea' => 'blob', |
||
1137 | ]; |
||
1138 | 22 | } |
|
1139 | |||
1140 | /** |
||
1141 | * {@inheritDoc} |
||
1142 | */ |
||
1143 | public function getVarcharMaxLength() |
||
1144 | { |
||
1145 | 48 | return 65535; |
|
1146 | } |
||
1147 | |||
1148 | /** |
||
1149 | * {@inheritdoc} |
||
1150 | */ |
||
1151 | public function getBinaryMaxLength() |
||
1152 | { |
||
1153 | 8 | return 0; |
|
1154 | } |
||
1155 | |||
1156 | /** |
||
1157 | * {@inheritdoc} |
||
1158 | */ |
||
1159 | public function getBinaryDefaultLength() |
||
1160 | { |
||
1161 | 8 | return 0; |
|
1162 | } |
||
1163 | |||
1164 | /** |
||
1165 | * {@inheritDoc} |
||
1166 | */ |
||
1167 | protected function getReservedKeywordsClass() |
||
1168 | { |
||
1169 | 47 | return Keywords\PostgreSQLKeywords::class; |
|
1170 | } |
||
1171 | |||
1172 | /** |
||
1173 | * {@inheritDoc} |
||
1174 | */ |
||
1175 | public function getBlobTypeDeclarationSQL(array $field) |
||
1176 | { |
||
1177 | 4 | return 'BYTEA'; |
|
1178 | } |
||
1179 | |||
1180 | /** |
||
1181 | * {@inheritdoc} |
||
1182 | */ |
||
1183 | public function quoteStringLiteral($str) |
||
1184 | { |
||
1185 | 68 | $str = str_replace('\\', '\\\\', $str); // PostgreSQL requires backslashes to be escaped aswell. |
|
1186 | |||
1187 | 68 | return parent::quoteStringLiteral($str); |
|
1188 | } |
||
1189 | } |
||
1190 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.