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.
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>.
20 namespace Doctrine\DBAL\Platforms
;
22 use Doctrine\DBAL\DBALException
;
23 use Doctrine\DBAL\Connection
;
24 use Doctrine\DBAL\Schema\Identifier
;
25 use Doctrine\DBAL\Types
;
26 use Doctrine\DBAL\Schema\Constraint
;
27 use Doctrine\DBAL\Schema\Sequence
;
28 use Doctrine\DBAL\Schema\Table
;
29 use Doctrine\DBAL\Schema\Index
;
30 use Doctrine\DBAL\Schema\ForeignKeyConstraint
;
31 use Doctrine\DBAL\Schema\TableDiff
;
32 use Doctrine\DBAL\Schema\Column
;
33 use Doctrine\DBAL\Schema\ColumnDiff
;
34 use Doctrine\DBAL\Types\Type
;
35 use Doctrine\DBAL\Events
;
36 use Doctrine\Common\EventManager
;
37 use Doctrine\DBAL\Event\SchemaCreateTableEventArgs
;
38 use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs
;
39 use Doctrine\DBAL\Event\SchemaDropTableEventArgs
;
40 use Doctrine\DBAL\Event\SchemaAlterTableEventArgs
;
41 use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs
;
42 use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs
;
43 use Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs
;
44 use Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs
;
47 * Base class for all DatabasePlatforms. The DatabasePlatforms are the central
48 * point of abstraction of platform-specific behaviors, features and SQL dialects.
49 * They are a passive source of information.
51 * @link www.doctrine-project.org
53 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
54 * @author Jonathan Wage <jonwage@gmail.com>
55 * @author Roman Borschel <roman@code-factory.org>
56 * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
57 * @author Benjamin Eberlei <kontakt@beberlei.de>
58 * @todo Remove any unnecessary methods.
60 abstract class AbstractPlatform
65 const CREATE_INDEXES
= 1;
70 const CREATE_FOREIGNKEYS
= 2;
75 const DATE_INTERVAL_UNIT_SECOND
= 'SECOND';
80 const DATE_INTERVAL_UNIT_MINUTE
= 'MINUTE';
85 const DATE_INTERVAL_UNIT_HOUR
= 'HOUR';
90 const DATE_INTERVAL_UNIT_DAY
= 'DAY';
95 const DATE_INTERVAL_UNIT_WEEK
= 'WEEK';
100 const DATE_INTERVAL_UNIT_MONTH
= 'MONTH';
105 const DATE_INTERVAL_UNIT_QUARTER
= 'QUARTER';
110 const DATE_INTERVAL_UNIT_YEAR
= 'YEAR';
115 const TRIM_UNSPECIFIED
= 0;
120 const TRIM_LEADING
= 1;
125 const TRIM_TRAILING
= 2;
135 protected $doctrineTypeMapping = null;
138 * Contains a list of all columns that should generate parseable column comments for type-detection
139 * in reverse engineering scenarios.
143 protected $doctrineTypeComments = null;
146 * @var \Doctrine\Common\EventManager
148 protected $_eventManager;
151 * Holds the KeywordList instance for the current platform.
153 * @var \Doctrine\DBAL\Platforms\Keywords\KeywordList
155 protected $_keywords;
160 public function __construct()
165 * Sets the EventManager used by the Platform.
167 * @param \Doctrine\Common\EventManager $eventManager
169 public function setEventManager(EventManager
$eventManager)
171 $this->_eventManager
= $eventManager;
175 * Gets the EventManager used by the Platform.
177 * @return \Doctrine\Common\EventManager
179 public function getEventManager()
181 return $this->_eventManager
;
185 * Returns the SQL snippet that declares a boolean column.
187 * @param array $columnDef
191 abstract public function getBooleanTypeDeclarationSQL(array $columnDef);
194 * Returns the SQL snippet that declares a 4 byte integer column.
196 * @param array $columnDef
200 abstract public function getIntegerTypeDeclarationSQL(array $columnDef);
203 * Returns the SQL snippet that declares an 8 byte integer column.
205 * @param array $columnDef
209 abstract public function getBigIntTypeDeclarationSQL(array $columnDef);
212 * Returns the SQL snippet that declares a 2 byte integer column.
214 * @param array $columnDef
218 abstract public function getSmallIntTypeDeclarationSQL(array $columnDef);
221 * Returns the SQL snippet that declares common properties of an integer column.
223 * @param array $columnDef
227 abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef);
230 * Lazy load Doctrine Type Mappings.
234 abstract protected function initializeDoctrineTypeMappings();
237 * Initializes Doctrine Type Mappings with the platform defaults
238 * and with all additional type mappings.
242 private function initializeAllDoctrineTypeMappings()
244 $this->initializeDoctrineTypeMappings();
246 foreach (Type
::getTypesMap() as $typeName => $className) {
247 foreach (Type
::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) {
248 $this->doctrineTypeMapping
[$dbType] = $typeName;
254 * Returns the SQL snippet used to declare a VARCHAR column type.
256 * @param array $field
260 public function getVarcharTypeDeclarationSQL(array $field)
262 if ( !isset($field['length'])) {
263 $field['length'] = $this->getVarcharDefaultLength();
266 $fixed = (isset($field['fixed'])) ?
$field['fixed'] : false;
268 if ($field['length'] > $this->getVarcharMaxLength()) {
269 return $this->getClobTypeDeclarationSQL($field);
272 return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed);
276 * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
278 * @param array $field The column definition.
282 public function getBinaryTypeDeclarationSQL(array $field)
284 if ( ! isset($field['length'])) {
285 $field['length'] = $this->getBinaryDefaultLength();
288 $fixed = isset($field['fixed']) ?
$field['fixed'] : false;
290 if ($field['length'] > $this->getBinaryMaxLength()) {
291 return $this->getBlobTypeDeclarationSQL($field);
294 return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed);
298 * Returns the SQL snippet to declare a GUID/UUID field.
300 * By default this maps directly to a CHAR(36) and only maps to more
301 * special datatypes when the underlying databases support this datatype.
303 * @param array $field
307 public function getGuidTypeDeclarationSQL(array $field)
309 $field['length'] = 36;
310 $field['fixed'] = true;
312 return $this->getVarcharTypeDeclarationSQL($field);
316 * Returns the SQL snippet to declare a JSON field.
318 * By default this maps directly to a CLOB and only maps to more
319 * special datatypes when the underlying databases support this datatype.
321 * @param array $field
325 public function getJsonTypeDeclarationSQL(array $field)
327 return $this->getClobTypeDeclarationSQL($field);
331 * @param integer $length
332 * @param boolean $fixed
336 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
338 protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
340 throw DBALException
::notSupported('VARCHARs not supported by Platform.');
344 * Returns the SQL snippet used to declare a BINARY/VARBINARY column type.
346 * @param integer $length The length of the column.
347 * @param boolean $fixed Whether the column length is fixed.
351 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
353 protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
355 throw DBALException
::notSupported('BINARY/VARBINARY column types are not supported by this platform.');
359 * Returns the SQL snippet used to declare a CLOB column type.
361 * @param array $field
365 abstract public function getClobTypeDeclarationSQL(array $field);
368 * Returns the SQL Snippet used to declare a BLOB column type.
370 * @param array $field
374 abstract public function getBlobTypeDeclarationSQL(array $field);
377 * Gets the name of the platform.
381 abstract public function getName();
384 * Registers a doctrine type to be used in conjunction with a column type of this platform.
386 * @param string $dbType
387 * @param string $doctrineType
389 * @throws \Doctrine\DBAL\DBALException If the type is not found.
391 public function registerDoctrineTypeMapping($dbType, $doctrineType)
393 if ($this->doctrineTypeMapping
=== null) {
394 $this->initializeAllDoctrineTypeMappings();
397 if (!Types\Type
::hasType($doctrineType)) {
398 throw DBALException
::typeNotFound($doctrineType);
401 $dbType = strtolower($dbType);
402 $this->doctrineTypeMapping
[$dbType] = $doctrineType;
406 * Gets the Doctrine type that is mapped for the given database column type.
408 * @param string $dbType
412 * @throws \Doctrine\DBAL\DBALException
414 public function getDoctrineTypeMapping($dbType)
416 if ($this->doctrineTypeMapping
=== null) {
417 $this->initializeAllDoctrineTypeMappings();
420 $dbType = strtolower($dbType);
422 if (!isset($this->doctrineTypeMapping
[$dbType])) {
423 throw new \Doctrine\DBAL\
DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it.");
426 return $this->doctrineTypeMapping
[$dbType];
430 * Checks if a database type is currently supported by this platform.
432 * @param string $dbType
436 public function hasDoctrineTypeMappingFor($dbType)
438 if ($this->doctrineTypeMapping
=== null) {
439 $this->initializeAllDoctrineTypeMappings();
442 $dbType = strtolower($dbType);
444 return isset($this->doctrineTypeMapping
[$dbType]);
448 * Initializes the Doctrine Type comments instance variable for in_array() checks.
452 protected function initializeCommentedDoctrineTypes()
454 $this->doctrineTypeComments
= array();
456 foreach (Type
::getTypesMap() as $typeName => $className) {
457 $type = Type
::getType($typeName);
459 if ($type->requiresSQLCommentHint($this)) {
460 $this->doctrineTypeComments
[] = $typeName;
466 * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type?
468 * @param \Doctrine\DBAL\Types\Type $doctrineType
472 public function isCommentedDoctrineType(Type
$doctrineType)
474 if ($this->doctrineTypeComments
=== null) {
475 $this->initializeCommentedDoctrineTypes();
478 return in_array($doctrineType->getName(), $this->doctrineTypeComments
);
482 * Marks this type as to be commented in ALTER TABLE and CREATE TABLE statements.
484 * @param string|\Doctrine\DBAL\Types\Type $doctrineType
488 public function markDoctrineTypeCommented($doctrineType)
490 if ($this->doctrineTypeComments
=== null) {
491 $this->initializeCommentedDoctrineTypes();
494 $this->doctrineTypeComments
[] = $doctrineType instanceof Type ?
$doctrineType->getName() : $doctrineType;
498 * Gets the comment to append to a column comment that helps parsing this type in reverse engineering.
500 * @param \Doctrine\DBAL\Types\Type $doctrineType
504 public function getDoctrineTypeComment(Type
$doctrineType)
506 return '(DC2Type:' . $doctrineType->getName() . ')';
510 * Gets the comment of a passed column modified by potential doctrine type comment hints.
512 * @param \Doctrine\DBAL\Schema\Column $column
516 protected function getColumnComment(Column
$column)
518 $comment = $column->getComment();
520 if ($this->isCommentedDoctrineType($column->getType())) {
521 $comment .= $this->getDoctrineTypeComment($column->getType());
528 * Gets the character used for identifier quoting.
532 public function getIdentifierQuoteCharacter()
538 * Gets the string portion that starts an SQL comment.
542 public function getSqlCommentStartString()
548 * Gets the string portion that ends an SQL comment.
552 public function getSqlCommentEndString()
558 * Gets the maximum length of a varchar field.
562 public function getVarcharMaxLength()
568 * Gets the default length of a varchar field.
572 public function getVarcharDefaultLength()
578 * Gets the maximum length of a binary field.
582 public function getBinaryMaxLength()
588 * Gets the default length of a binary field.
592 public function getBinaryDefaultLength()
598 * Gets all SQL wildcard characters of the platform.
602 public function getWildcards()
604 return array('%', '_');
608 * Returns the regular expression operator.
612 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
614 public function getRegexpExpression()
616 throw DBALException
::notSupported(__METHOD__
);
620 * Returns the global unique identifier expression.
624 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
626 public function getGuidExpression()
628 throw DBALException
::notSupported(__METHOD__
);
632 * Returns the SQL snippet to get the average value of a column.
634 * @param string $column The column to use.
636 * @return string Generated SQL including an AVG aggregate function.
638 public function getAvgExpression($column)
640 return 'AVG(' . $column . ')';
644 * Returns the SQL snippet to get the number of rows (without a NULL value) of a column.
646 * If a '*' is used instead of a column the number of selected rows is returned.
648 * @param string|integer $column The column to use.
650 * @return string Generated SQL including a COUNT aggregate function.
652 public function getCountExpression($column)
654 return 'COUNT(' . $column . ')';
658 * Returns the SQL snippet to get the highest value of a column.
660 * @param string $column The column to use.
662 * @return string Generated SQL including a MAX aggregate function.
664 public function getMaxExpression($column)
666 return 'MAX(' . $column . ')';
670 * Returns the SQL snippet to get the lowest value of a column.
672 * @param string $column The column to use.
674 * @return string Generated SQL including a MIN aggregate function.
676 public function getMinExpression($column)
678 return 'MIN(' . $column . ')';
682 * Returns the SQL snippet to get the total sum of a column.
684 * @param string $column The column to use.
686 * @return string Generated SQL including a SUM aggregate function.
688 public function getSumExpression($column)
690 return 'SUM(' . $column . ')';
696 * Returns the SQL snippet to get the md5 sum of a field.
698 * Note: Not SQL92, but common functionality.
700 * @param string $column
704 public function getMd5Expression($column)
706 return 'MD5(' . $column . ')';
710 * Returns the SQL snippet to get the length of a text field.
712 * @param string $column
716 public function getLengthExpression($column)
718 return 'LENGTH(' . $column . ')';
722 * Returns the SQL snippet to get the squared value of a column.
724 * @param string $column The column to use.
726 * @return string Generated SQL including an SQRT aggregate function.
728 public function getSqrtExpression($column)
730 return 'SQRT(' . $column . ')';
734 * Returns the SQL snippet to round a numeric field to the number of decimals specified.
736 * @param string $column
737 * @param integer $decimals
741 public function getRoundExpression($column, $decimals = 0)
743 return 'ROUND(' . $column . ', ' . $decimals . ')';
747 * Returns the SQL snippet to get the remainder of the division operation $expression1 / $expression2.
749 * @param string $expression1
750 * @param string $expression2
754 public function getModExpression($expression1, $expression2)
756 return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
760 * Returns the SQL snippet to trim a string.
762 * @param string $str The expression to apply the trim to.
763 * @param integer $pos The position of the trim (leading/trailing/both).
764 * @param string|boolean $char The char to trim, has to be quoted already. Defaults to space.
768 public function getTrimExpression($str, $pos = self
::TRIM_UNSPECIFIED
, $char = false)
773 case self
::TRIM_LEADING
:
774 $expression = 'LEADING ';
777 case self
::TRIM_TRAILING
:
778 $expression = 'TRAILING ';
781 case self
::TRIM_BOTH
:
782 $expression = 'BOTH ';
786 if (false !== $char) {
787 $expression .= $char . ' ';
790 if ($pos ||
false !== $char) {
791 $expression .= 'FROM ';
794 return 'TRIM(' . $expression . $str . ')';
798 * Returns the SQL snippet to trim trailing space characters from the expression.
800 * @param string $str Literal string or column name.
804 public function getRtrimExpression($str)
806 return 'RTRIM(' . $str . ')';
810 * Returns the SQL snippet to trim leading space characters from the expression.
812 * @param string $str Literal string or column name.
816 public function getLtrimExpression($str)
818 return 'LTRIM(' . $str . ')';
822 * Returns the SQL snippet to change all characters from the expression to uppercase,
823 * according to the current character set mapping.
825 * @param string $str Literal string or column name.
829 public function getUpperExpression($str)
831 return 'UPPER(' . $str . ')';
835 * Returns the SQL snippet to change all characters from the expression to lowercase,
836 * according to the current character set mapping.
838 * @param string $str Literal string or column name.
842 public function getLowerExpression($str)
844 return 'LOWER(' . $str . ')';
848 * Returns the SQL snippet to get the position of the first occurrence of substring $substr in string $str.
850 * @param string $str Literal string.
851 * @param string $substr Literal string to find.
852 * @param integer|boolean $startPos Position to start at, beginning of string by default.
856 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
858 public function getLocateExpression($str, $substr, $startPos = false)
860 throw DBALException
::notSupported(__METHOD__
);
864 * Returns the SQL snippet to get the current system date.
868 public function getNowExpression()
874 * Returns a SQL snippet to get a substring inside an SQL statement.
876 * Note: Not SQL92, but common functionality.
878 * SQLite only supports the 2 parameter variant of this function.
880 * @param string $value An sql string literal or column name/alias.
881 * @param integer $from Where to start the substring portion.
882 * @param integer|null $length The substring portion length.
886 public function getSubstringExpression($value, $from, $length = null)
888 if ($length === null) {
889 return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
892 return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')';
896 * Returns a SQL snippet to concatenate the given expressions.
898 * Accepts an arbitrary number of string parameters. Each parameter must contain an expression.
902 public function getConcatExpression()
904 return join(' || ', func_get_args());
908 * Returns the SQL for a logical not.
912 * $q = new Doctrine_Query();
914 * $q->select('*')->from('table')
915 * ->where($e->eq('id', $e->not('null'));
918 * @param string $expression
920 * @return string The logical expression.
922 public function getNotExpression($expression)
924 return 'NOT(' . $expression . ')';
928 * Returns the SQL that checks if an expression is null.
930 * @param string $expression The expression that should be compared to null.
932 * @return string The logical expression.
934 public function getIsNullExpression($expression)
936 return $expression . ' IS NULL';
940 * Returns the SQL that checks if an expression is not null.
942 * @param string $expression The expression that should be compared to null.
944 * @return string The logical expression.
946 public function getIsNotNullExpression($expression)
948 return $expression . ' IS NOT NULL';
952 * Returns the SQL that checks if an expression evaluates to a value between two values.
954 * The parameter $expression is checked if it is between $value1 and $value2.
956 * Note: There is a slight difference in the way BETWEEN works on some databases.
957 * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
958 * independence you should avoid using between().
960 * @param string $expression The value to compare to.
961 * @param string $value1 The lower value to compare with.
962 * @param string $value2 The higher value to compare with.
964 * @return string The logical expression.
966 public function getBetweenExpression($expression, $value1, $value2)
968 return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
972 * Returns the SQL to get the arccosine of a value.
974 * @param string $value
978 public function getAcosExpression($value)
980 return 'ACOS(' . $value . ')';
984 * Returns the SQL to get the sine of a value.
986 * @param string $value
990 public function getSinExpression($value)
992 return 'SIN(' . $value . ')';
996 * Returns the SQL to get the PI value.
1000 public function getPiExpression()
1006 * Returns the SQL to get the cosine of a value.
1008 * @param string $value
1012 public function getCosExpression($value)
1014 return 'COS(' . $value . ')';
1018 * Returns the SQL to calculate the difference in days between the two passed dates.
1020 * Computes diff = date1 - date2.
1022 * @param string $date1
1023 * @param string $date2
1027 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1029 public function getDateDiffExpression($date1, $date2)
1031 throw DBALException
::notSupported(__METHOD__
);
1035 * Returns the SQL to add the number of given seconds to a date.
1037 * @param string $date
1038 * @param integer $seconds
1042 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1044 public function getDateAddSecondsExpression($date, $seconds)
1046 return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, self
::DATE_INTERVAL_UNIT_SECOND
);
1050 * Returns the SQL to subtract the number of given seconds from a date.
1052 * @param string $date
1053 * @param integer $seconds
1057 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1059 public function getDateSubSecondsExpression($date, $seconds)
1061 return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, self
::DATE_INTERVAL_UNIT_SECOND
);
1065 * Returns the SQL to add the number of given minutes to a date.
1067 * @param string $date
1068 * @param integer $minutes
1072 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1074 public function getDateAddMinutesExpression($date, $minutes)
1076 return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, self
::DATE_INTERVAL_UNIT_MINUTE
);
1080 * Returns the SQL to subtract the number of given minutes from a date.
1082 * @param string $date
1083 * @param integer $minutes
1087 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1089 public function getDateSubMinutesExpression($date, $minutes)
1091 return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, self
::DATE_INTERVAL_UNIT_MINUTE
);
1095 * Returns the SQL to add the number of given hours to a date.
1097 * @param string $date
1098 * @param integer $hours
1102 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1104 public function getDateAddHourExpression($date, $hours)
1106 return $this->getDateArithmeticIntervalExpression($date, '+', $hours, self
::DATE_INTERVAL_UNIT_HOUR
);
1110 * Returns the SQL to subtract the number of given hours to a date.
1112 * @param string $date
1113 * @param integer $hours
1117 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1119 public function getDateSubHourExpression($date, $hours)
1121 return $this->getDateArithmeticIntervalExpression($date, '-', $hours, self
::DATE_INTERVAL_UNIT_HOUR
);
1125 * Returns the SQL to add the number of given days to a date.
1127 * @param string $date
1128 * @param integer $days
1132 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1134 public function getDateAddDaysExpression($date, $days)
1136 return $this->getDateArithmeticIntervalExpression($date, '+', $days, self
::DATE_INTERVAL_UNIT_DAY
);
1140 * Returns the SQL to subtract the number of given days to a date.
1142 * @param string $date
1143 * @param integer $days
1147 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1149 public function getDateSubDaysExpression($date, $days)
1151 return $this->getDateArithmeticIntervalExpression($date, '-', $days, self
::DATE_INTERVAL_UNIT_DAY
);
1155 * Returns the SQL to add the number of given weeks to a date.
1157 * @param string $date
1158 * @param integer $weeks
1162 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1164 public function getDateAddWeeksExpression($date, $weeks)
1166 return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, self
::DATE_INTERVAL_UNIT_WEEK
);
1170 * Returns the SQL to subtract the number of given weeks from a date.
1172 * @param string $date
1173 * @param integer $weeks
1177 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1179 public function getDateSubWeeksExpression($date, $weeks)
1181 return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, self
::DATE_INTERVAL_UNIT_WEEK
);
1185 * Returns the SQL to add the number of given months to a date.
1187 * @param string $date
1188 * @param integer $months
1192 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1194 public function getDateAddMonthExpression($date, $months)
1196 return $this->getDateArithmeticIntervalExpression($date, '+', $months, self
::DATE_INTERVAL_UNIT_MONTH
);
1200 * Returns the SQL to subtract the number of given months to a date.
1202 * @param string $date
1203 * @param integer $months
1207 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1209 public function getDateSubMonthExpression($date, $months)
1211 return $this->getDateArithmeticIntervalExpression($date, '-', $months, self
::DATE_INTERVAL_UNIT_MONTH
);
1215 * Returns the SQL to add the number of given quarters to a date.
1217 * @param string $date
1218 * @param integer $quarters
1222 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1224 public function getDateAddQuartersExpression($date, $quarters)
1226 return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, self
::DATE_INTERVAL_UNIT_QUARTER
);
1230 * Returns the SQL to subtract the number of given quarters from a date.
1232 * @param string $date
1233 * @param integer $quarters
1237 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1239 public function getDateSubQuartersExpression($date, $quarters)
1241 return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, self
::DATE_INTERVAL_UNIT_QUARTER
);
1245 * Returns the SQL to add the number of given years to a date.
1247 * @param string $date
1248 * @param integer $years
1252 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1254 public function getDateAddYearsExpression($date, $years)
1256 return $this->getDateArithmeticIntervalExpression($date, '+', $years, self
::DATE_INTERVAL_UNIT_YEAR
);
1260 * Returns the SQL to subtract the number of given years from a date.
1262 * @param string $date
1263 * @param integer $years
1267 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1269 public function getDateSubYearsExpression($date, $years)
1271 return $this->getDateArithmeticIntervalExpression($date, '-', $years, self
::DATE_INTERVAL_UNIT_YEAR
);
1275 * Returns the SQL for a date arithmetic expression.
1277 * @param string $date The column or literal representing a date to perform the arithmetic operation on.
1278 * @param string $operator The arithmetic operator (+ or -).
1279 * @param integer $interval The interval that shall be calculated into the date.
1280 * @param string $unit The unit of the interval that shall be calculated into the date.
1281 * One of the DATE_INTERVAL_UNIT_* constants.
1285 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1287 protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
1289 throw DBALException
::notSupported(__METHOD__
);
1293 * Returns the SQL bit AND comparison expression.
1295 * @param string $value1
1296 * @param string $value2
1300 public function getBitAndComparisonExpression($value1, $value2)
1302 return '(' . $value1 . ' & ' . $value2 . ')';
1306 * Returns the SQL bit OR comparison expression.
1308 * @param string $value1
1309 * @param string $value2
1313 public function getBitOrComparisonExpression($value1, $value2)
1315 return '(' . $value1 . ' | ' . $value2 . ')';
1319 * Returns the FOR UPDATE expression.
1323 public function getForUpdateSQL()
1325 return 'FOR UPDATE';
1329 * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
1331 * @param string $fromClause The FROM clause to append the hint for the given lock mode to.
1332 * @param integer|null $lockMode One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will
1333 * be appended to the FROM clause.
1337 public function appendLockHint($fromClause, $lockMode)
1343 * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock.
1345 * This defaults to the ANSI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database
1346 * vendors allow to lighten this constraint up to be a real read lock.
1350 public function getReadLockSQL()
1352 return $this->getForUpdateSQL();
1356 * Returns the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows.
1358 * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ANSI SQL standard.
1362 public function getWriteLockSQL()
1364 return $this->getForUpdateSQL();
1368 * Returns the SQL snippet to drop an existing database.
1370 * @param string $database The name of the database that should be dropped.
1374 public function getDropDatabaseSQL($database)
1376 return 'DROP DATABASE ' . $database;
1380 * Returns the SQL snippet to drop an existing table.
1382 * @param \Doctrine\DBAL\Schema\Table|string $table
1386 * @throws \InvalidArgumentException
1388 public function getDropTableSQL($table)
1392 if ($table instanceof Table
) {
1393 $table = $table->getQuotedName($this);
1394 } elseif (!is_string($table)) {
1395 throw new \
InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
1398 if (null !== $this->_eventManager
&& $this->_eventManager
->hasListeners(Events
::onSchemaDropTable
)) {
1399 $eventArgs = new SchemaDropTableEventArgs($tableArg, $this);
1400 $this->_eventManager
->dispatchEvent(Events
::onSchemaDropTable
, $eventArgs);
1402 if ($eventArgs->isDefaultPrevented()) {
1403 return $eventArgs->getSql();
1407 return 'DROP TABLE ' . $table;
1411 * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction.
1413 * @param \Doctrine\DBAL\Schema\Table|string $table
1417 public function getDropTemporaryTableSQL($table)
1419 return $this->getDropTableSQL($table);
1423 * Returns the SQL to drop an index from a table.
1425 * @param \Doctrine\DBAL\Schema\Index|string $index
1426 * @param \Doctrine\DBAL\Schema\Table|string $table
1430 * @throws \InvalidArgumentException
1432 public function getDropIndexSQL($index, $table = null)
1434 if ($index instanceof Index
) {
1435 $index = $index->getQuotedName($this);
1436 } elseif (!is_string($index)) {
1437 throw new \
InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
1440 return 'DROP INDEX ' . $index;
1444 * Returns the SQL to drop a constraint.
1446 * @param \Doctrine\DBAL\Schema\Constraint|string $constraint
1447 * @param \Doctrine\DBAL\Schema\Table|string $table
1451 public function getDropConstraintSQL($constraint, $table)
1453 if (! $constraint instanceof Constraint
) {
1454 $constraint = new Identifier($constraint);
1457 if (! $table instanceof Table
) {
1458 $table = new Identifier($table);
1461 $constraint = $constraint->getQuotedName($this);
1462 $table = $table->getQuotedName($this);
1464 return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint;
1468 * Returns the SQL to drop a foreign key.
1470 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey
1471 * @param \Doctrine\DBAL\Schema\Table|string $table
1475 public function getDropForeignKeySQL($foreignKey, $table)
1477 if (! $foreignKey instanceof ForeignKeyConstraint
) {
1478 $foreignKey = new Identifier($foreignKey);
1481 if (! $table instanceof Table
) {
1482 $table = new Identifier($table);
1485 $foreignKey = $foreignKey->getQuotedName($this);
1486 $table = $table->getQuotedName($this);
1488 return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey;
1492 * Returns the SQL statement(s) to create a table with the specified name, columns and constraints
1495 * @param \Doctrine\DBAL\Schema\Table $table
1496 * @param integer $createFlags
1498 * @return array The sequence of SQL statements.
1500 * @throws \Doctrine\DBAL\DBALException
1501 * @throws \InvalidArgumentException
1503 public function getCreateTableSQL(Table
$table, $createFlags = self
::CREATE_INDEXES
)
1505 if ( ! is_int($createFlags)) {
1506 throw new \
InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer.");
1509 if (count($table->getColumns()) === 0) {
1510 throw DBALException
::noColumnsSpecifiedForTable($table->getName());
1513 $tableName = $table->getQuotedName($this);
1514 $options = $table->getOptions();
1515 $options['uniqueConstraints'] = array();
1516 $options['indexes'] = array();
1517 $options['primary'] = array();
1519 if (($createFlags&self
::CREATE_INDEXES
) > 0) {
1520 foreach ($table->getIndexes() as $index) {
1521 /* @var $index Index */
1522 if ($index->isPrimary()) {
1523 $options['primary'] = $index->getQuotedColumns($this);
1524 $options['primary_index'] = $index;
1526 $options['indexes'][$index->getQuotedName($this)] = $index;
1531 $columnSql = array();
1534 foreach ($table->getColumns() as $column) {
1535 /* @var \Doctrine\DBAL\Schema\Column $column */
1537 if (null !== $this->_eventManager
&& $this->_eventManager
->hasListeners(Events
::onSchemaCreateTableColumn
)) {
1538 $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
1539 $this->_eventManager
->dispatchEvent(Events
::onSchemaCreateTableColumn
, $eventArgs);
1541 $columnSql = array_merge($columnSql, $eventArgs->getSql());
1543 if ($eventArgs->isDefaultPrevented()) {
1548 $columnData = $column->toArray();
1549 $columnData['name'] = $column->getQuotedName($this);
1550 $columnData['version'] = $column->hasPlatformOption("version") ?
$column->getPlatformOption('version') : false;
1551 $columnData['comment'] = $this->getColumnComment($column);
1553 if (strtolower($columnData['type']) == "string" && $columnData['length'] === null) {
1554 $columnData['length'] = 255;
1557 if (in_array($column->getName(), $options['primary'])) {
1558 $columnData['primary'] = true;
1561 $columns[$columnData['name']] = $columnData;
1564 if (($createFlags&self
::CREATE_FOREIGNKEYS
) > 0) {
1565 $options['foreignKeys'] = array();
1566 foreach ($table->getForeignKeys() as $fkConstraint) {
1567 $options['foreignKeys'][] = $fkConstraint;
1571 if (null !== $this->_eventManager
&& $this->_eventManager
->hasListeners(Events
::onSchemaCreateTable
)) {
1572 $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
1573 $this->_eventManager
->dispatchEvent(Events
::onSchemaCreateTable
, $eventArgs);
1575 if ($eventArgs->isDefaultPrevented()) {
1576 return array_merge($eventArgs->getSql(), $columnSql);
1580 $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
1581 if ($this->supportsCommentOnStatement()) {
1582 foreach ($table->getColumns() as $column) {
1583 $comment = $this->getColumnComment($column);
1585 if (null !== $comment && '' !== $comment) {
1586 $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment);
1591 return array_merge($sql, $columnSql);
1595 * @param string $tableName
1596 * @param string $columnName
1597 * @param string $comment
1601 public function getCommentOnColumnSQL($tableName, $columnName, $comment)
1603 $tableName = new Identifier($tableName);
1604 $columnName = new Identifier($columnName);
1605 $comment = $this->quoteStringLiteral($comment);
1607 return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) .
1612 * Returns the SQL used to create a table.
1614 * @param string $tableName
1615 * @param array $columns
1616 * @param array $options
1620 protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
1622 $columnListSql = $this->getColumnDeclarationListSQL($columns);
1624 if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
1625 foreach ($options['uniqueConstraints'] as $name => $definition) {
1626 $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
1630 if (isset($options['primary']) && ! empty($options['primary'])) {
1631 $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
1634 if (isset($options['indexes']) && ! empty($options['indexes'])) {
1635 foreach ($options['indexes'] as $index => $definition) {
1636 $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
1640 $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
1642 $check = $this->getCheckDeclarationSQL($columns);
1643 if ( ! empty($check)) {
1644 $query .= ', ' . $check;
1650 if (isset($options['foreignKeys'])) {
1651 foreach ((array) $options['foreignKeys'] as $definition) {
1652 $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
1662 public function getCreateTemporaryTableSnippetSQL()
1664 return "CREATE TEMPORARY TABLE";
1668 * Returns the SQL to create a sequence on this platform.
1670 * @param \Doctrine\DBAL\Schema\Sequence $sequence
1674 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1676 public function getCreateSequenceSQL(Sequence
$sequence)
1678 throw DBALException
::notSupported(__METHOD__
);
1682 * Returns the SQL to change a sequence on this platform.
1684 * @param \Doctrine\DBAL\Schema\Sequence $sequence
1688 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1690 public function getAlterSequenceSQL(Sequence
$sequence)
1692 throw DBALException
::notSupported(__METHOD__
);
1696 * Returns the SQL to create a constraint on a table on this platform.
1698 * @param \Doctrine\DBAL\Schema\Constraint $constraint
1699 * @param \Doctrine\DBAL\Schema\Table|string $table
1703 * @throws \InvalidArgumentException
1705 public function getCreateConstraintSQL(Constraint
$constraint, $table)
1707 if ($table instanceof Table
) {
1708 $table = $table->getQuotedName($this);
1711 $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this);
1713 $columnList = '('. implode(', ', $constraint->getQuotedColumns($this)) . ')';
1715 $referencesClause = '';
1716 if ($constraint instanceof Index
) {
1717 if ($constraint->isPrimary()) {
1718 $query .= ' PRIMARY KEY';
1719 } elseif ($constraint->isUnique()) {
1720 $query .= ' UNIQUE';
1722 throw new \
InvalidArgumentException(
1723 'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
1726 } elseif ($constraint instanceof ForeignKeyConstraint
) {
1727 $query .= ' FOREIGN KEY';
1729 $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) .
1730 ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')';
1732 $query .= ' '.$columnList.$referencesClause;
1738 * Returns the SQL to create an index on a table on this platform.
1740 * @param \Doctrine\DBAL\Schema\Index $index
1741 * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created.
1745 * @throws \InvalidArgumentException
1747 public function getCreateIndexSQL(Index
$index, $table)
1749 if ($table instanceof Table
) {
1750 $table = $table->getQuotedName($this);
1752 $name = $index->getQuotedName($this);
1753 $columns = $index->getQuotedColumns($this);
1755 if (count($columns) == 0) {
1756 throw new \
InvalidArgumentException("Incomplete definition. 'columns' required.");
1759 if ($index->isPrimary()) {
1760 return $this->getCreatePrimaryKeySQL($index, $table);
1763 $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
1764 $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index);
1770 * Adds condition for partial index.
1772 * @param \Doctrine\DBAL\Schema\Index $index
1776 protected function getPartialIndexSQL(Index
$index)
1778 if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
1779 return ' WHERE ' . $index->getOption('where');
1786 * Adds additional flags for index generation.
1788 * @param \Doctrine\DBAL\Schema\Index $index
1792 protected function getCreateIndexSQLFlags(Index
$index)
1794 return $index->isUnique() ?
'UNIQUE ' : '';
1798 * Returns the SQL to create an unnamed primary key constraint.
1800 * @param \Doctrine\DBAL\Schema\Index $index
1801 * @param \Doctrine\DBAL\Schema\Table|string $table
1805 public function getCreatePrimaryKeySQL(Index
$index, $table)
1807 return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
1811 * Returns the SQL to create a named schema.
1813 * @param string $schemaName
1816 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1818 public function getCreateSchemaSQL($schemaName)
1820 throw DBALException
::notSupported(__METHOD__
);
1824 * Quotes a string so that it can be safely used as a table or column name,
1825 * even if it is a reserved word of the platform. This also detects identifier
1826 * chains separated by dot and quotes them independently.
1828 * NOTE: Just because you CAN use quoted identifiers doesn't mean
1829 * you SHOULD use them. In general, they end up causing way more
1830 * problems than they solve.
1832 * @param string $str The identifier name to be quoted.
1834 * @return string The quoted identifier string.
1836 public function quoteIdentifier($str)
1838 if (strpos($str, ".") !== false) {
1839 $parts = array_map(array($this, "quoteSingleIdentifier"), explode(".", $str));
1841 return implode(".", $parts);
1844 return $this->quoteSingleIdentifier($str);
1848 * Quotes a single identifier (no dot chain separation).
1850 * @param string $str The identifier name to be quoted.
1852 * @return string The quoted identifier string.
1854 public function quoteSingleIdentifier($str)
1856 $c = $this->getIdentifierQuoteCharacter();
1858 return $c . str_replace($c, $c.$c, $str) . $c;
1862 * Returns the SQL to create a new foreign key.
1864 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key constraint.
1865 * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created.
1869 public function getCreateForeignKeySQL(ForeignKeyConstraint
$foreignKey, $table)
1871 if ($table instanceof Table
) {
1872 $table = $table->getQuotedName($this);
1875 $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
1881 * Gets the SQL statements for altering an existing table.
1883 * This method returns an array of SQL statements, since some platforms need several statements.
1885 * @param \Doctrine\DBAL\Schema\TableDiff $diff
1889 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
1891 public function getAlterTableSQL(TableDiff
$diff)
1893 throw DBALException
::notSupported(__METHOD__
);
1897 * @param \Doctrine\DBAL\Schema\Column $column
1898 * @param \Doctrine\DBAL\Schema\TableDiff $diff
1899 * @param array $columnSql
1903 protected function onSchemaAlterTableAddColumn(Column
$column, TableDiff
$diff, &$columnSql)
1905 if (null === $this->_eventManager
) {
1909 if ( ! $this->_eventManager
->hasListeners(Events
::onSchemaAlterTableAddColumn
)) {
1913 $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this);
1914 $this->_eventManager
->dispatchEvent(Events
::onSchemaAlterTableAddColumn
, $eventArgs);
1916 $columnSql = array_merge($columnSql, $eventArgs->getSql());
1918 return $eventArgs->isDefaultPrevented();
1922 * @param \Doctrine\DBAL\Schema\Column $column
1923 * @param \Doctrine\DBAL\Schema\TableDiff $diff
1924 * @param array $columnSql
1928 protected function onSchemaAlterTableRemoveColumn(Column
$column, TableDiff
$diff, &$columnSql)
1930 if (null === $this->_eventManager
) {
1934 if ( ! $this->_eventManager
->hasListeners(Events
::onSchemaAlterTableRemoveColumn
)) {
1938 $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this);
1939 $this->_eventManager
->dispatchEvent(Events
::onSchemaAlterTableRemoveColumn
, $eventArgs);
1941 $columnSql = array_merge($columnSql, $eventArgs->getSql());
1943 return $eventArgs->isDefaultPrevented();
1947 * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff
1948 * @param \Doctrine\DBAL\Schema\TableDiff $diff
1949 * @param array $columnSql
1953 protected function onSchemaAlterTableChangeColumn(ColumnDiff
$columnDiff, TableDiff
$diff, &$columnSql)
1955 if (null === $this->_eventManager
) {
1959 if ( ! $this->_eventManager
->hasListeners(Events
::onSchemaAlterTableChangeColumn
)) {
1963 $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this);
1964 $this->_eventManager
->dispatchEvent(Events
::onSchemaAlterTableChangeColumn
, $eventArgs);
1966 $columnSql = array_merge($columnSql, $eventArgs->getSql());
1968 return $eventArgs->isDefaultPrevented();
1972 * @param string $oldColumnName
1973 * @param \Doctrine\DBAL\Schema\Column $column
1974 * @param \Doctrine\DBAL\Schema\TableDiff $diff
1975 * @param array $columnSql
1979 protected function onSchemaAlterTableRenameColumn($oldColumnName, Column
$column, TableDiff
$diff, &$columnSql)
1981 if (null === $this->_eventManager
) {
1985 if ( ! $this->_eventManager
->hasListeners(Events
::onSchemaAlterTableRenameColumn
)) {
1989 $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this);
1990 $this->_eventManager
->dispatchEvent(Events
::onSchemaAlterTableRenameColumn
, $eventArgs);
1992 $columnSql = array_merge($columnSql, $eventArgs->getSql());
1994 return $eventArgs->isDefaultPrevented();
1998 * @param \Doctrine\DBAL\Schema\TableDiff $diff
2003 protected function onSchemaAlterTable(TableDiff
$diff, &$sql)
2005 if (null === $this->_eventManager
) {
2009 if ( ! $this->_eventManager
->hasListeners(Events
::onSchemaAlterTable
)) {
2013 $eventArgs = new SchemaAlterTableEventArgs($diff, $this);
2014 $this->_eventManager
->dispatchEvent(Events
::onSchemaAlterTable
, $eventArgs);
2016 $sql = array_merge($sql, $eventArgs->getSql());
2018 return $eventArgs->isDefaultPrevented();
2022 * @param \Doctrine\DBAL\Schema\TableDiff $diff
2026 protected function getPreAlterTableIndexForeignKeySQL(TableDiff
$diff)
2028 $tableName = $diff->getName($this)->getQuotedName($this);
2031 if ($this->supportsForeignKeyConstraints()) {
2032 foreach ($diff->removedForeignKeys
as $foreignKey) {
2033 $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2035 foreach ($diff->changedForeignKeys
as $foreignKey) {
2036 $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
2040 foreach ($diff->removedIndexes
as $index) {
2041 $sql[] = $this->getDropIndexSQL($index, $tableName);
2043 foreach ($diff->changedIndexes
as $index) {
2044 $sql[] = $this->getDropIndexSQL($index, $tableName);
2051 * @param \Doctrine\DBAL\Schema\TableDiff $diff
2055 protected function getPostAlterTableIndexForeignKeySQL(TableDiff
$diff)
2057 $tableName = (false !== $diff->newName
)
2058 ?
$diff->getNewName()->getQuotedName($this)
2059 : $diff->getName($this)->getQuotedName($this);
2063 if ($this->supportsForeignKeyConstraints()) {
2064 foreach ($diff->addedForeignKeys
as $foreignKey) {
2065 $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2068 foreach ($diff->changedForeignKeys
as $foreignKey) {
2069 $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
2073 foreach ($diff->addedIndexes
as $index) {
2074 $sql[] = $this->getCreateIndexSQL($index, $tableName);
2077 foreach ($diff->changedIndexes
as $index) {
2078 $sql[] = $this->getCreateIndexSQL($index, $tableName);
2081 foreach ($diff->renamedIndexes
as $oldIndexName => $index) {
2082 $oldIndexName = new Identifier($oldIndexName);
2085 $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName)
2093 * Returns the SQL for renaming an index on a table.
2095 * @param string $oldIndexName The name of the index to rename from.
2096 * @param \Doctrine\DBAL\Schema\Index $index The definition of the index to rename to.
2097 * @param string $tableName The table to rename the given index on.
2099 * @return array The sequence of SQL statements for renaming the given index.
2101 protected function getRenameIndexSQL($oldIndexName, Index
$index, $tableName)
2104 $this->getDropIndexSQL($oldIndexName, $tableName),
2105 $this->getCreateIndexSQL($index, $tableName)
2110 * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions.
2112 * @param \Doctrine\DBAL\Schema\TableDiff $diff
2116 protected function _getAlterTableIndexForeignKeySQL(TableDiff
$diff)
2118 return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff));
2122 * Gets declaration of a number of fields in bulk.
2124 * @param array $fields A multidimensional associative array.
2125 * The first dimension determines the field name, while the second
2126 * dimension is keyed with the name of the properties
2127 * of the field being declared as array indexes. Currently, the types
2128 * of supported field properties are as follows:
2131 * Integer value that determines the maximum length of the text
2132 * field. If this argument is missing the field should be
2133 * declared to have the longest length allowed by the DBMS.
2136 * Text value to be used as default for this field.
2139 * Boolean flag that indicates whether this field is constrained
2140 * to not be set to null.
2142 * Text value with the default CHARACTER SET for this field.
2144 * Text value with the default COLLATION for this field.
2150 public function getColumnDeclarationListSQL(array $fields)
2152 $queryFields = array();
2154 foreach ($fields as $fieldName => $field) {
2155 $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field);
2158 return implode(', ', $queryFields);
2162 * Obtains DBMS specific SQL code portion needed to declare a generic type
2163 * field to be used in statements like CREATE TABLE.
2165 * @param string $name The name the field to be declared.
2166 * @param array $field An associative array with the name of the properties
2167 * of the field being declared as array indexes. Currently, the types
2168 * of supported field properties are as follows:
2171 * Integer value that determines the maximum length of the text
2172 * field. If this argument is missing the field should be
2173 * declared to have the longest length allowed by the DBMS.
2176 * Text value to be used as default for this field.
2179 * Boolean flag that indicates whether this field is constrained
2180 * to not be set to null.
2182 * Text value with the default CHARACTER SET for this field.
2184 * Text value with the default COLLATION for this field.
2188 * column check constraint
2190 * a string that defines the complete column
2192 * @return string DBMS specific SQL code portion that should be used to declare the column.
2194 public function getColumnDeclarationSQL($name, array $field)
2196 if (isset($field['columnDefinition'])) {
2197 $columnDef = $this->getCustomTypeDeclarationSQL($field);
2199 $default = $this->getDefaultValueDeclarationSQL($field);
2201 $charset = (isset($field['charset']) && $field['charset']) ?
2202 ' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : '';
2204 $collation = (isset($field['collation']) && $field['collation']) ?
2205 ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
2207 $notnull = (isset($field['notnull']) && $field['notnull']) ?
' NOT NULL' : '';
2209 $unique = (isset($field['unique']) && $field['unique']) ?
2210 ' ' . $this->getUniqueFieldDeclarationSQL() : '';
2212 $check = (isset($field['check']) && $field['check']) ?
2213 ' ' . $field['check'] : '';
2215 $typeDecl = $field['type']->getSqlDeclaration($field, $this);
2216 $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
2218 if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') {
2219 $columnDef .= " COMMENT " . $this->quoteStringLiteral($field['comment']);
2223 return $name . ' ' . $columnDef;
2227 * Returns the SQL snippet that declares a floating point column of arbitrary precision.
2229 * @param array $columnDef
2233 public function getDecimalTypeDeclarationSQL(array $columnDef)
2235 $columnDef['precision'] = ( ! isset($columnDef['precision']) ||
empty($columnDef['precision']))
2236 ?
10 : $columnDef['precision'];
2237 $columnDef['scale'] = ( ! isset($columnDef['scale']) ||
empty($columnDef['scale']))
2238 ?
0 : $columnDef['scale'];
2240 return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')';
2244 * Obtains DBMS specific SQL code portion needed to set a default value
2245 * declaration to be used in statements like CREATE TABLE.
2247 * @param array $field The field definition array.
2249 * @return string DBMS specific SQL code portion needed to set a default value.
2251 public function getDefaultValueDeclarationSQL($field)
2253 $default = empty($field['notnull']) ?
' DEFAULT NULL' : '';
2255 if (isset($field['default'])) {
2256 $default = " DEFAULT '".$field['default']."'";
2257 if (isset($field['type'])) {
2258 if (in_array((string) $field['type'], array("Integer", "BigInt", "SmallInt"))) {
2259 $default = " DEFAULT ".$field['default'];
2260 } elseif (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) {
2261 $default = " DEFAULT ".$this->getCurrentTimestampSQL();
2262 } elseif ((string) $field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) {
2263 $default = " DEFAULT ".$this->getCurrentTimeSQL();
2264 } elseif ((string) $field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) {
2265 $default = " DEFAULT ".$this->getCurrentDateSQL();
2266 } elseif ((string) $field['type'] == 'Boolean') {
2267 $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'";
2276 * Obtains DBMS specific SQL code portion needed to set a CHECK constraint
2277 * declaration to be used in statements like CREATE TABLE.
2279 * @param array $definition The check definition.
2281 * @return string DBMS specific SQL code portion needed to set a CHECK constraint.
2283 public function getCheckDeclarationSQL(array $definition)
2285 $constraints = array();
2286 foreach ($definition as $field => $def) {
2287 if (is_string($def)) {
2288 $constraints[] = 'CHECK (' . $def . ')';
2290 if (isset($def['min'])) {
2291 $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')';
2294 if (isset($def['max'])) {
2295 $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')';
2300 return implode(', ', $constraints);
2304 * Obtains DBMS specific SQL code portion needed to set a unique
2305 * constraint declaration to be used in statements like CREATE TABLE.
2307 * @param string $name The name of the unique constraint.
2308 * @param \Doctrine\DBAL\Schema\Index $index The index definition.
2310 * @return string DBMS specific SQL code portion needed to set a constraint.
2312 * @throws \InvalidArgumentException
2314 public function getUniqueConstraintDeclarationSQL($name, Index
$index)
2316 $columns = $index->getQuotedColumns($this);
2317 $name = new Identifier($name);
2319 if (count($columns) === 0) {
2320 throw new \
InvalidArgumentException("Incomplete definition. 'columns' required.");
2323 return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE ('
2324 . $this->getIndexFieldDeclarationListSQL($columns)
2325 . ')' . $this->getPartialIndexSQL($index);
2329 * Obtains DBMS specific SQL code portion needed to set an index
2330 * declaration to be used in statements like CREATE TABLE.
2332 * @param string $name The name of the index.
2333 * @param \Doctrine\DBAL\Schema\Index $index The index definition.
2335 * @return string DBMS specific SQL code portion needed to set an index.
2337 * @throws \InvalidArgumentException
2339 public function getIndexDeclarationSQL($name, Index
$index)
2341 $columns = $index->getQuotedColumns($this);
2342 $name = new Identifier($name);
2344 if (count($columns) === 0) {
2345 throw new \
InvalidArgumentException("Incomplete definition. 'columns' required.");
2348 return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' ('
2349 . $this->getIndexFieldDeclarationListSQL($columns)
2350 . ')' . $this->getPartialIndexSQL($index);
2354 * Obtains SQL code portion needed to create a custom column,
2355 * e.g. when a field has the "columnDefinition" keyword.
2356 * Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate.
2358 * @param array $columnDef
2362 public function getCustomTypeDeclarationSQL(array $columnDef)
2364 return $columnDef['columnDefinition'];
2368 * Obtains DBMS specific SQL code portion needed to set an index
2369 * declaration to be used in statements like CREATE TABLE.
2371 * @param array $fields
2375 public function getIndexFieldDeclarationListSQL(array $fields)
2379 foreach ($fields as $field => $definition) {
2380 if (is_array($definition)) {
2383 $ret[] = $definition;
2387 return implode(', ', $ret);
2391 * Returns the required SQL string that fits between CREATE ... TABLE
2392 * to create the table as a temporary table.
2394 * Should be overridden in driver classes to return the correct string for the
2395 * specific database type.
2397 * The default is to return the string "TEMPORARY" - this will result in a
2398 * SQL error for any database that does not support temporary tables, or that
2399 * requires a different SQL command from "CREATE TEMPORARY TABLE".
2401 * @return string The string required to be placed between "CREATE" and "TABLE"
2402 * to generate a temporary table, if possible.
2404 public function getTemporaryTableSQL()
2410 * Some vendors require temporary table names to be qualified specially.
2412 * @param string $tableName
2416 public function getTemporaryTableName($tableName)
2422 * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2423 * of a field declaration to be used in statements like CREATE TABLE.
2425 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2427 * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2428 * of a field declaration.
2430 public function getForeignKeyDeclarationSQL(ForeignKeyConstraint
$foreignKey)
2432 $sql = $this->getForeignKeyBaseDeclarationSQL($foreignKey);
2433 $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey);
2439 * Returns the FOREIGN KEY query section dealing with non-standard options
2440 * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
2442 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key definition.
2446 public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint
$foreignKey)
2449 if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
2450 $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
2452 if ($foreignKey->hasOption('onDelete')) {
2453 $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
2460 * Returns the given referential action in uppercase if valid, otherwise throws an exception.
2462 * @param string $action The foreign key referential action.
2466 * @throws \InvalidArgumentException if unknown referential action given
2468 public function getForeignKeyReferentialActionSQL($action)
2470 $upper = strtoupper($action);
2479 throw new \
InvalidArgumentException('Invalid foreign key action: ' . $upper);
2484 * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
2485 * of a field declaration to be used in statements like CREATE TABLE.
2487 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey
2491 * @throws \InvalidArgumentException
2493 public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint
$foreignKey)
2496 if (strlen($foreignKey->getName())) {
2497 $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' ';
2499 $sql .= 'FOREIGN KEY (';
2501 if (count($foreignKey->getLocalColumns()) === 0) {
2502 throw new \
InvalidArgumentException("Incomplete definition. 'local' required.");
2504 if (count($foreignKey->getForeignColumns()) === 0) {
2505 throw new \
InvalidArgumentException("Incomplete definition. 'foreign' required.");
2507 if (strlen($foreignKey->getForeignTableName()) === 0) {
2508 throw new \
InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
2511 $sql .= implode(', ', $foreignKey->getQuotedLocalColumns($this))
2513 . $foreignKey->getQuotedForeignTableName($this) . ' ('
2514 . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')';
2520 * Obtains DBMS specific SQL code portion needed to set the UNIQUE constraint
2521 * of a field declaration to be used in statements like CREATE TABLE.
2523 * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
2524 * of a field declaration.
2526 public function getUniqueFieldDeclarationSQL()
2532 * Obtains DBMS specific SQL code portion needed to set the CHARACTER SET
2533 * of a field declaration to be used in statements like CREATE TABLE.
2535 * @param string $charset The name of the charset.
2537 * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
2538 * of a field declaration.
2540 public function getColumnCharsetDeclarationSQL($charset)
2546 * Obtains DBMS specific SQL code portion needed to set the COLLATION
2547 * of a field declaration to be used in statements like CREATE TABLE.
2549 * @param string $collation The name of the collation.
2551 * @return string DBMS specific SQL code portion needed to set the COLLATION
2552 * of a field declaration.
2554 public function getColumnCollationDeclarationSQL($collation)
2556 return $this->supportsColumnCollation() ?
'COLLATE ' . $collation : '';
2560 * Whether the platform prefers sequences for ID generation.
2561 * Subclasses should override this method to return TRUE if they prefer sequences.
2565 public function prefersSequences()
2571 * Whether the platform prefers identity columns (eg. autoincrement) for ID generation.
2572 * Subclasses should override this method to return TRUE if they prefer identity columns.
2576 public function prefersIdentityColumns()
2582 * Some platforms need the boolean values to be converted.
2584 * The default conversion in this implementation converts to integers (false => 0, true => 1).
2586 * Note: if the input is not a boolean the original input might be returned.
2588 * There are two contexts when converting booleans: Literals and Prepared Statements.
2589 * This method should handle the literal case
2591 * @param mixed $item A boolean or an array of them.
2593 * @return mixed A boolean database value or an array of them.
2595 public function convertBooleans($item)
2597 if (is_array($item)) {
2598 foreach ($item as $k => $value) {
2599 if (is_bool($value)) {
2600 $item[$k] = (int) $value;
2603 } elseif (is_bool($item)) {
2604 $item = (int) $item;
2611 * Some platforms have boolean literals that needs to be correctly converted
2613 * The default conversion tries to convert value into bool "(bool)$item"
2615 * @param mixed $item
2619 public function convertFromBoolean($item)
2621 return null === $item ?
null: (bool) $item ;
2625 * This method should handle the prepared statements case. When there is no
2626 * distinction, it's OK to use the same method.
2628 * Note: if the input is not a boolean the original input might be returned.
2630 * @param mixed $item A boolean or an array of them.
2632 * @return mixed A boolean database value or an array of them.
2634 public function convertBooleansToDatabaseValue($item)
2636 return $this->convertBooleans($item);
2640 * Returns the SQL specific for the platform to get the current date.
2644 public function getCurrentDateSQL()
2646 return 'CURRENT_DATE';
2650 * Returns the SQL specific for the platform to get the current time.
2654 public function getCurrentTimeSQL()
2656 return 'CURRENT_TIME';
2660 * Returns the SQL specific for the platform to get the current timestamp
2664 public function getCurrentTimestampSQL()
2666 return 'CURRENT_TIMESTAMP';
2670 * Returns the SQL for a given transaction isolation level Connection constant.
2672 * @param integer $level
2676 * @throws \InvalidArgumentException
2678 protected function _getTransactionIsolationLevelSQL($level)
2681 case Connection
::TRANSACTION_READ_UNCOMMITTED
:
2682 return 'READ UNCOMMITTED';
2683 case Connection
::TRANSACTION_READ_COMMITTED
:
2684 return 'READ COMMITTED';
2685 case Connection
::TRANSACTION_REPEATABLE_READ
:
2686 return 'REPEATABLE READ';
2687 case Connection
::TRANSACTION_SERIALIZABLE
:
2688 return 'SERIALIZABLE';
2690 throw new \
InvalidArgumentException('Invalid isolation level:' . $level);
2697 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2699 public function getListDatabasesSQL()
2701 throw DBALException
::notSupported(__METHOD__
);
2705 * Returns the SQL statement for retrieving the namespaces defined in the database.
2709 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2711 public function getListNamespacesSQL()
2713 throw DBALException
::notSupported(__METHOD__
);
2717 * @param string $database
2721 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2723 public function getListSequencesSQL($database)
2725 throw DBALException
::notSupported(__METHOD__
);
2729 * @param string $table
2733 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2735 public function getListTableConstraintsSQL($table)
2737 throw DBALException
::notSupported(__METHOD__
);
2741 * @param string $table
2742 * @param string|null $database
2746 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2748 public function getListTableColumnsSQL($table, $database = null)
2750 throw DBALException
::notSupported(__METHOD__
);
2756 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2758 public function getListTablesSQL()
2760 throw DBALException
::notSupported(__METHOD__
);
2766 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2768 public function getListUsersSQL()
2770 throw DBALException
::notSupported(__METHOD__
);
2774 * Returns the SQL to list all views of a database or user.
2776 * @param string $database
2780 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2782 public function getListViewsSQL($database)
2784 throw DBALException
::notSupported(__METHOD__
);
2788 * Returns the list of indexes for the current database.
2790 * The current database parameter is optional but will always be passed
2791 * when using the SchemaManager API and is the database the given table is in.
2793 * Attention: Some platforms only support currentDatabase when they
2794 * are connected with that database. Cross-database information schema
2795 * requests may be impossible.
2797 * @param string $table
2798 * @param string $currentDatabase
2802 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2804 public function getListTableIndexesSQL($table, $currentDatabase = null)
2806 throw DBALException
::notSupported(__METHOD__
);
2810 * @param string $table
2814 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2816 public function getListTableForeignKeysSQL($table)
2818 throw DBALException
::notSupported(__METHOD__
);
2822 * @param string $name
2823 * @param string $sql
2827 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2829 public function getCreateViewSQL($name, $sql)
2831 throw DBALException
::notSupported(__METHOD__
);
2835 * @param string $name
2839 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2841 public function getDropViewSQL($name)
2843 throw DBALException
::notSupported(__METHOD__
);
2847 * Returns the SQL snippet to drop an existing sequence.
2849 * @param Sequence|string $sequence
2853 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2855 public function getDropSequenceSQL($sequence)
2857 throw DBALException
::notSupported(__METHOD__
);
2861 * @param string $sequenceName
2865 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2867 public function getSequenceNextValSQL($sequenceName)
2869 throw DBALException
::notSupported(__METHOD__
);
2873 * Returns the SQL to create a new database.
2875 * @param string $database The name of the database that should be created.
2879 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2881 public function getCreateDatabaseSQL($database)
2883 throw DBALException
::notSupported(__METHOD__
);
2887 * Returns the SQL to set the transaction isolation level.
2889 * @param integer $level
2893 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2895 public function getSetTransactionIsolationSQL($level)
2897 throw DBALException
::notSupported(__METHOD__
);
2901 * Obtains DBMS specific SQL to be used to create datetime fields in
2902 * statements like CREATE TABLE.
2904 * @param array $fieldDeclaration
2908 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2910 public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
2912 throw DBALException
::notSupported(__METHOD__
);
2916 * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields.
2918 * @param array $fieldDeclaration
2922 public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
2924 return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration);
2929 * Obtains DBMS specific SQL to be used to create date fields in statements
2930 * like CREATE TABLE.
2932 * @param array $fieldDeclaration
2936 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2938 public function getDateTypeDeclarationSQL(array $fieldDeclaration)
2940 throw DBALException
::notSupported(__METHOD__
);
2944 * Obtains DBMS specific SQL to be used to create time fields in statements
2945 * like CREATE TABLE.
2947 * @param array $fieldDeclaration
2951 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2953 public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
2955 throw DBALException
::notSupported(__METHOD__
);
2959 * @param array $fieldDeclaration
2963 public function getFloatDeclarationSQL(array $fieldDeclaration)
2965 return 'DOUBLE PRECISION';
2969 * Gets the default transaction isolation level of the platform.
2971 * @return integer The default isolation level.
2973 * @see Doctrine\DBAL\Connection\TRANSACTION_* constants.
2975 public function getDefaultTransactionIsolationLevel()
2977 return Connection
::TRANSACTION_READ_COMMITTED
;
2980 /* supports*() methods */
2983 * Whether the platform supports sequences.
2987 public function supportsSequences()
2993 * Whether the platform supports identity columns.
2995 * Identity columns are columns that receive an auto-generated value from the
2996 * database on insert of a row.
3000 public function supportsIdentityColumns()
3006 * Whether the platform emulates identity columns through sequences.
3008 * Some platforms that do not support identity columns natively
3009 * but support sequences can emulate identity columns by using
3014 public function usesSequenceEmulatedIdentityColumns()
3020 * Returns the name of the sequence for a particular identity column in a particular table.
3022 * @param string $tableName The name of the table to return the sequence name for.
3023 * @param string $columnName The name of the identity column in the table to return the sequence name for.
3027 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3029 * @see usesSequenceEmulatedIdentityColumns
3031 public function getIdentitySequenceName($tableName, $columnName)
3033 throw DBALException
::notSupported(__METHOD__
);
3037 * Whether the platform supports indexes.
3041 public function supportsIndexes()
3047 * Whether the platform supports partial indexes.
3051 public function supportsPartialIndexes()
3057 * Whether the platform supports altering tables.
3061 public function supportsAlterTable()
3067 * Whether the platform supports transactions.
3071 public function supportsTransactions()
3077 * Whether the platform supports savepoints.
3081 public function supportsSavepoints()
3087 * Whether the platform supports releasing savepoints.
3091 public function supportsReleaseSavepoints()
3093 return $this->supportsSavepoints();
3097 * Whether the platform supports primary key constraints.
3101 public function supportsPrimaryConstraints()
3107 * Whether the platform supports foreign key constraints.
3111 public function supportsForeignKeyConstraints()
3117 * Whether this platform supports onUpdate in foreign key constraints.
3121 public function supportsForeignKeyOnUpdate()
3123 return ($this->supportsForeignKeyConstraints() && true);
3127 * Whether the platform supports database schemas.
3131 public function supportsSchemas()
3137 * Whether this platform can emulate schemas.
3139 * Platforms that either support or emulate schemas don't automatically
3140 * filter a schema for the namespaced elements in {@link
3141 * AbstractManager#createSchema}.
3145 public function canEmulateSchemas()
3151 * Returns the default schema name.
3155 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3157 public function getDefaultSchemaName()
3159 throw DBALException
::notSupported(__METHOD__
);
3163 * Whether this platform supports create database.
3165 * Some databases don't allow to create and drop databases at all or only with certain tools.
3169 public function supportsCreateDropDatabase()
3175 * Whether the platform supports getting the affected rows of a recent update/delete type query.
3179 public function supportsGettingAffectedRows()
3185 * Whether this platform support to add inline column comments as postfix.
3189 public function supportsInlineColumnComments()
3195 * Whether this platform support the proprietary syntax "COMMENT ON asset".
3199 public function supportsCommentOnStatement()
3205 * Does this platform have native guid type.
3209 public function hasNativeGuidType()
3215 * Does this platform have native JSON type.
3219 public function hasNativeJsonType()
3226 * @todo Remove in 3.0
3228 public function getIdentityColumnNullInsertSQL()
3234 * Whether this platform supports views.
3238 public function supportsViews()
3244 * Does this platform support column collation?
3248 public function supportsColumnCollation()
3254 * Gets the format string, as accepted by the date() function, that describes
3255 * the format of a stored datetime value of this platform.
3257 * @return string The format string.
3259 public function getDateTimeFormatString()
3261 return 'Y-m-d H:i:s';
3265 * Gets the format string, as accepted by the date() function, that describes
3266 * the format of a stored datetime with timezone value of this platform.
3268 * @return string The format string.
3270 public function getDateTimeTzFormatString()
3272 return 'Y-m-d H:i:s';
3276 * Gets the format string, as accepted by the date() function, that describes
3277 * the format of a stored date value of this platform.
3279 * @return string The format string.
3281 public function getDateFormatString()
3287 * Gets the format string, as accepted by the date() function, that describes
3288 * the format of a stored time value of this platform.
3290 * @return string The format string.
3292 public function getTimeFormatString()
3298 * Adds an driver-specific LIMIT clause to the query.
3300 * @param string $query
3301 * @param integer|null $limit
3302 * @param integer|null $offset
3306 * @throws DBALException
3308 final public function modifyLimitQuery($query, $limit, $offset = null)
3310 if ($limit !== null) {
3311 $limit = (int) $limit;
3314 if ($offset !== null) {
3315 $offset = (int) $offset;
3318 throw new DBALException("LIMIT argument offset=$offset is not valid");
3320 if ($offset > 0 && ! $this->supportsLimitOffset()) {
3321 throw new DBALException(sprintf("Platform %s does not support offset values in limit queries.", $this->getName()));
3325 return $this->doModifyLimitQuery($query, $limit, $offset);
3329 * Adds an driver-specific LIMIT clause to the query.
3331 * @param string $query
3332 * @param integer|null $limit
3333 * @param integer|null $offset
3337 protected function doModifyLimitQuery($query, $limit, $offset)
3339 if ($limit !== null) {
3340 $query .= ' LIMIT ' . $limit;
3343 if ($offset !== null) {
3344 $query .= ' OFFSET ' . $offset;
3351 * Whether the database platform support offsets in modify limit clauses.
3355 public function supportsLimitOffset()
3361 * Gets the character casing of a column in an SQL result set of this platform.
3363 * @param string $column The column name for which to get the correct character casing.
3365 * @return string The column name in the character casing used in SQL result sets.
3367 public function getSQLResultCasing($column)
3373 * Makes any fixes to a name of a schema element (table, sequence, ...) that are required
3374 * by restrictions of the platform, like a maximum length.
3376 * @param string $schemaElementName
3380 public function fixSchemaElementName($schemaElementName)
3382 return $schemaElementName;
3386 * Maximum length of any given database identifier, like tables or column names.
3390 public function getMaxIdentifierLength()
3396 * Returns the insert SQL for an empty insert statement.
3398 * @param string $tableName
3399 * @param string $identifierColumnName
3403 public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
3405 return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)';
3409 * Generates a Truncate Table SQL statement for a given table.
3411 * Cascade is not supported on many platforms but would optionally cascade the truncate by
3412 * following the foreign keys.
3414 * @param string $tableName
3415 * @param boolean $cascade
3419 public function getTruncateTableSQL($tableName, $cascade = false)
3421 $tableIdentifier = new Identifier($tableName);
3423 return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this);
3427 * This is for test reasons, many vendors have special requirements for dummy statements.
3431 public function getDummySelectSQL()
3437 * Returns the SQL to create a new savepoint.
3439 * @param string $savepoint
3443 public function createSavePoint($savepoint)
3445 return 'SAVEPOINT ' . $savepoint;
3449 * Returns the SQL to release a savepoint.
3451 * @param string $savepoint
3455 public function releaseSavePoint($savepoint)
3457 return 'RELEASE SAVEPOINT ' . $savepoint;
3461 * Returns the SQL to rollback a savepoint.
3463 * @param string $savepoint
3467 public function rollbackSavePoint($savepoint)
3469 return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
3473 * Returns the keyword list instance of this platform.
3475 * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList
3477 * @throws \Doctrine\DBAL\DBALException If no keyword list is specified.
3479 final public function getReservedKeywordsList()
3481 // Check for an existing instantiation of the keywords class.
3482 if ($this->_keywords
) {
3483 return $this->_keywords
;
3486 $class = $this->getReservedKeywordsClass();
3487 $keywords = new $class;
3488 if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList
) {
3489 throw DBALException
::notSupported(__METHOD__
);
3492 // Store the instance so it doesn't need to be generated on every request.
3493 $this->_keywords
= $keywords;
3499 * Returns the class name of the reserved keywords list.
3503 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
3505 protected function getReservedKeywordsClass()
3507 throw DBALException
::notSupported(__METHOD__
);
3511 * Quotes a literal string.
3512 * This method is NOT meant to fix SQL injections!
3513 * It is only meant to escape this platform's string literal
3514 * quote character inside the given literal string.
3516 * @param string $str The literal string to be quoted.
3518 * @return string The quoted literal string.
3520 public function quoteStringLiteral($str)
3522 $c = $this->getStringLiteralQuoteCharacter();
3524 return $c . str_replace($c, $c . $c, $str) . $c;
3528 * Gets the character used for string literal quoting.
3532 public function getStringLiteralQuoteCharacter()