Файл: concrete5.7.5.6/concrete/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php
Строк: 1275
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineDBALPlatforms;
use DoctrineDBALSchemaForeignKeyConstraint;
use DoctrineDBALSchemaIdentifier;
use DoctrineDBALSchemaIndex;
use DoctrineDBALSchemaSequence;
use DoctrineDBALSchemaTable;
use DoctrineDBALSchemaTableDiff;
use DoctrineDBALDBALException;
use DoctrineDBALTypesBinaryType;
/**
* OraclePlatform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OraclePlatform extends AbstractPlatform
{
/**
* Assertion for Oracle identifiers.
*
* @link http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm
*
* @param string $identifier
*
* @throws DBALException
*/
static public function assertValidIdentifier($identifier)
{
if ( ! preg_match('(^(([a-zA-Z]{1}[a-zA-Z0-9_$#]{0,})|("[^"]+"))$)', $identifier)) {
throw new DBALException("Invalid Oracle identifier");
}
}
/**
* {@inheritDoc}
*/
public function getSubstringExpression($value, $position, $length = null)
{
if ($length !== null) {
return "SUBSTR($value, $position, $length)";
}
return "SUBSTR($value, $position)";
}
/**
* {@inheritDoc}
*/
public function getNowExpression($type = 'timestamp')
{
switch ($type) {
case 'date':
case 'time':
case 'timestamp':
default:
return 'TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS')';
}
}
/**
* {@inheritDoc}
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'INSTR('.$str.', '.$substr.')';
}
return 'INSTR('.$str.', '.$substr.', '.$startPos.')';
}
/**
* {@inheritDoc}
*/
public function getGuidExpression()
{
return 'SYS_GUID()';
}
/**
* {@inheritdoc}
*/
protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit)
{
switch ($unit) {
case self::DATE_INTERVAL_UNIT_MONTH:
case self::DATE_INTERVAL_UNIT_QUARTER:
case self::DATE_INTERVAL_UNIT_YEAR:
switch ($unit) {
case self::DATE_INTERVAL_UNIT_QUARTER:
$interval *= 3;
break;
case self::DATE_INTERVAL_UNIT_YEAR:
$interval *= 12;
break;
}
return 'ADD_MONTHS(' . $date . ', ' . $operator . $interval . ')';
default:
$calculationClause = '';
switch ($unit) {
case self::DATE_INTERVAL_UNIT_SECOND:
$calculationClause = '/24/60/60';
break;
case self::DATE_INTERVAL_UNIT_MINUTE:
$calculationClause = '/24/60';
break;
case self::DATE_INTERVAL_UNIT_HOUR:
$calculationClause = '/24';
break;
case self::DATE_INTERVAL_UNIT_WEEK:
$calculationClause = '*7';
break;
}
return '(' . $date . $operator . $interval . $calculationClause . ')';
}
}
/**
* {@inheritDoc}
*
* Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate
* them to the difference in days. This is obviously a restriction of the original functionality, but we
* need to make this a portable function.
*/
public function getDateDiffExpression($date1, $date2)
{
return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))";
}
/**
* {@inheritDoc}
*/
public function getBitAndComparisonExpression($value1, $value2)
{
return 'BITAND('.$value1 . ', ' . $value2 . ')';
}
/**
* {@inheritDoc}
*/
public function getBitOrComparisonExpression($value1, $value2)
{
return '(' . $value1 . '-' .
$this->getBitAndComparisonExpression($value1, $value2)
. '+' . $value2 . ')';
}
/**
* {@inheritDoc}
*
* Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH.
* Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection
* in {@see listSequences()}
*/
public function getCreateSequenceSQL(Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .
' START WITH ' . $sequence->getInitialValue() .
' MINVALUE ' . $sequence->getInitialValue() .
' INCREMENT BY ' . $sequence->getAllocationSize() .
$this->getSequenceCacheSQL($sequence);
}
/**
* {@inheritDoc}
*/
public function getAlterSequenceSQL(Sequence $sequence)
{
return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize()
. $this->getSequenceCacheSQL($sequence);
}
/**
* Cache definition for sequences
*
* @param Sequence $sequence
*
* @return string
*/
private function getSequenceCacheSQL(Sequence $sequence)
{
if ($sequence->getCache() === 0) {
return ' NOCACHE';
} else if ($sequence->getCache() === 1) {
return ' NOCACHE';
} else if ($sequence->getCache() > 1) {
return ' CACHE ' . $sequence->getCache();
}
return '';
}
/**
* {@inheritDoc}
*/
public function getSequenceNextValSQL($sequenceName)
{
return 'SELECT ' . $sequenceName . '.nextval FROM DUAL';
}
/**
* {@inheritDoc}
*/
public function getSetTransactionIsolationSQL($level)
{
return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* {@inheritDoc}
*/
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case DoctrineDBALConnection::TRANSACTION_READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case DoctrineDBALConnection::TRANSACTION_READ_COMMITTED:
return 'READ COMMITTED';
case DoctrineDBALConnection::TRANSACTION_REPEATABLE_READ:
case DoctrineDBALConnection::TRANSACTION_SERIALIZABLE:
return 'SERIALIZABLE';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
}
/**
* {@inheritDoc}
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'NUMBER(1)';
}
/**
* {@inheritDoc}
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'NUMBER(10)';
}
/**
* {@inheritDoc}
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(20)';
}
/**
* {@inheritDoc}
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(5)';
}
/**
* {@inheritDoc}
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0)';
}
/**
* {@inheritDoc}
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITH TIME ZONE';
}
/**
* {@inheritDoc}
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* {@inheritDoc}
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* {@inheritDoc}
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return '';
}
/**
* {@inheritDoc}
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)')
: ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)');
}
/**
* {@inheritdoc}
*/
protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed)
{
return 'RAW(' . ($length ?: $this->getBinaryMaxLength()) . ')';
}
/**
* {@inheritdoc}
*/
public function getBinaryMaxLength()
{
return 2000;
}
/**
* {@inheritDoc}
*/
public function getClobTypeDeclarationSQL(array $field)
{
return 'CLOB';
}
/**
* {@inheritDoc}
*/
public function getListDatabasesSQL()
{
return 'SELECT username FROM all_users';
}
/**
* {@inheritDoc}
*/
public function getListSequencesSQL($database)
{
$database = $this->normalizeIdentifier($database);
return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ".
"WHERE SEQUENCE_OWNER = '" . $database->getName() . "'";
}
/**
* {@inheritDoc}
*/
protected function _getCreateTableSQL($table, array $columns, array $options = array())
{
$indexes = isset($options['indexes']) ? $options['indexes'] : array();
$options['indexes'] = array();
$sql = parent::_getCreateTableSQL($table, $columns, $options);
foreach ($columns as $name => $column) {
if (isset($column['sequence'])) {
$sql[] = $this->getCreateSequenceSQL($column['sequence'], 1);
}
if (isset($column['autoincrement']) && $column['autoincrement'] ||
(isset($column['autoinc']) && $column['autoinc'])) {
$sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table));
}
}
if (isset($indexes) && ! empty($indexes)) {
foreach ($indexes as $index) {
$sql[] = $this->getCreateIndexSQL($index, $table);
}
}
return $sql;
}
/**
* {@inheritDoc}
*
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html
*/
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
$table = $this->normalizeIdentifier($table);
return "SELECT uind.index_name AS name, " .
" uind.index_type AS type, " .
" decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " .
" uind_col.column_name AS column_name, " .
" uind_col.column_position AS column_pos, " .
" (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ".
"FROM user_indexes uind, user_ind_columns uind_col " .
"WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '" . $table->getName() . "' " .
"ORDER BY uind_col.column_position ASC";
}
/**
* {@inheritDoc}
*/
public function getListTablesSQL()
{
return 'SELECT * FROM sys.user_tables';
}
/**
* {@inheritDoc}
*/
public function getListViewsSQL($database)
{
return 'SELECT view_name, text FROM sys.user_views';
}
/**
* {@inheritDoc}
*/
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
/**
* {@inheritDoc}
*/
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
/**
* @param string $name
* @param string $table
* @param integer $start
*
* @return array
*/
public function getCreateAutoincrementSql($name, $table, $start = 1)
{
$tableIdentifier = $this->normalizeIdentifier($table);
$quotedTableName = $tableIdentifier->getQuotedName($this);
$unquotedTableName = $tableIdentifier->getName();
$nameIdentifier = $this->normalizeIdentifier($name);
$quotedName = $nameIdentifier->getQuotedName($this);
$unquotedName = $nameIdentifier->getName();
$sql = array();
$autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier);
$idx = new Index($autoincrementIdentifierName, array($quotedName), true, true);
$sql[] = 'DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = '' . $unquotedTableName . '' AND CONSTRAINT_TYPE = 'P';
IF constraints_Count = 0 OR constraints_Count = '' THEN
EXECUTE IMMEDIATE ''.$this->getCreateConstraintSQL($idx, $quotedTableName).'';
END IF;
END;';
$sequenceName = $this->getIdentitySequenceName(
$tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName,
$nameIdentifier->isQuoted() ? $quotedName : $unquotedName
);
$sequence = new Sequence($sequenceName, $start);
$sql[] = $this->getCreateSequenceSQL($sequence);
$sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . '
BEFORE INSERT
ON ' . $quotedTableName . '
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL;
IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.'.$quotedName.' = 0) THEN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = '' . $sequence->getName() . '';
SELECT :NEW.' . $quotedName . ' INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;';
return $sql;
}
/**
* Returns the SQL statements to drop the autoincrement for the given table name.
*
* @param string $table The table name to drop the autoincrement for.
*
* @return array
*/
public function getDropAutoincrementSql($table)
{
$table = $this->normalizeIdentifier($table);
$autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table);
$identitySequenceName = $this->getIdentitySequenceName(
$table->isQuoted() ? $table->getQuotedName($this) : $table->getName(),
''
);
return array(
'DROP TRIGGER ' . $autoincrementIdentifierName,
$this->getDropSequenceSQL($identitySequenceName),
$this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)),
);
}
/**
* Normalizes the given identifier.
*
* Uppercases the given identifier if it is not quoted by intention
* to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers.
*
* @param string $name The identifier to normalize.
*
* @return Identifier The normalized identifier.
*/
private function normalizeIdentifier($name)
{
$identifier = new Identifier($name);
return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name));
}
/**
* Returns the autoincrement primary key identifier name for the given table identifier.
*
* Quotes the autoincrement primary key identifier name
* if the given table name is quoted by intention.
*
* @param Identifier $table The table identifier to return the autoincrement primary key identifier name for.
*
* @return string
*/
private function getAutoincrementIdentifierName(Identifier $table)
{
$identifierName = $table->getName() . '_AI_PK';
return $table->isQuoted()
? $this->quoteSingleIdentifier($identifierName)
: $identifierName;
}
/**
* {@inheritDoc}
*/
public function getListTableForeignKeysSQL($table)
{
$table = $table = $this->normalizeIdentifier($table);
return "SELECT alc.constraint_name,
alc.DELETE_RULE,
alc.search_condition,
cols.column_name "local_column",
cols.position,
r_alc.table_name "references_table",
r_cols.column_name "foreign_column"
FROM user_cons_columns cols
LEFT JOIN user_constraints alc
ON alc.constraint_name = cols.constraint_name
LEFT JOIN user_constraints r_alc
ON alc.r_constraint_name = r_alc.constraint_name
LEFT JOIN user_cons_columns r_cols
ON r_alc.constraint_name = r_cols.constraint_name
AND cols.position = r_cols.position
WHERE alc.constraint_name = cols.constraint_name
AND alc.constraint_type = 'R'
AND alc.table_name = '" . $table->getName() . "'
ORDER BY alc.constraint_name ASC, cols.position ASC";
}
/**
* {@inheritDoc}
*/
public function getListTableConstraintsSQL($table)
{
$table = $this->normalizeIdentifier($table);
return "SELECT * FROM user_constraints WHERE table_name = '" . $table->getName() . "'";
}
/**
* {@inheritDoc}
*/
public function getListTableColumnsSQL($table, $database = null)
{
$table = $this->normalizeIdentifier($table);
$tabColumnsTableName = "user_tab_columns";
$colCommentsTableName = "user_col_comments";
$ownerCondition = '';
if (null !== $database) {
$database = $this->normalizeIdentifier($database);
$tabColumnsTableName = "all_tab_columns";
$colCommentsTableName = "all_col_comments";
$ownerCondition = "AND c.owner = '" . $database->getName() . "'";
}
return "SELECT c.*, d.comments FROM $tabColumnsTableName c ".
"INNER JOIN " . $colCommentsTableName . " d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ".
"WHERE c.table_name = '" . $table->getName() . "' ".$ownerCondition." ORDER BY c.column_name";
}
/**
* {@inheritDoc}
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof Sequence) {
$sequence = $sequence->getQuotedName($this);
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* {@inheritDoc}
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof ForeignKeyConstraint) {
$foreignKey = $foreignKey->getQuotedName($this);
}
if ($table instanceof Table) {
$table = $table->getQuotedName($this);
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;
}
/**
* {@inheritdoc}
*/
public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
{
$referentialAction = null;
if ($foreignKey->hasOption('onDelete')) {
$referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
}
return $referentialAction ? ' ON DELETE ' . $referentialAction : '';
}
/**
* {@inheritdoc}
*/
public function getForeignKeyReferentialActionSQL($action)
{
$action = strtoupper($action);
switch ($action) {
case 'RESTRICT': // RESTRICT is not supported, therefore falling back to NO ACTION.
case 'NO ACTION':
// NO ACTION cannot be declared explicitly,
// therefore returning empty string to indicate to OMIT the referential clause.
return '';
case 'CASCADE':
case 'SET NULL':
return $action;
default:
// SET DEFAULT is not supported, throw exception instead.
throw new InvalidArgumentException('Invalid foreign key action: ' . $action);
}
}
/**
* {@inheritDoc}
*/
public function getDropDatabaseSQL($database)
{
return 'DROP USER ' . $database . ' CASCADE';
}
/**
* {@inheritDoc}
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$commentsSQL = array();
$columnSql = array();
$fields = array();
foreach ($diff->addedColumns as $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
if ($comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$comment
);
}
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ADD (' . implode(', ', $fields) . ')';
}
$fields = array();
foreach ($diff->changedColumns as $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
/* @var $columnDiff DoctrineDBALSchemaColumnDiff */
$column = $columnDiff->column;
// Do not generate column alteration clause if type is binary and only fixed property has changed.
// Oracle only supports binary type columns with variable length.
// Avoids unnecessary table alteration statements.
if ($column->getType() instanceof BinaryType &&
$columnDiff->hasChanged('fixed') &&
count($columnDiff->changedProperties) === 1
) {
continue;
}
$columnHasChangedComment = $columnDiff->hasChanged('comment');
/**
* Do not add query part if only comment has changed
*/
if ( ! ($columnHasChangedComment && count($columnDiff->changedProperties) === 1)) {
$columnInfo = $column->toArray();
if ( ! $columnDiff->hasChanged('notnull')) {
unset($columnInfo['notnull']);
}
$fields[] = $column->getQuotedName($this) . $this->getColumnDeclarationSQL('', $columnInfo);
}
if ($columnHasChangedComment) {
$commentsSQL[] = $this->getCommentOnColumnSQL(
$diff->getName($this)->getQuotedName($this),
$column->getQuotedName($this),
$this->getColumnComment($column)
);
}
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' MODIFY (' . implode(', ', $fields) . ')';
}
foreach ($diff->renamedColumns as $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$oldColumnName = new Identifier($oldColumnName);
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) .
' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) .' TO ' . $column->getQuotedName($this);
}
$fields = array();
foreach ($diff->removedColumns as $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$fields[] = $column->getQuotedName($this);
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' DROP (' . implode(', ', $fields).')';
}
$tableSql = array();
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$sql = array_merge($sql, $commentsSQL);
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this);
}
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
}
return array_merge($sql, $tableSql, $columnSql);
}
/**
* {@inheritdoc}
*/
public function getColumnDeclarationSQL($name, array $field)
{
if (isset($field['columnDefinition'])) {
$columnDef = $this->getCustomTypeDeclarationSQL($field);
} else {
$default = $this->getDefaultValueDeclarationSQL($field);
$notnull = '';
if (isset($field['notnull'])) {
$notnull = $field['notnull'] ? ' NOT NULL' : ' NULL';
}
$unique = (isset($field['unique']) && $field['unique']) ?
' ' . $this->getUniqueFieldDeclarationSQL() : '';
$check = (isset($field['check']) && $field['check']) ?
' ' . $field['check'] : '';
$typeDecl = $field['type']->getSqlDeclaration($field, $this);
$columnDef = $typeDecl . $default . $notnull . $unique . $check;
}
return $name . ' ' . $columnDef;
}
/**
* {@inheritdoc}
*/
protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName)
{
if (strpos($tableName, '.') !== false) {
list($schema) = explode('.', $tableName);
$oldIndexName = $schema . '.' . $oldIndexName;
}
return array('ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this));
}
/**
* {@inheritDoc}
*/
public function prefersSequences()
{
return true;
}
/**
* {@inheritdoc}
*/
public function usesSequenceEmulatedIdentityColumns()
{
return true;
}
/**
* {@inheritdoc}
*/
public function getIdentitySequenceName($tableName, $columnName)
{
$table = new Identifier($tableName);
// No usage of column name to preserve BC compatibility with <2.5
$identitySequenceName = $table->getName() . '_SEQ';
if ($table->isQuoted()) {
$identitySequenceName = '"' . $identitySequenceName . '"';
}
$identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName);
return $identitySequenceIdentifier->getQuotedName($this);
}
/**
* {@inheritDoc}
*/
public function supportsCommentOnStatement()
{
return true;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'oracle';
}
/**
* {@inheritDoc}
*/
protected function doModifyLimitQuery($query, $limit, $offset = null)
{
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^s*SELECT/i', $query)) {
if (!preg_match('/sFROMs/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
$max = $offset + $limit;
$column = '*';
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT * FROM (SELECT a.' . $column . ', rownum AS doctrine_rownum FROM (' .
$query .
') a WHERE rownum <= ' . $max . ') WHERE doctrine_rownum >= ' . $min;
} else {
$query = 'SELECT a.' . $column . ' FROM (' . $query . ') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
}
/**
* {@inheritDoc}
*
* Oracle returns all column names in SQL result sets in uppercase.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
/**
* {@inheritDoc}
*/
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE GLOBAL TEMPORARY TABLE";
}
/**
* {@inheritDoc}
*/
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:sP';
}
/**
* {@inheritDoc}
*/
public function getDateFormatString()
{
return 'Y-m-d 00:00:00';
}
/**
* {@inheritDoc}
*/
public function getTimeFormatString()
{
return '1900-01-01 H:i:s';
}
/**
* {@inheritDoc}
*/
public function fixSchemaElementName($schemaElementName)
{
if (strlen($schemaElementName) > 30) {
// Trim it
return substr($schemaElementName, 0, 30);
}
return $schemaElementName;
}
/**
* {@inheritDoc}
*/
public function getMaxIdentifierLength()
{
return 30;
}
/**
* {@inheritDoc}
*/
public function supportsSequences()
{
return true;
}
/**
* {@inheritDoc}
*/
public function supportsForeignKeyOnUpdate()
{
return false;
}
/**
* {@inheritDoc}
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* {@inheritDoc}
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE TABLE '.$tableName;
}
/**
* {@inheritDoc}
*/
public function getDummySelectSQL()
{
return 'SELECT 1 FROM DUAL';
}
/**
* {@inheritDoc}
*/
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'integer' => 'integer',
'number' => 'integer',
'pls_integer' => 'boolean',
'binary_integer' => 'boolean',
'varchar' => 'string',
'varchar2' => 'string',
'nvarchar2' => 'string',
'char' => 'string',
'nchar' => 'string',
'date' => 'datetime',
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'float' => 'float',
'binary_float' => 'float',
'binary_double' => 'float',
'long' => 'string',
'clob' => 'text',
'nclob' => 'text',
'raw' => 'binary',
'long raw' => 'blob',
'rowid' => 'string',
'urowid' => 'string',
'blob' => 'blob',
);
}
/**
* {@inheritDoc}
*/
public function releaseSavePoint($savepoint)
{
return '';
}
/**
* {@inheritDoc}
*/
protected function getReservedKeywordsClass()
{
return 'DoctrineDBALPlatformsKeywordsOracleKeywords';
}
/**
* {@inheritDoc}
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'BLOB';
}
}