Added Doctrine_Hydrate_Alias for more flexible alias handling, small fixes for many classes
This commit is contained in:
parent
83d68f5d43
commit
be7931ed3a
@ -50,8 +50,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
* one of the following (true, false, 'emulated')
|
||||
*/
|
||||
protected $supported = array();
|
||||
|
||||
protected $options = array();
|
||||
/**
|
||||
* @var array $modules an array containing all modules
|
||||
* transaction Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction
|
||||
@ -75,6 +73,10 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
'export' => false,
|
||||
'unitOfWork' => false,
|
||||
);
|
||||
/**
|
||||
* @var array $properties an array of connection properties
|
||||
*/
|
||||
protected $properties = array();
|
||||
/**
|
||||
* @var array $availibleDrivers an array containing all availible drivers
|
||||
*/
|
||||
@ -145,7 +147,10 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
$class = 'Doctrine_' . ucwords($name) . '_' . $this->getName();
|
||||
$this->modules[$name] = new $class($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isset($this->properties[$name]))
|
||||
return $this->properties[$name];
|
||||
|
||||
|
||||
return $this->modules[$name];
|
||||
}
|
||||
@ -206,9 +211,12 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
|
||||
return $str;
|
||||
}
|
||||
return $str;
|
||||
//$str = str_replace($this->identifier_quoting['end'], $this->identifier_quoting['escape'] . $this->identifier_quoting['end'], $str);
|
||||
//return $this->identifier_quoting['start'] . $str . $this->identifier_quoting['end'];
|
||||
$str = str_replace($this->properties['identifier_quoting']['end'],
|
||||
$this->properties['identifier_quoting']['escape'] .
|
||||
$this->properties['identifier_quoting']['end'], $str);
|
||||
|
||||
return $this->properties['identifier_quoting']['start']
|
||||
. $str . $this->properties['identifier_quoting']['end'];
|
||||
}
|
||||
/**
|
||||
* returns the manager that created this connection
|
||||
@ -291,7 +299,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
*/
|
||||
public function getIndexName($idx) {
|
||||
return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT),
|
||||
preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
|
||||
preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,9 +65,26 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => true
|
||||
);
|
||||
|
||||
$this->properties['string_quoting'] = array('start' => "'",
|
||||
'end' => "'",
|
||||
'escape' => '\\',
|
||||
'escape_pattern' => '\\');
|
||||
|
||||
$this->properties['identifier_quoting'] = array('start' => '`',
|
||||
'end' => '`',
|
||||
'escape' => '`');
|
||||
|
||||
$this->properties['sql_comments'] = array(
|
||||
array('start' => '-- ', 'end' => "\n", 'escape' => false),
|
||||
array('start' => '#', 'end' => "\n", 'escape' => false),
|
||||
array('start' => '/*', 'end' => '*/', 'escape' => false),
|
||||
);
|
||||
|
||||
$this->properties['varchar_max_length'] = 255;
|
||||
|
||||
parent::__construct($manager, $adapter);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the next free id of a sequence
|
||||
*
|
||||
@ -103,7 +120,7 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
|
||||
$sequenceName = $this->quoteIdentifier($this->getSequenceName($seqName), true);
|
||||
$seqcolName = $this->quoteIdentifier($this->options['seqcol_name'], true);
|
||||
$query = 'SELECT MAX(' . $seqcolName . ') FROM ' . $sequenceName;
|
||||
return $this->queryOne($query, 'integer');
|
||||
return $this->fetchOne($query);
|
||||
}
|
||||
/**
|
||||
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
|
||||
|
@ -65,8 +65,6 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
|
||||
'pattern_escaping' => true,
|
||||
);
|
||||
|
||||
$this->options['multi_query'] = false;
|
||||
|
||||
parent::__construct($manager, $adapter);
|
||||
}
|
||||
/**
|
||||
|
@ -21,19 +21,20 @@
|
||||
/**
|
||||
* Doctrine_DataDict
|
||||
*
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
class Doctrine_DataDict {
|
||||
|
||||
protected $dbh;
|
||||
|
||||
public function __construct($dbh = null) {
|
||||
|
||||
$file = Doctrine::getPath().DIRECTORY_SEPARATOR."Doctrine".DIRECTORY_SEPARATOR."adodb-hack".DIRECTORY_SEPARATOR."adodb.inc.php";
|
||||
|
||||
if( ! file_exists($file))
|
||||
|
@ -29,7 +29,7 @@ Doctrine::autoload('Doctrine_DataDict');
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
class Doctrine_DataDict_Mysql extends Doctrine_DataDict {
|
||||
class Doctrine_DataDict_Mysql extends Doctrine_Connection_Module {
|
||||
/**
|
||||
* Obtain DBMS specific SQL code portion needed to declare an text type
|
||||
* field to be used in statements like CREATE TABLE.
|
||||
@ -55,6 +55,11 @@ class Doctrine_DataDict_Mysql extends Doctrine_DataDict {
|
||||
*/
|
||||
public function getNativeDeclaration($field) {
|
||||
switch ($field['type']) {
|
||||
case 'char':
|
||||
$length = (! empty($field['length'])) ? $field['length'] : false;
|
||||
|
||||
return $length ? 'CHAR('.$length.')' : 'CHAR(255)';
|
||||
case 'varchar':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'string':
|
||||
@ -321,12 +326,15 @@ class Doctrine_DataDict_Mysql extends Doctrine_DataDict {
|
||||
$field['default'] = empty($field['notnull']) ? null : 0;
|
||||
}
|
||||
$default = ' DEFAULT '.$this->conn->getDbh()->quote($field['default']);
|
||||
} elseif (empty($field['notnull'])) {
|
||||
}
|
||||
/**
|
||||
elseif (empty($field['notnull'])) {
|
||||
$default = ' DEFAULT NULL';
|
||||
}
|
||||
*/
|
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
|
||||
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
|
||||
$unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : '';
|
||||
|
||||
$name = $this->conn->quoteIdentifier($name, true);
|
||||
|
||||
|
@ -357,15 +357,15 @@ class Doctrine_DataDict_Pgsql extends Doctrine_Connection_Module {
|
||||
*/
|
||||
public function getNativeDeclaration(array $field) {
|
||||
switch ($field['type']) {
|
||||
case 'char':
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'varchar':
|
||||
case 'char':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : $db->options['default_text_field_length'];
|
||||
$length = (isset($field['length']) && $field['length']) ? $field['length'] : null;
|
||||
// TODO: $db->options['default_text_field_length'];
|
||||
|
||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
|
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
||||
@ -413,16 +413,16 @@ class Doctrine_DataDict_Pgsql extends Doctrine_Connection_Module {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Maps a native array description of a field to a MDB2 datatype and length
|
||||
* Maps a native array description of a field to a portable Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
*
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
public function getDoctrineDeclaration(array $field) {
|
||||
public function getPortableDeclaration(array $field) {
|
||||
|
||||
$length = $field['length'];
|
||||
if ($length == '-1' && !empty($field['atttypmod'])) {
|
||||
if ($length == '-1' && isset($field['atttypmod'])) {
|
||||
$length = $field['atttypmod'] - 4;
|
||||
}
|
||||
if ((int)$length <= 0) {
|
||||
|
@ -347,11 +347,102 @@ class Doctrine_Export extends Doctrine_Connection_Module {
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldDeclarationList(array $fields) {
|
||||
foreach ($fields as $field_name => $field) {
|
||||
$query = $this->conn->dataDict->getNativeDeclaration($field['type'], $field_name, $field);
|
||||
$query_fields[] = $query;
|
||||
foreach ($fields as $fieldName => $field) {
|
||||
$query = $this->getDeclaration($fieldName, $field);
|
||||
|
||||
$queryFields[] = $query;
|
||||
}
|
||||
return implode(', ', $query_fields);
|
||||
return implode(', ', $queryFields);
|
||||
}
|
||||
/**
|
||||
* Obtain DBMS specific SQL code portion needed to declare a generic type
|
||||
* field to be used in statements like CREATE TABLE.
|
||||
*
|
||||
* @param string $name name the field to be declared.
|
||||
* @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.
|
||||
* charset
|
||||
* Text value with the default CHARACTER SET for this field.
|
||||
* collation
|
||||
* Text value with the default COLLATION for this field.
|
||||
* @return string DBMS specific SQL code portion that should be used to
|
||||
* declare the specified field.
|
||||
*/
|
||||
public function getDeclaration($name, $field) {
|
||||
|
||||
$default = '';
|
||||
if(isset($field['default'])) {
|
||||
if ($field['default'] === '') {
|
||||
$field['default'] = empty($field['notnull'])
|
||||
? null : $this->valid_default_values[$field['type']];
|
||||
if ($field['default'] === ''
|
||||
&& ($db->options['portability'] & Doctrine::PORTABILITY_EMPTY_TO_NULL)
|
||||
) {
|
||||
$field['default'] = ' ';
|
||||
}
|
||||
}
|
||||
$default = ' DEFAULT ' . $this->conn->getDbh()->quote($field['default']);
|
||||
}
|
||||
/**
|
||||
TODO: is this really needed for portability?
|
||||
elseif(empty($field['notnull'])) {
|
||||
$default = ' DEFAULT NULL';
|
||||
}
|
||||
*/
|
||||
|
||||
$charset = empty($field['charset']) ? '' :
|
||||
' '.$this->getCharsetFieldDeclaration($field['charset']);
|
||||
|
||||
$collation = empty($field['collation']) ? '' :
|
||||
' '.$this->getCollationFieldDeclaration($field['collation']);
|
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
||||
|
||||
$name = $this->conn->quoteIdentifier($name, true);
|
||||
|
||||
$method = 'get' . $field['type'] . 'Declaration';
|
||||
|
||||
if(method_exists($this->conn->dataDict, $method))
|
||||
return $this->conn->dataDict->$method($name, $field);
|
||||
else
|
||||
$dec = $this->conn->dataDict->getNativeDeclaration($field);
|
||||
|
||||
return $name . ' ' . $dec . $charset . $default . $notnull . $collation;
|
||||
}
|
||||
/**
|
||||
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
|
||||
* of a field declaration to be used in statements like CREATE TABLE.
|
||||
*
|
||||
* @param string $charset name of the charset
|
||||
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
|
||||
* of a field declaration.
|
||||
*/
|
||||
public function getCharsetFieldDeclaration($charset) {
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* Obtain DBMS specific SQL code portion needed to set the COLLATION
|
||||
* of a field declaration to be used in statements like CREATE TABLE.
|
||||
*
|
||||
* @param string $collation name of the collation
|
||||
* @return string DBMS specific SQL code portion needed to set the COLLATION
|
||||
* of a field declaration.
|
||||
*/
|
||||
public function getCollationFieldDeclaration($collation) {
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* export
|
||||
|
@ -92,10 +92,8 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
protected $pendingAggregates = array();
|
||||
|
||||
protected $aggregateMap = array();
|
||||
|
||||
protected $shortAliases = array();
|
||||
|
||||
protected $shortAliasIndexes = array();
|
||||
|
||||
protected $aliasHandler;
|
||||
/**
|
||||
* @var array $parts SQL query string parts
|
||||
*/
|
||||
@ -120,6 +118,7 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
$connection = Doctrine_Manager::getInstance()->getCurrentConnection();
|
||||
|
||||
$this->connection = $connection;
|
||||
$this->aliasHandler = new Doctrine_Hydrate_Alias();
|
||||
}
|
||||
/**
|
||||
* getComponentAliases
|
||||
@ -235,8 +234,7 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
$this->joins = array();
|
||||
$this->tableIndexes = array();
|
||||
$this->tableAliases = array();
|
||||
$this->shortAliases = array();
|
||||
$this->shortAliasIndexes = array();
|
||||
$this->aliasHandler->clear();
|
||||
}
|
||||
/**
|
||||
* getConnection
|
||||
@ -544,34 +542,14 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
return false;
|
||||
}
|
||||
public function getShortAliasIndex($alias) {
|
||||
if( ! isset($this->shortAliasIndexes[$alias]))
|
||||
return 0;
|
||||
|
||||
return $this->shortAliasIndexes[$alias];
|
||||
return $this->aliasHandler->getShortAliasIndex($alias);
|
||||
}
|
||||
public function generateShortAlias($tableName) {
|
||||
$char = strtolower(substr($tableName, 0, 1));
|
||||
|
||||
$alias = $char;
|
||||
|
||||
if( ! isset($this->shortAliasIndexes[$alias]))
|
||||
$this->shortAliasIndexes[$alias] = 1;
|
||||
|
||||
while(isset($this->shortAliases[$alias])) {
|
||||
$alias = $char . ++$this->shortAliasIndexes[$alias];
|
||||
}
|
||||
$this->shortAliases[$alias] = $tableName;
|
||||
|
||||
return $alias;
|
||||
return $this->aliasHandler->generateShortAlias($tableName);
|
||||
}
|
||||
|
||||
public function getShortAlias($tableName) {
|
||||
$alias = array_search($tableName, $this->shortAliases);
|
||||
|
||||
if($alias !== false)
|
||||
return $alias;
|
||||
|
||||
return $this->generateShortAlias($tableName);
|
||||
return $this->aliasHandler->getShortAlias($tableName);
|
||||
}
|
||||
/**
|
||||
* applyInheritance
|
||||
|
@ -98,8 +98,8 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera
|
||||
Doctrine::ATTR_AUTO_TYPE_VLD => true,
|
||||
Doctrine::ATTR_CREATE_TABLES => true,
|
||||
Doctrine::ATTR_QUERY_LIMIT => Doctrine::LIMIT_RECORDS,
|
||||
Doctrine::ATTR_IDXNAME_FORMAT => '%_idx',
|
||||
Doctrine::ATTR_SEQNAME_FORMAT => '%_seq',
|
||||
Doctrine::ATTR_IDXNAME_FORMAT => "%s_idx",
|
||||
Doctrine::ATTR_SEQNAME_FORMAT => "%s_seq",
|
||||
Doctrine::ATTR_QUOTE_IDENTIFIER => false,
|
||||
Doctrine::ATTR_SEQCOL_NAME => 'id',
|
||||
Doctrine::ATTR_PORTABILITY => Doctrine::PORTABILITY_ALL,
|
||||
|
@ -343,8 +343,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$this->fetchModes = array();
|
||||
$this->tableIndexes = array();
|
||||
$this->tableAliases = array();
|
||||
$this->shortAliases = array();
|
||||
$this->shortAliasIndexes = array();
|
||||
$this->aliasHandler->clear();
|
||||
|
||||
$class = "Doctrine_Query_".ucwords($name);
|
||||
$parser = new $class($this);
|
||||
@ -621,8 +620,8 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
if(strpos($part, "'") !== false)
|
||||
continue;
|
||||
|
||||
if(isset($this->shortAliases[$part])) {
|
||||
$parts[$k] = $this->generateNewAlias($part);
|
||||
if($this->aliasHandler->hasAliasFor($part)) {
|
||||
$parts[$k] = $this->aliasHandler->generateNewAlias($part);
|
||||
}
|
||||
|
||||
if(strpos($part, '.') !== false) {
|
||||
@ -631,7 +630,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$trimmed = ltrim($e[0], '( ');
|
||||
$pos = strpos($e[0], $trimmed);
|
||||
|
||||
$e[0] = substr($e[0], 0, $pos) . $this->generateNewAlias($trimmed);
|
||||
$e[0] = substr($e[0], 0, $pos) . $this->aliasHandler->generateNewAlias($trimmed);
|
||||
$parts[$k] = implode('.', $e);
|
||||
}
|
||||
}
|
||||
@ -639,7 +638,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
|
||||
return $subquery;
|
||||
}
|
||||
|
||||
/**
|
||||
public function generateNewAlias($alias) {
|
||||
if(isset($this->shortAliases[$alias])) {
|
||||
// generate a new alias
|
||||
@ -656,6 +655,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
|
||||
return $alias;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user