/** * Walks down a SelectStatement AST node, wrapping it in a COUNT (SELECT DISTINCT) * * Note that the ORDER BY clause is not removed. Many SQL implementations (e.g. MySQL) * are able to cache subqueries. By keeping the ORDER BY clause intact, the limitSubQuery * that will most likely be executed next can be read from the native SQL cache. * * @param SelectStatement $AST * @return string */ public function walkSelectStatement(SelectStatement $AST) { $sql = parent::walkSelectStatement($AST); // Find out the SQL alias of the identifier column of the root entity // It may be possible to make this work with multiple root entities but that // would probably require issuing multiple queries or doing a UNION SELECT // so for now, It's not supported. // Get the root entity and alias from the AST fromClause $from = $AST->fromClause->identificationVariableDeclarations; if (count($from) > 1) { throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } $rootClass = $from[0]->rangeVariableDeclaration->abstractSchemaName; $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; // Get the identity properties from the metadata $rootIdentifier = $this->queryComponents[$rootAlias]['metadata']->identifier; // For every identifier, find out the SQL alias by combing through the ResultSetMapping $sqlIdentifier = array(); foreach ($rootIdentifier as $property) { foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { $sqlIdentifier[$property] = $alias; } } } if (count($rootIdentifier) != count($sqlIdentifier)) { throw new \RuntimeException(sprintf('Not all identifier properties can be found in the ResultSetMapping: %s', implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))))); } // Build the counter query return sprintf('SELECT %s AS _dctrn_count FROM (SELECT DISTINCT %s FROM (%s) AS _dctrn_result) AS _dctrn_table', $this->platform->getCountExpression('*'), implode(', ', $sqlIdentifier), $sql); }
/** * @group DBAL-374 */ public function testQuotedColumnInIndexPropagation() { $this->markTestSkipped('requires big refactoring of Platforms'); $table = new Table('`quoted`'); $table->addColumn('`key`', 'string'); $table->addIndex(array('key')); $sql = $this->_platform->getCreateTableSQL($table); $this->assertEquals($this->getQuotedColumnInIndexSQL(), $sql); }
/** * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT * * @param SelectStatement $AST * @return string */ public function walkSelectStatement(SelectStatement $AST) { $innerSql = parent::walkSelectStatement($AST); // Find out the SQL alias of the identifier column of the root entity // It may be possible to make this work with multiple root entities but that // would probably require issuing multiple queries or doing a UNION SELECT // so for now, It's not supported. // Get the root entity and alias from the AST fromClause $from = $AST->fromClause->identificationVariableDeclarations; if (count($from) !== 1) { throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; $rootClass = $this->queryComponents[$rootAlias]['metadata']; $rootIdentifier = $rootClass->identifier; // For every identifier, find out the SQL alias by combing through the ResultSetMapping $sqlIdentifier = array(); foreach ($rootIdentifier as $property) { if (isset($rootClass->fieldMappings[$property])) { foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { $sqlIdentifier[$property] = $alias; } } } if (isset($rootClass->associationMappings[$property])) { $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { $sqlIdentifier[$property] = $alias; } } } } if (count($rootIdentifier) != count($sqlIdentifier)) { throw new \RuntimeException(sprintf('Not all identifier properties can be found in the ResultSetMapping: %s', implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))))); } // Build the counter query $sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result', implode(', ', $sqlIdentifier), $innerSql); if ($this->platform instanceof PostgreSqlPlatform) { //http://www.doctrine-project.org/jira/browse/DDC-1958 $this->getPostgresqlSql($AST, $sqlIdentifier, $innerSql, $sql); } // Apply the limit and offset $sql = $this->platform->modifyLimitQuery($sql, $this->maxResults, $this->firstResult); // Add the columns to the ResultSetMapping. It's not really nice but // it works. Preferably I'd clear the RSM or simply create a new one // but that is not possible from inside the output walker, so we dirty // up the one we have. foreach ($sqlIdentifier as $property => $alias) { $this->rsm->addScalarResult($alias, $property); } return $sql; }
/** * Lock all rows of this entity matching the given criteria with the specified pessimistic lock mode * * @param array $criteria * @param int $lockMode * @return void */ public function lock(array $criteria, $lockMode) { $conditionSql = $this->_getSelectConditionSQL($criteria); if ($lockMode == LockMode::PESSIMISTIC_READ) { $lockSql = $this->_platform->getReadLockSql(); } else { if ($lockMode == LockMode::PESSIMISTIC_WRITE) { $lockSql = $this->_platform->getWriteLockSql(); } } $sql = 'SELECT 1 ' . $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode) . ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql; list($params, $types) = $this->expandParameters($criteria); $stmt = $this->_conn->executeQuery($sql, $params, $types); }
/** * Lock all rows of this entity matching the given criteria with the specified pessimistic lock mode * * @param array $criteria * @param int $lockMode * @return void */ public function lock(array $criteria, $lockMode) { $conditionSql = $this->_getSelectConditionSQL($criteria); if ($lockMode == LockMode::PESSIMISTIC_READ) { $lockSql = $this->_platform->getReadLockSql(); } else { if ($lockMode == LockMode::PESSIMISTIC_WRITE) { $lockSql = $this->_platform->getWriteLockSql(); } } $sql = 'SELECT 1 ' . $this->getLockTablesSql() . ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql; $params = array_values($criteria); $this->_conn->executeQuery($sql, $params); }
/** * Lock all rows of this entity matching the given criteria with the specified pessimistic lock mode * * @param array $criteria * @param int $lockMode * @return void */ public function lock(array $criteria, $lockMode) { $conditionSql = $this->_getSelectConditionSQL($criteria); if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_READ) { $lockSql = $this->_platform->getReadLockSql(); } else { if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) { $lockSql = $this->_platform->getWriteLockSql(); } } $sql = 'SELECT 1 FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($this->_class->name) . ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql; $params = array_values($criteria); $this->_conn->executeQuery($sql, $params); }
private function getRevisionId() { if ($this->revisionId === null) { $date = date_create("now")->format($this->platform->getDateTimeFormatString()); if ($this->config->getCurrentUser() != null) { $userId = $this->config->getCurrentUser()->getId(); } else { $userId = null; } $this->conn->insert($this->config->getRevisionTableName(), array('timestamp' => $date, 'user_id' => $userId, 'note' => $this->config->getNote(), 'ipaddress' => $this->config->getIpAddress())); $sequenceName = $this->platform->supportsSequences() ? 'REVISIONS_ID_SEQ' : null; $this->revisionId = $this->conn->lastInsertId($sequenceName); } return $this->revisionId; }
/** * Gets the SQL snippet for all join columns of the given class that are to be * placed in an SQL SELECT statement. * * @param $class * @return string * @todo Not reused... inline? */ private function _getSelectJoinColumnsSQL(ClassMetadata $class) { $sql = ''; foreach ($class->associationMappings as $assoc) { if ($assoc->isOwningSide && $assoc->isOneToOne()) { foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { $columnAlias = $srcColumn . $this->_sqlAliasCounter++; $sql .= ', ' . $this->_getSQLTableAlias($this->_class->name) . ".{$srcColumn} AS {$columnAlias}"; $resultColumnName = $this->_platform->getSQLResultCasing($columnAlias); if (!isset($this->_resultColumnNames[$resultColumnName])) { $this->_resultColumnNames[$resultColumnName] = $srcColumn; } } } } return $sql; }
/** * Shrani array sprememb entitet v bazo * * @param array $changes */ protected function saveChanges($changes) { $sql = "INSERT INTO {$this->tableName} (razred, objectId, upor, datum, tip, data)\n VALUES (?, ?, ?, ?, ?, ?)"; $stmt = $this->conn->prepare($sql); $date = date_create("now")->format($this->platform->getDateTimeFormatString()); $user = $this->identity ? $this->identity->getId() : null; foreach ($changes as $objectId => $change) { $class = get_class($change['entity']); $type = $change['type']; $data = serialize($change['data']); $stmt->bindValue(1, $class, \PDO::PARAM_STR); $stmt->bindValue(2, $objectId, \PDO::PARAM_STR); $stmt->bindValue(3, $user, \PDO::PARAM_STR); $stmt->bindValue(4, $date, \PDO::PARAM_STR); $stmt->bindValue(5, $type, \PDO::PARAM_STR); $stmt->bindValue(6, $data, \PDO::PARAM_STR); $stmt->execute(); } }
/** * Get the SQL Statements to drop the given schema from underlying db. * * @param Schema $dropSchema * @return array */ public function getDropSchema(Schema $dropSchema) { $visitor = new DropSchemaSqlCollector($this->platform); $sm = $this->conn->getSchemaManager(); $fullSchema = $sm->createSchema(); foreach ($fullSchema->getTables() as $table) { if ($dropSchema->hasTable($table->getName())) { $visitor->acceptTable($table); } foreach ($table->getForeignKeys() as $foreignKey) { if (!$dropSchema->hasTable($table->getName())) { continue; } if (!$dropSchema->hasTable($foreignKey->getForeignTableName())) { continue; } $visitor->acceptForeignKey($table, $foreignKey); } } if (!$this->platform->supportsSequences()) { return $visitor->getQueries(); } foreach ($dropSchema->getSequences() as $sequence) { $visitor->acceptSequence($sequence); } foreach ($dropSchema->getTables() as $table) { /* @var $sequence Table */ if (!$table->hasPrimaryKey()) { continue; } $columns = $table->getPrimaryKey()->getColumns(); if (count($columns) > 1) { continue; } $checkSequence = $table->getName() . "_" . $columns[0] . "_seq"; if ($fullSchema->hasSequence($checkSequence)) { $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); } } return $visitor->getQueries(); }
/** * Gets an SQL column alias for a column name. * * @param string $columnName * @return string */ public function getSQLColumnAlias($columnName) { // Trim the column alias to the maximum identifier length of the platform. // If the alias is to long, characters are cut off from the beginning. return $this->_platform->getSQLResultCasing(substr($columnName . $this->_sqlAliasCounter++, -$this->_platform->getMaxIdentifierLength())); }
/** * rollbackSavePoint * releases given savepoint * * @param string $savepoint name of a savepoint to rollback to * @return void */ public function rollbackSavepoint($savepoint) { if (!$this->_platform->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_conn->exec($this->_platform->rollbackSavePoint($savepoint)); }
/** * Quote a string so it can be safely used as a table or column name, even if * it is a reserved name. * * Delimiting style depends on the underlying database platform that is being used. * * NOTE: Just because you CAN use quoted identifiers does not mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * * @param string $str The name to be quoted. * @return string The quoted name. */ public function quoteIdentifier($str) { return $this->_platform->quoteIdentifier($str); }
/** * @group DBAL-45 */ public function testKeywordList() { $keywordList = $this->_platform->getReservedKeywordsList(); $this->assertInstanceOf('Doctrine\\DBAL\\Platforms\\Keywords\\KeywordList', $keywordList); $this->assertTrue($keywordList->isKeyword('table')); }
public function testGetCustomColumnDeclarationSql() { $field = array('columnDefinition' => 'MEDIUMINT(6) UNSIGNED'); $this->assertEquals('foo MEDIUMINT(6) UNSIGNED', $this->_platform->getColumnDeclarationSQL('foo', $field)); }
/** * Sets the transaction isolation level. * * @param integer $level The level to set. */ public function setTransactionIsolation($level) { $this->_transactionIsolationLevel = $level; return $this->exec($this->_platform->getSetTransactionIsolationSql($level)); }