composer package updates
[openemr.git] / vendor / doctrine / dbal / lib / Doctrine / DBAL / Platforms / AbstractPlatform.php
bloba86980dcf6b9e342699eb4ce6b0578f0efb6113a
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.
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;
46 /**
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
52 * @since 2.0
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
62 /**
63 * @var integer
65 const CREATE_INDEXES = 1;
67 /**
68 * @var integer
70 const CREATE_FOREIGNKEYS = 2;
72 /**
73 * @var string
75 const DATE_INTERVAL_UNIT_SECOND = 'SECOND';
77 /**
78 * @var string
80 const DATE_INTERVAL_UNIT_MINUTE = 'MINUTE';
82 /**
83 * @var string
85 const DATE_INTERVAL_UNIT_HOUR = 'HOUR';
87 /**
88 * @var string
90 const DATE_INTERVAL_UNIT_DAY = 'DAY';
92 /**
93 * @var string
95 const DATE_INTERVAL_UNIT_WEEK = 'WEEK';
97 /**
98 * @var string
100 const DATE_INTERVAL_UNIT_MONTH = 'MONTH';
103 * @var string
105 const DATE_INTERVAL_UNIT_QUARTER = 'QUARTER';
108 * @var string
110 const DATE_INTERVAL_UNIT_YEAR = 'YEAR';
113 * @var integer
115 const TRIM_UNSPECIFIED = 0;
118 * @var integer
120 const TRIM_LEADING = 1;
123 * @var integer
125 const TRIM_TRAILING = 2;
128 * @var integer
130 const TRIM_BOTH = 3;
133 * @var array|null
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.
141 * @var array|null
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;
158 * Constructor.
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
189 * @return string
191 abstract public function getBooleanTypeDeclarationSQL(array $columnDef);
194 * Returns the SQL snippet that declares a 4 byte integer column.
196 * @param array $columnDef
198 * @return string
200 abstract public function getIntegerTypeDeclarationSQL(array $columnDef);
203 * Returns the SQL snippet that declares an 8 byte integer column.
205 * @param array $columnDef
207 * @return string
209 abstract public function getBigIntTypeDeclarationSQL(array $columnDef);
212 * Returns the SQL snippet that declares a 2 byte integer column.
214 * @param array $columnDef
216 * @return string
218 abstract public function getSmallIntTypeDeclarationSQL(array $columnDef);
221 * Returns the SQL snippet that declares common properties of an integer column.
223 * @param array $columnDef
225 * @return string
227 abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef);
230 * Lazy load Doctrine Type Mappings.
232 * @return void
234 abstract protected function initializeDoctrineTypeMappings();
237 * Initializes Doctrine Type Mappings with the platform defaults
238 * and with all additional type mappings.
240 * @return void
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
258 * @return string
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.
280 * @return string
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
305 * @return string
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
323 * @return string
325 public function getJsonTypeDeclarationSQL(array $field)
327 return $this->getClobTypeDeclarationSQL($field);
331 * @param integer $length
332 * @param boolean $fixed
334 * @return string
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.
349 * @return string
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
363 * @return string
365 abstract public function getClobTypeDeclarationSQL(array $field);
368 * Returns the SQL Snippet used to declare a BLOB column type.
370 * @param array $field
372 * @return string
374 abstract public function getBlobTypeDeclarationSQL(array $field);
377 * Gets the name of the platform.
379 * @return string
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
410 * @return string
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
434 * @return boolean
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.
450 * @return void
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
470 * @return boolean
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
486 * @return void
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
502 * @return string
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
514 * @return string
516 protected function getColumnComment(Column $column)
518 $comment = $column->getComment();
520 if ($this->isCommentedDoctrineType($column->getType())) {
521 $comment .= $this->getDoctrineTypeComment($column->getType());
524 return $comment;
528 * Gets the character used for identifier quoting.
530 * @return string
532 public function getIdentifierQuoteCharacter()
534 return '"';
538 * Gets the string portion that starts an SQL comment.
540 * @return string
542 public function getSqlCommentStartString()
544 return "--";
548 * Gets the string portion that ends an SQL comment.
550 * @return string
552 public function getSqlCommentEndString()
554 return "\n";
558 * Gets the maximum length of a varchar field.
560 * @return integer
562 public function getVarcharMaxLength()
564 return 4000;
568 * Gets the default length of a varchar field.
570 * @return integer
572 public function getVarcharDefaultLength()
574 return 255;
578 * Gets the maximum length of a binary field.
580 * @return integer
582 public function getBinaryMaxLength()
584 return 4000;
588 * Gets the default length of a binary field.
590 * @return integer
592 public function getBinaryDefaultLength()
594 return 255;
598 * Gets all SQL wildcard characters of the platform.
600 * @return array
602 public function getWildcards()
604 return array('%', '_');
608 * Returns the regular expression operator.
610 * @return string
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.
622 * @return string
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 . ')';
693 // scalar functions
696 * Returns the SQL snippet to get the md5 sum of a field.
698 * Note: Not SQL92, but common functionality.
700 * @param string $column
702 * @return string
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
714 * @return string
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
739 * @return string
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
752 * @return string
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.
766 * @return string
768 public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
770 $expression = '';
772 switch ($pos) {
773 case self::TRIM_LEADING:
774 $expression = 'LEADING ';
775 break;
777 case self::TRIM_TRAILING:
778 $expression = 'TRAILING ';
779 break;
781 case self::TRIM_BOTH:
782 $expression = 'BOTH ';
783 break;
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.
802 * @return string
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.
814 * @return string
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.
827 * @return string
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.
840 * @return string
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.
854 * @return string
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.
866 * @return string
868 public function getNowExpression()
870 return 'NOW()';
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.
884 * @return string
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.
900 * @return string
902 public function getConcatExpression()
904 return join(' || ', func_get_args());
908 * Returns the SQL for a logical not.
910 * Example:
911 * <code>
912 * $q = new Doctrine_Query();
913 * $e = $q->expr;
914 * $q->select('*')->from('table')
915 * ->where($e->eq('id', $e->not('null'));
916 * </code>
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
976 * @return string
978 public function getAcosExpression($value)
980 return 'ACOS(' . $value . ')';
984 * Returns the SQL to get the sine of a value.
986 * @param string $value
988 * @return string
990 public function getSinExpression($value)
992 return 'SIN(' . $value . ')';
996 * Returns the SQL to get the PI value.
998 * @return string
1000 public function getPiExpression()
1002 return 'PI()';
1006 * Returns the SQL to get the cosine of a value.
1008 * @param string $value
1010 * @return string
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
1025 * @return string
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
1040 * @return string
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
1055 * @return string
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
1070 * @return string
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
1085 * @return string
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
1100 * @return string
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
1115 * @return string
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
1130 * @return string
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
1145 * @return string
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
1160 * @return string
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
1175 * @return string
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
1190 * @return string
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
1205 * @return string
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
1220 * @return string
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
1235 * @return string
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
1250 * @return string
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
1265 * @return string
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.
1283 * @return string
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
1298 * @return string
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
1311 * @return string
1313 public function getBitOrComparisonExpression($value1, $value2)
1315 return '(' . $value1 . ' | ' . $value2 . ')';
1319 * Returns the FOR UPDATE expression.
1321 * @return string
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.
1335 * @return string
1337 public function appendLockHint($fromClause, $lockMode)
1339 return $fromClause;
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.
1348 * @return string
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.
1360 * @return string
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.
1372 * @return string
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
1384 * @return string
1386 * @throws \InvalidArgumentException
1388 public function getDropTableSQL($table)
1390 $tableArg = $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
1415 * @return string
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
1428 * @return string
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
1449 * @return string
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
1473 * @return string
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
1493 * on this platform.
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;
1525 } else {
1526 $options['indexes'][$index->getQuotedName($this)] = $index;
1531 $columnSql = array();
1532 $columns = 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()) {
1544 continue;
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
1599 * @return string
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) .
1608 " IS " . $comment;
1612 * Returns the SQL used to create a table.
1614 * @param string $tableName
1615 * @param array $columns
1616 * @param array $options
1618 * @return array
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;
1646 $query .= ')';
1648 $sql[] = $query;
1650 if (isset($options['foreignKeys'])) {
1651 foreach ((array) $options['foreignKeys'] as $definition) {
1652 $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
1656 return $sql;
1660 * @return string
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
1672 * @return string
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
1686 * @return string
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
1701 * @return string
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';
1721 } else {
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;
1734 return $query;
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.
1743 * @return string
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);
1766 return $query;
1770 * Adds condition for partial index.
1772 * @param \Doctrine\DBAL\Schema\Index $index
1774 * @return string
1776 protected function getPartialIndexSQL(Index $index)
1778 if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
1779 return ' WHERE ' . $index->getOption('where');
1782 return '';
1786 * Adds additional flags for index generation.
1788 * @param \Doctrine\DBAL\Schema\Index $index
1790 * @return string
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
1803 * @return string
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
1815 * @return string
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.
1867 * @return string
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);
1877 return $query;
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
1887 * @return array
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
1901 * @return boolean
1903 protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql)
1905 if (null === $this->_eventManager) {
1906 return false;
1909 if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) {
1910 return false;
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
1926 * @return boolean
1928 protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql)
1930 if (null === $this->_eventManager) {
1931 return false;
1934 if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) {
1935 return false;
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
1951 * @return boolean
1953 protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql)
1955 if (null === $this->_eventManager) {
1956 return false;
1959 if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) {
1960 return false;
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
1977 * @return boolean
1979 protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql)
1981 if (null === $this->_eventManager) {
1982 return false;
1985 if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) {
1986 return false;
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
1999 * @param array $sql
2001 * @return boolean
2003 protected function onSchemaAlterTable(TableDiff $diff, &$sql)
2005 if (null === $this->_eventManager) {
2006 return false;
2009 if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) {
2010 return false;
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
2024 * @return array
2026 protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
2028 $tableName = $diff->getName($this)->getQuotedName($this);
2030 $sql = array();
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);
2047 return $sql;
2051 * @param \Doctrine\DBAL\Schema\TableDiff $diff
2053 * @return array
2055 protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
2057 $tableName = (false !== $diff->newName)
2058 ? $diff->getNewName()->getQuotedName($this)
2059 : $diff->getName($this)->getQuotedName($this);
2061 $sql = array();
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);
2083 $sql = array_merge(
2084 $sql,
2085 $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName)
2089 return $sql;
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)
2103 return array(
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
2114 * @return array
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:
2130 * length
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.
2135 * default
2136 * Text value to be used as default for this field.
2138 * notnull
2139 * Boolean flag that indicates whether this field is constrained
2140 * to not be set to null.
2141 * charset
2142 * Text value with the default CHARACTER SET for this field.
2143 * collation
2144 * Text value with the default COLLATION for this field.
2145 * unique
2146 * unique constraint
2148 * @return string
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:
2170 * length
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.
2175 * default
2176 * Text value to be used as default for this field.
2178 * notnull
2179 * Boolean flag that indicates whether this field is constrained
2180 * to not be set to null.
2181 * charset
2182 * Text value with the default CHARACTER SET for this field.
2183 * collation
2184 * Text value with the default COLLATION for this field.
2185 * unique
2186 * unique constraint
2187 * check
2188 * column check constraint
2189 * columnDefinition
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);
2198 } else {
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
2231 * @return string
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']) . "'";
2272 return $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 . ')';
2289 } else {
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
2360 * @return string
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
2373 * @return string
2375 public function getIndexFieldDeclarationListSQL(array $fields)
2377 $ret = array();
2379 foreach ($fields as $field => $definition) {
2380 if (is_array($definition)) {
2381 $ret[] = $field;
2382 } else {
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()
2406 return 'TEMPORARY';
2410 * Some vendors require temporary table names to be qualified specially.
2412 * @param string $tableName
2414 * @return string
2416 public function getTemporaryTableName($tableName)
2418 return $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);
2435 return $sql;
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.
2444 * @return string
2446 public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
2448 $query = '';
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'));
2456 return $query;
2460 * Returns the given referential action in uppercase if valid, otherwise throws an exception.
2462 * @param string $action The foreign key referential action.
2464 * @return string
2466 * @throws \InvalidArgumentException if unknown referential action given
2468 public function getForeignKeyReferentialActionSQL($action)
2470 $upper = strtoupper($action);
2471 switch ($upper) {
2472 case 'CASCADE':
2473 case 'SET NULL':
2474 case 'NO ACTION':
2475 case 'RESTRICT':
2476 case 'SET DEFAULT':
2477 return $upper;
2478 default:
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
2489 * @return string
2491 * @throws \InvalidArgumentException
2493 public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey)
2495 $sql = '';
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))
2512 . ') REFERENCES '
2513 . $foreignKey->getQuotedForeignTableName($this) . ' ('
2514 . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')';
2516 return $sql;
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()
2528 return 'UNIQUE';
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)
2542 return '';
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.
2563 * @return boolean
2565 public function prefersSequences()
2567 return false;
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.
2574 * @return boolean
2576 public function prefersIdentityColumns()
2578 return false;
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;
2607 return $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
2617 * @return bool|null
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.
2642 * @return string
2644 public function getCurrentDateSQL()
2646 return 'CURRENT_DATE';
2650 * Returns the SQL specific for the platform to get the current time.
2652 * @return string
2654 public function getCurrentTimeSQL()
2656 return 'CURRENT_TIME';
2660 * Returns the SQL specific for the platform to get the current timestamp
2662 * @return string
2664 public function getCurrentTimestampSQL()
2666 return 'CURRENT_TIMESTAMP';
2670 * Returns the SQL for a given transaction isolation level Connection constant.
2672 * @param integer $level
2674 * @return string
2676 * @throws \InvalidArgumentException
2678 protected function _getTransactionIsolationLevelSQL($level)
2680 switch ($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';
2689 default:
2690 throw new \InvalidArgumentException('Invalid isolation level:' . $level);
2695 * @return string
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.
2707 * @return string
2709 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2711 public function getListNamespacesSQL()
2713 throw DBALException::notSupported(__METHOD__);
2717 * @param string $database
2719 * @return string
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
2731 * @return string
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
2744 * @return string
2746 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2748 public function getListTableColumnsSQL($table, $database = null)
2750 throw DBALException::notSupported(__METHOD__);
2754 * @return string
2756 * @throws \Doctrine\DBAL\DBALException If not supported on this platform.
2758 public function getListTablesSQL()
2760 throw DBALException::notSupported(__METHOD__);
2764 * @return string
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
2778 * @return string
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
2800 * @return string
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
2812 * @return string
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
2825 * @return string
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
2837 * @return string
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
2851 * @return string
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
2863 * @return string
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.
2877 * @return string
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
2891 * @return string
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
2906 * @return string
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
2920 * @return string
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
2934 * @return string
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
2949 * @return string
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
2961 * @return string
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.
2985 * @return boolean
2987 public function supportsSequences()
2989 return false;
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.
2998 * @return boolean
3000 public function supportsIdentityColumns()
3002 return false;
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
3010 * sequences.
3012 * @return boolean
3014 public function usesSequenceEmulatedIdentityColumns()
3016 return false;
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.
3025 * @return string
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.
3039 * @return boolean
3041 public function supportsIndexes()
3043 return true;
3047 * Whether the platform supports partial indexes.
3049 * @return boolean
3051 public function supportsPartialIndexes()
3053 return false;
3057 * Whether the platform supports altering tables.
3059 * @return boolean
3061 public function supportsAlterTable()
3063 return true;
3067 * Whether the platform supports transactions.
3069 * @return boolean
3071 public function supportsTransactions()
3073 return true;
3077 * Whether the platform supports savepoints.
3079 * @return boolean
3081 public function supportsSavepoints()
3083 return true;
3087 * Whether the platform supports releasing savepoints.
3089 * @return boolean
3091 public function supportsReleaseSavepoints()
3093 return $this->supportsSavepoints();
3097 * Whether the platform supports primary key constraints.
3099 * @return boolean
3101 public function supportsPrimaryConstraints()
3103 return true;
3107 * Whether the platform supports foreign key constraints.
3109 * @return boolean
3111 public function supportsForeignKeyConstraints()
3113 return true;
3117 * Whether this platform supports onUpdate in foreign key constraints.
3119 * @return boolean
3121 public function supportsForeignKeyOnUpdate()
3123 return ($this->supportsForeignKeyConstraints() && true);
3127 * Whether the platform supports database schemas.
3129 * @return boolean
3131 public function supportsSchemas()
3133 return false;
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}.
3143 * @return boolean
3145 public function canEmulateSchemas()
3147 return false;
3151 * Returns the default schema name.
3153 * @return string
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.
3167 * @return boolean
3169 public function supportsCreateDropDatabase()
3171 return true;
3175 * Whether the platform supports getting the affected rows of a recent update/delete type query.
3177 * @return boolean
3179 public function supportsGettingAffectedRows()
3181 return true;
3185 * Whether this platform support to add inline column comments as postfix.
3187 * @return boolean
3189 public function supportsInlineColumnComments()
3191 return false;
3195 * Whether this platform support the proprietary syntax "COMMENT ON asset".
3197 * @return boolean
3199 public function supportsCommentOnStatement()
3201 return false;
3205 * Does this platform have native guid type.
3207 * @return boolean
3209 public function hasNativeGuidType()
3211 return false;
3215 * Does this platform have native JSON type.
3217 * @return boolean
3219 public function hasNativeJsonType()
3221 return false;
3225 * @deprecated
3226 * @todo Remove in 3.0
3228 public function getIdentityColumnNullInsertSQL()
3230 return "";
3234 * Whether this platform supports views.
3236 * @return boolean
3238 public function supportsViews()
3240 return true;
3244 * Does this platform support column collation?
3246 * @return boolean
3248 public function supportsColumnCollation()
3250 return false;
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()
3283 return 'Y-m-d';
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()
3294 return 'H:i:s';
3298 * Adds an driver-specific LIMIT clause to the query.
3300 * @param string $query
3301 * @param integer|null $limit
3302 * @param integer|null $offset
3304 * @return string
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;
3317 if ($offset < 0) {
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
3335 * @return string
3337 protected function doModifyLimitQuery($query, $limit, $offset)
3339 if ($limit !== null) {
3340 $query .= ' LIMIT ' . $limit;
3343 if ($offset !== null) {
3344 $query .= ' OFFSET ' . $offset;
3347 return $query;
3351 * Whether the database platform support offsets in modify limit clauses.
3353 * @return boolean
3355 public function supportsLimitOffset()
3357 return true;
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)
3369 return $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
3378 * @return string
3380 public function fixSchemaElementName($schemaElementName)
3382 return $schemaElementName;
3386 * Maximum length of any given database identifier, like tables or column names.
3388 * @return integer
3390 public function getMaxIdentifierLength()
3392 return 63;
3396 * Returns the insert SQL for an empty insert statement.
3398 * @param string $tableName
3399 * @param string $identifierColumnName
3401 * @return string
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
3417 * @return string
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.
3429 * @return string
3431 public function getDummySelectSQL()
3433 return 'SELECT 1';
3437 * Returns the SQL to create a new savepoint.
3439 * @param string $savepoint
3441 * @return string
3443 public function createSavePoint($savepoint)
3445 return 'SAVEPOINT ' . $savepoint;
3449 * Returns the SQL to release a savepoint.
3451 * @param string $savepoint
3453 * @return string
3455 public function releaseSavePoint($savepoint)
3457 return 'RELEASE SAVEPOINT ' . $savepoint;
3461 * Returns the SQL to rollback a savepoint.
3463 * @param string $savepoint
3465 * @return string
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;
3495 return $keywords;
3499 * Returns the class name of the reserved keywords list.
3501 * @return string
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.
3530 * @return string
3532 public function getStringLiteralQuoteCharacter()
3534 return "'";