1
0
mirror of synced 2025-01-06 00:57:10 +03:00
This commit is contained in:
zYne 2007-05-27 18:56:04 +00:00
parent 2973b274e4
commit fa11260e75
11 changed files with 271 additions and 292 deletions

View File

@ -31,7 +31,7 @@
* @version $Revision$ * @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Cache_Array implements Countable class Doctrine_Cache_Array implements Countable, Doctrine_Cache_Interface
{ {
/** /**
* @var array $data an array of cached data * @var array $data an array of cached data

View File

@ -22,6 +22,28 @@ Doctrine::autoload('Doctrine_Configurable');
/** /**
* Doctrine_Connection * Doctrine_Connection
* *
* A wrapper layer on top of PDO / Doctrine_Adapter
*
* Doctrine_Connection is the heart of any Doctrine based application.
*
* 1. Event listeners
* An easy to use, pluggable eventlistener architecture. Aspects such as
* logging, query profiling and caching can be easily implemented through
* the use of these listeners
*
* 2. Lazy-connecting
* Creating an instance of Doctrine_Connection does not connect
* to database. Connecting to database is only invoked when actually needed
* (for example when query() is being called)
*
* 3. Convenience methods
* Doctrine_Connection provides many convenience methods.
*
* 4. Modular structure
* Higher level functionality such as schema importing, exporting, sequence handling etc.
* is divided into modules. For a full list of connection modules see
* Doctrine_Connection::$_modules
*
* @package Doctrine * @package Doctrine
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping * @category Object Relational Mapping
@ -70,12 +92,19 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* *
* sequence Doctrine_Sequence driver, handles sequential id generation and retrieval * sequence Doctrine_Sequence driver, handles sequential id generation and retrieval
* *
* unitOfWork Doctrine_Connection_UnitOfWork handles many orm functionalities such as object
* deletion and saving
*
* formatter Doctrine_Formatter handles data formatting, quoting and escaping
*
* @see Doctrine_Connection::__get() * @see Doctrine_Connection::__get()
* @see Doctrine_DataDict * @see Doctrine_DataDict
* @see Doctrine_Expression * @see Doctrine_Expression
* @see Doctrine_Export * @see Doctrine_Export
* @see Doctrine_Transaction * @see Doctrine_Transaction
* @see Doctrine_Sequence * @see Doctrine_Sequence
* @see Doctrine_Connection_UnitOfWork
* @see Doctrine_Formatter
*/ */
private $modules = array('transaction' => false, private $modules = array('transaction' => false,
'expression' => false, 'expression' => false,
@ -84,22 +113,18 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
'import' => false, 'import' => false,
'sequence' => false, 'sequence' => false,
'unitOfWork' => false, 'unitOfWork' => false,
'formatter' => false
); );
/** /**
* @var array $properties an array of connection properties * @var array $properties an array of connection properties
*/ */
protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false), protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false),
array('start' => '/*', 'end' => '*/', 'escape' => false) array('start' => '/*', 'end' => '*/', 'escape' => false)),
), 'identifier_quoting' => array('start' => '"', 'end' => '"','escape' => '"'),
'identifier_quoting' => array('start' => '"',
'end' => '"',
'escape' => '"'
),
'string_quoting' => array('start' => "'", 'string_quoting' => array('start' => "'",
'end' => "'", 'end' => "'",
'escape' => false, 'escape' => false,
'escape_pattern' => false 'escape_pattern' => false),
),
'wildcards' => array('%', '_'), 'wildcards' => array('%', '_'),
'varchar_max_length' => 255, 'varchar_max_length' => 255,
); );
@ -179,6 +204,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
case 'unitOfWork': case 'unitOfWork':
$this->modules[$name] = new Doctrine_Connection_UnitOfWork($this); $this->modules[$name] = new Doctrine_Connection_UnitOfWork($this);
break; break;
case 'formatter':
$this->modules[$name] = new Doctrine_Formatter($this);
break;
default: default:
$class = 'Doctrine_' . ucwords($name) . '_' . $this->getName(); $class = 'Doctrine_' . ucwords($name) . '_' . $this->getName();
$this->modules[$name] = new $class($this); $this->modules[$name] = new $class($this);
@ -187,97 +215,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
return $this->modules[$name]; return $this->modules[$name];
} }
/**
* Quotes pattern (% and _) characters in a string)
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change signature at
* any time until labelled as non-experimental
*
* @param string the input string to quote
*
* @return string quoted string
*/
public function escapePattern($text)
{
if ($this->string_quoting['escape_pattern']) {
$text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text);
foreach ($this->wildcards as $wildcard) {
$text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text);
}
}
return $text;
}
/**
* convertBoolean
* some drivers need the boolean values to be converted into integers
* when using DQL API
*
* This method takes care of that conversion
*
* @param array $item
* @return void
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $k => $value) {
if (is_bool($item)) {
$item[$k] = (int) $value;
}
}
} else {
if (is_bool($item)) {
$item = (int) $item;
}
}
return $item;
}
/**
* Quote a string so it can be safely used as a table or column name
*
* Delimiting style depends on which database driver is being used.
*
* NOTE: just because you CAN use delimited identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* Portability is broken by using the following characters inside
* delimited identifiers:
* + backtick (<kbd>`</kbd>) -- due to MySQL
* + double quote (<kbd>"</kbd>) -- due to Oracle
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
*
* Delimited identifiers are known to generally work correctly under
* the following drivers:
* + mssql
* + mysql
* + mysqli
* + oci8
* + pgsql
* + sqlite
*
* InterBase doesn't seem to be able to use delimited identifiers
* via PHP 4. They work fine under PHP 5.
*
* @param string $str identifier name to be quoted
* @param bool $checkOption check the 'quote_identifier' option
*
* @return string quoted identifier string
*/
public function quoteIdentifier($str, $checkOption = true)
{
if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
return $str;
}
$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 * returns the manager that created this connection
* *
@ -313,100 +250,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
public function supports($feature) public function supports($feature)
{ {
return (isset($this->supported[$feature]) return (isset($this->supported[$feature])
&& ($this->supported[$feature] === 'emulated' && ($this->supported[$feature] === 'emulated'
|| $this->supported[$feature] || $this->supported[$feature]));
)
);
} }
/**
* quote
* quotes given input parameter
*
* @param mixed $input parameter to be quoted
* @param string $type
* @return mixed
*/
public function quote($input, $type = null)
{
if ($type == null) {
$type = gettype($input);
}
switch ($type) {
case 'integer':
case 'enum':
case 'boolean':
case 'double':
case 'float':
case 'bool':
case 'int':
return $input;
case 'array':
case 'object':
$input = serialize($input);
case 'string':
case 'char':
case 'varchar':
case 'text':
case 'gzip':
case 'blob':
case 'clob':
return $this->dbh->quote($input);
}
}
/**
* Removes any formatting in an sequence name using the 'seqname_format' option
*
* @param string $sqn string that containts name of a potential sequence
* @return string name of the sequence with possible formatting removed
*/
public function fixSequenceName($sqn)
{
$seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i';
$seqName = preg_replace($seqPattern, '\\1', $sqn);
if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) {
return $seqName;
}
return $sqn;
}
/**
* Removes any formatting in an index name using the 'idxname_format' option
*
* @param string $idx string that containts name of anl index
* @return string name of the index with possible formatting removed
*/
public function fixIndexName($idx)
{
$indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i';
$indexName = preg_replace($indexPattern, '\\1', $idx);
if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) {
return $indexName;
}
return $idx;
}
/**
* adds sequence name formatting to a sequence name
*
* @param string name of the sequence
* @return string formatted sequence name
*/
public function getSequenceName($sqn)
{
return sprintf($this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT),
preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn));
}
/**
* adds index name formatting to a index name
*
* @param string name of the index
* @return string formatted index name
*/
public function getIndexName($idx)
{
return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT),
preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
}
/** /**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same * query, except that if there is already a row in the table with the same
@ -507,6 +353,68 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
public function setCharset($charset) public function setCharset($charset)
{ {
}
/**
* Quote a string so it can be safely used as a table or column name
*
* Delimiting style depends on which database driver is being used.
*
* NOTE: just because you CAN use delimited identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* Portability is broken by using the following characters inside
* delimited identifiers:
* + backtick (<kbd>`</kbd>) -- due to MySQL
* + double quote (<kbd>"</kbd>) -- due to Oracle
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
*
* Delimited identifiers are known to generally work correctly under
* the following drivers:
* + mssql
* + mysql
* + mysqli
* + oci8
* + pgsql
* + sqlite
*
* InterBase doesn't seem to be able to use delimited identifiers
* via PHP 4. They work fine under PHP 5.
*
* @param string $str identifier name to be quoted
* @param bool $checkOption check the 'quote_identifier' option
*
* @return string quoted identifier string
*/
public function quoteIdentifier($str, $checkOption = true)
{
return $this->formatter->quoteIdentifier($str, $checkOption);
}
/**
* convertBooleans
* some drivers need the boolean values to be converted into integers
* when using DQL API
*
* This method takes care of that conversion
*
* @param array $item
* @return void
*/
public function convertBooleans($item)
{
return $this->formatter->convertBooleans($item);
}
/**
* quote
* quotes given input parameter
*
* @param mixed $input parameter to be quoted
* @param string $type
* @return mixed
*/
public function quote($input, $type = null)
{
return $this->formatter->quote($input, $type);
} }
/** /**
* Set the date/time format for the current connection * Set the date/time format for the current connection
@ -689,7 +597,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
if ( ! empty($params)) { if ( ! empty($params)) {
$stmt = $this->dbh->prepare($query); $stmt = $this->dbh->prepare($query);
$stmt->execute($params); $stmt->execute($params);
return $stmt; return $stmt;
} else { } else {
return $this->dbh->query($query); return $this->dbh->query($query);
} }
@ -977,61 +885,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{ {
$this->transaction->rollback(); $this->transaction->rollback();
} }
/**
* saves the given record
*
* @param Doctrine_Record $record
* @return void
*/
public function save(Doctrine_Record $record)
{
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
switch ($record->state()) {
case Doctrine_Record::STATE_TDIRTY:
$this->unitOfWork->insert($record);
break;
case Doctrine_Record::STATE_DIRTY:
case Doctrine_Record::STATE_PROXY:
$this->unitOfWork->update($record);
break;
case Doctrine_Record::STATE_CLEAN:
case Doctrine_Record::STATE_TCLEAN:
// do nothing
break;
}
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record);
}
/**
* deletes this data access object and all the related composites
* this operation is isolated by a transaction
*
* this event can be listened by the onPreDelete and onDelete listeners
*
* @return boolean true on success, false on failure
*/
public function delete(Doctrine_Record $record)
{
if ( ! $record->exists()) {
return false;
}
$this->beginTransaction();
$record->getTable()->getListener()->onPreDelete($record);
$this->unitOfWork->deleteComposites($record);
$this->transaction->addDelete($record);
$record->getTable()->getListener()->onDelete($record);
$record->state(Doctrine_Record::STATE_TCLEAN);
$this->commit();
return true;
}
/** /**
* returns a string representation of this object * returns a string representation of this object
* @return string * @return string

View File

@ -40,8 +40,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* 'correct' order. Basically this means that the records of those * 'correct' order. Basically this means that the records of those
* components can be saved safely in the order specified by the returned array. * components can be saved safely in the order specified by the returned array.
* *
* @param array $tables * @param array $tables an array of Doctrine_Table objects or component names
* @return array * @return array an array of component names in flushing order
*/ */
public function buildFlushTree(array $tables) public function buildFlushTree(array $tables)
{ {
@ -131,6 +131,61 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
} }
return array_values($tree); return array_values($tree);
} }
/**
* saves the given record
*
* @param Doctrine_Record $record
* @return void
*/
public function save(Doctrine_Record $record)
{
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
switch ($record->state()) {
case Doctrine_Record::STATE_TDIRTY:
$this->insert($record);
break;
case Doctrine_Record::STATE_DIRTY:
case Doctrine_Record::STATE_PROXY:
$this->update($record);
break;
case Doctrine_Record::STATE_CLEAN:
case Doctrine_Record::STATE_TCLEAN:
// do nothing
break;
}
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record);
}
/**
* deletes this data access object and all the related composites
* this operation is isolated by a transaction
*
* this event can be listened by the onPreDelete and onDelete listeners
*
* @return boolean true on success, false on failure
*/
public function delete(Doctrine_Record $record)
{
if ( ! $record->exists()) {
return false;
}
$this->conn->beginTransaction();
$record->getTable()->getListener()->onPreDelete($record);
$this->deleteComposites($record);
$this->conn->transaction->addDelete($record);
$record->getTable()->getListener()->onDelete($record);
$record->state(Doctrine_Record::STATE_TCLEAN);
$this->conn->commit();
return true;
}
/** /**
* saveRelated * saveRelated
* saves all related records to $record * saves all related records to $record
@ -241,7 +296,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$table = $this->conn->getTable($name); $table = $this->conn->getTable($name);
foreach ($table->getRepository() as $record) { foreach ($table->getRepository() as $record) {
$this->conn->save($record); $this->save($record);
} }
} }
@ -275,19 +330,16 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$set[] = $name . ' = ?'; $set[] = $name . ' = ?';
if ($value instanceof Doctrine_Record) { if ($value instanceof Doctrine_Record) {
switch ($value->state()) { if ( ! $value->exists()) {
case Doctrine_Record::STATE_TCLEAN: $record->save($this->conn);
case Doctrine_Record::STATE_TDIRTY:
$record->save($this->conn);
default:
$array[$name] = $value->getIncremented();
$record->set($name, $value->getIncremented());
} }
$array[$name] = $value->getIncremented();
$record->set($name, $value->getIncremented());
} }
} }
$params = array_values($array); $params = array_values($array);
$id = $record->obtainIdentifier(); $id = $record->obtainIdentifier();
if ( ! is_array($id)) { if ( ! is_array($id)) {
$id = array($id); $id = array($id);

View File

@ -20,19 +20,11 @@
*/ */
/** /**
* Doctrine_Db * Doctrine_Db
* A thin wrapper layer on top of PDO / Doctrine_Adapter *
* *
* Doctrine_Db provides the following things to underlying database hanlder * Doctrine_Db provides the following things to underlying database hanlder
* *
* 1. Event listeners
* An easy to use, pluggable eventlistener architecture. Aspects such as
* logging, query profiling and caching can be easily implemented through
* the use of these listeners
*
* 2. Lazy-connecting
* Creating an instance of Doctrine_Db does not connect
* to database. Connecting to database is only invoked when actually needed
* (for example when query() is being called)
* *
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL

View File

@ -58,7 +58,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
return $text; return $text;
} }
/** /**
* convertBoolean * convertBooleans
* some drivers need the boolean values to be converted into integers * some drivers need the boolean values to be converted into integers
* when using DQL API * when using DQL API
* *
@ -116,15 +116,15 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
*/ */
public function quoteIdentifier($str, $checkOption = true) public function quoteIdentifier($str, $checkOption = true)
{ {
if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) { if ($checkOption && ! $this->conn->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
return $str; return $str;
} }
$str = str_replace($this->properties['identifier_quoting']['end'], $tmp = $this->conn->identifier_quoting;
$this->properties['identifier_quoting']['escape'] . $str = str_replace($tmp['end'],
$this->properties['identifier_quoting']['end'], $str); $tmp['escape'] .
$tmp['end'], $str);
return $this->properties['identifier_quoting']['start'] return $tmp['start'] . $str . $tmp['end'];
. $str . $this->properties['identifier_quoting']['end'];
} }
/** /**
* quote * quote
@ -158,7 +158,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
case 'gzip': case 'gzip':
case 'blob': case 'blob':
case 'clob': case 'clob':
return $this->dbh->quote($input); return $this->conn->getDbh()->quote($input);
} }
} }
/** /**
@ -169,7 +169,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
*/ */
public function fixSequenceName($sqn) public function fixSequenceName($sqn)
{ {
$seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i'; $seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->conn->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i';
$seqName = preg_replace($seqPattern, '\\1', $sqn); $seqName = preg_replace($seqPattern, '\\1', $sqn);
if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) { if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) {
@ -185,7 +185,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
*/ */
public function fixIndexName($idx) public function fixIndexName($idx)
{ {
$indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i'; $indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->conn->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i';
$indexName = preg_replace($indexPattern, '\\1', $idx); $indexName = preg_replace($indexPattern, '\\1', $idx);
if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) { if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) {
return $indexName; return $indexName;
@ -200,7 +200,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
*/ */
public function getSequenceName($sqn) public function getSequenceName($sqn)
{ {
return sprintf($this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT), return sprintf($this->conn->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT),
preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn)); preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn));
} }
/** /**
@ -211,7 +211,7 @@ class Doctrine_Formatter extends Doctrine_Connection_Module
*/ */
public function getIndexName($idx) public function getIndexName($idx)
{ {
return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT), return sprintf($this->conn->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT),
preg_replace('/[^a-z0-9_\$]/i', '_', $idx)); preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
} }
} }

View File

@ -140,9 +140,9 @@ class Doctrine_Import_Builder
$i++; $i++;
} }
$content = sprintf(self::$tpl, $created, $className, implode("\n", $columns)); $content = sprintf(self::$tpl, $created, $className, implode("\n", $columns));
$bytes = file_put_contents($fileName, $content); $bytes = file_put_contents($fileName, $content);
if ($bytes === false) { if ($bytes === false) {
throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $fileName); throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $fileName);

View File

@ -4,7 +4,7 @@
* Created: %s * Created: %s
*/ */
class %s extends Doctrine_Record class %s extends Doctrine_Record
{ {%s
public function setTableDefinition() public function setTableDefinition()
{ {
%s %s
@ -12,5 +12,5 @@ class %s extends Doctrine_Record
public function setUp() public function setUp()
{ {
} }%s
} }

View File

@ -158,7 +158,7 @@ class Doctrine_RawSql extends Doctrine_Query_Abstract
// force-add all primary key fields // force-add all primary key fields
foreach ($this->getAliases() as $tableAlias => $componentAlias) { foreach ($this->getTableAliases() as $tableAlias => $componentAlias) {
$map = $this->_aliasMap[$componentAlias]; $map = $this->_aliasMap[$componentAlias];
foreach ($map['table']->getPrimaryKeys() as $key) { foreach ($map['table']->getPrimaryKeys() as $key) {

View File

@ -890,7 +890,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$saveLater = $conn->unitOfWork->saveRelated($this); $saveLater = $conn->unitOfWork->saveRelated($this);
if ($this->isValid()) { if ($this->isValid()) {
$conn->save($this); $conn->unitOfWork->save($this);
} else { } else {
$conn->transaction->addInvalid($this); $conn->transaction->addInvalid($this);
} }
@ -1106,7 +1106,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
if ($conn == null) { if ($conn == null) {
$conn = $this->_table->getConnection(); $conn = $this->_table->getConnection();
} }
return $conn->delete($this); return $conn->unitOfWork->delete($this);
} }
/** /**
* copy * copy
@ -1152,7 +1152,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @param integer $id * @param integer $id
* @return void * @return void
*/ */
final public function assignIdentifier($id = false) public function assignIdentifier($id = false)
{ {
if ($id === false) { if ($id === false) {
$this->_id = array(); $this->_id = array();

View File

@ -171,7 +171,6 @@ class Doctrine_Record_Filter
} }
} }
return $data; return $data;
} }
/** /**

View File

@ -32,5 +32,88 @@ Doctrine::autoload('Doctrine_Sequence');
*/ */
class Doctrine_Sequence_Db2 extends Doctrine_Sequence class Doctrine_Sequence_Db2 extends Doctrine_Sequence
{ {
/**
* Return the most recent value from the specified sequence in the database.
* This is supported only on RDBMS brands that support sequences
* (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
*
* @param string $sequenceName
* @return integer
* @throws Doctrine_Adapter_Db2_Exception
*/
public function lastSequenceId($sequenceName)
{
$this->_connect();
$sql = 'SELECT PREVVAL FOR '.$this->quoteIdentifier($sequenceName).' AS VAL FROM SYSIBM.SYSDUMMY1';
$stmt = $this->query($sql);
$result = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
if ($result) {
return $result[0]['VAL'];
} else {
return null;
}
}
/**
* Generate a new value from the specified sequence in the database, and return it.
* This is supported only on RDBMS brands that support sequences
* (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
*
* @param string $sequenceName
* @return integer
* @throws Doctrine_Adapter_Db2_Exception
*/
public function nextSequenceId($sequenceName)
{
$this->_connect();
$sql = 'SELECT NEXTVAL FOR '.$this->quoteIdentifier($sequenceName).' AS VAL FROM SYSIBM.SYSDUMMY1';
$stmt = $this->query($sql);
$result = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
if ($result) {
return $result[0]['VAL'];
} else {
return null;
}
}
/**
* Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
*
* As a convention, on RDBMS brands that support sequences
* (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
* from the arguments and returns the last id generated by that sequence.
* On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
* returns the last value generated for such a column, and the table name
* argument is disregarded.
*
* The IDENTITY_VAL_LOCAL() function gives the last generated identity value
* in the current process, even if it was for a GENERATED column.
*
* @param string $tableName OPTIONAL
* @param string $primaryKey OPTIONAL
* @return integer
* @throws Doctrine_Adapter_Db2_Exception
*/
public function lastInsertId($tableName = null, $primaryKey = null)
{
$this->_connect();
if ($tableName !== null) {
$sequenceName = $tableName;
if ($primaryKey) {
$sequenceName .= "_$primaryKey";
}
$sequenceName .= '_seq';
return $this->lastSequenceId($sequenceName);
}
$sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
$stmt = $this->query($sql);
$result = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
if ($result) {
return $result[0]['VAL'];
} else {
return null;
}
}
} }