Updated some docs, added identifier quoting to DQL, fixed some test cases, fixed dql select part handling
This commit is contained in:
parent
cb20dfafc7
commit
df0511e9dc
@ -31,6 +31,45 @@
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
*/
|
||||
class Doctrine_DataDict extends Doctrine_Connection_Module {
|
||||
/**
|
||||
* Obtain an array of changes that may need to applied
|
||||
*
|
||||
* @param array $current new definition
|
||||
* @param array $previous old definition
|
||||
* @return array containing all changes that will need to be applied
|
||||
*/
|
||||
public function compareDefinition($current, $previous) {
|
||||
$type = !empty($current['type']) ? $current['type'] : null;
|
||||
|
||||
if (!method_exists($this, "_compare{$type}Definition")) {
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
||||
'type "'.$current['type'].'" is not yet supported', __FUNCTION__);
|
||||
}
|
||||
|
||||
if (empty($previous['type']) || $previous['type'] != $type) {
|
||||
return $current;
|
||||
}
|
||||
|
||||
$change = $this->{"_compare{$type}Definition"}($current, $previous);
|
||||
|
||||
if ($previous['type'] != $type) {
|
||||
$change['type'] = true;
|
||||
}
|
||||
|
||||
$previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
|
||||
$notnull = !empty($current['notnull']) ? $current['notnull'] : false;
|
||||
if ($previous_notnull != $notnull) {
|
||||
$change['notnull'] = true;
|
||||
}
|
||||
|
||||
$previous_default = array_key_exists('default', $previous) ? $previous['default'] :
|
||||
($previous_notnull ? '' : null);
|
||||
$default = array_key_exists('default', $current) ? $current['default'] :
|
||||
($notnull ? '' : null);
|
||||
if ($previous_default !== $default) {
|
||||
$change['default'] = true;
|
||||
}
|
||||
|
||||
return $change;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,5 +50,77 @@ class Doctrine_DataDict_Informix extends Doctrine_DataDict {
|
||||
and i.idxname=s.idxname and tr.tabid=r.ptabid
|
||||
and s2.constrid=r.primary and i2.idxname=s2.idxname",
|
||||
);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function getNativeDeclaration($field) {
|
||||
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';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -223,10 +223,44 @@ class Doctrine_Export extends Doctrine_Connection_Module {
|
||||
* 'last_login' => array()
|
||||
* )
|
||||
* )
|
||||
* @throws PDOException
|
||||
* @return void
|
||||
*/
|
||||
public function createIndex($table, $name, array $definition) {
|
||||
return $this->conn->getDbh()->query($this->createIndexSql($table, $name, $definition));
|
||||
}
|
||||
/**
|
||||
* Get the stucture of a field into an array
|
||||
*
|
||||
*
|
||||
* @param string $table name of the table on which the index is to be created
|
||||
* @param string $name name of the index to be created
|
||||
* @param array $definition associative array that defines properties of the index to be created.
|
||||
* Currently, only one property named FIELDS is supported. This property
|
||||
* is also an associative with the names of the index fields as array
|
||||
* indexes. Each entry of this array is set to another type of associative
|
||||
* array that specifies properties of the index that are specific to
|
||||
* each field.
|
||||
*
|
||||
* Currently, only the sorting property is supported. It should be used
|
||||
* to define the sorting direction of the index. It may be set to either
|
||||
* ascending or descending.
|
||||
*
|
||||
* Not all DBMS support index sorting direction configuration. The DBMS
|
||||
* drivers of those that do not support it ignore this property. Use the
|
||||
* function supports() to determine whether the DBMS driver can manage indexes.
|
||||
*
|
||||
* Example
|
||||
* array(
|
||||
* 'fields' => array(
|
||||
* 'user_name' => array(
|
||||
* 'sorting' => 'ascending'
|
||||
* ),
|
||||
* 'last_login' => array()
|
||||
* )
|
||||
* )
|
||||
* @return string
|
||||
*/
|
||||
public function createIndexSql($table, $name, array $definition) {
|
||||
$table = $this->conn->quoteIdentifier($table);
|
||||
$name = $this->conn->quoteIdentifier($name);
|
||||
|
||||
@ -237,10 +271,8 @@ class Doctrine_Export extends Doctrine_Connection_Module {
|
||||
}
|
||||
$query .= ' ('. implode(', ', $fields) . ')';
|
||||
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* alter an existing table
|
||||
* (this method is implemented by the drivers)
|
||||
@ -331,6 +363,98 @@ class Doctrine_Export extends Doctrine_Connection_Module {
|
||||
* @return void
|
||||
*/
|
||||
public function alterTable($name, array $changes, $check) {
|
||||
$this->conn->getDbh()->query($this->alterTableSql($name, $changes, $check));
|
||||
}
|
||||
/**
|
||||
* alter an existing table
|
||||
* (this method is implemented by the drivers)
|
||||
*
|
||||
* @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 MDB2 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 MDB2 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 string
|
||||
*/
|
||||
public function alterTableSql($name, array $changes, $check) {
|
||||
throw new Doctrine_Export_Exception('Alter table not supported by this driver.');
|
||||
}
|
||||
/**
|
||||
|
@ -74,10 +74,10 @@ class Doctrine_Export_Sqlite extends Doctrine_Export {
|
||||
if(isset($field['sorting'])) {
|
||||
switch ($field['sorting']) {
|
||||
case 'ascending':
|
||||
$fieldString.= ' ASC';
|
||||
$fieldString .= ' ASC';
|
||||
break;
|
||||
case 'descending':
|
||||
$fieldString.= ' DESC';
|
||||
$fieldString .= ' DESC';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +55,9 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
*/
|
||||
protected $params = array();
|
||||
/**
|
||||
* @var Doctrine_Connection $connection Doctrine_Connection object
|
||||
* @var Doctrine_Connection $conn Doctrine_Connection object
|
||||
*/
|
||||
protected $connection;
|
||||
protected $conn;
|
||||
/**
|
||||
* @var Doctrine_View $view Doctrine_View object
|
||||
*/
|
||||
@ -115,7 +115,7 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
if( ! ($connection instanceof Doctrine_Connection))
|
||||
$connection = Doctrine_Manager::getInstance()->getCurrentConnection();
|
||||
|
||||
$this->connection = $connection;
|
||||
$this->conn = $connection;
|
||||
$this->aliasHandler = new Doctrine_Hydrate_Alias();
|
||||
}
|
||||
/**
|
||||
@ -240,7 +240,7 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
* @return Doctrine_Connection
|
||||
*/
|
||||
public function getConnection() {
|
||||
return $this->connection;
|
||||
return $this->conn;
|
||||
}
|
||||
/**
|
||||
* setView
|
||||
@ -340,10 +340,10 @@ abstract class Doctrine_Hydrate extends Doctrine_Access {
|
||||
$query = $this->view->getSelectSql();
|
||||
|
||||
if($this->isLimitSubqueryUsed() &&
|
||||
$this->connection->getDBH()->getAttribute(PDO::ATTR_DRIVER_NAME) !== 'mysql')
|
||||
$this->conn->getDBH()->getAttribute(PDO::ATTR_DRIVER_NAME) !== 'mysql')
|
||||
$params = array_merge($params, $params);
|
||||
|
||||
$stmt = $this->connection->execute($query, $params);
|
||||
$stmt = $this->conn->execute($query, $params);
|
||||
|
||||
if($this->aggregate)
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
@ -18,6 +18,7 @@
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.com>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Hydrate');
|
||||
/**
|
||||
* Doctrine_Query
|
||||
*
|
||||
@ -457,7 +458,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
public function getQueryBase() {
|
||||
switch($this->type) {
|
||||
case self::DELETE:
|
||||
if($this->connection->getName() == 'mysql')
|
||||
if($this->conn->getName() == 'mysql')
|
||||
$q = 'DELETE '.end($this->tableAliases).' FROM ';
|
||||
else
|
||||
$q = 'DELETE FROM ';
|
||||
@ -501,15 +502,13 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
if($this->isDistinct())
|
||||
$str = 'DISTINCT ';
|
||||
|
||||
$q = 'SELECT '.$str.implode(", ",$this->parts["select"]).
|
||||
' FROM ';
|
||||
$q = $this->getQueryBase();
|
||||
|
||||
$q .= $this->parts['from'];
|
||||
|
||||
if( ! empty($this->parts['join'])) {
|
||||
foreach($this->parts['join'] as $part) {
|
||||
$q .= " ".implode(' ', $part);
|
||||
$q .= ' '.implode(' ', $part);
|
||||
}
|
||||
}
|
||||
|
||||
@ -527,10 +526,10 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$subquery = $this->getLimitSubquery();
|
||||
|
||||
|
||||
switch(strtolower($this->connection->getName())) {
|
||||
switch(strtolower($this->conn->getName())) {
|
||||
case 'mysql':
|
||||
// mysql doesn't support LIMIT in subqueries
|
||||
$list = $this->connection->execute($subquery, $params)->fetchAll(PDO::FETCH_COLUMN);
|
||||
$list = $this->conn->execute($subquery, $params)->fetchAll(PDO::FETCH_COLUMN);
|
||||
$subquery = implode(', ', $list);
|
||||
break;
|
||||
case 'pgsql':
|
||||
@ -555,7 +554,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$q .= ( ! empty($this->parts['orderby']))? ' ORDER BY ' . implode(' ', $this->parts['orderby']):'';
|
||||
|
||||
if($modifyLimit)
|
||||
$q = $this->connection->modifyLimitQuery($q, $this->parts['limit'], $this->parts['offset']);
|
||||
$q = $this->conn->modifyLimitQuery($q, $this->parts['limit'], $this->parts['offset']);
|
||||
|
||||
// return to the previous state
|
||||
if( ! empty($string))
|
||||
@ -586,7 +585,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
// initialize the base of the subquery
|
||||
$subquery = 'SELECT DISTINCT ' . $primaryKey;
|
||||
|
||||
if($this->connection->getDBH()->getAttribute(PDO::ATTR_DRIVER_NAME) == 'pgsql') {
|
||||
if($this->conn->getDBH()->getAttribute(PDO::ATTR_DRIVER_NAME) == 'pgsql') {
|
||||
// pgsql needs the order by fields to be preserved in select clause
|
||||
|
||||
foreach($this->parts['orderby'] as $part) {
|
||||
@ -623,7 +622,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$subquery .= ( ! empty($this->parts['orderby']))? ' ORDER BY ' . implode(' ', $this->parts['orderby']):'';
|
||||
|
||||
// add driver specific limit clause
|
||||
$subquery = $this->connection->modifyLimitQuery($subquery, $this->parts['limit'], $this->parts['offset']);
|
||||
$subquery = $this->conn->modifyLimitQuery($subquery, $this->parts['limit'], $this->parts['offset']);
|
||||
|
||||
$parts = self::quoteExplode($subquery, ' ', "'", "'");
|
||||
|
||||
@ -1059,7 +1058,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
if($key == 0) {
|
||||
$currPath = substr($currPath,1);
|
||||
|
||||
$table = $this->connection->getTable($name);
|
||||
$table = $this->conn->getTable($name);
|
||||
|
||||
|
||||
$tname = $this->aliasHandler->getShortAlias($table->getTableName());
|
||||
@ -1068,7 +1067,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$this->tableIndexes[$tname] = 1;
|
||||
|
||||
|
||||
$this->parts["from"] = $table->getTableName() . ' ' . $tname;
|
||||
$this->parts["from"] = $this->conn->quoteIdentifier($table->getTableName()) . ' ' . $tname;
|
||||
|
||||
$this->tableAliases[$currPath] = $tname;
|
||||
|
||||
@ -1097,7 +1096,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
} else
|
||||
$tname2 = $this->aliasHandler->generateShortAlias($original);
|
||||
|
||||
$aliasString = $original . ' ' . $tname2;
|
||||
$aliasString = $this->conn->quoteIdentifier($original) . ' ' . $tname2;
|
||||
|
||||
switch($mark) {
|
||||
case ':':
|
||||
@ -1113,7 +1112,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
if( ! $fk->isOneToOne()) {
|
||||
$this->needsSubquery = true;
|
||||
}
|
||||
|
||||
|
||||
if( ! $loadFields || $fk->getTable()->usesInheritanceMap()) {
|
||||
$this->subqueryAliases[] = $tname2;
|
||||
}
|
||||
@ -1126,16 +1125,17 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
if( ! $loadFields) {
|
||||
$this->subqueryAliases[] = $assocTableName;
|
||||
}
|
||||
$this->parts["join"][$tname][$assocTableName] = $join.$assocTableName . ' ON ' .$tname . '.'
|
||||
$this->parts["join"][$tname][$assocTableName] = $join . $assocTableName . ' ON ' . $tname . '.'
|
||||
. $table->getIdentifier() . ' = '
|
||||
. $assocTableName . '.' . $fk->getLocal();
|
||||
|
||||
$this->parts["join"][$tname][$tname2] = $join.$aliasString . ' ON ' .$tname2 . '.'
|
||||
$this->parts["join"][$tname][$tname2] = $join . $aliasString . ' ON ' . $tname2 . '.'
|
||||
. $table->getIdentifier() . ' = '
|
||||
. $assocTableName . '.' . $fk->getForeign();
|
||||
|
||||
} else {
|
||||
$this->parts["join"][$tname][$tname2] = $join.$aliasString . ' ON ' .$tname . '.'
|
||||
$this->parts["join"][$tname][$tname2] = $join . $aliasString
|
||||
. ' ON ' . $tname . '.'
|
||||
. $fk->getLocal() . ' = ' . $tname2 . '.' . $fk->getForeign();
|
||||
}
|
||||
|
||||
@ -1160,8 +1160,12 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$this->tables[$tableName] = $table;
|
||||
|
||||
if($loadFields) {
|
||||
|
||||
|
||||
$skip = false;
|
||||
|
||||
if( ! empty($this->pendingFields))
|
||||
$skip = true;
|
||||
|
||||
if($componentAlias) {
|
||||
$this->compAliases[$componentAlias] = $currPath;
|
||||
|
||||
@ -1174,6 +1178,7 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable {
|
||||
$skip = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! $skip)
|
||||
$this->parseFields($fullname, $tableName, $e2, $currPath);
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ Doctrine::autoload('Doctrine_Hydrate');
|
||||
/**
|
||||
* Doctrine_RawSql
|
||||
*
|
||||
* @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_RawSql extends Doctrine_Hydrate {
|
||||
/**
|
||||
* @var array $fields
|
||||
@ -217,9 +217,9 @@ class Doctrine_RawSql extends Doctrine_Hydrate {
|
||||
$tableName = $table->getAliasName($component);
|
||||
|
||||
|
||||
$table = $this->connection->getTable($tableName);
|
||||
$table = $this->conn->getTable($tableName);
|
||||
} else {
|
||||
$table = $this->connection->getTable($component);
|
||||
$table = $this->conn->getTable($component);
|
||||
}
|
||||
$this->tables[$alias] = $table;
|
||||
$this->fetchModes[$alias] = Doctrine::FETCH_IMMEDIATE;
|
||||
|
@ -1364,6 +1364,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
$this->_table->getOption($name);
|
||||
else
|
||||
$this->_table->setOption($name, $value);
|
||||
}
|
||||
public function hasIndex($name ) {
|
||||
|
||||
}
|
||||
/**
|
||||
* addListener
|
||||
|
@ -19,17 +19,10 @@
|
||||
* <http://www.phpdoctrine.com>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Access');
|
||||
/**
|
||||
* @package Doctrine
|
||||
* @url http://www.phpdoctrine.com
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
|
||||
* @author Konsta Vesterinen
|
||||
* @version $Id$
|
||||
*/
|
||||
/**
|
||||
* class Doctrine_Schema_Object
|
||||
* Catches any non-property call from child classes and throws an exception.
|
||||
*
|
||||
* @package Doctrine
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
@ -37,6 +30,7 @@ Doctrine::autoload('Doctrine_Access');
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
|
||||
*/
|
||||
abstract class Doctrine_Schema_Object extends Doctrine_Access implements IteratorAggregate, Countable {
|
||||
|
||||
|
@ -775,7 +775,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
|
||||
* @return string
|
||||
*/
|
||||
final public function getTableName() {
|
||||
return $this->conn->quoteIdentifier($this->options['tableName']);
|
||||
return $this->options['tableName'];
|
||||
}
|
||||
/**
|
||||
* create
|
||||
|
@ -1,27 +1,24 @@
|
||||
<?php
|
||||
|
||||
// find all users
|
||||
|
||||
$coll = $conn->query("FROM User");
|
||||
|
||||
// find all users with only their names (and primary keys) fetched
|
||||
|
||||
$coll = $conn->query("FROM User(name)");
|
||||
|
||||
// find all groups
|
||||
|
||||
$coll = $conn->query("FROM Group");
|
||||
$coll = $q->from("FROM Group");
|
||||
|
||||
// find all users and user emails
|
||||
|
||||
$coll = $conn->query("FROM User.Email");
|
||||
$coll = $q->from("FROM User.Email");
|
||||
|
||||
// find all users and user emails with only user name and
|
||||
// find all users and user emails with only user name and
|
||||
// age + email address loaded
|
||||
|
||||
$coll = $conn->query("FROM User(name, age).Email(address)");
|
||||
$coll = $q->select('u.name, u.age, e.address')
|
||||
->from('FROM User u')
|
||||
->leftJoin('u.Email e')
|
||||
->execute();
|
||||
|
||||
// find all users, user email and user phonenumbers
|
||||
|
||||
$coll = $conn->query("FROM User.Email, User.Phonenumber");
|
||||
$coll = $q->from('FROM User u')
|
||||
->leftJoin('u.Email e')
|
||||
->leftJoin('u.Phonenumber p')
|
||||
->execute();
|
||||
?>
|
||||
|
@ -1,3 +1,18 @@
|
||||
DQL FROM -part is used for selecting tables as well as for selecting fields. Related components are selected either
|
||||
with colon-operator or dot-operator (See <a href="documentation.php?index=2.8.php">Relation operators</a>). <br \>You can place
|
||||
the selected fields in () -brackets (eg. 'FROM User(name, id)'). If you are about to select all fields you can simple use 'FROM User'.
|
||||
<?php ?>
|
||||
The FROM clause indicates the component or components from which to retrieve records.
|
||||
If you name more than one component, you are performing a join.
|
||||
For each table specified, you can optionally specify an alias. Doctrine_Query offers easy to use
|
||||
methods such as from(), addFrom(), leftJoin() and innerJoin() for managing the FROM part of your DQL query.
|
||||
|
||||
<?php
|
||||
renderCode("<?php
|
||||
// find all users
|
||||
\$q = new Doctrine_Query();
|
||||
|
||||
\$coll = \$q->from('User')->execute();
|
||||
|
||||
// find all users with only their names (and primary keys) fetched
|
||||
|
||||
\$coll = \$q->select('u.name')->('User u');
|
||||
?>");
|
||||
?>
|
||||
|
@ -1,69 +1,97 @@
|
||||
<pre>
|
||||
FEATURES:
|
||||
|
||||
GENERAL FEATURES
|
||||
- Fully object-oriented following best practices and design patterns
|
||||
- Multiple databases
|
||||
- Database connection pooling with connection-record -registry
|
||||
- Runtime configuration (no XML needed!)
|
||||
- Very modular structure (only uses the needed features)
|
||||
- The whole framework can be compiled into a single file
|
||||
- Leveled configuration (attributes can be set at global, connection and table levels)
|
||||
|
||||
DATABASE ABSTRACTION:
|
||||
- A DSN (data source name) or array format for specifying database servers
|
||||
- Datatype abstraction and on demand datatype conversion
|
||||
- supports PDO
|
||||
- Database query profiling
|
||||
- Query caching
|
||||
- Sequence / autoincrement emulation
|
||||
- Replace emulation
|
||||
- RDBMS management methods (creating, dropping, altering)
|
||||
- SQL function call abstraction
|
||||
- SQL expression abstraction
|
||||
- Pattern matching abstraction
|
||||
- Portable error codes
|
||||
- Nested transactions
|
||||
- Transaction isolation abstraction
|
||||
- Transaction savepoint abstraction
|
||||
- Index/Unique Key/Primary Key support
|
||||
- Ability to read the information schema
|
||||
- Reverse engineering schemas from an existing database
|
||||
- LIMIT / OFFSET emulation
|
||||
<?php
|
||||
include("top.php");
|
||||
?>
|
||||
|
||||
|
||||
OBJECT RELATIONAL MAPPING:
|
||||
General features:
|
||||
- Validators
|
||||
- Transactional errorStack for easy retrieval of all errors
|
||||
- EventListeners
|
||||
- UnitOfWork pattern (easy saving of all pending objects)
|
||||
- Uses ActiveRecord pattern
|
||||
- State-wise records and transactions
|
||||
- Importing existing database schemas to Doctrine ActiveRecord objects
|
||||
- Exporting Doctrine ActiveRecords to database (= automatic table creation)
|
||||
<table width="100%" cellspacing=0 cellpadding=0>
|
||||
<tr>
|
||||
<td width=50>
|
||||
<td>
|
||||
<td align="left" valign="top">
|
||||
<table width="100%" cellspacing=1 cellpadding=1>
|
||||
<tr>
|
||||
<td bgcolor="white">
|
||||
<img src="images/logo.jpg" align="left"><b class="title">Doctrine - PHP Data Persistence and ORM Tool</b>
|
||||
<hr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
Mapping:
|
||||
- Composite, Natural, Autoincremented and Sequential identifiers
|
||||
- PHP Array / Object data types for columns (automatic serialization/unserialization)
|
||||
- Gzip datatype for all databases
|
||||
- Emulated enum datatype for all databases
|
||||
- Datatype abstraction
|
||||
- Column aggregation inheritance
|
||||
- One-class-one-table inheritance as well as One-table
|
||||
- One-to-many, many-to-one, one-to-one and many-to-many relations
|
||||
- Self-referencing relations even for association table relations
|
||||
- Relation aliases
|
||||
|
||||
Object population:
|
||||
- DQL (Doctrine Query Language), an EJB 3 spec compliant OQL
|
||||
- <b>The limit-subquery-algorithm</b>
|
||||
- OO-style query API for both DQL and raw SQL
|
||||
- Object population from database views
|
||||
- Object population through raw SQL
|
||||
|
||||
Transactions and locking:
|
||||
- Pessimistic offline locking
|
||||
- Savepoints, transaction isolation levels and nested transactions
|
||||
- Transactional query optimization (gathering of DELETE statements)
|
||||
</pre>
|
||||
<ul>
|
||||
<b class='title'>GENERAL FEATURES</b>
|
||||
<ul>
|
||||
<li \> Fully object-oriented following best practices and design patterns
|
||||
<li \>Multiple databases
|
||||
<li \>Database connection pooling with connection-record -registry
|
||||
<li \>Runtime configuration (no XML needed!)
|
||||
<li \>Very modular structure (only uses the needed features)
|
||||
<li \>The whole framework can be compiled into a single file
|
||||
<li \>Leveled configuration (attributes can be set at global, connection and table levels)
|
||||
</ul>
|
||||
<br \>
|
||||
<b class='title'>DATABASE ABSTRACTION</b>
|
||||
<ul>
|
||||
<li \>A DSN (data source name) or array format for specifying database servers
|
||||
<li \>Datatype abstraction and on demand datatype conversion
|
||||
<li \>supports PDO
|
||||
<li \>Database query profiling
|
||||
<li \>Query caching
|
||||
<li \>Sequence / autoincrement emulation
|
||||
<li \>Replace emulation
|
||||
<li \>RDBMS management methods (creating, dropping, altering)
|
||||
<li \>SQL function call abstraction
|
||||
<li \>SQL expression abstraction
|
||||
<li \>Pattern matching abstraction
|
||||
<li \>Portable error codes
|
||||
<li \>Nested transactions
|
||||
<li \>Transaction isolation abstraction
|
||||
<li \>Transaction savepoint abstraction
|
||||
<li \>Index/Unique Key/Primary Key support
|
||||
<li \>Ability to read the information schema
|
||||
<li \>Reverse engineering schemas from an existing database
|
||||
<li \>LIMIT / OFFSET emulation
|
||||
</ul>
|
||||
<br \>
|
||||
<b class='title'>OBJECT RELATIONAL MAPPING</b>:
|
||||
<ul>
|
||||
<b class='title'>General features</b>
|
||||
<li \>Validators
|
||||
<li \>Transactional errorStack for easy retrieval of all errors
|
||||
<li \>EventListeners
|
||||
<li \>UnitOfWork pattern (easy saving of all pending objects)
|
||||
<li \>Uses ActiveRecord pattern
|
||||
<li \>State-wise records and transactions
|
||||
<li \>Importing existing database schemas to Doctrine ActiveRecord objects
|
||||
<li \>Exporting Doctrine ActiveRecords to database (= automatic table creation)
|
||||
<br \><br \>
|
||||
<b class='title'>Mapping</b>
|
||||
<li \>Composite, Natural, Autoincremented and Sequential identifiers
|
||||
<li \>PHP Array / Object data types for columns (automatic serialization/unserialization)
|
||||
<li \>Gzip datatype for all databases
|
||||
<li \>Emulated enum datatype for all databases
|
||||
<li \>Datatype abstraction
|
||||
<li \>Column aggregation inheritance
|
||||
<li \>One-class-one-table inheritance as well as One-table
|
||||
<li \>One-to-many, many-to-one, one-to-one and many-to-many relations
|
||||
<li \>Self-referencing relations even for association table relations
|
||||
<li \>Relation aliases
|
||||
<br \><br \>
|
||||
<b class='title'>Object population</b>
|
||||
<li \>DQL (Doctrine Query Language), an EJB 3 spec compliant OQL
|
||||
<li \><b>The limit-subquery-algorithm</b>
|
||||
<li \>OO-style query API for both DQL and raw SQL
|
||||
<li \>Object population from database views
|
||||
<li \>Object population through raw SQL
|
||||
<br \><br \>
|
||||
<b class='title'>Transactions and locking</b>
|
||||
<li \>Pessimistic offline locking
|
||||
<li \>Savepoints, transaction isolation levels and nested transactions
|
||||
<li \>Transactional query optimization (gathering of DELETE statements)
|
||||
</ul>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -10,7 +10,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
|
||||
|
||||
public function testLimitWithOneToOneLeftJoin() {
|
||||
$q = new Doctrine_Query($this->connection);
|
||||
$q->from('User(id).Email')->limit(5);
|
||||
$q->select('u.id, e.*')->from('User u, u.Email e')->limit(5);
|
||||
|
||||
$users = $q->execute();
|
||||
$this->assertEqual($users->count(), 5);
|
||||
@ -19,15 +19,14 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
|
||||
}
|
||||
public function testLimitWithOneToOneInnerJoin() {
|
||||
$q = new Doctrine_Query($this->connection);
|
||||
$q->from('User(id):Email')->limit(5);
|
||||
$q->select('u.id, e.*')->from('User u, u:Email e')->limit(5);
|
||||
|
||||
$users = $q->execute();
|
||||
$this->assertEqual($users->count(), 5);
|
||||
$this->assertEqual($q->getQuery(), "SELECT e.id AS e__id, e2.id AS e2__id, e2.address AS e2__address FROM entity e INNER JOIN email e2 ON e.email_id = e2.id WHERE (e.type = 0) LIMIT 5");
|
||||
}
|
||||
public function testLimitWithOneToManyLeftJoin() {
|
||||
$this->query->from("User(id).Phonenumber");
|
||||
$this->query->limit(5);
|
||||
$this->query->select('u.id, p.*')->from('User u, u.Phonenumber p')->limit(5);
|
||||
|
||||
$sql = $this->query->getQuery();
|
||||
$this->assertEqual($this->query->getQuery(),
|
||||
@ -87,7 +86,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
|
||||
}
|
||||
|
||||
public function testLimitWithOneToManyInnerJoin() {
|
||||
$this->query->select('u.id')->from("User u INNER JOIN u.Phonenumber");
|
||||
$this->query->select('u.id, p.*')->from('User u INNER JOIN u.Phonenumber p');
|
||||
$this->query->limit(5);
|
||||
|
||||
|
||||
@ -114,8 +113,8 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
|
||||
|
||||
public function testLimitWithPreparedQueries() {
|
||||
$q = new Doctrine_Query();
|
||||
$q->from("User(id).Phonenumber(id)");
|
||||
$q->where("User.name = ?");
|
||||
$q->select('u.id, p.id')->from('User u LEFT JOIN u.Phonenumber p');
|
||||
$q->where("u.name = ?");
|
||||
$q->limit(5);
|
||||
$users = $q->execute(array('zYne'));
|
||||
|
||||
@ -128,7 +127,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
|
||||
'SELECT e.id AS e__id, p.id AS p__id FROM entity e LEFT JOIN phonenumber p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM entity e2 WHERE e2.name = ? AND (e2.type = 0) LIMIT 5) AND e.name = ? AND (e.type = 0)');
|
||||
|
||||
$q = new Doctrine_Query();
|
||||
$q->from("User(id).Phonenumber(id)");
|
||||
$q->select('u.id, p.id')->from('User u LEFT JOIN u.Phonenumber p');
|
||||
$q->where("User.name LIKE ? || User.name LIKE ?");
|
||||
$q->limit(5);
|
||||
$users = $q->execute(array('%zYne%', '%Arnold%'));
|
||||
|
@ -17,7 +17,7 @@ class Doctrine_Query_Select_TestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertEqual($q->getQuery(), 'SELECT COUNT(e.id) AS e__0 FROM entity e WHERE (e.type = 0)');
|
||||
}
|
||||
|
||||
public function testMultipleAggregateFunctions() {
|
||||
public function testSelectPartSupportsMultipleAggregateFunctions() {
|
||||
$q = new Doctrine_Query();
|
||||
|
||||
$q->parseQuery('SELECT MAX(u.id), MIN(u.name) FROM User u');
|
||||
|
@ -43,6 +43,7 @@ require_once('QuerySelectTestCase.php');
|
||||
require_once('QueryShortAliasesTestCase.php');
|
||||
require_once('QueryDeleteTestCase.php');
|
||||
require_once('QueryUpdateTestCase.php');
|
||||
require_once('QueryIdentifierQuotingTestCase.php');
|
||||
|
||||
require_once('UnitOfWorkTestCase.php');
|
||||
|
||||
@ -146,8 +147,8 @@ $test->addTestCase(new Doctrine_Export_Firebird_TestCase());
|
||||
|
||||
|
||||
$test->addTestCase(new Doctrine_Configurable_TestCase());
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
|
||||
$test->addTestCase(new Doctrine_Transaction_TestCase());
|
||||
@ -258,6 +259,7 @@ $test->addTestCase(new Doctrine_Query_Limit_TestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_Query_Select_TestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_Query_IdentifierQuoting_TestCase());
|
||||
|
||||
|
||||
//$test->addTestCase(new Doctrine_Cache_Query_SqliteTestCase());
|
||||
|
Loading…
x
Reference in New Issue
Block a user