vendor/doctrine-dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 /*
       
     3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
     4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
     5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
     6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
     7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
     8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
     9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    14  *
       
    15  * This software consists of voluntary contributions made by many individuals
       
    16  * and is licensed under the LGPL. For more information, see
       
    17  * <http://www.doctrine-project.org>.
       
    18 */
       
    19 
       
    20 namespace Doctrine\DBAL\Platforms;
       
    21 
       
    22 use Doctrine\DBAL\DBALException;
       
    23 use Doctrine\DBAL\Schema\Index;
       
    24 use Doctrine\DBAL\Schema\TableDiff;
       
    25 
       
    26 class DB2Platform extends AbstractPlatform
       
    27 {
       
    28     public function initializeDoctrineTypeMappings()
       
    29     {
       
    30         $this->doctrineTypeMapping = array(
       
    31             'smallint'      => 'smallint',
       
    32             'bigint'        => 'bigint',
       
    33             'integer'       => 'integer',
       
    34             'time'          => 'time',
       
    35             'date'          => 'date',
       
    36             'varchar'       => 'string',
       
    37             'character'     => 'string',
       
    38             'clob'          => 'text',
       
    39             'decimal'       => 'decimal',
       
    40             'double'        => 'float',
       
    41             'real'          => 'float',
       
    42             'timestamp'     => 'datetime',
       
    43         );
       
    44     }
       
    45 
       
    46     /**
       
    47      * Gets the SQL snippet used to declare a VARCHAR column type.
       
    48      *
       
    49      * @param array $field
       
    50      */
       
    51     protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
       
    52     {
       
    53         return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
       
    54                 : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
       
    55     }
       
    56 
       
    57     /**
       
    58      * Gets the SQL snippet used to declare a CLOB column type.
       
    59      *
       
    60      * @param array $field
       
    61      */
       
    62     public function getClobTypeDeclarationSQL(array $field)
       
    63     {
       
    64         // todo clob(n) with $field['length'];
       
    65         return 'CLOB(1M)';
       
    66     }
       
    67 
       
    68     /**
       
    69      * Gets the name of the platform.
       
    70      *
       
    71      * @return string
       
    72      */
       
    73     public function getName()
       
    74     {
       
    75         return 'db2';
       
    76     }
       
    77 
       
    78 
       
    79     /**
       
    80      * Gets the SQL snippet that declares a boolean column.
       
    81      *
       
    82      * @param array $columnDef
       
    83      * @return string
       
    84      */
       
    85     public function getBooleanTypeDeclarationSQL(array $columnDef)
       
    86     {
       
    87         return 'SMALLINT';
       
    88     }
       
    89 
       
    90     /**
       
    91      * Gets the SQL snippet that declares a 4 byte integer column.
       
    92      *
       
    93      * @param array $columnDef
       
    94      * @return string
       
    95      */
       
    96     public function getIntegerTypeDeclarationSQL(array $columnDef)
       
    97     {
       
    98         return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
       
    99     }
       
   100 
       
   101     /**
       
   102      * Gets the SQL snippet that declares an 8 byte integer column.
       
   103      *
       
   104      * @param array $columnDef
       
   105      * @return string
       
   106      */
       
   107     public function getBigIntTypeDeclarationSQL(array $columnDef)
       
   108     {
       
   109         return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
       
   110     }
       
   111 
       
   112     /**
       
   113      * Gets the SQL snippet that declares a 2 byte integer column.
       
   114      *
       
   115      * @param array $columnDef
       
   116      * @return string
       
   117      */
       
   118     public function getSmallIntTypeDeclarationSQL(array $columnDef)
       
   119     {
       
   120         return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
       
   121     }
       
   122 
       
   123     /**
       
   124      * Gets the SQL snippet that declares common properties of an integer column.
       
   125      *
       
   126      * @param array $columnDef
       
   127      * @return string
       
   128      */
       
   129     protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
       
   130     {
       
   131         $autoinc = '';
       
   132         if ( ! empty($columnDef['autoincrement'])) {
       
   133             $autoinc = ' GENERATED BY DEFAULT AS IDENTITY';
       
   134         }
       
   135         return $autoinc;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Obtain DBMS specific SQL to be used to create datetime fields in
       
   140      * statements like CREATE TABLE
       
   141      *
       
   142      * @param array $fieldDeclaration
       
   143      * @return string
       
   144      */
       
   145     public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
       
   146     {
       
   147         if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
       
   148             return "TIMESTAMP(0) WITH DEFAULT";
       
   149         }
       
   150 
       
   151         return 'TIMESTAMP(0)';
       
   152     }
       
   153 
       
   154     /**
       
   155      * Obtain DBMS specific SQL to be used to create date fields in statements
       
   156      * like CREATE TABLE.
       
   157      *
       
   158      * @param array $fieldDeclaration
       
   159      * @return string
       
   160      */
       
   161     public function getDateTypeDeclarationSQL(array $fieldDeclaration)
       
   162     {
       
   163         return 'DATE';
       
   164     }
       
   165 
       
   166     /**
       
   167      * Obtain DBMS specific SQL to be used to create time fields in statements
       
   168      * like CREATE TABLE.
       
   169      *
       
   170      * @param array $fieldDeclaration
       
   171      * @return string
       
   172      */
       
   173     public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
       
   174     {
       
   175         return 'TIME';
       
   176     }
       
   177 
       
   178     public function getListDatabasesSQL()
       
   179     {
       
   180         throw DBALException::notSupported(__METHOD__);
       
   181     }
       
   182 
       
   183     public function getListSequencesSQL($database)
       
   184     {
       
   185         throw DBALException::notSupported(__METHOD__);
       
   186     }
       
   187 
       
   188     public function getListTableConstraintsSQL($table)
       
   189     {
       
   190         throw DBALException::notSupported(__METHOD__);
       
   191     }
       
   192 
       
   193     /**
       
   194      * This code fragment is originally from the Zend_Db_Adapter_Db2 class.
       
   195      *
       
   196      * @license New BSD License
       
   197      * @param  string $table
       
   198      * @return string
       
   199      */
       
   200     public function getListTableColumnsSQL($table, $database = null)
       
   201     {
       
   202         return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
       
   203                 c.typename, c.default, c.nulls, c.length, c.scale,
       
   204                 c.identity, tc.type AS tabconsttype, k.colseq
       
   205                 FROM syscat.columns c
       
   206                 LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
       
   207                 ON (k.tabschema = tc.tabschema
       
   208                     AND k.tabname = tc.tabname
       
   209                     AND tc.type = 'P'))
       
   210                 ON (c.tabschema = k.tabschema
       
   211                     AND c.tabname = k.tabname
       
   212                     AND c.colname = k.colname)
       
   213                 WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno";
       
   214     }
       
   215 
       
   216     public function getListTablesSQL()
       
   217     {
       
   218         return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'";
       
   219     }
       
   220 
       
   221     public function getListUsersSQL()
       
   222     {
       
   223         throw DBALException::notSupported(__METHOD__);
       
   224     }
       
   225 
       
   226     /**
       
   227      * Get the SQL to list all views of a database or user.
       
   228      *
       
   229      * @param string $database
       
   230      * @return string
       
   231      */
       
   232     public function getListViewsSQL($database)
       
   233     {
       
   234         return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS";
       
   235     }
       
   236 
       
   237     public function getListTableIndexesSQL($table, $currentDatabase = null)
       
   238     {
       
   239         return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')";
       
   240     }
       
   241 
       
   242     public function getListTableForeignKeysSQL($table)
       
   243     {
       
   244         return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ".
       
   245                "FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')";
       
   246     }
       
   247 
       
   248     public function getCreateViewSQL($name, $sql)
       
   249     {
       
   250         return "CREATE VIEW ".$name." AS ".$sql;
       
   251     }
       
   252 
       
   253     public function getDropViewSQL($name)
       
   254     {
       
   255         return "DROP VIEW ".$name;
       
   256     }
       
   257 
       
   258     public function getDropSequenceSQL($sequence)
       
   259     {
       
   260         throw DBALException::notSupported(__METHOD__);
       
   261     }
       
   262 
       
   263     public function getSequenceNextValSQL($sequenceName)
       
   264     {
       
   265         throw DBALException::notSupported(__METHOD__);
       
   266     }
       
   267 
       
   268     public function getCreateDatabaseSQL($database)
       
   269     {
       
   270         return "CREATE DATABASE ".$database;
       
   271     }
       
   272 
       
   273     public function getDropDatabaseSQL($database)
       
   274     {
       
   275         return "DROP DATABASE ".$database.";";
       
   276     }
       
   277 
       
   278     public function supportsCreateDropDatabase()
       
   279     {
       
   280         return false;
       
   281     }
       
   282 
       
   283     /**
       
   284      * Whether the platform supports releasing savepoints.
       
   285      *
       
   286      * @return boolean
       
   287      */
       
   288     public function supportsReleaseSavepoints()
       
   289     {
       
   290         return false;
       
   291     }
       
   292 
       
   293     /**
       
   294      * Gets the SQL specific for the platform to get the current date.
       
   295      *
       
   296      * @return string
       
   297      */
       
   298     public function getCurrentDateSQL()
       
   299     {
       
   300         return 'VALUES CURRENT DATE';
       
   301     }
       
   302 
       
   303     /**
       
   304      * Gets the SQL specific for the platform to get the current time.
       
   305      *
       
   306      * @return string
       
   307      */
       
   308     public function getCurrentTimeSQL()
       
   309     {
       
   310         return 'VALUES CURRENT TIME';
       
   311     }
       
   312 
       
   313     /**
       
   314      * Gets the SQL specific for the platform to get the current timestamp
       
   315      *
       
   316      * @return string
       
   317      */
       
   318 
       
   319     public function getCurrentTimestampSQL()
       
   320     {
       
   321         return "VALUES CURRENT TIMESTAMP";
       
   322     }
       
   323 
       
   324     /**
       
   325      * Obtain DBMS specific SQL code portion needed to set an index
       
   326      * declaration to be used in statements like CREATE TABLE.
       
   327      *
       
   328      * @param string $name          name of the index
       
   329      * @param Index $index          index definition
       
   330      * @return string               DBMS specific SQL code portion needed to set an index
       
   331      */
       
   332     public function getIndexDeclarationSQL($name, Index $index)
       
   333     {
       
   334         return $this->getUniqueConstraintDeclarationSQL($name, $index);
       
   335     }
       
   336 
       
   337     /**
       
   338      * @param string $tableName
       
   339      * @param array $columns
       
   340      * @param array $options
       
   341      * @return array
       
   342      */
       
   343     protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
       
   344     {
       
   345         $indexes = array();
       
   346         if (isset($options['indexes'])) {
       
   347             $indexes = $options['indexes'];
       
   348         }
       
   349         $options['indexes'] = array();
       
   350         
       
   351         $sqls = parent::_getCreateTableSQL($tableName, $columns, $options);
       
   352 
       
   353         foreach ($indexes as $index => $definition) {
       
   354             $sqls[] = $this->getCreateIndexSQL($definition, $tableName);
       
   355         }
       
   356         return $sqls;
       
   357     }
       
   358 
       
   359     /**
       
   360      * Gets the SQL to alter an existing table.
       
   361      *
       
   362      * @param TableDiff $diff
       
   363      * @return array
       
   364      */
       
   365     public function getAlterTableSQL(TableDiff $diff)
       
   366     {
       
   367         $sql = array();
       
   368 
       
   369         $queryParts = array();
       
   370         foreach ($diff->addedColumns AS $fieldName => $column) {
       
   371             $queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
       
   372         }
       
   373 
       
   374         foreach ($diff->removedColumns AS $column) {
       
   375             $queryParts[] =  'DROP COLUMN ' . $column->getQuotedName($this);
       
   376         }
       
   377 
       
   378         foreach ($diff->changedColumns AS $columnDiff) {
       
   379             /* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
       
   380             $column = $columnDiff->column;
       
   381             $queryParts[] =  'ALTER ' . ($columnDiff->oldColumnName) . ' '
       
   382                     . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
       
   383         }
       
   384 
       
   385         foreach ($diff->renamedColumns AS $oldColumnName => $column) {
       
   386             $queryParts[] =  'RENAME ' . $oldColumnName . ' TO ' . $column->getQuotedName($this);
       
   387         }
       
   388 
       
   389         if (count($queryParts) > 0) {
       
   390             $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts);
       
   391         }
       
   392 
       
   393         $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
       
   394 
       
   395         if ($diff->newName !== false) {
       
   396             $sql[] =  'RENAME TABLE TO ' . $diff->newName;
       
   397         }
       
   398 
       
   399         return $sql;
       
   400     }
       
   401 
       
   402     public function getDefaultValueDeclarationSQL($field)
       
   403     {
       
   404         if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) {
       
   405             if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
       
   406                 $field['default'] = 0;
       
   407             } else if((string)$field['type'] == "DateTime") {
       
   408                 $field['default'] = "00-00-00 00:00:00";
       
   409             } else if ((string)$field['type'] == "Date") {
       
   410                 $field['default'] = "00-00-00";
       
   411             } else if((string)$field['type'] == "Time") {
       
   412                 $field['default'] = "00:00:00";
       
   413             } else {
       
   414                 $field['default'] = '';
       
   415             }
       
   416         }
       
   417 
       
   418         unset($field['default']); // @todo this needs fixing
       
   419         if (isset($field['version']) && $field['version']) {
       
   420             if ((string)$field['type'] != "DateTime") {
       
   421                 $field['default'] = "1";
       
   422             }
       
   423         }
       
   424 
       
   425         return parent::getDefaultValueDeclarationSQL($field);
       
   426     }
       
   427 
       
   428     /**
       
   429      * Get the insert sql for an empty insert statement
       
   430      *
       
   431      * @param string $tableName
       
   432      * @param string $identifierColumnName
       
   433      * @return string $sql
       
   434      */
       
   435     public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
       
   436     {
       
   437         return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)';
       
   438     }
       
   439 
       
   440     public function getCreateTemporaryTableSnippetSQL()
       
   441     {
       
   442         return "DECLARE GLOBAL TEMPORARY TABLE";
       
   443     }
       
   444 
       
   445     /**
       
   446      * DB2 automatically moves temporary tables into the SESSION. schema.
       
   447      *
       
   448      * @param  string $tableName
       
   449      * @return string
       
   450      */
       
   451     public function getTemporaryTableName($tableName)
       
   452     {
       
   453         return "SESSION." . $tableName;
       
   454     }
       
   455 
       
   456     protected function doModifyLimitQuery($query, $limit, $offset = null)
       
   457     {
       
   458         if ($limit === null && $offset === null) {
       
   459             return $query;
       
   460         }
       
   461 
       
   462         $limit = (int)$limit;
       
   463         $offset = (int)(($offset)?:0);
       
   464 
       
   465         // Todo OVER() needs ORDER BY data!
       
   466         $sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '.
       
   467                'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit);
       
   468         return $sql;
       
   469     }
       
   470 
       
   471     /**
       
   472      * returns the position of the first occurrence of substring $substr in string $str
       
   473      *
       
   474      * @param string $substr    literal string to find
       
   475      * @param string $str       literal string
       
   476      * @param int    $pos       position to start at, beginning of string by default
       
   477      * @return integer
       
   478      */
       
   479     public function getLocateExpression($str, $substr, $startPos = false)
       
   480     {
       
   481         if ($startPos == false) {
       
   482             return 'LOCATE(' . $substr . ', ' . $str . ')';
       
   483         } else {
       
   484             return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
       
   485         }
       
   486     }
       
   487 
       
   488     /**
       
   489      * return string to call a function to get a substring inside an SQL statement
       
   490      *
       
   491      * Note: Not SQL92, but common functionality.
       
   492      *
       
   493      * SQLite only supports the 2 parameter variant of this function
       
   494      *
       
   495      * @param  string $value         an sql string literal or column name/alias
       
   496      * @param  integer $from     where to start the substring portion
       
   497      * @param  integer $len       the substring portion length
       
   498      * @return string
       
   499      */
       
   500     public function getSubstringExpression($value, $from, $len = null)
       
   501     {
       
   502         if ($len === null)
       
   503             return 'SUBSTR(' . $value . ', ' . $from . ')';
       
   504         else {
       
   505             return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
       
   506         }
       
   507     }
       
   508 
       
   509     public function supportsIdentityColumns()
       
   510     {
       
   511         return true;
       
   512     }
       
   513 
       
   514     public function prefersIdentityColumns()
       
   515     {
       
   516         return true;
       
   517     }
       
   518 
       
   519     /**
       
   520      * Gets the character casing of a column in an SQL result set of this platform.
       
   521      *
       
   522      * DB2 returns all column names in SQL result sets in uppercase.
       
   523      *
       
   524      * @param string $column The column name for which to get the correct character casing.
       
   525      * @return string The column name in the character casing used in SQL result sets.
       
   526      */
       
   527     public function getSQLResultCasing($column)
       
   528     {
       
   529         return strtoupper($column);
       
   530     }
       
   531 
       
   532     public function getForUpdateSQL()
       
   533     {
       
   534         return ' WITH RR USE AND KEEP UPDATE LOCKS';
       
   535     }
       
   536 
       
   537     public function getDummySelectSQL()
       
   538     {
       
   539         return 'SELECT 1 FROM sysibm.sysdummy1';
       
   540     }
       
   541 
       
   542     /**
       
   543      * DB2 supports savepoints, but they work semantically different than on other vendor platforms.
       
   544      *
       
   545      * TODO: We have to investigate how to get DB2 up and running with savepoints.
       
   546      *
       
   547      * @return bool
       
   548      */
       
   549     public function supportsSavepoints()
       
   550     {
       
   551         return false;
       
   552     }
       
   553     
       
   554     protected function getReservedKeywordsClass()
       
   555     {
       
   556         return 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords';
       
   557     }
       
   558 }