source: pro-violet-viettel/sourcecode/application/libraries/Doctrine/DBAL/Platforms/DB2Platform.php @ 345

Last change on this file since 345 was 345, checked in by quyenla, 11 years ago

collaborator page

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