public function setSubselect($subselect) { if ($this->_simpleArithmeticExpression) { throw \Doctrine\Common\DoctrineException::updateMe(); } $this->_subselect = $subselect; }
/** * Adds an adapter-specific LIMIT clause to the SELECT statement. * [ borrowed from Zend Framework ] * * @param string $query * @param mixed $limit * @param mixed $offset * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html * @return string * @override */ public function writeLimitClause($query, $limit = false, $offset = false) { if ($limit > 0) { $count = intval($limit); $offset = intval($offset); if ($offset < 0) { throw \Doctrine\Common\DoctrineException::limitOffsetInvalid($offset); } $orderby = stristr($query, 'ORDER BY'); if ($orderby !== false) { $sort = stripos($orderby, 'desc') !== false ? 'desc' : 'asc'; $order = str_ireplace('ORDER BY', '', $orderby); $order = trim(preg_replace('/ASC|DESC/i', '', $order)); } $query = preg_replace('/^SELECT\\s/i', 'SELECT TOP ' . ($count + $offset) . ' ', $query); $query = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $query . ') AS inner_tbl'; if ($orderby !== false) { $query .= ' ORDER BY ' . $order . ' '; $query .= stripos($sort, 'asc') !== false ? 'DESC' : 'ASC'; } $query .= ') AS outer_tbl'; if ($orderby !== false) { $query .= ' ORDER BY ' . $order . ' ' . $sort; } return $query; } return $query; }
/** * Overrides an already defined type to use a different implementation. * * @param string $name * @param string $className */ public static function overrideType($name, $className) { if (!isset(self::$_typesMap[$name])) { throw DoctrineException::typeNotFound($name); } self::$_typesMap[$name] = $className; }
/** * Add a single namespace to CLI. * Example of inclusion support to a single namespace: * * [php] * $cliOrmNamespace->addNamespace('my-custom-namespace'); * * @param string $name CLI Namespace name * * @return CliController This object instance */ public function addNamespace($name) { $name = self::formatName($name); if ($this->hasNamespace($name)) { throw DoctrineException::cannotOverrideNamespace($name); } return $this->overrideNamespace($name); }
/** * constructor * * @param Doctrine_Connection $conn Doctrine_Connection object, every connection * statement holds an instance of Doctrine_Connection * @param mixed $stmt */ public function __construct(Connection $conn, $stmt) { $this->_conn = $conn; $this->_stmt = $stmt; if ($stmt === false) { throw \Doctrine\Common\DoctrineException::updateMe('Unknown statement object given.'); } }
/** * {@inheritdoc} */ public function __construct($options) { if (!isset($options['connection']) || !$options['connection'] instanceof Doctrine_DBAL_Connection) { throw \Doctrine\Common\DoctrineException::updateMe('Connection option not set.'); } if (!isset($options['tableName']) || !is_string($options['tableName'])) { throw \Doctrine\Common\DoctrineException::updateMe('Table name option not set.'); } $this->_options = $options; }
/** * Initializes a new instance of the <tt>ProxyFactory</tt> class that is * connected to the given <tt>EntityManager</tt>. * * @param EntityManager $em The EntityManager the new factory works for. * @param string $proxyDir The directory to use for the proxy classes. It must exist. * @param string $proxyNs The namespace to use for the proxy classes. * @param boolean $autoGenerate Whether to automatically generate proxy classes. */ public function __construct(EntityManager $em, $proxyDir, $proxyNs, $autoGenerate = false) { if (!$proxyDir) { throw DoctrineException::proxyDirectoryRequired(); } if (!$proxyNs) { throw DoctrineException::proxyNamespaceRequired(); } $this->_em = $em; $this->_proxyDir = $proxyDir; $this->_autoGenerate = $autoGenerate; $this->_proxyNamespace = $proxyNs; }
/** * Returns the identifier assigned to the given entity. * * @param object $entity * @return mixed * @override */ public function generate(EntityManager $em, $entity) { $class = $em->getClassMetadata(get_class($entity)); $identifier = null; if ($class->isIdentifierComposite()) { $identifier = array(); $idFields = $class->getIdentifierFieldNames(); foreach ($idFields as $idField) { $identifier[] = $value = $class->getReflectionProperty($idField)->getValue($entity); if (isset($value)) { $identifier[] = $value; } } } else { $value = $class->getReflectionProperty($class->getSingleIdentifierFieldName())->getValue($entity); if (isset($value)) { $identifier = array($value); } } if (!$identifier) { throw DoctrineException::updateMe("Entity of type '" . get_class($entity) . "' is missing an assigned ID."); } return $identifier; }
/** * alter an existing table * * @param string $name name of the table that is intended to be changed. * @param array $changes associative array that contains the details of each type * of change that is intended to be performed. The types of * changes that are currently supported are defined as follows: * * name * * New name for the table. * * add * * Associative array with the names of fields to be added as * indexes of the array. The value of each entry of the array * should be set to another associative array with the properties * of the fields to be added. The properties of the fields should * be the same as defined by the Metabase parser. * * * remove * * Associative array with the names of fields to be removed as indexes * of the array. Currently the values assigned to each entry are ignored. * An empty array should be used for future compatibility. * * rename * * Associative array with the names of fields to be renamed as indexes * of the array. The value of each entry of the array should be set to * another associative array with the entry named name with the new * field name and the entry named Declaration that is expected to contain * the portion of the field declaration already in DBMS specific SQL code * as it is used in the CREATE TABLE statement. * * change * * Associative array with the names of the fields to be changed as indexes * of the array. Keep in mind that if it is intended to change either the * name of a field and any other properties, the change array entries * should have the new names of the fields as array indexes. * * The value of each entry of the array should be set to another associative * array with the properties of the fields to that are meant to be changed as * array entries. These entries should be assigned to the new values of the * respective properties. The properties of the fields should be the same * as defined by the Metabase parser. * * Example * array( * 'name' => 'userlist', * 'add' => array( * 'quota' => array( * 'type' => 'integer', * 'unsigned' => 1 * ) * ), * 'remove' => array( * 'file_limit' => array(), * 'time_limit' => array() * ), * 'change' => array( * 'name' => array( * 'length' => '20', * 'definition' => array( * 'type' => 'text', * 'length' => 20, * ), * ) * ), * 'rename' => array( * 'sex' => array( * 'name' => 'gender', * 'definition' => array( * 'type' => 'text', * 'length' => 1, * 'default' => 'M', * ), * ) * ) * ) * * @param boolean $check indicates whether the function should just check if the DBMS driver * can perform the requested table alterations if the value is true or * actually perform them otherwise. * @return void */ public function alterTable($name, array $changes, $check = false) { foreach ($changes as $changeName => $change) { switch ($changeName) { case 'add': break; case 'remove': break; case 'name': case 'rename': case 'change': default: throw \Doctrine\Common\DoctrineException::updateMe('alterTable: change type "' . $changeName . '" not yet supported'); } } $query = ''; if (!empty($changes['add']) && is_array($changes['add'])) { foreach ($changes['add'] as $fieldName => $field) { if ($query) { $query .= ', '; } $query .= 'ADD ' . $this->getDeclaration($fieldName, $field); } } if (!empty($changes['remove']) && is_array($changes['remove'])) { foreach ($changes['remove'] as $fieldName => $field) { if ($query) { $query .= ', '; } $field_name = $this->conn->quoteIdentifier($fieldName, true); $query .= 'DROP COLUMN ' . $fieldName; } } if (!$query) { return false; } $name = $this->conn->quoteIdentifier($name, true); return $this->conn->exec('ALTER TABLE ' . $name . ' ' . $query); }
/** * lists all databases * * @return array */ public function listDatabases() { if (!$this->_conn->getAttribute(Doctrine::ATTR_EMULATE_DATABASE)) { throw \Doctrine\Common\DoctrineException::updateMe('database listing is only supported if the "emulate_database" option is enabled'); } /** if ($this->_conn->options['database_name_prefix']) { $query = 'SELECT SUBSTR(username, '; $query.= (strlen($this->_conn->getAttribute(['database_name_prefix'])+1); $query.= ") FROM sys.dba_users WHERE username LIKE '"; $query.= $this->_conn->options['database_name_prefix']."%'"; } else { */ $query = 'SELECT username FROM sys.dba_users'; $result2 = $this->_conn->standaloneQuery($query); $result = $result2->fetchColumn(); return $result; }
/** * getIndexFieldDeclarationList * Obtain DBMS specific SQL code portion needed to set an index * declaration to be used in statements like CREATE TABLE. * * @return string * @override */ public function getIndexFieldDeclarationListSql(array $fields) { $declFields = array(); foreach ($fields as $fieldName => $field) { $fieldString = $this->quoteIdentifier($fieldName); if (is_array($field)) { if (isset($field['length'])) { $fieldString .= '(' . $field['length'] . ')'; } if (isset($field['sorting'])) { $sort = strtoupper($field['sorting']); switch ($sort) { case 'ASC': case 'DESC': $fieldString .= ' ' . $sort; break; default: throw DoctrineException::updateMe('Unknown index sorting option given.'); } } } else { $fieldString = $this->quoteIdentifier($field); } $declFields[] = $fieldString; } return implode(', ', $declFields); }
/** * Factory method to create EntityManager instances. * * @param mixed $conn An array with the connection parameters or an existing * Connection instance. * @param string $name The name of the EntityManager. * @param Configuration $config The Configuration instance to use. * @param EventManager $eventManager The EventManager instance to use. * @return EntityManager The created EntityManager. */ public static function create($conn, Configuration $config = null, EventManager $eventManager = null) { if (is_array($conn)) { $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, $eventManager); } else { if (!$conn instanceof Connection) { throw DoctrineException::updateMe("Invalid parameter '{$conn}'."); } } if ($config === null) { $config = new Configuration(); } if ($eventManager === null) { $eventManager = new EventManager(); } $em = new EntityManager($conn, $config, $eventManager); return $em; }
/** * {@inheritdoc} */ public function __construct() { if (!extension_loaded('apc')) { \Doctrine\Common\DoctrineException::updateMe('The apc extension must be loaded in order to use the ApcCache.'); } }
/** * SelectExpression ::= * IdentificationVariable | StateFieldPathExpression | * (AggregateExpression | "(" Subselect ")" | FunctionDeclaration) [["AS"] AliasResultVariable] * * @return \Doctrine\ORM\Query\AST\SelectExpression */ public function SelectExpression() { $expression = null; $fieldAliasIdentificationVariable = null; $peek = $this->_lexer->glimpse(); // First we recognize for an IdentificationVariable (DQL class alias) if ($peek['value'] != '.' && $peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) { $expression = $this->IdentificationVariable(); } else { if (($isFunction = $this->_isFunction()) !== false || $this->_isSubselect()) { if ($isFunction) { if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) { $expression = $this->AggregateExpression(); } else { $expression = $this->FunctionDeclaration(); } } else { $this->match(Lexer::T_OPEN_PARENTHESIS); $expression = $this->Subselect(); $this->match(Lexer::T_CLOSE_PARENTHESIS); } if ($this->_lexer->isNextToken(Lexer::T_AS)) { $this->match(Lexer::T_AS); } if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { $token = $this->_lexer->lookahead; $fieldAliasIdentificationVariable = $this->AliasResultVariable(); // Include AliasResultVariable in query components. $this->_queryComponents[$fieldAliasIdentificationVariable] = array('resultVariable' => $expression, 'nestingLevel' => $this->_nestingLevel, 'token' => $token); } } else { // Deny hydration of partial objects if doctrine.forcePartialLoad query hint not defined if ($this->_query->getHydrationMode() == Query::HYDRATE_OBJECT && !$this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { throw DoctrineException::partialObjectsAreDangerous(); } $expression = $this->StateFieldPathExpression(); } } return new AST\SelectExpression($expression, $fieldAliasIdentificationVariable); }
public function generate(EntityManager $em, $entity) { throw \Doctrine\Common\DoctrineException::updateMe("Not implemented"); }
/** * Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL. * * @param CollectionMemberExpression * @return string The SQL. */ public function walkCollectionMemberExpression($collMemberExpr) { $sql = $collMemberExpr->not ? 'NOT ' : ''; $sql .= 'EXISTS (SELECT 1 FROM '; $entityExpr = $collMemberExpr->entityExpression; $collPathExpr = $collMemberExpr->collectionValuedPathExpression; $parts = $collPathExpr->parts; $fieldName = array_pop($parts); $dqlAlias = $collPathExpr->identificationVariable . (!empty($parts) ? '.' . implode('.', $parts) : ''); $class = $this->_queryComponents[$dqlAlias]['metadata']; if ($entityExpr instanceof AST\InputParameter) { $dqlParamKey = $entityExpr->name; $entity = $this->_query->getParameter($dqlParamKey); } else { //TODO throw DoctrineException::notImplemented(); } $assoc = $class->associationMappings[$fieldName]; if ($assoc->isOneToMany()) { $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); $targetTableAlias = $this->getSqlTableAlias($targetClass->primaryTable['name']); $sourceTableAlias = $this->getSqlTableAlias($class->primaryTable['name'], $dqlAlias); $sql .= $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' WHERE '; $owningAssoc = $targetClass->associationMappings[$assoc->mappedByFieldName]; $first = true; foreach ($owningAssoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) { if ($first) { $first = false; } else { $sql .= ' AND '; } $sql .= $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform) . ' = ' . $targetTableAlias . '.' . $owningAssoc->getQuotedJoinColumnName($sourceColumn, $this->_platform); } $sql .= ' AND '; $first = true; foreach ($targetClass->identifier as $idField) { if ($first) { $first = false; } else { $sql .= ' AND '; } $this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++); $sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?'; } } else { // many-to-many $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); $owningAssoc = $assoc->isOwningSide ? $assoc : $targetClass->associationMappings[$assoc->mappedByFieldName]; $joinTable = $assoc->isOwningSide ? $assoc->joinTable : $owningAssoc->joinTable; // SQL table aliases $joinTableAlias = $this->getSqlTableAlias($joinTable['name']); $targetTableAlias = $this->getSqlTableAlias($targetClass->primaryTable['name']); $sourceTableAlias = $this->getSqlTableAlias($class->primaryTable['name'], $dqlAlias); // join to target table $sql .= $assoc->getQuotedJoinTableName($this->_platform) . ' ' . $joinTableAlias . ' INNER JOIN ' . $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' ON '; // join conditions $joinColumns = $assoc->isOwningSide ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns']; $referencedColumnClass = $assoc->isOwningSide ? $class : $targetClass; $first = true; foreach ($joinColumns as $joinColumn) { if ($first) { $first = false; } else { $sql .= ' AND '; } $sql .= $joinTableAlias . '.' . $owningAssoc->getQuotedJoinColumnName($joinColumn['name'], $this->_platform) . ' = ' . $sourceTableAlias . '.' . $referencedColumnClass->getQuotedColumnName($referencedColumnClass->fieldNames[$joinColumn['referencedColumnName']], $this->_platform); } $sql .= ' WHERE '; $joinColumns = $assoc->isOwningSide ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns']; $first = true; foreach ($joinColumns as $joinColumn) { if ($first) { $first = false; } else { $sql .= ' AND '; } $sql .= $joinTableAlias . '.' . $owningAssoc->getQuotedJoinColumnName($joinColumn['name'], $this->_platform) . ' = ' . $targetTableAlias . '.' . $referencedColumnClass->getQuotedColumnName($referencedColumnClass->fieldNames[$joinColumn['referencedColumnName']], $this->_platform); } $sql .= ' AND '; $first = true; foreach ($targetClass->identifier as $idField) { if ($first) { $first = false; } else { $sql .= ' AND '; } $this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++); $sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?'; } } return $sql . ')'; }
/** * create sequence * * @param string $seqName name of the sequence to be created * @param string $start start value of the sequence; default is 1 * @param array $options An associative array of table options: * array( * 'comment' => 'Foo', * 'charset' => 'utf8', * 'collate' => 'utf8_unicode_ci', * ); * @return boolean */ public function createSequence($seqName, $start = 1, array $options = array()) { $sequenceName = $this->_conn->formatter->getSequenceName($seqName); $this->_conn->exec('CREATE GENERATOR ' . $sequenceName); try { $this->_conn->exec('SET GENERATOR ' . $sequenceName . ' TO ' . ($start - 1)); return true; } catch (Doctrine\DBAL\ConnectionException $e) { try { $this->dropSequence($seqName); } catch (Doctrine\DBAL\ConnectionException $e) { throw \Doctrine\Common\DoctrineException::updateMe('Could not drop inconsistent sequence table'); } } throw \Doctrine\Common\DoctrineException::updateMe('could not create sequence table'); }
/** * Obtain DBMS specific SQL code portion needed to declare an text type * field to be used in statements like CREATE TABLE. * * @param array $field associative array with the name of the properties * of the field being declared as array indexes. Currently, the types * of supported field properties are as follows: * * length * Integer value that determines the maximum length of the text * field. If this argument is missing the field should be * declared to have the longest length allowed by the DBMS. * * default * Text value to be used as default for this field. * * notnull * Boolean flag that indicates whether this field is constrained * to not be set to null. * * @return string DBMS specific SQL code portion that should be used to * declare the specified field. * @override */ public function getNativeDeclaration($field) { if (!isset($field['type'])) { throw \Doctrine\Common\DoctrineException::updateMe('Missing column type.'); } switch ($field['type']) { case 'char': case 'varchar': case 'array': case 'object': case 'string': if (empty($field['length']) && array_key_exists('default', $field)) { $field['length'] = $this->conn->varchar_max_length; } $length = !empty($field['length']) ? $field['length'] : false; $fixed = isset($field['fixed']) && $field['fixed'] || $field['type'] == 'char' ? true : false; return $fixed ? $length ? 'CHAR(' . $length . ')' : 'CHAR(255)' : ($length ? 'VARCHAR(' . $length . ')' : 'NVARCHAR'); case 'clob': return 'TEXT'; case 'blob': return 'BLOB'; case 'integer': if (!empty($field['length'])) { $length = $field['length']; if ($length <= 1) { return 'SMALLINT'; } elseif ($length == 2) { return 'SMALLINT'; } elseif ($length == 3 || $length == 4) { return 'INTEGER'; } elseif ($length > 4) { return 'DECIMAL(20)'; } } return 'INT'; case 'boolean': return 'SMALLINT'; case 'date': return 'DATE'; case 'time': return 'DATETIME YEAR TO SECOND'; case 'timestamp': return 'DATETIME'; case 'float': return 'FLOAT'; case 'decimal': return 'DECIMAL'; } throw \Doctrine\Common\DoctrineException::updateMe('Unknown field type \'' . $field['type'] . '\'.'); }
/** * Adds support for magic finders. * * @return array|object The found entity/entities. * @throws BadMethodCallException If the method called is an invalid find* method * or no find* method at all and therefore an invalid * method call. */ public function __call($method, $arguments) { if (substr($method, 0, 6) == 'findBy') { $by = substr($method, 6, strlen($method)); $method = 'findBy'; } else { if (substr($method, 0, 9) == 'findOneBy') { $by = substr($method, 9, strlen($method)); $method = 'findOneBy'; } else { throw new \BadMethodCallException("Undefined method '{$method}'."); } } if (!isset($arguments[0])) { throw DoctrineException::findByNameRequired(); } $fieldName = lcfirst(\Doctrine\Common\Util\Inflector::classify($by)); if ($this->_class->hasField($fieldName)) { return $this->{$method}(array($fieldName => $arguments[0])); } else { throw \Doctrine\Common\DoctrineException::invalidFindBy($by); } }
public function generate(EntityManager $em, $entity) { throw \Doctrine\Common\DoctrineException::notImplemented(__CLASS__ . '::' . __FUNCTION__); }
/** * Deletes an entity as part of the current unit of work. * * This method is internally called during delete() cascades as it tracks * the already visited entities to prevent infinite recursions. * * @param object $entity The entity to delete. * @param array $visited The map of the already visited entities. */ private function _doDelete($entity, array &$visited) { $oid = spl_object_hash($entity); if (isset($visited[$oid])) { return; // Prevent infinite recursion } $visited[$oid] = $entity; // mark visited switch ($this->getEntityState($entity)) { case self::STATE_NEW: case self::STATE_DELETED: // nothing to do break; case self::STATE_MANAGED: $this->registerDeleted($entity); break; case self::STATE_DETACHED: throw DoctrineException::updateMe("A detached entity can't be deleted."); default: throw DoctrineException::updateMe("Encountered invalid entity state."); } $this->_cascadeDelete($entity, $visited); }
/** * Checks the list of parameters. * * @param array $params */ private static function _checkParams(array $params) { // check existance of mandatory parameters // driver if (!isset($params['driver']) && !isset($params['driverClass'])) { throw DoctrineException::driverRequired(); } // check validity of parameters // driver if (isset($params['driver']) && !isset(self::$_driverMap[$params['driver']])) { throw DoctrineException::unknownDriver($params['driver']); } }
/** * create a new table * * @param string $name Name of the database that should be created * @param array $fields Associative array that contains the definition of each field of the new table * The indexes of the array entries are the names of the fields of the table an * the array entry values are associative arrays like those that are meant to be * passed with the field definitions to get[Type]Declaration() functions. * array( * 'id' => array( * 'type' => 'integer', * 'unsigned' => 1 * 'notnull' => 1 * 'default' => 0 * ), * 'name' => array( * 'type' => 'text', * 'length' => 12 * ), * 'password' => array( * 'type' => 'text', * 'length' => 12 * ) * ); * @param array $options An associative array of table options: * * @return void * @override */ protected function _getCreateTableSql($name, array $columns, array $options = array()) { if (!$name) { throw DoctrineException::invalidTableName($name); } if (empty($columns)) { throw DoctrineException::noFieldsSpecifiedForTable($name); } $queryFields = $this->getColumnDeclarationListSql($columns); $autoinc = false; foreach ($columns as $field) { if (isset($field['autoincrement']) && $field['autoincrement']) { $autoinc = true; break; } } if (!$autoinc && isset($options['primary']) && !empty($options['primary'])) { $keyColumns = array_unique(array_values($options['primary'])); $keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns); $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } $query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')'; if (isset($options['indexes']) && !empty($options['indexes'])) { foreach ($options['indexes'] as $index => $indexDef) { $query[] = $this->getCreateIndexSql($indexDef, $name); } } if (isset($options['unique']) && !empty($options['unique'])) { foreach ($options['unique'] as $index => $indexDef) { $query[] = $this->getCreateIndexSql($indexDef, $name); } } return $query; }
/** * Gets the name of the single id field. Note that this only works on * entity classes that have a single-field pk. * * @return string */ public function getSingleIdentifierFieldName() { if ($this->isIdentifierComposite) { throw DoctrineException::updateMe("Calling getSingleIdentifierFieldName " . "on a class that uses a composite identifier is not allowed."); } return $this->identifier[0]; }
/** * {@inheritdoc} */ public function __construct() { if (!extension_loaded('memcache')) { throw \Doctrine\Common\DoctrineException::updateMe('In order to use Memcache driver, the memcache extension must be loaded.'); } }
/** * Enter description here... * * @param integer $level */ public function getSetTransactionIsolationSql($level) { throw DoctrineException::updateMe('Set transaction isolation not supported by this platform.'); }
/** * create sequence * * @param string $sequenceName name of the sequence to be created * @param string $start start value of the sequence; default is 1 * @param array $options An associative array of table options: * array( * 'comment' => 'Foo', * 'charset' => 'utf8', * 'collate' => 'utf8_unicode_ci', * 'type' => 'innodb', * ); * @return boolean * @override */ public function createSequence($sequenceName, $start = 1, array $options = array()) { $sequenceName = $this->_conn->quoteIdentifier($this->_conn->getSequenceName($sequenceName), true); $seqcolName = $this->_conn->quoteIdentifier($this->_conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true); $optionsStrings = array(); if (isset($options['comment']) && !empty($options['comment'])) { $optionsStrings['comment'] = 'COMMENT = ' . $this->_conn->quote($options['comment'], 'string'); } if (isset($options['charset']) && !empty($options['charset'])) { $optionsStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset']; if (isset($options['collate'])) { $optionsStrings['collate'] .= ' COLLATE ' . $options['collate']; } } $type = false; if (isset($options['type'])) { $type = $options['type']; } else { $type = $this->_conn->default_table_type; } if ($type) { $optionsStrings[] = 'ENGINE = ' . $type; } try { $query = 'CREATE TABLE ' . $sequenceName . ' (' . $seqcolName . ' INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (' . $seqcolName . '))'; if (!empty($options_strings)) { $query .= ' ' . implode(' ', $options_strings); } $res = $this->_conn->exec($query); } catch (Doctrine\DBAL\ConnectionException $e) { throw \Doctrine\Common\DoctrineException::updateMe('could not create sequence table'); } if ($start == 1) { return true; } $query = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (' . ($start - 1) . ')'; $res = $this->_conn->exec($query); // Handle error try { $res = $this->_conn->exec('DROP TABLE ' . $sequenceName); } catch (Doctrine\DBAL\ConnectionException $e) { throw \Doctrine\Common\DoctrineException::updateMe('could not drop inconsistent sequence table'); } return $res; }
private function _convertColumn($className, $name, $column, ClassMetadataInfo $metadata) { if (is_string($column)) { $string = $column; $column = array(); $column['type'] = $string; } if (!isset($column['name'])) { $column['name'] = $name; } // check if a column alias was used (column_name as field_name) if (preg_match("/(\\w+)\\sas\\s(\\w+)/i", $column['name'], $matches)) { $name = $matches[1]; $column['name'] = $name; $column['alias'] = $matches[2]; } if (preg_match("/([a-zA-Z]+)\\(([0-9]+)\\)/", $column['type'], $matches)) { $column['type'] = $matches[1]; $column['length'] = $matches[2]; } $column['type'] = strtolower($column['type']); // check if legacy column type (1.x) needs to be mapped to a 2.0 one if (isset($this->_legacyTypeMap[$column['type']])) { $column['type'] = $this->_legacyTypeMap[$column['type']]; } if (!\Doctrine\DBAL\Types\Type::hasType($column['type'])) { throw DoctrineException::couldNotMapDoctrine1Type($column['type']); } $fieldMapping = array(); if (isset($column['primary'])) { $fieldMapping['id'] = true; } $fieldMapping['fieldName'] = isset($column['alias']) ? $column['alias'] : $name; $fieldMapping['columnName'] = $column['name']; $fieldMapping['type'] = $column['type']; if (isset($column['length'])) { $fieldMapping['length'] = $column['length']; } $allowed = array('precision', 'scale', 'unique', 'options', 'notnull', 'version'); foreach ($column as $key => $value) { if (in_array($key, $allowed)) { $fieldMapping[$key] = $value; } } $metadata->mapField($fieldMapping); if (isset($column['autoincrement'])) { $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); } else { if (isset($column['sequence'])) { $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE); $metadata->setSequenceGeneratorDefinition($definition); $definition = array('sequenceName' => is_array($column['sequence']) ? $column['sequence']['name'] : $column['sequence']); if (isset($column['sequence']['size'])) { $definition['allocationSize'] = $column['sequence']['size']; } if (isset($column['sequence']['value'])) { $definition['initialValue'] = $column['sequence']['value']; } } } return $fieldMapping; }
/** * create a new table * * @param string $name Name of the database that should be created * @param array $fields Associative array that contains the definition of each field of the new table * The indexes of the array entries are the names of the fields of the table an * the array entry values are associative arrays like those that are meant to be * passed with the field definitions to get[Type]Declaration() functions. * array( * 'id' => array( * 'type' => 'integer', * 'unsigned' => 1 * 'notnull' => 1 * 'default' => 0 * ), * 'name' => array( * 'type' => 'text', * 'length' => 12 * ), * 'password' => array( * 'type' => 'text', * 'length' => 12 * ) * ); * @param array $options An associative array of table options: * * @return void * @override */ public function getCreateTableSql($name, array $fields, array $options = array()) { if (!$name) { throw DoctrineException::invalidTableName($name); } if (empty($fields)) { throw DoctrineException::noFieldsSpecifiedForTable($name); } $queryFields = $this->getColumnDeclarationListSql($fields); $autoinc = false; foreach ($fields as $field) { if (isset($field['autoincrement']) && $field['autoincrement']) { $autoinc = true; break; } } if (!$autoinc && isset($options['primary']) && !empty($options['primary'])) { $keyColumns = array_unique(array_values($options['primary'])); $keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns); $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } $name = $this->quoteIdentifier($name, true); $sql = 'CREATE TABLE ' . $name . ' (' . $queryFields; /*if ($check = $this->getCheckDeclarationSql($fields)) { $sql .= ', ' . $check; } if (isset($options['checks']) && $check = $this->getCheckDeclarationSql($options['checks'])) { $sql .= ', ' . $check; }*/ $sql .= ')'; $query[] = $sql; if (isset($options['indexes']) && !empty($options['indexes'])) { foreach ($options['indexes'] as $index => $definition) { $query[] = $this->getCreateIndexSql($name, $index, $definition); } } return $query; }
/** * Looks up the field name for a (lowercased) column name. * * This is mostly used during hydration, because we want to make the * conversion to field names while iterating over the result set for best * performance. By doing this at that point, we can avoid re-iterating over * the data just to convert the column names to field names. * * However, when this is happening, we don't know the real * class name to instantiate yet (the row data may target a sub-type), hence * this method looks up the field name in the subclass mappings if it's not * found on this class mapping. * This lookup on subclasses is costly but happens only *once* for a column * during hydration because the hydrator caches effectively. * * @return string The field name. * @throws DoctrineException If the field name could not be found. */ private function _lookupDeclaringClass($class, $fieldName) { if (isset($class->reflFields[$fieldName])) { return $class; } foreach ($class->subClasses as $subClass) { $subClassMetadata = $this->_em->getClassMetadata($subClass); if ($subClassMetadata->hasField($fieldName)) { return $subClassMetadata; } } throw DoctrineException::updateMe("No owner found for field '{$fieldName}' during hydration."); }