Continued refactorings. Started to refactor the DBAL layer.
This commit is contained in:
parent
a769997450
commit
e704cd0fd2
63 changed files with 3744 additions and 3184 deletions
|
@ -29,7 +29,8 @@
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove.
|
||||
*/
|
||||
class Doctrine_Adapter
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::Common::Cache;
|
||||
|
||||
/**
|
||||
* Doctrine_Cache_Apc
|
||||
|
@ -28,7 +30,8 @@
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Rename to ApcCache
|
||||
*/
|
||||
class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
|
||||
{
|
||||
|
|
|
@ -1837,6 +1837,20 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
|
|||
{
|
||||
$this->_generatorType = $type;
|
||||
}
|
||||
|
||||
public function completeIdentifierMapping()
|
||||
{
|
||||
if ($this->getIdGeneratorType() == self::GENERATOR_TYPE_AUTO) {
|
||||
$platform = $this->_em->getConnection()->getDatabasePlatform();
|
||||
if ($platform->prefersSequences()) {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_SEQUENCE;
|
||||
} else if ($platform->prefersIdentityColumns()) {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_IDENTITY;
|
||||
} else {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_TABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -295,28 +295,7 @@ class Doctrine_ClassMetadata_Factory
|
|||
// are unnecessary as we can easily replace them with polymorphic calls on
|
||||
// the connection (or another) object. We just need to decide where to put
|
||||
// the id generation types.
|
||||
if ($class->getIdGeneratorType() == Doctrine_ClassMetadata::GENERATOR_TYPE_AUTO) {
|
||||
switch (strtolower($this->_em->getConnection()->getDriverName())) {
|
||||
case 'mysql':
|
||||
// pick IDENTITY
|
||||
$class->setIdGeneratorType(Doctrine_ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
||||
break;
|
||||
case 'oracle':
|
||||
//pick SEQUENCE
|
||||
break;
|
||||
case 'postgres':
|
||||
//pick SEQUENCE
|
||||
break;
|
||||
case 'firebird':
|
||||
//pick what?
|
||||
break;
|
||||
case 'mssql':
|
||||
//pick what?
|
||||
default:
|
||||
throw new Doctrine_Exception("Encountered unknown database driver: "
|
||||
. $this->_em->getConnection()->getDriverName());
|
||||
}
|
||||
}
|
||||
$class->completeIdentifierMapping();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#namespace Doctrine::DBAL::Connections;
|
||||
|
||||
#use Doctrine::Common::Configuration;
|
||||
#use Doctrine::Common::EventManager;
|
||||
#use Doctrine::DBAL::Exceptions::ConnectionException;
|
||||
|
||||
/**
|
||||
* A thin connection wrapper on top of PDO.
|
||||
|
@ -40,7 +42,6 @@
|
|||
* Doctrine_Connection provides many convenience methods such as fetchAll(), fetchOne() etc.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
|
@ -62,9 +63,9 @@
|
|||
* 'masterConnectionResolver' => new MyMasterConnectionResolver()
|
||||
*
|
||||
* Doctrine::DBAL could ship with a simple standard broker that uses a primitive
|
||||
* round-robin approach to distribution. User can provide its own resolvers.
|
||||
* round-robin approach to distribution. User can provide its own brokers.
|
||||
*/
|
||||
abstract class Doctrine_Connection implements Countable
|
||||
abstract class Doctrine_Connection
|
||||
{
|
||||
/**
|
||||
* The PDO database handle.
|
||||
|
@ -87,13 +88,6 @@ abstract class Doctrine_Connection implements Countable
|
|||
*/
|
||||
protected $_eventManager;
|
||||
|
||||
/**
|
||||
* The attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_attributes = array();
|
||||
|
||||
/**
|
||||
* Name of the connection
|
||||
*
|
||||
|
@ -111,7 +105,7 @@ abstract class Doctrine_Connection implements Countable
|
|||
/**
|
||||
* Whether or not a connection has been established.
|
||||
*
|
||||
* @var boolean $isConnected
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_isConnected = false;
|
||||
|
||||
|
@ -122,22 +116,6 @@ abstract class Doctrine_Connection implements Countable
|
|||
*/
|
||||
protected $_quoteIdentifiers;
|
||||
|
||||
/**
|
||||
* The connection properties.
|
||||
*
|
||||
* @var array $properties
|
||||
*/
|
||||
protected $properties = array(
|
||||
'sql_comments' => array(
|
||||
array('start' => '--', 'end' => "\n", 'escape' => false),
|
||||
array('start' => '/*', 'end' => '*/', 'escape' => false)),
|
||||
'identifier_quoting' => array('start' => '"', 'end' => '"','escape' => '"'),
|
||||
'string_quoting' => array('start' => "'", 'end' => "'", 'escape' => false,
|
||||
'escape_pattern' => false),
|
||||
'wildcards' => array('%', '_'),
|
||||
'varchar_max_length' => 255,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $serverInfo
|
||||
*/
|
||||
|
@ -173,7 +151,14 @@ abstract class Doctrine_Connection implements Countable
|
|||
*
|
||||
* @var Doctrine::DBAL::Platforms::DatabasePlatform
|
||||
*/
|
||||
protected $_databasePlatform;
|
||||
protected $_platform;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @var Doctrine::DBAL::Transactions::Transaction
|
||||
*/
|
||||
protected $_transaction;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -237,18 +222,14 @@ abstract class Doctrine_Connection implements Countable
|
|||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
* Gets the DatabasePlatform for the connection.
|
||||
*
|
||||
* @param unknown_type $name
|
||||
* @return unknown
|
||||
* @todo Remove. Move properties to DatabasePlatform.
|
||||
* @return Doctrine::DBAL::Platforms::DatabasePlatform
|
||||
*/
|
||||
public function getProperty($name)
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
if ( ! isset($this->properties[$name])) {
|
||||
throw Doctrine_Connection_Exception::unknownProperty($name);
|
||||
}
|
||||
return $this->properties[$name];
|
||||
throw new Doctrine_Connection_Exception("No DatabasePlatform available "
|
||||
. "for connection " . get_class($this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -827,7 +808,8 @@ abstract class Doctrine_Connection implements Countable
|
|||
}
|
||||
|
||||
/**
|
||||
* execute
|
||||
* Executes an SQL SELECT query with the given parameters.
|
||||
*
|
||||
* @param string $query sql query
|
||||
* @param array $params query parameters
|
||||
*
|
||||
|
@ -860,11 +842,13 @@ abstract class Doctrine_Connection implements Countable
|
|||
}
|
||||
|
||||
/**
|
||||
* exec
|
||||
* Executes an SQL INSERT/UPDATE/DELETE query with the given parameters.
|
||||
*
|
||||
* @param string $query sql query
|
||||
* @param array $params query parameters
|
||||
*
|
||||
* @return PDOStatement|Doctrine_Adapter_Statement
|
||||
* @todo Rename to executeUpdate().
|
||||
*/
|
||||
public function exec($query, array $params = array()) {
|
||||
$this->connect();
|
||||
|
@ -891,30 +875,6 @@ abstract class Doctrine_Connection implements Countable
|
|||
$this->rethrowException($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
* @todo Rather orm stuff
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
|
||||
{
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dbms specific LIMIT/OFFSET SQL for the subqueries that are used in the
|
||||
* context of the limit-subquery algorithm.
|
||||
*
|
||||
* @return string
|
||||
* @todo Rather ORM stuff
|
||||
*/
|
||||
public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false,
|
||||
$offset = false, $isManip = false)
|
||||
{
|
||||
return $this->modifyLimitQuery($query, $limit, $offset, $isManip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given exception into a driver-specific exception and rethrows it.
|
||||
|
@ -945,7 +905,7 @@ abstract class Doctrine_Connection implements Countable
|
|||
* @return integer
|
||||
* @todo Better name: getQueryCount()
|
||||
*/
|
||||
public function count()
|
||||
public function getQueryCount()
|
||||
{
|
||||
return $this->_queryCount;
|
||||
}
|
||||
|
@ -1030,7 +990,7 @@ abstract class Doctrine_Connection implements Countable
|
|||
*/
|
||||
public function beginTransaction($savepoint = null)
|
||||
{
|
||||
return $this->transaction->beginTransaction($savepoint);
|
||||
return $this->_transaction->beginTransaction($savepoint);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1260,14 +1220,6 @@ abstract class Doctrine_Connection implements Countable
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFormatter()
|
||||
{
|
||||
if ( ! $this->modules['formatter']) {
|
||||
$this->modules['formatter'] = new Doctrine_Formatter($this);
|
||||
}
|
||||
return $this->modules['formatter'];
|
||||
}
|
||||
|
||||
public function getSequenceManager()
|
||||
{
|
||||
|
@ -1277,16 +1229,4 @@ abstract class Doctrine_Connection implements Countable
|
|||
}
|
||||
return $this->modules['sequence'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default (preferred) Id generation strategy of the database platform.
|
||||
*
|
||||
* @todo Sure, the id generator types are more ORM functionality but they're
|
||||
* still kind of dbal related. Maybe we need another set of classes (DatabasePlatform?)
|
||||
* but im not so sure...
|
||||
*/
|
||||
/*abstract*/ public function getDefaultIdGeneratorType()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Connection');
|
||||
|
||||
/**
|
||||
* Doctrine_Connection_Db2
|
||||
*
|
||||
|
|
|
@ -45,38 +45,9 @@ class Doctrine_Connection_Firebird extends Doctrine_Connection
|
|||
* @param Doctrine_Manager $manager
|
||||
* @param PDO $pdo database handle
|
||||
*/
|
||||
public function __construct(Doctrine_Manager $manager, $adapter)
|
||||
public function __construct(array $params)
|
||||
{
|
||||
|
||||
$this->supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'current_id' => true,
|
||||
'limit_queries' => 'emulated',
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => false,
|
||||
'pattern_escaping' => true
|
||||
);
|
||||
// initialize all driver options
|
||||
/**
|
||||
$this->options['DBA_username'] = false;
|
||||
$this->options['DBA_password'] = false;
|
||||
$this->options['database_path'] = '';
|
||||
$this->options['database_extension'] = '.gdb';
|
||||
$this->options['server_version'] = '';
|
||||
*/
|
||||
parent::__construct($manager, $adapter);
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,23 +63,4 @@ class Doctrine_Connection_Firebird extends Doctrine_Connection
|
|||
$this->exec($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an driver-specific LIMIT clause to the query
|
||||
*
|
||||
* @param string $query query to modify
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @return string modified query
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit, $offset)
|
||||
{
|
||||
if ( ! $offset) {
|
||||
$offset = 0;
|
||||
}
|
||||
if ($limit > 0) {
|
||||
$query = preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i',
|
||||
"SELECT FIRST $limit SKIP $offset", $query);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Connection');
|
||||
|
||||
/**
|
||||
* Doctrine_Connection_Mysql
|
||||
*
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @since 1.0
|
||||
* @todo Remove.
|
||||
*/
|
||||
class Doctrine_Connection_Mock extends Doctrine_Connection_Common
|
||||
{
|
||||
|
@ -48,7 +49,12 @@ class Doctrine_Connection_Mock extends Doctrine_Connection_Common
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return new Doctrine_DatabasePlatform_MySqlPlatform();
|
||||
}
|
||||
|
||||
public function quote($input, $type = null)
|
||||
|
|
|
@ -44,28 +44,9 @@ class Doctrine_Connection_Mssql extends Doctrine_Connection
|
|||
* @param Doctrine_Manager $manager
|
||||
* @param PDO $pdo database handle
|
||||
*/
|
||||
public function __construct(Doctrine_Manager $manager, $adapter)
|
||||
public function __construct(array $params)
|
||||
{
|
||||
// initialize all driver options
|
||||
$this->supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => 'emulated',
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => 'emulated',
|
||||
);
|
||||
|
||||
parent::__construct($manager, $adapter);
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,52 +78,6 @@ class Doctrine_Connection_Mssql extends Doctrine_Connection
|
|||
return '[' . str_replace(']', ']]', $identifier) . ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit, $offset, $isManip = false)
|
||||
{
|
||||
if ($limit > 0) {
|
||||
$count = intval($limit);
|
||||
|
||||
$offset = intval($offset);
|
||||
if ($offset < 0) {
|
||||
throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* return version information about the server
|
||||
*
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
/**
|
||||
* Doctrine_Connection_Mysql
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Connection
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
|
@ -49,47 +47,7 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
|
|||
* @param PDO|Doctrine_Adapter $adapter database handler
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
$this->supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => false,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => true,
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => 'emulated',
|
||||
'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($params);
|
||||
}
|
||||
|
||||
|
@ -232,5 +190,18 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
|
|||
}
|
||||
|
||||
return $dsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DatabasePlatform for the connection.
|
||||
*
|
||||
* @return Doctrine::DBAL::Platforms::MySqlPlatform
|
||||
*/
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
if ( ! $this->_platform) {
|
||||
$this->_platform = new Doctrine_DatabasePlatform_MySqlPlatform();
|
||||
}
|
||||
return $this->_platform;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
/**
|
||||
* Doctrine_Connection_Oracle
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Connection
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
|
@ -37,38 +35,9 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection
|
|||
*/
|
||||
protected $driverName = 'Oracle';
|
||||
|
||||
public function __construct(Doctrine_Manager $manager, $adapter)
|
||||
public function __construct(array $params)
|
||||
{
|
||||
$this->supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => false, // implementation is broken
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => true,
|
||||
);
|
||||
/**
|
||||
$this->options['DBA_username'] = false;
|
||||
$this->options['DBA_password'] = false;
|
||||
$this->options['database_name_prefix'] = false;
|
||||
$this->options['emulate_database'] = true;
|
||||
$this->options['default_tablespace'] = false;
|
||||
$this->options['default_text_field_length'] = 2000;
|
||||
$this->options['result_prefetching'] = false;
|
||||
*/
|
||||
parent::__construct($manager, $adapter);
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,60 +48,4 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection
|
|||
{
|
||||
$this->exec('ALTER SESSION SET NLS_DATE_FORMAT = "' . $format . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an driver-specific LIMIT clause to the query
|
||||
*
|
||||
* @param string $query query to modify
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @return string the modified query
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
|
||||
{
|
||||
return $this->_createLimitSubquery($query, $limit, $offset);
|
||||
}
|
||||
|
||||
private function _createLimitSubquery($query, $limit, $offset, $column = null)
|
||||
{
|
||||
$limit = (int) $limit;
|
||||
$offset = (int) $offset;
|
||||
if (preg_match('/^\s*SELECT/i', $query)) {
|
||||
if ( ! preg_match('/\sFROM\s/i', $query)) {
|
||||
$query .= " FROM dual";
|
||||
}
|
||||
if ($limit > 0) {
|
||||
$max = $offset + $limit;
|
||||
$column = $column === null ? '*' : $column;
|
||||
if ($offset > 0) {
|
||||
$min = $offset + 1;
|
||||
$query = 'SELECT b.'.$column.' FROM ('.
|
||||
'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
|
||||
. $query . ') a '.
|
||||
') b '.
|
||||
'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;
|
||||
} else {
|
||||
$query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL for Oracle that can be used in the subquery for the limit-subquery
|
||||
* algorithm.
|
||||
*/
|
||||
public function modifyLimitSubquery(Doctrine_ClassMetadata $rootClass, $query, $limit = false,
|
||||
$offset = false, $isManip = false)
|
||||
{
|
||||
// NOTE: no composite key support
|
||||
$columnNames = $rootClass->getIdentifierColumnNames();
|
||||
if (count($columnNames) > 1) {
|
||||
throw new Doctrine_Connection_Exception("Composite keys in LIMIT queries are "
|
||||
. "currently not supported.");
|
||||
}
|
||||
$column = $columnNames[0];
|
||||
return $this->_createLimitSubquery($query, $limit, $offset, $column);
|
||||
}
|
||||
}
|
|
@ -24,8 +24,6 @@
|
|||
/**
|
||||
* PgsqlConnection
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Connection
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
|
@ -46,39 +44,9 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common
|
|||
* @param Doctrine_Manager $manager
|
||||
* @param PDO $pdo database handle
|
||||
*/
|
||||
public function __construct(Doctrine_Manager $manager, $adapter)
|
||||
public function __construct(array $params)
|
||||
{
|
||||
// initialize all driver options
|
||||
$this->supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'current_id' => true,
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => 'emulated',
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => true,
|
||||
);
|
||||
|
||||
$this->properties['string_quoting'] = array('start' => "'",
|
||||
'end' => "'",
|
||||
'escape' => "'",
|
||||
'escape_pattern' => '\\');
|
||||
|
||||
$this->properties['identifier_quoting'] = array('start' => '"',
|
||||
'end' => '"',
|
||||
'escape' => '"');
|
||||
parent::__construct($manager, $adapter);
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,43 +88,6 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common
|
|||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes a query string for various DBMS specific reasons
|
||||
*
|
||||
* @param string $query query to modify
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @param boolean $isManip if the query is a DML query
|
||||
* @return string modified query
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
|
||||
{
|
||||
if ($limit > 0) {
|
||||
$query = rtrim($query);
|
||||
|
||||
if (substr($query, -1) == ';') {
|
||||
$query = substr($query, 0, -1);
|
||||
}
|
||||
|
||||
if ($isManip) {
|
||||
$manip = preg_replace('/^(DELETE FROM|UPDATE).*$/', '\\1', $query);
|
||||
$from = $match[2];
|
||||
$where = $match[3];
|
||||
$query = $manip . ' ' . $from . ' WHERE ctid=(SELECT ctid FROM '
|
||||
. $from . ' ' . $where . ' LIMIT ' . $limit . ')';
|
||||
|
||||
} else {
|
||||
if ( ! empty($limit)) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
if ( ! empty($offset)) {
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* return version information about the server
|
||||
*
|
||||
|
|
|
@ -47,30 +47,8 @@ class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common
|
|||
* @param PDO $pdo database handle
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
$this->supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => false,
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => false, // not implemented
|
||||
'prepared_statements' => 'emulated',
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => false,
|
||||
);
|
||||
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if ($this->_isConnected) {
|
||||
$this->_pdo->sqliteCreateFunction('mod', array('Doctrine_Expression_Sqlite', 'modImpl'), 2);
|
||||
$this->_pdo->sqliteCreateFunction('md5', 'md5', 1);
|
||||
|
|
|
@ -28,191 +28,10 @@
|
|||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Firebird extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'varchar':
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'char':
|
||||
case 'text':
|
||||
case 'gzip':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : 16777215; // TODO: $this->conn->options['default_text_field_length'];
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')';
|
||||
case 'clob':
|
||||
return 'BLOB SUB_TYPE 1';
|
||||
case 'blob':
|
||||
return 'BLOB SUB_TYPE 0';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'SMALLINT';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'TIMESTAMP';
|
||||
case 'float':
|
||||
return 'DOUBLE PRECISION';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
public function getPortableDeclaration($field)
|
||||
{
|
||||
$length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null;
|
||||
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
$dbType = strtolower($field['type']);
|
||||
$field['field_sub_type'] = !empty($field['field_sub_type'])
|
||||
? strtolower($field['field_sub_type']) : null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'smallint':
|
||||
case 'integer':
|
||||
case 'int64':
|
||||
//these may be 'numeric' or 'decimal'
|
||||
if (isset($field['field_sub_type'])) {
|
||||
$field['type'] = $field['field_sub_type'];
|
||||
return $this->getPortableDeclaration($field);
|
||||
}
|
||||
case 'bigint':
|
||||
case 'quad':
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'varchar':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'cstring':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'double precision':
|
||||
case 'd_float':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
break;
|
||||
case 'blob':
|
||||
$type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'CHARACTER SET ' . $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'COLLATE ' . $collation;
|
||||
}
|
||||
}
|
|
@ -31,80 +31,5 @@
|
|||
*/
|
||||
class Doctrine_DataDict_Informix extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('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 new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_DataDict');
|
||||
|
||||
/**
|
||||
* @package Doctrine
|
||||
* @subpackage DataDict
|
||||
|
@ -29,166 +29,10 @@ Doctrine::autoload('Doctrine_DataDict');
|
|||
* @author David Coallier <davidc@php.net> (PEAR MDB2 Mssql driver)
|
||||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Mssql extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'text':
|
||||
case 'char':
|
||||
case 'varchar':
|
||||
case 'string':
|
||||
case 'gzip':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : false;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->options['default_text_field_length'].')')
|
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 8000) {
|
||||
return 'VARCHAR('.$length.')';
|
||||
}
|
||||
}
|
||||
return 'TEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 8000) {
|
||||
return "VARBINARY($length)";
|
||||
}
|
||||
}
|
||||
return 'IMAGE';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'BIT';
|
||||
case 'date':
|
||||
return 'CHAR(' . strlen('YYYY-MM-DD') . ')';
|
||||
case 'time':
|
||||
return 'CHAR(' . strlen('HH:MM:SS') . ')';
|
||||
case 'timestamp':
|
||||
return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')';
|
||||
case 'float':
|
||||
return 'FLOAT';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a MDB2 datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
public function getPortableDeclaration($field)
|
||||
{
|
||||
$db_type = preg_replace('/[\d\(\)]/','', strtolower($field['type']) );
|
||||
$length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null;
|
||||
|
||||
$type = array();
|
||||
// todo: unsigned handling seems to be missing
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name']))
|
||||
$field['name'] = '';
|
||||
|
||||
switch ($db_type) {
|
||||
case 'bit':
|
||||
$type[0] = 'boolean';
|
||||
break;
|
||||
case 'tinyint':
|
||||
case 'smallint':
|
||||
case 'int':
|
||||
$type[0] = 'integer';
|
||||
if ($length == 1) {
|
||||
$type[] = 'boolean';
|
||||
}
|
||||
break;
|
||||
case 'datetime':
|
||||
$type[0] = 'timestamp';
|
||||
break;
|
||||
case 'float':
|
||||
case 'real':
|
||||
case 'numeric':
|
||||
$type[0] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'money':
|
||||
$type[0] = 'decimal';
|
||||
break;
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'ntext':
|
||||
case 'nvarchar':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'nchar':
|
||||
$type[0] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^[is|has]/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($db_type, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'image':
|
||||
case 'varbinary':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$db_type);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,391 +28,9 @@
|
|||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Mysql extends Doctrine_DataDict
|
||||
{
|
||||
protected $keywords = array(
|
||||
'ADD', 'ALL', 'ALTER',
|
||||
'ANALYZE', 'AND', 'AS',
|
||||
'ASC', 'ASENSITIVE', 'BEFORE',
|
||||
'BETWEEN', 'BIGINT', 'BINARY',
|
||||
'BLOB', 'BOTH', 'BY',
|
||||
'CALL', 'CASCADE', 'CASE',
|
||||
'CHANGE', 'CHAR', 'CHARACTER',
|
||||
'CHECK', 'COLLATE', 'COLUMN',
|
||||
'CONDITION', 'CONNECTION', 'CONSTRAINT',
|
||||
'CONTINUE', 'CONVERT', 'CREATE',
|
||||
'CROSS', 'CURRENT_DATE', 'CURRENT_TIME',
|
||||
'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR',
|
||||
'DATABASE', 'DATABASES', 'DAY_HOUR',
|
||||
'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND',
|
||||
'DEC', 'DECIMAL', 'DECLARE',
|
||||
'DEFAULT', 'DELAYED', 'DELETE',
|
||||
'DESC', 'DESCRIBE', 'DETERMINISTIC',
|
||||
'DISTINCT', 'DISTINCTROW', 'DIV',
|
||||
'DOUBLE', 'DROP', 'DUAL',
|
||||
'EACH', 'ELSE', 'ELSEIF',
|
||||
'ENCLOSED', 'ESCAPED', 'EXISTS',
|
||||
'EXIT', 'EXPLAIN', 'FALSE',
|
||||
'FETCH', 'FLOAT', 'FLOAT4',
|
||||
'FLOAT8', 'FOR', 'FORCE',
|
||||
'FOREIGN', 'FROM', 'FULLTEXT',
|
||||
'GRANT', 'GROUP', 'HAVING',
|
||||
'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE',
|
||||
'HOUR_SECOND', 'IF', 'IGNORE',
|
||||
'IN', 'INDEX', 'INFILE',
|
||||
'INNER', 'INOUT', 'INSENSITIVE',
|
||||
'INSERT', 'INT', 'INT1',
|
||||
'INT2', 'INT3', 'INT4',
|
||||
'INT8', 'INTEGER', 'INTERVAL',
|
||||
'INTO', 'IS', 'ITERATE',
|
||||
'JOIN', 'KEY', 'KEYS',
|
||||
'KILL', 'LEADING', 'LEAVE',
|
||||
'LEFT', 'LIKE', 'LIMIT',
|
||||
'LINES', 'LOAD', 'LOCALTIME',
|
||||
'LOCALTIMESTAMP', 'LOCK', 'LONG',
|
||||
'LONGBLOB', 'LONGTEXT', 'LOOP',
|
||||
'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB',
|
||||
'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT',
|
||||
'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD',
|
||||
'MODIFIES', 'NATURAL', 'NOT',
|
||||
'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC',
|
||||
'ON', 'OPTIMIZE', 'OPTION',
|
||||
'OPTIONALLY', 'OR', 'ORDER',
|
||||
'OUT', 'OUTER', 'OUTFILE',
|
||||
'PRECISION', 'PRIMARY', 'PROCEDURE',
|
||||
'PURGE', 'RAID0', 'READ',
|
||||
'READS', 'REAL', 'REFERENCES',
|
||||
'REGEXP', 'RELEASE', 'RENAME',
|
||||
'REPEAT', 'REPLACE', 'REQUIRE',
|
||||
'RESTRICT', 'RETURN', 'REVOKE',
|
||||
'RIGHT', 'RLIKE', 'SCHEMA',
|
||||
'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT',
|
||||
'SENSITIVE', 'SEPARATOR', 'SET',
|
||||
'SHOW', 'SMALLINT', 'SONAME',
|
||||
'SPATIAL', 'SPECIFIC', 'SQL',
|
||||
'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING',
|
||||
'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT',
|
||||
'SSL', 'STARTING', 'STRAIGHT_JOIN',
|
||||
'TABLE', 'TERMINATED', 'THEN',
|
||||
'TINYBLOB', 'TINYINT', 'TINYTEXT',
|
||||
'TO', 'TRAILING', 'TRIGGER',
|
||||
'TRUE', 'UNDO', 'UNION',
|
||||
'UNIQUE', 'UNLOCK', 'UNSIGNED',
|
||||
'UPDATE', 'USAGE', 'USE',
|
||||
'USING', 'UTC_DATE', 'UTC_TIME',
|
||||
'UTC_TIMESTAMP', 'VALUES', 'VARBINARY',
|
||||
'VARCHAR', 'VARCHARACTER', 'VARYING',
|
||||
'WHEN', 'WHERE', 'WHILE',
|
||||
'WITH', 'WRITE', 'X509',
|
||||
'XOR', 'YEAR_MONTH', 'ZEROFILL'
|
||||
);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
|
||||
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':
|
||||
case 'gzip':
|
||||
if ( ! isset($field['length'])) {
|
||||
if (array_key_exists('default', $field)) {
|
||||
$field['length'] = $this->conn->varchar_max_length;
|
||||
} else {
|
||||
$field['length'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$length = ($field['length'] <= $this->conn->varchar_max_length) ? $field['length'] : false;
|
||||
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
|
||||
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYTEXT';
|
||||
} elseif ($length <= 65532) {
|
||||
return 'TEXT';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMTEXT';
|
||||
}
|
||||
}
|
||||
return 'LONGTEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYBLOB';
|
||||
} elseif ($length <= 65532) {
|
||||
return 'BLOB';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMBLOB';
|
||||
}
|
||||
}
|
||||
return 'LONGBLOB';
|
||||
case 'enum':
|
||||
if ($this->conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) {
|
||||
$values = array();
|
||||
foreach ($field['values'] as $value) {
|
||||
$values[] = $this->conn->quote($value, 'varchar');
|
||||
}
|
||||
return 'ENUM('.implode(', ', $values).')';
|
||||
}
|
||||
// fall back to integer
|
||||
case 'integer':
|
||||
case 'int':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 1) {
|
||||
return 'TINYINT';
|
||||
} elseif ($length == 2) {
|
||||
return 'SMALLINT';
|
||||
} elseif ($length == 3) {
|
||||
return 'MEDIUMINT';
|
||||
} elseif ($length == 4) {
|
||||
return 'INT';
|
||||
} elseif ($length > 4) {
|
||||
return 'BIGINT';
|
||||
}
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'TINYINT(1)';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'DATETIME';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'DOUBLE';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
$dbType = strtolower($field['type']);
|
||||
$dbType = strtok($dbType, '(), ');
|
||||
if ($dbType == 'national') {
|
||||
$dbType = strtok('(), ');
|
||||
}
|
||||
if (isset($field['length'])) {
|
||||
$length = $field['length'];
|
||||
$decimal = '';
|
||||
} else {
|
||||
$length = strtok('(), ');
|
||||
$decimal = strtok('(), ');
|
||||
}
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
$values = null;
|
||||
|
||||
switch ($dbType) {
|
||||
case 'tinyint':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 1;
|
||||
break;
|
||||
case 'smallint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 2;
|
||||
break;
|
||||
case 'mediumint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 3;
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 8;
|
||||
break;
|
||||
case 'tinytext':
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
$fixed = false;
|
||||
case 'string':
|
||||
case 'char':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
if ($decimal == 'binary') {
|
||||
$type[] = 'blob';
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
$type[] = 'enum';
|
||||
preg_match_all('/\'((?:\'\'|[^\'])*)\'/', $field['type'], $matches);
|
||||
$length = 0;
|
||||
$fixed = false;
|
||||
if (is_array($matches)) {
|
||||
foreach ($matches[1] as &$value) {
|
||||
$value = str_replace('\'\'', '\'', $value);
|
||||
$length = max($length, strlen($value));
|
||||
}
|
||||
if ($length == '1' && count($matches[1]) == 2) {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} else {
|
||||
$values = $matches[1];
|
||||
}
|
||||
}
|
||||
$type[] = 'integer';
|
||||
break;
|
||||
case 'set':
|
||||
$fixed = false;
|
||||
$type[] = 'text';
|
||||
$type[] = 'integer';
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
break;
|
||||
case 'unknown':
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
|
||||
}
|
||||
|
||||
$length = ((int) $length == 0) ? null : (int) $length;
|
||||
|
||||
if ($values === null) {
|
||||
return array('type' => $type, 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed);
|
||||
} else {
|
||||
return array('type' => $type, 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed, 'values' => $values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'CHARACTER SET ' . $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'COLLATE ' . $collation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,174 +26,10 @@
|
|||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Oracle extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* 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(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'gzip':
|
||||
case 'char':
|
||||
case 'varchar':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : 16777215; // TODO: $this->conn->options['default_text_field_length'];
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')';
|
||||
case 'clob':
|
||||
return 'CLOB';
|
||||
case 'blob':
|
||||
return 'BLOB';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
if ( ! empty($field['length'])) {
|
||||
return 'NUMBER('.$field['length'].')';
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'NUMBER(1)';
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'timestamp':
|
||||
return 'DATE';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'NUMBER';
|
||||
case 'decimal':
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'NUMBER(*,'.$scale.')';
|
||||
default:
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @throws Doctrine_DataDict_Oracle_Exception
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
if ( ! isset($field['data_type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Native oracle definition must have a data_type key specified');
|
||||
}
|
||||
|
||||
$dbType = strtolower($field['data_type']);
|
||||
$type = array();
|
||||
$length = $unsigned = $fixed = null;
|
||||
if ( ! empty($field['data_length'])) {
|
||||
$length = $field['data_length'];
|
||||
}
|
||||
|
||||
if ( ! isset($field['column_name'])) {
|
||||
$field['column_name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'integer':
|
||||
case 'pls_integer':
|
||||
case 'binary_integer':
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'varchar':
|
||||
case 'varchar2':
|
||||
case 'nvarchar2':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'nchar':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'number':
|
||||
if ( ! empty($field['data_scale'])) {
|
||||
$type[] = 'decimal';
|
||||
} else {
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'long':
|
||||
$type[] = 'string';
|
||||
case 'clob':
|
||||
case 'nclob':
|
||||
$type[] = 'clob';
|
||||
break;
|
||||
case 'blob':
|
||||
case 'raw':
|
||||
case 'long raw':
|
||||
case 'bfile':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'rowid':
|
||||
case 'urowid':
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_DataDict');
|
||||
|
||||
/**
|
||||
* @package Doctrine
|
||||
* @subpackage DataDict
|
||||
|
@ -29,547 +29,9 @@ Doctrine::autoload('Doctrine_DataDict');
|
|||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Pgsql extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* @param array $reservedKeyWords an array of reserved keywords by pgsql
|
||||
*/
|
||||
protected static $reservedKeyWords = array(
|
||||
'abort',
|
||||
'absolute',
|
||||
'access',
|
||||
'action',
|
||||
'add',
|
||||
'after',
|
||||
'aggregate',
|
||||
'all',
|
||||
'alter',
|
||||
'analyse',
|
||||
'analyze',
|
||||
'and',
|
||||
'any',
|
||||
'as',
|
||||
'asc',
|
||||
'assertion',
|
||||
'assignment',
|
||||
'at',
|
||||
'authorization',
|
||||
'backward',
|
||||
'before',
|
||||
'begin',
|
||||
'between',
|
||||
'bigint',
|
||||
'binary',
|
||||
'bit',
|
||||
'boolean',
|
||||
'both',
|
||||
'by',
|
||||
'cache',
|
||||
'called',
|
||||
'cascade',
|
||||
'case',
|
||||
'cast',
|
||||
'chain',
|
||||
'char',
|
||||
'character',
|
||||
'characteristics',
|
||||
'check',
|
||||
'checkpoint',
|
||||
'class',
|
||||
'close',
|
||||
'cluster',
|
||||
'coalesce',
|
||||
'collate',
|
||||
'column',
|
||||
'comment',
|
||||
'commit',
|
||||
'committed',
|
||||
'constraint',
|
||||
'constraints',
|
||||
'conversion',
|
||||
'convert',
|
||||
'copy',
|
||||
'create',
|
||||
'createdb',
|
||||
'createuser',
|
||||
'cross',
|
||||
'current_date',
|
||||
'current_time',
|
||||
'current_timestamp',
|
||||
'current_user',
|
||||
'cursor',
|
||||
'cycle',
|
||||
'database',
|
||||
'day',
|
||||
'deallocate',
|
||||
'dec',
|
||||
'decimal',
|
||||
'declare',
|
||||
'default',
|
||||
'deferrable',
|
||||
'deferred',
|
||||
'definer',
|
||||
'delete',
|
||||
'delimiter',
|
||||
'delimiters',
|
||||
'desc',
|
||||
'distinct',
|
||||
'do',
|
||||
'domain',
|
||||
'double',
|
||||
'drop',
|
||||
'each',
|
||||
'else',
|
||||
'encoding',
|
||||
'encrypted',
|
||||
'end',
|
||||
'escape',
|
||||
'except',
|
||||
'exclusive',
|
||||
'execute',
|
||||
'exists',
|
||||
'explain',
|
||||
'external',
|
||||
'extract',
|
||||
'false',
|
||||
'fetch',
|
||||
'float',
|
||||
'for',
|
||||
'force',
|
||||
'foreign',
|
||||
'forward',
|
||||
'freeze',
|
||||
'from',
|
||||
'full',
|
||||
'function',
|
||||
'get',
|
||||
'global',
|
||||
'grant',
|
||||
'group',
|
||||
'handler',
|
||||
'having',
|
||||
'hour',
|
||||
'ilike',
|
||||
'immediate',
|
||||
'immutable',
|
||||
'implicit',
|
||||
'in',
|
||||
'increment',
|
||||
'index',
|
||||
'inherits',
|
||||
'initially',
|
||||
'inner',
|
||||
'inout',
|
||||
'input',
|
||||
'insensitive',
|
||||
'insert',
|
||||
'instead',
|
||||
'int',
|
||||
'integer',
|
||||
'intersect',
|
||||
'interval',
|
||||
'into',
|
||||
'invoker',
|
||||
'is',
|
||||
'isnull',
|
||||
'isolation',
|
||||
'join',
|
||||
'key',
|
||||
'lancompiler',
|
||||
'language',
|
||||
'leading',
|
||||
'left',
|
||||
'level',
|
||||
'like',
|
||||
'limit',
|
||||
'listen',
|
||||
'load',
|
||||
'local',
|
||||
'localtime',
|
||||
'localtimestamp',
|
||||
'location',
|
||||
'lock',
|
||||
'match',
|
||||
'maxvalue',
|
||||
'minute',
|
||||
'minvalue',
|
||||
'mode',
|
||||
'month',
|
||||
'move',
|
||||
'names',
|
||||
'national',
|
||||
'natural',
|
||||
'nchar',
|
||||
'new',
|
||||
'next',
|
||||
'no',
|
||||
'nocreatedb',
|
||||
'nocreateuser',
|
||||
'none',
|
||||
'not',
|
||||
'nothing',
|
||||
'notify',
|
||||
'notnull',
|
||||
'null',
|
||||
'nullif',
|
||||
'numeric',
|
||||
'of',
|
||||
'off',
|
||||
'offset',
|
||||
'oids',
|
||||
'old',
|
||||
'on',
|
||||
'only',
|
||||
'operator',
|
||||
'option',
|
||||
'or',
|
||||
'order',
|
||||
'out',
|
||||
'outer',
|
||||
'overlaps',
|
||||
'overlay',
|
||||
'owner',
|
||||
'partial',
|
||||
'password',
|
||||
'path',
|
||||
'pendant',
|
||||
'placing',
|
||||
'position',
|
||||
'precision',
|
||||
'prepare',
|
||||
'primary',
|
||||
'prior',
|
||||
'privileges',
|
||||
'procedural',
|
||||
'procedure',
|
||||
'read',
|
||||
'real',
|
||||
'recheck',
|
||||
'references',
|
||||
'reindex',
|
||||
'relative',
|
||||
'rename',
|
||||
'replace',
|
||||
'reset',
|
||||
'restrict',
|
||||
'returns',
|
||||
'revoke',
|
||||
'right',
|
||||
'rollback',
|
||||
'row',
|
||||
'rule',
|
||||
'schema',
|
||||
'scroll',
|
||||
'second',
|
||||
'security',
|
||||
'select',
|
||||
'sequence',
|
||||
'serializable',
|
||||
'session',
|
||||
'session_user',
|
||||
'set',
|
||||
'setof',
|
||||
'share',
|
||||
'show',
|
||||
'similar',
|
||||
'simple',
|
||||
'smallint',
|
||||
'some',
|
||||
'stable',
|
||||
'start',
|
||||
'statement',
|
||||
'statistics',
|
||||
'stdin',
|
||||
'stdout',
|
||||
'storage',
|
||||
'strict',
|
||||
'substring',
|
||||
'sysid',
|
||||
'table',
|
||||
'temp',
|
||||
'template',
|
||||
'temporary',
|
||||
'then',
|
||||
'time',
|
||||
'timestamp',
|
||||
'to',
|
||||
'toast',
|
||||
'trailing',
|
||||
'transaction',
|
||||
'treat',
|
||||
'trigger',
|
||||
'trim',
|
||||
'true',
|
||||
'truncate',
|
||||
'trusted',
|
||||
'type',
|
||||
'unencrypted',
|
||||
'union',
|
||||
'unique',
|
||||
'unknown',
|
||||
'unlisten',
|
||||
'until',
|
||||
'update',
|
||||
'usage',
|
||||
'user',
|
||||
'using',
|
||||
'vacuum',
|
||||
'valid',
|
||||
'validator',
|
||||
'values',
|
||||
'varchar',
|
||||
'varying',
|
||||
'verbose',
|
||||
'version',
|
||||
'view',
|
||||
'volatile',
|
||||
'when',
|
||||
'where',
|
||||
'with',
|
||||
'without',
|
||||
'work',
|
||||
'write',
|
||||
'year',
|
||||
'zone'
|
||||
);
|
||||
|
||||
/**
|
||||
* 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(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'char':
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'varchar':
|
||||
case 'gzip':
|
||||
// TODO: what is the maximum VARCHAR length in pgsql ?
|
||||
$length = (isset($field['length']) && $field['length'] && $field['length'] < 10000) ? $field['length'] : null;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR('.$this->conn->options['default_text_field_length'].')')
|
||||
: ($length ? 'VARCHAR(' .$length . ')' : 'TEXT');
|
||||
|
||||
case 'clob':
|
||||
return 'TEXT';
|
||||
case 'blob':
|
||||
return 'BYTEA';
|
||||
case 'enum':
|
||||
case 'integer':
|
||||
case 'int':
|
||||
if ( ! empty($field['autoincrement'])) {
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length > 4) {
|
||||
return 'BIGSERIAL';
|
||||
}
|
||||
}
|
||||
return 'SERIAL';
|
||||
}
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 2) {
|
||||
return 'SMALLINT';
|
||||
} elseif ($length == 3 || $length == 4) {
|
||||
return 'INT';
|
||||
} elseif ($length > 4) {
|
||||
return 'BIGINT';
|
||||
}
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'BOOLEAN';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME without time zone';
|
||||
case 'timestamp':
|
||||
return 'TIMESTAMP without time zone';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'FLOAT';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'NUMERIC('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 getPortableDeclaration(array $field)
|
||||
{
|
||||
|
||||
$length = (isset($field['length'])) ? $field['length'] : null;
|
||||
if ($length == '-1' && isset($field['atttypmod'])) {
|
||||
$length = $field['atttypmod'] - 4;
|
||||
}
|
||||
if ((int)$length <= 0) {
|
||||
$length = null;
|
||||
}
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
$dbType = strtolower($field['type']);
|
||||
|
||||
switch ($dbType) {
|
||||
case 'smallint':
|
||||
case 'int2':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 2;
|
||||
if ($length == '2') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
case 'int4':
|
||||
case 'integer':
|
||||
case 'serial':
|
||||
case 'serial4':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'int8':
|
||||
case 'bigserial':
|
||||
case 'serial8':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 8;
|
||||
break;
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
$type[] = 'boolean';
|
||||
$length = 1;
|
||||
break;
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'interval':
|
||||
case '_varchar':
|
||||
$fixed = false;
|
||||
case 'unknown':
|
||||
case 'char':
|
||||
case 'bpchar':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
case 'timestamptz':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'float4':
|
||||
case 'float8':
|
||||
case 'double':
|
||||
case 'double precision':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'money':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
case 'bytea':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'oid':
|
||||
$type[] = 'blob';
|
||||
$type[] = 'clob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
/**
|
||||
* parseBoolean
|
||||
* parses a literal boolean value and returns
|
||||
* proper sql equivalent
|
||||
*
|
||||
* @param string $value boolean value to be parsed
|
||||
* @return string parsed boolean value
|
||||
*/
|
||||
public function parseBoolean($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_DataDict');
|
||||
|
||||
/**
|
||||
* @package Doctrine
|
||||
* @subpackage DataDict
|
||||
|
@ -27,218 +27,10 @@ Doctrine::autoload('Doctrine_DataDict');
|
|||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @since 1.0
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_DataDict_Sqlite extends Doctrine_DataDict
|
||||
{
|
||||
/**
|
||||
* 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.
|
||||
* @author Lukas Smith (PEAR MDB2 library)
|
||||
* @return string DBMS specific SQL code portion that should be used to
|
||||
* declare the specified field.
|
||||
*/
|
||||
public function getNativeDeclaration(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'text':
|
||||
case 'object':
|
||||
case 'array':
|
||||
case 'string':
|
||||
case 'char':
|
||||
case 'gzip':
|
||||
case 'varchar':
|
||||
$length = (isset($field['length']) && $field['length']) ? $field['length'] : null;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TEXTFLD_LENGTH).')')
|
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYTEXT';
|
||||
} elseif ($length <= 65535) {
|
||||
return 'TEXT';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMTEXT';
|
||||
}
|
||||
}
|
||||
return 'LONGTEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYBLOB';
|
||||
} elseif ($length <= 65535) {
|
||||
return 'BLOB';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMBLOB';
|
||||
}
|
||||
}
|
||||
return 'LONGBLOB';
|
||||
case 'enum':
|
||||
case 'integer':
|
||||
case 'boolean':
|
||||
case 'int':
|
||||
return 'INTEGER';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'DATETIME';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'DOUBLE';//($this->conn->options['fixed_float'] ? '('.
|
||||
//($this->conn->options['fixed_float']+2).','.$this->conn->options['fixed_float'].')' : '');
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
$dbType = strtolower($field['type']);
|
||||
$length = (isset($field['length'])) ? $field['length'] : null;
|
||||
$unsigned = (isset($field['unsigned'])) ? $field['unsigned'] : null;
|
||||
$fixed = null;
|
||||
$type = array();
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'boolean':
|
||||
$type[] = 'boolean';
|
||||
break;
|
||||
case 'tinyint':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 1;
|
||||
break;
|
||||
case 'smallint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 2;
|
||||
break;
|
||||
case 'mediumint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 3;
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
case 'serial':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'bigserial':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 8;
|
||||
break;
|
||||
case 'clob':
|
||||
case 'tinytext':
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'varchar2':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
$type[] = 'text';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
$length = null;
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
$length = null;
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
916
lib/Doctrine/DatabasePlatform.php
Normal file
916
lib/Doctrine/DatabasePlatform.php
Normal file
|
@ -0,0 +1,916 @@
|
|||
<?php
|
||||
|
||||
#namespace Doctrine::DBAL::Platforms;
|
||||
|
||||
/**
|
||||
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
|
||||
* point of abstraction of platform-specific behaviors, features and SQL dialects.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
abstract class Doctrine_DatabasePlatform
|
||||
{
|
||||
/**
|
||||
* An array containing all features this platform supports, keys representing feature
|
||||
* names and values as one of the following (true, false, 'emulated').
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_supported = array();
|
||||
|
||||
/**
|
||||
* Platform specific properties. Subclasses can override these in the
|
||||
* constructor.
|
||||
*
|
||||
* @var array $properties
|
||||
*/
|
||||
protected $_properties = array(
|
||||
'sql_comments' => array(
|
||||
array(
|
||||
'start' => '--',
|
||||
'end' => "\n",
|
||||
'escape' => false
|
||||
),
|
||||
array(
|
||||
'start' => '/*',
|
||||
'end' => '*/',
|
||||
'escape' => false
|
||||
)
|
||||
),
|
||||
'identifier_quoting' => array(
|
||||
'start' => '"',
|
||||
'end' => '"',
|
||||
'escape' => '"'
|
||||
),
|
||||
'string_quoting' => array(
|
||||
'start' => "'",
|
||||
'end' => "'",
|
||||
'escape' => false,
|
||||
'escape_pattern' => false
|
||||
),
|
||||
'wildcards' => array('%', '_'),
|
||||
'varchar_max_length' => 255,
|
||||
);
|
||||
|
||||
public function __construct() {}
|
||||
|
||||
/**
|
||||
* Checks whether a certain feature is supported.
|
||||
*
|
||||
* @param string $feature the name of the feature
|
||||
* @return boolean whether or not this drivers supports given feature
|
||||
*/
|
||||
public function supports($feature)
|
||||
{
|
||||
return (isset($this->_supported[$feature]) &&
|
||||
($this->_supported[$feature] === 'emulated' || $this->_supported[$feature]));
|
||||
}
|
||||
|
||||
/**
|
||||
* regexp
|
||||
* returns the regular expression operator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRegexpExpression()
|
||||
{
|
||||
throw new Doctrine_Expression_Exception('Regular expression operator is not supported by this database driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average value of a column
|
||||
*
|
||||
* @param string $column the column to use
|
||||
* @return string generated sql including an AVG aggregate function
|
||||
*/
|
||||
public function getAvgExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'AVG(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows (without a NULL value) of a column
|
||||
*
|
||||
* If a '*' is used instead of a column the number of selected rows
|
||||
* is returned.
|
||||
*
|
||||
* @param string|integer $column the column to use
|
||||
* @return string generated sql including a COUNT aggregate function
|
||||
*/
|
||||
public function getCountExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'COUNT(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest value of a column
|
||||
*
|
||||
* @param string $column the column to use
|
||||
* @return string generated sql including a MAX aggregate function
|
||||
*/
|
||||
public function getMaxExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'MAX(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowest value of a column
|
||||
*
|
||||
* @param string $column the column to use
|
||||
* @return string
|
||||
*/
|
||||
public function getMinExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'MIN(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total sum of a column
|
||||
*
|
||||
* @param string $column the column to use
|
||||
* @return string
|
||||
*/
|
||||
public function getSumExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'SUM(' . $column . ')';
|
||||
}
|
||||
|
||||
// scalar functions
|
||||
|
||||
/**
|
||||
* Returns the md5 sum of a field.
|
||||
*
|
||||
* Note: Not SQL92, but common functionality
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMd5Expression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'MD5(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of a text field.
|
||||
*
|
||||
* @param string $expression1
|
||||
* @param string $expression2
|
||||
* @return string
|
||||
*/
|
||||
public function getLengthExpression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
return 'LENGTH(' . $column . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a numeric field to the number of decimals specified.
|
||||
*
|
||||
* @param string $expression1
|
||||
* @param string $expression2
|
||||
* @return string
|
||||
*/
|
||||
public function getRoundExpression($column, $decimals = 0)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
|
||||
return 'ROUND(' . $column . ', ' . $decimals . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division operation
|
||||
* $expression1 / $expression2.
|
||||
*
|
||||
* @param string $expression1
|
||||
* @param string $expression2
|
||||
* @return string
|
||||
*/
|
||||
public function getModExpression($expression1, $expression2)
|
||||
{
|
||||
$expression1 = $this->getIdentifier($expression1);
|
||||
$expression2 = $this->getIdentifier($expression2);
|
||||
return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* trim
|
||||
* returns the string $str with leading and proceeding space characters removed
|
||||
*
|
||||
* @param string $str literal string or column name
|
||||
* @return string
|
||||
*/
|
||||
public function getTrimExpression($str)
|
||||
{
|
||||
return 'TRIM(' . $str . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* rtrim
|
||||
* returns the string $str with proceeding space characters removed
|
||||
*
|
||||
* @param string $str literal string or column name
|
||||
* @return string
|
||||
*/
|
||||
public function getRtrimExpression($str)
|
||||
{
|
||||
return 'RTRIM(' . $str . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* ltrim
|
||||
* returns the string $str with leading space characters removed
|
||||
*
|
||||
* @param string $str literal string or column name
|
||||
* @return string
|
||||
*/
|
||||
public function getLtrimExpression($str)
|
||||
{
|
||||
return 'LTRIM(' . $str . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* upper
|
||||
* Returns the string $str with all characters changed to
|
||||
* uppercase according to the current character set mapping.
|
||||
*
|
||||
* @param string $str literal string or column name
|
||||
* @return string
|
||||
*/
|
||||
public function getUpperExpression($str)
|
||||
{
|
||||
return 'UPPER(' . $str . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* lower
|
||||
* Returns the string $str with all characters changed to
|
||||
* lowercase according to the current character set mapping.
|
||||
*
|
||||
* @param string $str literal string or column name
|
||||
* @return string
|
||||
*/
|
||||
public function getLowerExpression($str)
|
||||
{
|
||||
return 'LOWER(' . $str . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* locate
|
||||
* returns the position of the first occurrence of substring $substr in string $str
|
||||
*
|
||||
* @param string $substr literal string to find
|
||||
* @param string $str literal string
|
||||
* @return integer
|
||||
*/
|
||||
public function getLocateExpression($str, $substr)
|
||||
{
|
||||
return 'LOCATE(' . $str . ', ' . $substr . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current system date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNowExpression()
|
||||
{
|
||||
return 'NOW()';
|
||||
}
|
||||
|
||||
/**
|
||||
* soundex
|
||||
* Returns a string to call a function to compute the
|
||||
* soundex encoding of a string
|
||||
*
|
||||
* The string "?000" is returned if the argument is NULL.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string SQL soundex function with given parameter
|
||||
*/
|
||||
public function getSoundexExpression($value)
|
||||
{
|
||||
throw new Doctrine_Expression_Exception('SQL soundex function not supported by this driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* SQLite only supports the 2 parameter variant of this function
|
||||
*
|
||||
* @param string $value an sql string literal or column name/alias
|
||||
* @param integer $position where to start the substring portion
|
||||
* @param integer $length the substring portion length
|
||||
* @return string SQL substring function with given parameters
|
||||
*/
|
||||
public function getSubstringExpression($value, $from, $len = null)
|
||||
{
|
||||
$value = $this->getIdentifier($value);
|
||||
if ($len === null)
|
||||
return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
|
||||
else {
|
||||
$len = $this->getIdentifier($len);
|
||||
return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $len . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a series of strings concatinated
|
||||
*
|
||||
* concat() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain an expression
|
||||
*
|
||||
* @param string $arg1, $arg2 ... $argN strings that will be concatinated.
|
||||
* @return string
|
||||
*/
|
||||
public function getConcatExpression()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return join(' || ' , $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL for a logical not.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $e = $q->expr;
|
||||
* $q->select('*')->from('table')
|
||||
* ->where($e->eq('id', $e->not('null'));
|
||||
* </code>
|
||||
*
|
||||
* @return string a logical expression
|
||||
*/
|
||||
public function getNotExpression($expression)
|
||||
{
|
||||
$expression = $this->getIdentifier($expression);
|
||||
return 'NOT(' . $expression . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to perform the same mathematical operation over an array
|
||||
* of values or expressions.
|
||||
*
|
||||
* basicMath() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain a value or an expression or an array with values or
|
||||
* expressions.
|
||||
*
|
||||
* @param string $type the type of operation, can be '+', '-', '*' or '/'.
|
||||
* @param string|array(string)
|
||||
* @return string an expression
|
||||
*/
|
||||
private function getBasicMathExpression($type, array $args)
|
||||
{
|
||||
$elements = $this->getIdentifiers($args);
|
||||
if (count($elements) < 1) {
|
||||
return '';
|
||||
}
|
||||
if (count($elements) == 1) {
|
||||
return $elements[0];
|
||||
} else {
|
||||
return '(' . implode(' ' . $type . ' ', $elements) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to add values or expressions together.
|
||||
*
|
||||
* add() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain a value or an expression or an array with values or
|
||||
* expressions.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $e = $q->expr;
|
||||
*
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($e->eq($e->add('id', 2), 12));
|
||||
* </code>
|
||||
*
|
||||
* @param string|array(string)
|
||||
* @return string an expression
|
||||
*/
|
||||
public function getAddExpression(array $args)
|
||||
{
|
||||
return $this->basicMath('+', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to subtract values or expressions from eachother.
|
||||
*
|
||||
* subtract() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain a value or an expression or an array with values or
|
||||
* expressions.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $e = $q->expr;
|
||||
*
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($e->eq($e->sub('id', 2), 12));
|
||||
* </code>
|
||||
*
|
||||
* @param string|array(string)
|
||||
* @return string an expression
|
||||
*/
|
||||
public function getSubExpression(array $args)
|
||||
{
|
||||
return $this->basicMath('-', $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to multiply values or expressions by eachother.
|
||||
*
|
||||
* multiply() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain a value or an expression or an array with values or
|
||||
* expressions.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $e = $q->expr;
|
||||
*
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($e->eq($e->mul('id', 2), 12));
|
||||
* </code>
|
||||
*
|
||||
* @param string|array(string)
|
||||
* @return string an expression
|
||||
*/
|
||||
public function getMulExpression(array $args)
|
||||
{
|
||||
return $this->basicMath('*', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to divide values or expressions by eachother.
|
||||
*
|
||||
* divide() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain a value or an expression or an array with values or
|
||||
* expressions.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $e = $q->expr;
|
||||
*
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($e->eq($e->div('id', 2), 12));
|
||||
* </code>
|
||||
*
|
||||
* @param string|array(string)
|
||||
* @return string an expression
|
||||
*/
|
||||
public function getDivExpression(array $args)
|
||||
{
|
||||
return $this->basicMath('/', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if two values are equal.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->eq('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getEqExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' = ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if two values are unequal.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->neq('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getNeqExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' <> ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if one value is greater than another value.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->gt('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getGtExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' > ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if one value is greater than or equal to
|
||||
* another value.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->gte('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getGteExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' >= ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if one value is less than another value.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->lt('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getLtExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' < ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if one value is less than or equal to
|
||||
* another value.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->lte('id', 1));
|
||||
* </code>
|
||||
*
|
||||
* @param string $value1 logical expression to compare
|
||||
* @param string $value2 logical expression to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getLteExpression($value1, $value2)
|
||||
{
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $value1 . ' <= ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL to check if a value is one in a set of
|
||||
* given values..
|
||||
*
|
||||
* in() accepts an arbitrary number of parameters. The first parameter
|
||||
* must always specify the value that should be matched against. Successive
|
||||
* must contain a logical expression or an array with logical expressions.
|
||||
* These expressions will be matched against the first parameter.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->in( 'id', array(1,2,3)));
|
||||
* </code>
|
||||
*
|
||||
* @param string $column the value that should be matched against
|
||||
* @param string|array(string) values that will be matched against $column
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getInExpression($column, $values)
|
||||
{
|
||||
if ( ! is_array($values)) {
|
||||
$values = array($values);
|
||||
}
|
||||
$values = $this->getIdentifiers($values);
|
||||
$column = $this->getIdentifier($column);
|
||||
|
||||
if (count($values) == 0) {
|
||||
throw new Doctrine_Expression_Exception('Values array for IN operator should not be empty.');
|
||||
}
|
||||
return $column . ' IN (' . implode(', ', $values) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns SQL that checks if a expression is null.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->isNull('id'));
|
||||
* </code>
|
||||
*
|
||||
* @param string $expression the expression that should be compared to null
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getIsNullExpression($expression)
|
||||
{
|
||||
$expression = $this->getIdentifier($expression);
|
||||
return $expression . ' IS NULL';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns SQL that checks if a expression is not null.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->isNotNull('id'));
|
||||
* </code>
|
||||
*
|
||||
* @param string $expression the expression that should be compared to null
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getIsNotNullExpression($expression)
|
||||
{
|
||||
$expression = $this->getIdentifier($expression);
|
||||
return $expression . ' IS NOT NULL';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns SQL that checks if an expression evaluates to a value between
|
||||
* two values.
|
||||
*
|
||||
* The parameter $expression is checked if it is between $value1 and $value2.
|
||||
*
|
||||
* Note: There is a slight difference in the way BETWEEN works on some databases.
|
||||
* http://www.w3schools.com/sql/sql_between.asp. If you want complete database
|
||||
* independence you should avoid using between().
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $q = new Doctrine_Query();
|
||||
* $q->select('u.*')
|
||||
* ->from('User u')
|
||||
* ->where($q->expr->between('id', 1, 5));
|
||||
* </code>
|
||||
*
|
||||
* @param string $expression the value to compare to
|
||||
* @param string $value1 the lower value to compare with
|
||||
* @param string $value2 the higher value to compare with
|
||||
* @return string logical expression
|
||||
*/
|
||||
public function getBetweenExpression($expression, $value1, $value2)
|
||||
{
|
||||
$expression = $this->getIdentifier($expression);
|
||||
$value1 = $this->getIdentifier($value1);
|
||||
$value2 = $this->getIdentifier($value2);
|
||||
return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
*/
|
||||
public function getGuidExpression()
|
||||
{
|
||||
throw new Doctrine_Expression_Exception('method not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* returns arcus cosine SQL string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAcosExpression($value)
|
||||
{
|
||||
return 'ACOS(' . $value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* sin
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function getSinExpression($value)
|
||||
{
|
||||
return 'SIN(' . $value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* pi
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getPiExpression()
|
||||
{
|
||||
return 'PI()';
|
||||
}
|
||||
|
||||
/**
|
||||
* cos
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
* @author Jonathan H. Wage
|
||||
*/
|
||||
public function getCosExpression($value)
|
||||
{
|
||||
return 'COS(' . $value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* build a pattern matching string
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
||||
* @param string $field optional field name that is being matched against
|
||||
* (might be required when emulating ILIKE)
|
||||
*
|
||||
* @return string SQL pattern
|
||||
*/
|
||||
public function getMatchPatternExpression($pattern, $operator = null, $field = null)
|
||||
{
|
||||
throw new Doctrine_Expression_Exception("Method not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
abstract public function getNativeDeclaration($field);
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
*/
|
||||
abstract public function getPortableDeclaration(array $field);
|
||||
|
||||
/**
|
||||
* Whether the platform prefers sequences for ID generation.
|
||||
* Subclasses should override this method to return TRUE if they prefer sequences.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function prefersSequences()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the platform prefers identity columns (eg. autoincrement) for ID generation.
|
||||
* Subclasses should override this method to return TRUE if they prefer identity columns.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function prefersIdentityColumns()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a LIMIT/OFFSET clause to the query.
|
||||
* This default implementation writes the syntax "LIMIT x OFFSET y" to the
|
||||
* query which is supported by MySql, PostgreSql and Sqlite.
|
||||
* Any database platforms that do not support this syntax should override
|
||||
* this implementation and provide their own.
|
||||
*
|
||||
* @param string $query The SQL string to write to / append to.
|
||||
* @param mixed $limit
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function writeLimitClause($query, $limit = false, $offset = false)
|
||||
{
|
||||
$limit = (int) $limit;
|
||||
$offset = (int) $offset;
|
||||
|
||||
if ($limit && $offset) {
|
||||
$query .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} elseif ($limit && ! $offset) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
} elseif ( ! $limit && $offset) {
|
||||
$query .= ' LIMIT 999999999999 OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates DBMS specific LIMIT/OFFSET SQL for the subqueries that are used in the
|
||||
* context of the limit-subquery construction.
|
||||
* This default implementation uses the normal LIMIT/OFFSET creation of the
|
||||
* platform as provided by {@see modifyLimitQuery()}. This means LIMIT/OFFSET
|
||||
* in subqueries don't get any special treatment. Most of the time this is not
|
||||
* sufficient (eg. MySql does not allow LIMIT in subqueries) and the concrete
|
||||
* platforms should provide their own implementation.
|
||||
*
|
||||
* @param string $query The SQL string to write to / append to.
|
||||
* @return string
|
||||
*/
|
||||
public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass, $query,
|
||||
$limit = false, $offset = false)
|
||||
{
|
||||
return $this->modifyLimitQuery($query, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $name
|
||||
* @return unknown
|
||||
* @todo Remove. Move properties to DatabasePlatform.
|
||||
*/
|
||||
public function getProperty($name)
|
||||
{
|
||||
if ( ! isset($this->_properties[$name])) {
|
||||
throw Doctrine_Connection_Exception::unknownProperty($name);
|
||||
}
|
||||
return $this->_properties[$name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
271
lib/Doctrine/DatabasePlatform/FirebirdPlatform.php
Normal file
271
lib/Doctrine/DatabasePlatform/FirebirdPlatform.php
Normal file
|
@ -0,0 +1,271 @@
|
|||
<?php
|
||||
|
||||
#namespace Doctrine::DBAL::Platforms;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_DatabasePlatform_FirebirdPlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->_supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'current_id' => true,
|
||||
'limit_queries' => 'emulated',
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => false,
|
||||
'pattern_escaping' => true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an driver-specific LIMIT clause to the query
|
||||
*
|
||||
* @param string $query query to modify
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @return string modified query
|
||||
* @override
|
||||
*/
|
||||
public function writeLimitClause($query, $limit, $offset)
|
||||
{
|
||||
if ( ! $offset) {
|
||||
$offset = 0;
|
||||
}
|
||||
if ($limit > 0) {
|
||||
$query = preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i',
|
||||
"SELECT FIRST $limit SKIP $offset", $query);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* return string for internal table used when calling only a function
|
||||
*
|
||||
* @return string for internal table used when calling only a function
|
||||
*/
|
||||
public function getFunctionTableExpression()
|
||||
{
|
||||
return ' FROM RDB$DATABASE';
|
||||
}
|
||||
|
||||
/**
|
||||
* build string to define escape pattern string
|
||||
*
|
||||
* @return string define escape pattern
|
||||
* @override
|
||||
*/
|
||||
public function getPatternEscapeStringExpression()
|
||||
{
|
||||
return " ESCAPE '". $this->_properties['escape_pattern'] ."'";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'varchar':
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'char':
|
||||
case 'text':
|
||||
case 'gzip':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : 16777215; // TODO: $this->conn->options['default_text_field_length'];
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')';
|
||||
case 'clob':
|
||||
return 'BLOB SUB_TYPE 1';
|
||||
case 'blob':
|
||||
return 'BLOB SUB_TYPE 0';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'SMALLINT';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'TIMESTAMP';
|
||||
case 'float':
|
||||
return 'DOUBLE PRECISION';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration($field)
|
||||
{
|
||||
$length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null;
|
||||
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
$dbType = strtolower($field['type']);
|
||||
$field['field_sub_type'] = !empty($field['field_sub_type'])
|
||||
? strtolower($field['field_sub_type']) : null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'smallint':
|
||||
case 'integer':
|
||||
case 'int64':
|
||||
//these may be 'numeric' or 'decimal'
|
||||
if (isset($field['field_sub_type'])) {
|
||||
$field['type'] = $field['field_sub_type'];
|
||||
return $this->getPortableDeclaration($field);
|
||||
}
|
||||
case 'bigint':
|
||||
case 'quad':
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'varchar':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'cstring':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'double precision':
|
||||
case 'd_float':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
break;
|
||||
case 'blob':
|
||||
$type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'CHARACTER SET ' . $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'COLLATE ' . $collation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
98
lib/Doctrine/DatabasePlatform/InformixPlatform.php
Normal file
98
lib/Doctrine/DatabasePlatform/InformixPlatform.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
#namespace Doctrine::DBAL::Platforms;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_DatabasePlatform_InformixPlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 new Doctrine_DataDict_Exception('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 new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
302
lib/Doctrine/DatabasePlatform/MsSqlPlatform.php
Normal file
302
lib/Doctrine/DatabasePlatform/MsSqlPlatform.php
Normal file
|
@ -0,0 +1,302 @@
|
|||
<?php
|
||||
|
||||
class Doctrine_DatabasePlatform_MsSqlPlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// initialize all driver options
|
||||
$this->_supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => 'emulated',
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => 'emulated',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, $offset)
|
||||
{
|
||||
if ($limit > 0) {
|
||||
$count = intval($limit);
|
||||
|
||||
$offset = intval($offset);
|
||||
if ($offset < 0) {
|
||||
throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time:
|
||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
||||
* - CURRENT_DATE (date, DATE type)
|
||||
* - CURRENT_TIME (time, TIME type)
|
||||
*
|
||||
* @return string to call a variable with the current timestamp
|
||||
* @override
|
||||
*/
|
||||
public function getNowExpression($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'time':
|
||||
case 'date':
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'GETDATE()';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* @return string to call a function to get a substring
|
||||
* @override
|
||||
*/
|
||||
public function getSubstringExpression($value, $position, $length = null)
|
||||
{
|
||||
if ( ! is_null($length)) {
|
||||
return 'SUBSTRING(' . $value . ', ' . $position . ', ' . $length . ')';
|
||||
}
|
||||
return 'SUBSTRING(' . $value . ', ' . $position . ', LEN(' . $value . ') - ' . $position . ' + 1)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string to concatenate two or more string parameters
|
||||
*
|
||||
* @param string $arg1
|
||||
* @param string $arg2
|
||||
* @param string $values...
|
||||
* @return string to concatenate two strings
|
||||
* @override
|
||||
*/
|
||||
public function getConcatExpression()
|
||||
{
|
||||
$args = func_get_args();
|
||||
return '(' . implode(' + ', $args) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
* @override
|
||||
*/
|
||||
public function getGuidExpression()
|
||||
{
|
||||
return 'NEWID()';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'text':
|
||||
case 'char':
|
||||
case 'varchar':
|
||||
case 'string':
|
||||
case 'gzip':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : false;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->options['default_text_field_length'].')')
|
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 8000) {
|
||||
return 'VARCHAR('.$length.')';
|
||||
}
|
||||
}
|
||||
return 'TEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 8000) {
|
||||
return "VARBINARY($length)";
|
||||
}
|
||||
}
|
||||
return 'IMAGE';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'BIT';
|
||||
case 'date':
|
||||
return 'CHAR(' . strlen('YYYY-MM-DD') . ')';
|
||||
case 'time':
|
||||
return 'CHAR(' . strlen('HH:MM:SS') . ')';
|
||||
case 'timestamp':
|
||||
return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')';
|
||||
case 'float':
|
||||
return 'FLOAT';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a MDB2 datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration($field)
|
||||
{
|
||||
$db_type = preg_replace('/[\d\(\)]/','', strtolower($field['type']) );
|
||||
$length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null;
|
||||
|
||||
$type = array();
|
||||
// todo: unsigned handling seems to be missing
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name']))
|
||||
$field['name'] = '';
|
||||
|
||||
switch ($db_type) {
|
||||
case 'bit':
|
||||
$type[0] = 'boolean';
|
||||
break;
|
||||
case 'tinyint':
|
||||
case 'smallint':
|
||||
case 'int':
|
||||
$type[0] = 'integer';
|
||||
if ($length == 1) {
|
||||
$type[] = 'boolean';
|
||||
}
|
||||
break;
|
||||
case 'datetime':
|
||||
$type[0] = 'timestamp';
|
||||
break;
|
||||
case 'float':
|
||||
case 'real':
|
||||
case 'numeric':
|
||||
$type[0] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'money':
|
||||
$type[0] = 'decimal';
|
||||
break;
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'ntext':
|
||||
case 'nvarchar':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'nchar':
|
||||
$type[0] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^[is|has]/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($db_type, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'image':
|
||||
case 'varbinary':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$db_type);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
560
lib/Doctrine/DatabasePlatform/MySqlPlatform.php
Normal file
560
lib/Doctrine/DatabasePlatform/MySqlPlatform.php
Normal file
|
@ -0,0 +1,560 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* The MySqlPlatform provides the behavior, features and SQL dialect of the
|
||||
* MySQL database platform.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
/**
|
||||
* MySql reserved words.
|
||||
*
|
||||
* @var array
|
||||
* @todo Needed? What about lazy initialization?
|
||||
*/
|
||||
protected static $_reservedKeywords = array(
|
||||
'ADD', 'ALL', 'ALTER',
|
||||
'ANALYZE', 'AND', 'AS',
|
||||
'ASC', 'ASENSITIVE', 'BEFORE',
|
||||
'BETWEEN', 'BIGINT', 'BINARY',
|
||||
'BLOB', 'BOTH', 'BY',
|
||||
'CALL', 'CASCADE', 'CASE',
|
||||
'CHANGE', 'CHAR', 'CHARACTER',
|
||||
'CHECK', 'COLLATE', 'COLUMN',
|
||||
'CONDITION', 'CONNECTION', 'CONSTRAINT',
|
||||
'CONTINUE', 'CONVERT', 'CREATE',
|
||||
'CROSS', 'CURRENT_DATE', 'CURRENT_TIME',
|
||||
'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR',
|
||||
'DATABASE', 'DATABASES', 'DAY_HOUR',
|
||||
'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND',
|
||||
'DEC', 'DECIMAL', 'DECLARE',
|
||||
'DEFAULT', 'DELAYED', 'DELETE',
|
||||
'DESC', 'DESCRIBE', 'DETERMINISTIC',
|
||||
'DISTINCT', 'DISTINCTROW', 'DIV',
|
||||
'DOUBLE', 'DROP', 'DUAL',
|
||||
'EACH', 'ELSE', 'ELSEIF',
|
||||
'ENCLOSED', 'ESCAPED', 'EXISTS',
|
||||
'EXIT', 'EXPLAIN', 'FALSE',
|
||||
'FETCH', 'FLOAT', 'FLOAT4',
|
||||
'FLOAT8', 'FOR', 'FORCE',
|
||||
'FOREIGN', 'FROM', 'FULLTEXT',
|
||||
'GRANT', 'GROUP', 'HAVING',
|
||||
'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE',
|
||||
'HOUR_SECOND', 'IF', 'IGNORE',
|
||||
'IN', 'INDEX', 'INFILE',
|
||||
'INNER', 'INOUT', 'INSENSITIVE',
|
||||
'INSERT', 'INT', 'INT1',
|
||||
'INT2', 'INT3', 'INT4',
|
||||
'INT8', 'INTEGER', 'INTERVAL',
|
||||
'INTO', 'IS', 'ITERATE',
|
||||
'JOIN', 'KEY', 'KEYS',
|
||||
'KILL', 'LEADING', 'LEAVE',
|
||||
'LEFT', 'LIKE', 'LIMIT',
|
||||
'LINES', 'LOAD', 'LOCALTIME',
|
||||
'LOCALTIMESTAMP', 'LOCK', 'LONG',
|
||||
'LONGBLOB', 'LONGTEXT', 'LOOP',
|
||||
'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB',
|
||||
'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT',
|
||||
'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD',
|
||||
'MODIFIES', 'NATURAL', 'NOT',
|
||||
'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC',
|
||||
'ON', 'OPTIMIZE', 'OPTION',
|
||||
'OPTIONALLY', 'OR', 'ORDER',
|
||||
'OUT', 'OUTER', 'OUTFILE',
|
||||
'PRECISION', 'PRIMARY', 'PROCEDURE',
|
||||
'PURGE', 'RAID0', 'READ',
|
||||
'READS', 'REAL', 'REFERENCES',
|
||||
'REGEXP', 'RELEASE', 'RENAME',
|
||||
'REPEAT', 'REPLACE', 'REQUIRE',
|
||||
'RESTRICT', 'RETURN', 'REVOKE',
|
||||
'RIGHT', 'RLIKE', 'SCHEMA',
|
||||
'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT',
|
||||
'SENSITIVE', 'SEPARATOR', 'SET',
|
||||
'SHOW', 'SMALLINT', 'SONAME',
|
||||
'SPATIAL', 'SPECIFIC', 'SQL',
|
||||
'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING',
|
||||
'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT',
|
||||
'SSL', 'STARTING', 'STRAIGHT_JOIN',
|
||||
'TABLE', 'TERMINATED', 'THEN',
|
||||
'TINYBLOB', 'TINYINT', 'TINYTEXT',
|
||||
'TO', 'TRAILING', 'TRIGGER',
|
||||
'TRUE', 'UNDO', 'UNION',
|
||||
'UNIQUE', 'UNLOCK', 'UNSIGNED',
|
||||
'UPDATE', 'USAGE', 'USE',
|
||||
'USING', 'UTC_DATE', 'UTC_TIME',
|
||||
'UTC_TIMESTAMP', 'VALUES', 'VARBINARY',
|
||||
'VARCHAR', 'VARCHARACTER', 'VARYING',
|
||||
'WHEN', 'WHERE', 'WHILE',
|
||||
'WITH', 'WRITE', 'X509',
|
||||
'XOR', 'YEAR_MONTH', 'ZEROFILL'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new MySqlPlatform.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->_supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => false,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => true,
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => 'emulated',
|
||||
'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;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the regular expression operator
|
||||
*
|
||||
* @return string
|
||||
* @override
|
||||
*/
|
||||
public function getRegexpExpression()
|
||||
{
|
||||
return 'RLIKE';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return string to generate float between 0 and 1
|
||||
*/
|
||||
public function getRandomExpression()
|
||||
{
|
||||
return 'RAND()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a pattern matching string.
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental.
|
||||
*
|
||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
||||
* @param string $field optional field name that is being matched against
|
||||
* (might be required when emulating ILIKE)
|
||||
*
|
||||
* @return string SQL pattern
|
||||
* @override
|
||||
*/
|
||||
public function getMatchPatternExpression($pattern, $operator = null, $field = null)
|
||||
{
|
||||
$match = '';
|
||||
if ( ! is_null($operator)) {
|
||||
$field = is_null($field) ? '' : $field.' ';
|
||||
$operator = strtoupper($operator);
|
||||
switch ($operator) {
|
||||
// case insensitive
|
||||
case 'ILIKE':
|
||||
$match = $field.'LIKE ';
|
||||
break;
|
||||
// case sensitive
|
||||
case 'LIKE':
|
||||
$match = $field.'LIKE BINARY ';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Expression_Mysql_Exception('not a supported operator type:'. $operator);
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
foreach ($pattern as $key => $value) {
|
||||
if ($key % 2) {
|
||||
$match .= $value;
|
||||
} else {
|
||||
$match .= $this->conn->escapePattern($this->conn->escape($value));
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
$match.= $this->patternEscapeString();
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
* @override
|
||||
*/
|
||||
public function getGuidExpression()
|
||||
{
|
||||
return 'UUID()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a series of strings concatinated
|
||||
*
|
||||
* concat() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain an expression or an array with expressions.
|
||||
*
|
||||
* @param string|array(string) strings that will be concatinated.
|
||||
* @override
|
||||
*/
|
||||
public function getConcatExpression()
|
||||
{
|
||||
$args = func_get_args();
|
||||
return 'CONCAT(' . join(', ', (array) $args) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
|
||||
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':
|
||||
case 'gzip':
|
||||
if ( ! isset($field['length'])) {
|
||||
if (array_key_exists('default', $field)) {
|
||||
$field['length'] = $this->conn->varchar_max_length;
|
||||
} else {
|
||||
$field['length'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$length = ($field['length'] <= $this->conn->varchar_max_length) ? $field['length'] : false;
|
||||
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
|
||||
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYTEXT';
|
||||
} elseif ($length <= 65532) {
|
||||
return 'TEXT';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMTEXT';
|
||||
}
|
||||
}
|
||||
return 'LONGTEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYBLOB';
|
||||
} elseif ($length <= 65532) {
|
||||
return 'BLOB';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMBLOB';
|
||||
}
|
||||
}
|
||||
return 'LONGBLOB';
|
||||
case 'enum':
|
||||
if ($this->conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) {
|
||||
$values = array();
|
||||
foreach ($field['values'] as $value) {
|
||||
$values[] = $this->conn->quote($value, 'varchar');
|
||||
}
|
||||
return 'ENUM('.implode(', ', $values).')';
|
||||
}
|
||||
// fall back to integer
|
||||
case 'integer':
|
||||
case 'int':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 1) {
|
||||
return 'TINYINT';
|
||||
} elseif ($length == 2) {
|
||||
return 'SMALLINT';
|
||||
} elseif ($length == 3) {
|
||||
return 'MEDIUMINT';
|
||||
} elseif ($length == 4) {
|
||||
return 'INT';
|
||||
} elseif ($length > 4) {
|
||||
return 'BIGINT';
|
||||
}
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'TINYINT(1)';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'DATETIME';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'DOUBLE';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
$dbType = strtolower($field['type']);
|
||||
$dbType = strtok($dbType, '(), ');
|
||||
if ($dbType == 'national') {
|
||||
$dbType = strtok('(), ');
|
||||
}
|
||||
if (isset($field['length'])) {
|
||||
$length = $field['length'];
|
||||
$decimal = '';
|
||||
} else {
|
||||
$length = strtok('(), ');
|
||||
$decimal = strtok('(), ');
|
||||
}
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
$values = null;
|
||||
|
||||
switch ($dbType) {
|
||||
case 'tinyint':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 1;
|
||||
break;
|
||||
case 'smallint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 2;
|
||||
break;
|
||||
case 'mediumint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 3;
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 8;
|
||||
break;
|
||||
case 'tinytext':
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
$fixed = false;
|
||||
case 'string':
|
||||
case 'char':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
if ($decimal == 'binary') {
|
||||
$type[] = 'blob';
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
$type[] = 'enum';
|
||||
preg_match_all('/\'((?:\'\'|[^\'])*)\'/', $field['type'], $matches);
|
||||
$length = 0;
|
||||
$fixed = false;
|
||||
if (is_array($matches)) {
|
||||
foreach ($matches[1] as &$value) {
|
||||
$value = str_replace('\'\'', '\'', $value);
|
||||
$length = max($length, strlen($value));
|
||||
}
|
||||
if ($length == '1' && count($matches[1]) == 2) {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} else {
|
||||
$values = $matches[1];
|
||||
}
|
||||
}
|
||||
$type[] = 'integer';
|
||||
break;
|
||||
case 'set':
|
||||
$fixed = false;
|
||||
$type[] = 'text';
|
||||
$type[] = 'integer';
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
break;
|
||||
case 'unknown':
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
|
||||
}
|
||||
|
||||
$length = ((int) $length == 0) ? null : (int) $length;
|
||||
|
||||
if ($values === null) {
|
||||
return array('type' => $type, 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed);
|
||||
} else {
|
||||
return array('type' => $type, 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed, 'values' => $values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'CHARACTER SET ' . $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'COLLATE ' . $collation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the platform prefers identity columns for ID generation.
|
||||
* MySql prefers "autoincrement" identity columns since sequences can only
|
||||
* be emulated with a table.
|
||||
*
|
||||
* @return boolean
|
||||
* @override
|
||||
*/
|
||||
public function prefersIdentityColumns()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
325
lib/Doctrine/DatabasePlatform/OraclePlatform.php
Normal file
325
lib/Doctrine/DatabasePlatform/OraclePlatform.php
Normal file
|
@ -0,0 +1,325 @@
|
|||
<?php
|
||||
|
||||
class Doctrine_DatabasePlatform_OraclePlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->_supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => true,
|
||||
'affected_rows' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => false, // implementation is broken
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an driver-specific LIMIT clause to the query
|
||||
*
|
||||
* @param string $query query to modify
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @return string the modified query
|
||||
* @override
|
||||
*/
|
||||
public function writeLimitClause($query, $limit = false, $offset = false)
|
||||
{
|
||||
return $this->_createLimitSubquery($query, $limit, $offset);
|
||||
}
|
||||
|
||||
private function _createLimitSubquery($query, $limit, $offset, $column = null)
|
||||
{
|
||||
$limit = (int) $limit;
|
||||
$offset = (int) $offset;
|
||||
if (preg_match('/^\s*SELECT/i', $query)) {
|
||||
if ( ! preg_match('/\sFROM\s/i', $query)) {
|
||||
$query .= " FROM dual";
|
||||
}
|
||||
if ($limit > 0) {
|
||||
$max = $offset + $limit;
|
||||
$column = $column === null ? '*' : $column;
|
||||
if ($offset > 0) {
|
||||
$min = $offset + 1;
|
||||
$query = 'SELECT b.'.$column.' FROM ('.
|
||||
'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
|
||||
. $query . ') a '.
|
||||
') b '.
|
||||
'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;
|
||||
} else {
|
||||
$query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL for Oracle that can be used in the subquery for the limit-subquery
|
||||
* algorithm.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass,
|
||||
$query, $limit = false, $offset = false)
|
||||
{
|
||||
// NOTE: no composite key support
|
||||
$columnNames = $rootClass->getIdentifierColumnNames();
|
||||
if (count($columnNames) > 1) {
|
||||
throw new Doctrine_Connection_Exception("Composite keys in LIMIT queries are "
|
||||
. "currently not supported.");
|
||||
}
|
||||
$column = $columnNames[0];
|
||||
|
||||
return $this->_createLimitSubquery($query, $limit, $offset, $column);
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* @param string $value an sql string literal or column name/alias
|
||||
* @param integer $position where to start the substring portion
|
||||
* @param integer $length the substring portion length
|
||||
* @return string SQL substring function with given parameters
|
||||
* @override
|
||||
*/
|
||||
public function getSubstringExpression($value, $position, $length = null)
|
||||
{
|
||||
if ($length !== null)
|
||||
return "SUBSTR($value, $position, $length)";
|
||||
|
||||
return "SUBSTR($value, $position)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time:
|
||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
||||
* - CURRENT_DATE (date, DATE type)
|
||||
* - CURRENT_TIME (time, TIME type)
|
||||
*
|
||||
* @return string to call a variable with the current timestamp
|
||||
* @override
|
||||
*/
|
||||
public function getNowExpression($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* random
|
||||
*
|
||||
* @return string an oracle SQL string that generates a float between 0 and 1
|
||||
* @override
|
||||
*/
|
||||
public function getRandomExpression()
|
||||
{
|
||||
return 'dbms_random.value';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
* @override
|
||||
*/
|
||||
public function getGuidExpression()
|
||||
{
|
||||
return 'SYS_GUID()';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'gzip':
|
||||
case 'char':
|
||||
case 'varchar':
|
||||
$length = !empty($field['length'])
|
||||
? $field['length'] : 16777215; // TODO: $this->conn->options['default_text_field_length'];
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')';
|
||||
case 'clob':
|
||||
return 'CLOB';
|
||||
case 'blob':
|
||||
return 'BLOB';
|
||||
case 'integer':
|
||||
case 'enum':
|
||||
case 'int':
|
||||
if ( ! empty($field['length'])) {
|
||||
return 'NUMBER('.$field['length'].')';
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'NUMBER(1)';
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'timestamp':
|
||||
return 'DATE';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'NUMBER';
|
||||
case 'decimal':
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'NUMBER(*,'.$scale.')';
|
||||
default:
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to a doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @throws Doctrine_DataDict_Oracle_Exception
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
if ( ! isset($field['data_type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Native oracle definition must have a data_type key specified');
|
||||
}
|
||||
|
||||
$dbType = strtolower($field['data_type']);
|
||||
$type = array();
|
||||
$length = $unsigned = $fixed = null;
|
||||
if ( ! empty($field['data_length'])) {
|
||||
$length = $field['data_length'];
|
||||
}
|
||||
|
||||
if ( ! isset($field['column_name'])) {
|
||||
$field['column_name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'integer':
|
||||
case 'pls_integer':
|
||||
case 'binary_integer':
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'varchar':
|
||||
case 'varchar2':
|
||||
case 'nvarchar2':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
case 'nchar':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'number':
|
||||
if ( ! empty($field['data_scale'])) {
|
||||
$type[] = 'decimal';
|
||||
} else {
|
||||
$type[] = 'integer';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['column_name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'long':
|
||||
$type[] = 'string';
|
||||
case 'clob':
|
||||
case 'nclob':
|
||||
$type[] = 'clob';
|
||||
break;
|
||||
case 'blob':
|
||||
case 'raw':
|
||||
case 'long raw':
|
||||
case 'bfile':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'rowid':
|
||||
case 'urowid':
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
515
lib/Doctrine/DatabasePlatform/PostgreSqlPlatform.php
Normal file
515
lib/Doctrine/DatabasePlatform/PostgreSqlPlatform.php
Normal file
|
@ -0,0 +1,515 @@
|
|||
<?php
|
||||
|
||||
|
||||
class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
/**
|
||||
* The reserved keywords by pgsql. Ordered alphabetically.
|
||||
*
|
||||
* @param array
|
||||
* @todo Nedded? What about lazy initialization?
|
||||
*/
|
||||
protected static $_reservedKeywords = array(
|
||||
'abort', 'absolute', 'access', 'action', 'add', 'after', 'aggregate',
|
||||
'all', 'alter', 'analyse', 'analyze', 'and', 'any', 'as', 'asc',
|
||||
'assertion', 'assignment', 'at', 'authorization', 'backward', 'before',
|
||||
'begin', 'between', 'bigint', 'binary', 'bit', 'boolean', 'both',
|
||||
'by', 'cache', 'called', 'cascade', 'case', 'cast', 'chain', 'char',
|
||||
'character', 'characteristics', 'check', 'checkpoint', 'class',
|
||||
'close', 'cluster', 'coalesce', 'collate', 'column', 'comment',
|
||||
'commit', 'committed', 'constraint', 'constraints', 'conversion',
|
||||
'convert', 'copy', 'create', 'createdb', 'createuser', 'cross',
|
||||
'current_date', 'current_time', 'current_timestamp', 'current_user',
|
||||
'cursor', 'cycle', 'database', 'day', 'deallocate', 'dec', 'decimal',
|
||||
'declare', 'default', 'deferrable', 'deferred', 'definer', 'delete',
|
||||
'delimiter', 'delimiters', 'desc', 'distinct', 'do', 'domain', 'double',
|
||||
'drop', 'each', 'else', 'encoding', 'encrypted', 'end', 'escape',
|
||||
'except', 'exclusive', 'execute', 'exists', 'explain', 'external',
|
||||
'extract', 'false', 'fetch', 'float', 'for', 'force', 'foreign',
|
||||
'forward', 'freeze', 'from', 'full', 'function', 'get', 'global',
|
||||
'grant', 'group', 'handler', 'having', 'hour', 'ilike', 'immediate',
|
||||
'immutable', 'implicit', 'in', 'increment', 'index', 'inherits',
|
||||
'initially', 'inner', 'inout', 'input', 'insensitive', 'insert',
|
||||
'instead', 'int', 'integer', 'intersect', 'interval', 'into', 'invoker',
|
||||
'is', 'isnull', 'isolation', 'join', 'key', 'lancompiler', 'language',
|
||||
'leading', 'left', 'level', 'like', 'limit', 'listen', 'load', 'local',
|
||||
'localtime', 'localtimestamp', 'location', 'lock', 'match', 'maxvalue',
|
||||
'minute', 'minvalue', 'mode', 'month', 'move', 'names', 'national',
|
||||
'natural', 'nchar', 'new', 'next', 'no', 'nocreatedb', 'nocreateuser',
|
||||
'none', 'not', 'nothing', 'notify', 'notnull', 'null', 'nullif',
|
||||
'numeric', 'of', 'off', 'offset', 'oids', 'old', 'on', 'only', 'operator',
|
||||
'option', 'or', 'order', 'out', 'outer', 'overlaps', 'overlay',
|
||||
'owner', 'partial', 'password', 'path', 'pendant', 'placing', 'position',
|
||||
'precision', 'prepare', 'primary', 'prior', 'privileges', 'procedural',
|
||||
'procedure', 'read', 'real', 'recheck', 'references', 'reindex',
|
||||
'relative', 'rename', 'replace', 'reset', 'restrict', 'returns',
|
||||
'revoke', 'right', 'rollback', 'row', 'rule', 'schema', 'scroll',
|
||||
'second', 'security', 'select', 'sequence', 'serializable', 'session',
|
||||
'session_user', 'set', 'setof', 'share', 'show', 'similar', 'simple',
|
||||
'smallint', 'some', 'stable', 'start', 'statement', 'statistics',
|
||||
'stdin', 'stdout', 'storage', 'strict', 'substring', 'sysid', 'table',
|
||||
'temp', 'template', 'temporary', 'then', 'time', 'timestamp', 'to',
|
||||
'toast', 'trailing', 'transaction', 'treat', 'trigger', 'trim', 'true',
|
||||
'truncate', 'trusted', 'type', 'unencrypted', 'union', 'unique',
|
||||
'unknown', 'unlisten', 'until', 'update', 'usage', 'user', 'using',
|
||||
'vacuum', 'valid', 'validator', 'values', 'varchar', 'varying',
|
||||
'verbose', 'version', 'view', 'volatile', 'when', 'where', 'with',
|
||||
'without', 'work', 'write', 'year','zone');
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new PostgreSqlPlatform.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->_supported = array(
|
||||
'sequences' => true,
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => true,
|
||||
'current_id' => true,
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => 'emulated',
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => 'emulated',
|
||||
'primary_key' => true,
|
||||
'result_introspection' => true,
|
||||
'prepared_statements' => true,
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => true,
|
||||
);
|
||||
|
||||
$this->_properties['string_quoting'] = array('start' => "'",
|
||||
'end' => "'",
|
||||
'escape' => "'",
|
||||
'escape_pattern' => '\\');
|
||||
$this->_properties['identifier_quoting'] = array('start' => '"',
|
||||
'end' => '"',
|
||||
'escape' => '"');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'char':
|
||||
case 'string':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'varchar':
|
||||
case 'gzip':
|
||||
// TODO: what is the maximum VARCHAR length in pgsql ?
|
||||
$length = (isset($field['length']) && $field['length'] && $field['length'] < 10000) ? $field['length'] : null;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR('.$this->conn->options['default_text_field_length'].')')
|
||||
: ($length ? 'VARCHAR(' .$length . ')' : 'TEXT');
|
||||
|
||||
case 'clob':
|
||||
return 'TEXT';
|
||||
case 'blob':
|
||||
return 'BYTEA';
|
||||
case 'enum':
|
||||
case 'integer':
|
||||
case 'int':
|
||||
if ( ! empty($field['autoincrement'])) {
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length > 4) {
|
||||
return 'BIGSERIAL';
|
||||
}
|
||||
}
|
||||
return 'SERIAL';
|
||||
}
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 2) {
|
||||
return 'SMALLINT';
|
||||
} elseif ($length == 3 || $length == 4) {
|
||||
return 'INT';
|
||||
} elseif ($length > 4) {
|
||||
return 'BIGINT';
|
||||
}
|
||||
}
|
||||
return 'INT';
|
||||
case 'boolean':
|
||||
return 'BOOLEAN';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME without time zone';
|
||||
case 'timestamp':
|
||||
return 'TIMESTAMP without time zone';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'FLOAT';
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'NUMERIC('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
|
||||
$length = (isset($field['length'])) ? $field['length'] : null;
|
||||
if ($length == '-1' && isset($field['atttypmod'])) {
|
||||
$length = $field['atttypmod'] - 4;
|
||||
}
|
||||
if ((int)$length <= 0) {
|
||||
$length = null;
|
||||
}
|
||||
$type = array();
|
||||
$unsigned = $fixed = null;
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
$dbType = strtolower($field['type']);
|
||||
|
||||
switch ($dbType) {
|
||||
case 'smallint':
|
||||
case 'int2':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 2;
|
||||
if ($length == '2') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
case 'int4':
|
||||
case 'integer':
|
||||
case 'serial':
|
||||
case 'serial4':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'int8':
|
||||
case 'bigserial':
|
||||
case 'serial8':
|
||||
$type[] = 'integer';
|
||||
$unsigned = false;
|
||||
$length = 8;
|
||||
break;
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
$type[] = 'boolean';
|
||||
$length = 1;
|
||||
break;
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'interval':
|
||||
case '_varchar':
|
||||
$fixed = false;
|
||||
case 'unknown':
|
||||
case 'char':
|
||||
case 'bpchar':
|
||||
$type[] = 'string';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
case 'timestamptz':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'float4':
|
||||
case 'float8':
|
||||
case 'double':
|
||||
case 'double precision':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'money':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
case 'bytea':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'oid':
|
||||
$type[] = 'blob';
|
||||
$type[] = 'clob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the md5 sum of a field.
|
||||
*
|
||||
* Note: Not SQL92, but common functionality
|
||||
*
|
||||
* md5() works with the default PostgreSQL 8 versions.
|
||||
*
|
||||
* If you are using PostgreSQL 7.x or older you need
|
||||
* to make sure that the digest procedure is installed.
|
||||
* If you use RPMS (Redhat and Mandrake) install the postgresql-contrib
|
||||
* package. You must then install the procedure by running this shell command:
|
||||
* <code>
|
||||
* psql [dbname] < /usr/share/pgsql/contrib/pgcrypto.sql
|
||||
* </code>
|
||||
* You should make sure you run this as the postgres user.
|
||||
*
|
||||
* @return string
|
||||
* @override
|
||||
*/
|
||||
public function getMd5Expression($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
|
||||
if ($this->_version > 7) {
|
||||
return 'MD5(' . $column . ')';
|
||||
} else {
|
||||
return 'encode(digest(' . $column .', md5), hex)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns part of a string.
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* @param string $value the target $value the string or the string column.
|
||||
* @param int $from extract from this characeter.
|
||||
* @param int $len extract this amount of characters.
|
||||
* @return string sql that extracts part of a string.
|
||||
* @override
|
||||
*/
|
||||
public function getSubstringExpression($value, $from, $len = null)
|
||||
{
|
||||
$value = $this->getIdentifier($value);
|
||||
|
||||
if ($len === null) {
|
||||
$len = $this->getIdentifier($len);
|
||||
return 'SUBSTR(' . $value . ', ' . $from . ')';
|
||||
} else {
|
||||
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQLs AGE(<timestamp1> [, <timestamp2>]) function.
|
||||
*
|
||||
* @param string $timestamp1 timestamp to subtract from NOW()
|
||||
* @param string $timestamp2 optional; if given: subtract arguments
|
||||
* @return string
|
||||
*/
|
||||
public function getAgeExpression($timestamp1, $timestamp2 = null)
|
||||
{
|
||||
if ( $timestamp2 == null ) {
|
||||
return 'AGE(' . $timestamp1 . ')';
|
||||
}
|
||||
return 'AGE(' . $timestamp1 . ', ' . $timestamp2 . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQLs DATE_PART( <text>, <time> ) function.
|
||||
*
|
||||
* @param string $text what to extract
|
||||
* @param string $time timestamp or interval to extract from
|
||||
* @return string
|
||||
*/
|
||||
public function getDatePartExpression($text, $time)
|
||||
{
|
||||
return 'DATE_PART(' . $text . ', ' . $time . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQLs TO_CHAR( <time>, <text> ) function.
|
||||
*
|
||||
* @param string $time timestamp or interval
|
||||
* @param string $text how to the format the output
|
||||
* @return string
|
||||
*/
|
||||
public function getToCharExpression($time, $text)
|
||||
{
|
||||
return 'TO_CHAR(' . $time . ', ' . $text . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL string to return the current system date and time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNowExpression()
|
||||
{
|
||||
return 'LOCALTIMESTAMP(0)';
|
||||
}
|
||||
|
||||
/**
|
||||
* regexp
|
||||
*
|
||||
* @return string the regular expression operator
|
||||
* @override
|
||||
*/
|
||||
public function getRegexpExpression()
|
||||
{
|
||||
return 'SIMILAR TO';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return return string to generate float between 0 and 1
|
||||
* @access public
|
||||
* @override
|
||||
*/
|
||||
public function getRandomExpression()
|
||||
{
|
||||
return 'RANDOM()';
|
||||
}
|
||||
|
||||
/**
|
||||
* build a pattern matching string
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
||||
* @param string $field optional field name that is being matched against
|
||||
* (might be required when emulating ILIKE)
|
||||
*
|
||||
* @return string SQL pattern
|
||||
* @override
|
||||
*/
|
||||
public function getMatchPatternExpression($pattern, $operator = null, $field = null)
|
||||
{
|
||||
$match = '';
|
||||
if ( ! is_null($operator)) {
|
||||
$field = is_null($field) ? '' : $field.' ';
|
||||
$operator = strtoupper($operator);
|
||||
switch ($operator) {
|
||||
// case insensitive
|
||||
case 'ILIKE':
|
||||
$match = $field.'ILIKE ';
|
||||
break;
|
||||
// case sensitive
|
||||
case 'LIKE':
|
||||
$match = $field.'LIKE ';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Expression_Pgsql_Exception('not a supported operator type:'. $operator);
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
foreach ($pattern as $key => $value) {
|
||||
if ($key % 2) {
|
||||
$match.= $value;
|
||||
} else {
|
||||
$match.= $this->conn->escapePattern($this->conn->escape($value));
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
$match.= $this->patternEscapeString();
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses a literal boolean value and returns
|
||||
* proper sql equivalent
|
||||
*
|
||||
* @param string $value boolean value to be parsed
|
||||
* @return string parsed boolean value
|
||||
*/
|
||||
public function parseBoolean($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
385
lib/Doctrine/DatabasePlatform/SqlitePlatform.php
Normal file
385
lib/Doctrine/DatabasePlatform/SqlitePlatform.php
Normal file
|
@ -0,0 +1,385 @@
|
|||
<?php
|
||||
|
||||
#namespace Doctrine::DBAL::Platforms;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_DatabasePlatform_SqlitePlatform extends Doctrine_DatabasePlatform
|
||||
{
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->_supported = array(
|
||||
'sequences' => 'emulated',
|
||||
'indexes' => true,
|
||||
'affected_rows' => true,
|
||||
'summary_functions' => true,
|
||||
'order_by_text' => true,
|
||||
'current_id' => 'emulated',
|
||||
'limit_queries' => true,
|
||||
'LOBs' => true,
|
||||
'replace' => true,
|
||||
'transactions' => true,
|
||||
'savepoints' => false,
|
||||
'sub_selects' => true,
|
||||
'auto_increment' => true,
|
||||
'primary_key' => true,
|
||||
'result_introspection' => false, // not implemented
|
||||
'prepared_statements' => 'emulated',
|
||||
'identifier_quoting' => true,
|
||||
'pattern_escaping' => false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the md5 sum of the data that SQLite's md5() function receives.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return string
|
||||
*/
|
||||
public static function md5Impl($data)
|
||||
{
|
||||
return md5($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modules of the data that SQLite's mod() function receives.
|
||||
*
|
||||
* @param integer $dividend
|
||||
* @param integer $divisor
|
||||
* @return string
|
||||
*/
|
||||
public static function modImpl($dividend, $divisor)
|
||||
{
|
||||
return $dividend % $divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* locate
|
||||
* returns the position of the first occurrence of substring $substr in string $str that
|
||||
* SQLite's locate() function receives
|
||||
*
|
||||
* @param string $substr literal string to find
|
||||
* @param string $str literal string
|
||||
* @return string
|
||||
*/
|
||||
public static function locateImpl($substr, $str)
|
||||
{
|
||||
return strpos($str, $substr);
|
||||
}
|
||||
public static function sha1Impl($str)
|
||||
{
|
||||
return sha1($str);
|
||||
}
|
||||
public static function ltrimImpl($str)
|
||||
{
|
||||
return ltrim($str);
|
||||
}
|
||||
public static function rtrimImpl($str)
|
||||
{
|
||||
return rtrim($str);
|
||||
}
|
||||
public static function trimImpl($str)
|
||||
{
|
||||
return trim($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the regular expression operator
|
||||
*
|
||||
* @return string
|
||||
* @override
|
||||
*/
|
||||
public function getRegexpExpression()
|
||||
{
|
||||
return 'RLIKE';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string to call a function to compute the
|
||||
* soundex encoding of a string
|
||||
*
|
||||
* The string "?000" is returned if the argument is NULL.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string SQL soundex function with given parameter
|
||||
*/
|
||||
public function getSoundexExpression($value)
|
||||
{
|
||||
return 'SOUNDEX(' . $value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time.
|
||||
*
|
||||
* @return string sqlite function as string
|
||||
* @override
|
||||
*/
|
||||
public function getNowExpression($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'time':
|
||||
return 'time(\'now\')';
|
||||
case 'date':
|
||||
return 'date(\'now\')';
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'datetime(\'now\')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return string to generate float between 0 and 1
|
||||
* @override
|
||||
*/
|
||||
public function getRandomExpression()
|
||||
{
|
||||
return '((RANDOM() + 2147483648) / 4294967296)';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* SQLite only supports the 2 parameter variant of this function
|
||||
*
|
||||
* @param string $value an sql string literal or column name/alias
|
||||
* @param integer $position where to start the substring portion
|
||||
* @param integer $length the substring portion length
|
||||
* @return string SQL substring function with given parameters
|
||||
* @override
|
||||
*/
|
||||
public function getSubstringExpression($value, $position, $length = null)
|
||||
{
|
||||
if ($length !== null) {
|
||||
return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')';
|
||||
}
|
||||
return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @author Lukas Smith (PEAR MDB2 library)
|
||||
* @return string DBMS specific SQL code portion that should be used to
|
||||
* declare the specified field.
|
||||
* @override
|
||||
*/
|
||||
public function getNativeDeclaration(array $field)
|
||||
{
|
||||
if ( ! isset($field['type'])) {
|
||||
throw new Doctrine_DataDict_Exception('Missing column type.');
|
||||
}
|
||||
switch ($field['type']) {
|
||||
case 'text':
|
||||
case 'object':
|
||||
case 'array':
|
||||
case 'string':
|
||||
case 'char':
|
||||
case 'gzip':
|
||||
case 'varchar':
|
||||
$length = (isset($field['length']) && $field['length']) ? $field['length'] : null;
|
||||
|
||||
$fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TEXTFLD_LENGTH).')')
|
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
|
||||
case 'clob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYTEXT';
|
||||
} elseif ($length <= 65535) {
|
||||
return 'TEXT';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMTEXT';
|
||||
}
|
||||
}
|
||||
return 'LONGTEXT';
|
||||
case 'blob':
|
||||
if ( ! empty($field['length'])) {
|
||||
$length = $field['length'];
|
||||
if ($length <= 255) {
|
||||
return 'TINYBLOB';
|
||||
} elseif ($length <= 65535) {
|
||||
return 'BLOB';
|
||||
} elseif ($length <= 16777215) {
|
||||
return 'MEDIUMBLOB';
|
||||
}
|
||||
}
|
||||
return 'LONGBLOB';
|
||||
case 'enum':
|
||||
case 'integer':
|
||||
case 'boolean':
|
||||
case 'int':
|
||||
return 'INTEGER';
|
||||
case 'date':
|
||||
return 'DATE';
|
||||
case 'time':
|
||||
return 'TIME';
|
||||
case 'timestamp':
|
||||
return 'DATETIME';
|
||||
case 'float':
|
||||
case 'double':
|
||||
return 'DOUBLE';//($this->conn->options['fixed_float'] ? '('.
|
||||
//($this->conn->options['fixed_float']+2).','.$this->conn->options['fixed_float'].')' : '');
|
||||
case 'decimal':
|
||||
$length = !empty($field['length']) ? $field['length'] : 18;
|
||||
$scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
|
||||
return 'DECIMAL('.$length.','.$scale.')';
|
||||
}
|
||||
throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a native array description of a field to Doctrine datatype and length
|
||||
*
|
||||
* @param array $field native field description
|
||||
* @return array containing the various possible types, length, sign, fixed
|
||||
* @override
|
||||
*/
|
||||
public function getPortableDeclaration(array $field)
|
||||
{
|
||||
$dbType = strtolower($field['type']);
|
||||
$length = (isset($field['length'])) ? $field['length'] : null;
|
||||
$unsigned = (isset($field['unsigned'])) ? $field['unsigned'] : null;
|
||||
$fixed = null;
|
||||
$type = array();
|
||||
|
||||
if ( ! isset($field['name'])) {
|
||||
$field['name'] = '';
|
||||
}
|
||||
|
||||
switch ($dbType) {
|
||||
case 'boolean':
|
||||
$type[] = 'boolean';
|
||||
break;
|
||||
case 'tinyint':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 1;
|
||||
break;
|
||||
case 'smallint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 2;
|
||||
break;
|
||||
case 'mediumint':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 3;
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
case 'serial':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 4;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'bigserial':
|
||||
$type[] = 'integer';
|
||||
$unsigned = preg_match('/ unsigned/i', $field['type']);
|
||||
$length = 8;
|
||||
break;
|
||||
case 'clob':
|
||||
case 'tinytext':
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
case 'varchar':
|
||||
case 'varchar2':
|
||||
$fixed = false;
|
||||
case 'char':
|
||||
$type[] = 'text';
|
||||
if ($length == '1') {
|
||||
$type[] = 'boolean';
|
||||
if (preg_match('/^(is|has)/', $field['name'])) {
|
||||
$type = array_reverse($type);
|
||||
}
|
||||
} elseif (strstr($dbType, 'text')) {
|
||||
$type[] = 'clob';
|
||||
}
|
||||
if ($fixed !== false) {
|
||||
$fixed = true;
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$type[] = 'timestamp';
|
||||
$length = null;
|
||||
break;
|
||||
case 'time':
|
||||
$type[] = 'time';
|
||||
$length = null;
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'real':
|
||||
$type[] = 'float';
|
||||
$length = null;
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'numeric':
|
||||
$type[] = 'decimal';
|
||||
$length = null;
|
||||
break;
|
||||
case 'tinyblob':
|
||||
case 'mediumblob':
|
||||
case 'longblob':
|
||||
case 'blob':
|
||||
$type[] = 'blob';
|
||||
$length = null;
|
||||
break;
|
||||
case 'year':
|
||||
$type[] = 'integer';
|
||||
$type[] = 'date';
|
||||
$length = null;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
|
||||
}
|
||||
|
||||
return array('type' => $type,
|
||||
'length' => $length,
|
||||
'unsigned' => $unsigned,
|
||||
'fixed' => $fixed);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -28,6 +28,10 @@
|
|||
* NOTE: Methods that are intended for internal use only but must be public
|
||||
* are marked INTERNAL: and begin with an underscore "_" to indicate that they
|
||||
* ideally would not be public and to minimize naming collisions.
|
||||
*
|
||||
* The "final" modifiers on most methods prevent accidental overrides.
|
||||
* It is not desirable that subclasses can override these methods.
|
||||
* The persistence layer should stay in the background as much as possible.
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
|
@ -81,7 +85,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
|
|||
/**
|
||||
* Index used for creating object identifiers (oid's).
|
||||
*
|
||||
* @var integer $index
|
||||
* @var integer
|
||||
*/
|
||||
private static $_index = 1;
|
||||
|
||||
|
@ -240,14 +244,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
*/
|
||||
/*final public function _setIdentifier(array $identifier)
|
||||
{
|
||||
$this->_id = $identifier;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Serializes the entity.
|
||||
|
|
|
@ -168,14 +168,26 @@ class Doctrine_EntityManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the transaction object used by the EntityManager to manage
|
||||
* database transactions.
|
||||
*
|
||||
* @return Doctrine::DBAL::Transaction
|
||||
* Starts a database transaction.
|
||||
*/
|
||||
public function getTransaction()
|
||||
public function beginTransaction()
|
||||
{
|
||||
return $this->_conn->getTransaction();
|
||||
return $this->_conn->beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits a running database transaction.
|
||||
* This causes a flush() of the EntityManager if the flush mode is set to
|
||||
* AUTO or COMMIT.
|
||||
*
|
||||
* @return unknown
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if ($this->_flushMode == self::FLUSHMODE_AUTO || $this->_flushMode == self::FLUSHMODE_COMMIT) {
|
||||
$this->flush();
|
||||
}
|
||||
return $this->_conn->commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,11 +18,16 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::Common::Events;
|
||||
|
||||
/**
|
||||
* EventSubscriber.
|
||||
* An EventSubscriber knows itself what events it is interested in.
|
||||
* If an EventSubscriber is added to an EventManager, the manager invokes
|
||||
* getSubscribedEvents() and registers the subscriber as a listener for all
|
||||
* returned events.
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
|
|
|
@ -1069,6 +1069,7 @@ class Doctrine_Export extends Doctrine_Connection_Module
|
|||
* occurred during the create table operation
|
||||
* @param array $classes
|
||||
* @return void
|
||||
* @todo ORM stuff
|
||||
*/
|
||||
public function exportClasses(array $classes)
|
||||
{
|
||||
|
@ -1279,6 +1280,7 @@ class Doctrine_Export extends Doctrine_Connection_Module
|
|||
* occurred during the create table operation
|
||||
* @return boolean whether or not the export operation was successful
|
||||
* false if table already existed in the database
|
||||
* @todo ORM stuff
|
||||
*/
|
||||
public function exportTable(Doctrine_ClassMetadata $metadata)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Firebird
|
||||
*
|
||||
|
@ -30,28 +30,10 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Firebird extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* return string for internal table used when calling only a function
|
||||
*
|
||||
* @return string for internal table used when calling only a function
|
||||
* @access public
|
||||
*/
|
||||
public function functionTable()
|
||||
{
|
||||
return ' FROM RDB$DATABASE';
|
||||
}
|
||||
|
||||
/**
|
||||
* build string to define escape pattern string
|
||||
*
|
||||
* @return string define escape pattern
|
||||
*/
|
||||
function patternEscapeString()
|
||||
{
|
||||
return " ESCAPE '". $this->conn->string_quoting['escape_pattern'] ."'";
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Informix
|
||||
*
|
||||
|
@ -28,7 +28,8 @@ Doctrine::autoload('Doctrine_Expression');
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Informix extends Doctrine_Expression
|
||||
{ }
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Mssql
|
||||
*
|
||||
|
@ -28,65 +28,10 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Mssql extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time:
|
||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
||||
* - CURRENT_DATE (date, DATE type)
|
||||
* - CURRENT_TIME (time, TIME type)
|
||||
*
|
||||
* @return string to call a variable with the current timestamp
|
||||
* @access public
|
||||
*/
|
||||
public function now($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'time':
|
||||
case 'date':
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'GETDATE()';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* @return string to call a function to get a substring
|
||||
*/
|
||||
public function substring($value, $position, $length = null)
|
||||
{
|
||||
if ( ! is_null($length)) {
|
||||
return 'SUBSTRING(' . $value . ', ' . $position . ', ' . $length . ')';
|
||||
}
|
||||
return 'SUBSTRING(' . $value . ', ' . $position . ', LEN(' . $value . ') - ' . $position . ' + 1)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string to concatenate two or more string parameters
|
||||
*
|
||||
* @param string $arg1
|
||||
* @param string $arg2
|
||||
* @param string $values...
|
||||
* @return string to concatenate two strings
|
||||
*/
|
||||
public function concat()
|
||||
{
|
||||
$args = func_get_args();
|
||||
return '(' . implode(' + ', $args) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
*/
|
||||
public function guid()
|
||||
{
|
||||
return 'NEWID()';
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Mysql
|
||||
*
|
||||
|
@ -29,100 +29,9 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Mysql extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* returns the regular expression operator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function regexp()
|
||||
{
|
||||
return 'RLIKE';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return string to generate float between 0 and 1
|
||||
*/
|
||||
public function random()
|
||||
{
|
||||
return 'RAND()';
|
||||
}
|
||||
|
||||
/**
|
||||
* build a pattern matching string
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
||||
* @param string $field optional field name that is being matched against
|
||||
* (might be required when emulating ILIKE)
|
||||
*
|
||||
* @return string SQL pattern
|
||||
*/
|
||||
public function matchPattern($pattern, $operator = null, $field = null)
|
||||
{
|
||||
$match = '';
|
||||
if ( ! is_null($operator)) {
|
||||
$field = is_null($field) ? '' : $field.' ';
|
||||
$operator = strtoupper($operator);
|
||||
switch ($operator) {
|
||||
// case insensitive
|
||||
case 'ILIKE':
|
||||
$match = $field.'LIKE ';
|
||||
break;
|
||||
// case sensitive
|
||||
case 'LIKE':
|
||||
$match = $field.'LIKE BINARY ';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Expression_Mysql_Exception('not a supported operator type:'. $operator);
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
foreach ($pattern as $key => $value) {
|
||||
if ($key % 2) {
|
||||
$match .= $value;
|
||||
} else {
|
||||
$match .= $this->conn->escapePattern($this->conn->escape($value));
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
$match.= $this->patternEscapeString();
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
*/
|
||||
public function guid()
|
||||
{
|
||||
return 'UUID()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a series of strings concatinated
|
||||
*
|
||||
* concat() accepts an arbitrary number of parameters. Each parameter
|
||||
* must contain an expression or an array with expressions.
|
||||
*
|
||||
* @param string|array(string) strings that will be concatinated.
|
||||
*/
|
||||
public function concat()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return 'CONCAT(' . join(', ', (array) $args) . ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Sqlite
|
||||
*
|
||||
|
@ -28,65 +28,10 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Oracle extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* @param string $value an sql string literal or column name/alias
|
||||
* @param integer $position where to start the substring portion
|
||||
* @param integer $length the substring portion length
|
||||
* @return string SQL substring function with given parameters
|
||||
*/
|
||||
public function substring($value, $position, $length = null)
|
||||
{
|
||||
if ($length !== null)
|
||||
return "SUBSTR($value, $position, $length)";
|
||||
|
||||
return "SUBSTR($value, $position)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time:
|
||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
|
||||
* - CURRENT_DATE (date, DATE type)
|
||||
* - CURRENT_TIME (time, TIME type)
|
||||
*
|
||||
* @return string to call a variable with the current timestamp
|
||||
*/
|
||||
public function now($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* random
|
||||
*
|
||||
* @return string an oracle SQL string that generates a float between 0 and 1
|
||||
*/
|
||||
public function random()
|
||||
{
|
||||
return 'dbms_random.value';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns global unique identifier
|
||||
*
|
||||
* @return string to get global unique identifier
|
||||
*/
|
||||
public function guid()
|
||||
{
|
||||
return 'SYS_GUID()';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Pgsql
|
||||
*
|
||||
|
@ -29,174 +29,9 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Pgsql extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* Returns the md5 sum of a field.
|
||||
*
|
||||
* Note: Not SQL92, but common functionality
|
||||
*
|
||||
* md5() works with the default PostgreSQL 8 versions.
|
||||
*
|
||||
* If you are using PostgreSQL 7.x or older you need
|
||||
* to make sure that the digest procedure is installed.
|
||||
* If you use RPMS (Redhat and Mandrake) install the postgresql-contrib
|
||||
* package. You must then install the procedure by running this shell command:
|
||||
* <code>
|
||||
* psql [dbname] < /usr/share/pgsql/contrib/pgcrypto.sql
|
||||
* </code>
|
||||
* You should make sure you run this as the postgres user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function md5($column)
|
||||
{
|
||||
$column = $this->getIdentifier($column);
|
||||
|
||||
if ($this->version > 7) {
|
||||
return 'MD5(' . $column . ')';
|
||||
} else {
|
||||
return 'encode(digest(' . $column .', md5), hex)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns part of a string.
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* @param string $value the target $value the string or the string column.
|
||||
* @param int $from extract from this characeter.
|
||||
* @param int $len extract this amount of characters.
|
||||
* @return string sql that extracts part of a string.
|
||||
*/
|
||||
public function substring($value, $from, $len = null)
|
||||
{
|
||||
$value = $this->getIdentifier($value);
|
||||
|
||||
if ($len === null) {
|
||||
$len = $this->getIdentifier($len);
|
||||
return 'SUBSTR(' . $value . ', ' . $from . ')';
|
||||
} else {
|
||||
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQLs AGE(<timestamp1> [, <timestamp2>]) function.
|
||||
*
|
||||
* @param string $timestamp1 timestamp to subtract from NOW()
|
||||
* @param string $timestamp2 optional; if given: subtract arguments
|
||||
* @return string
|
||||
*/
|
||||
public function age($timestamp1, $timestamp2 = null) {
|
||||
if ( $timestamp2 == null ) {
|
||||
return 'AGE(' . $timestamp1 . ')';
|
||||
}
|
||||
return 'AGE(' . $timestamp1 . ', ' . $timestamp2 . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQLs DATE_PART( <text>, <time> ) function.
|
||||
*
|
||||
* @param string $text what to extract
|
||||
* @param string $time timestamp or interval to extract from
|
||||
* @return string
|
||||
*/
|
||||
public function date_part($text, $time) {
|
||||
return 'DATE_PART(' . $text . ', ' . $time . ')';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PostgreSQLs TO_CHAR( <time>, <text> ) function.
|
||||
*
|
||||
* @param string $time timestamp or interval
|
||||
* @param string $text how to the format the output
|
||||
* @return string
|
||||
*/
|
||||
public function to_char($time, $text) {
|
||||
return 'TO_CHAR(' . $time . ', ' . $text . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL string to return the current system date and time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function now()
|
||||
{
|
||||
return 'LOCALTIMESTAMP(0)';
|
||||
}
|
||||
|
||||
/**
|
||||
* regexp
|
||||
*
|
||||
* @return string the regular expression operator
|
||||
*/
|
||||
public function regexp()
|
||||
{
|
||||
return 'SIMILAR TO';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return return string to generate float between 0 and 1
|
||||
* @access public
|
||||
*/
|
||||
public function random()
|
||||
{
|
||||
return 'RANDOM()';
|
||||
}
|
||||
|
||||
/**
|
||||
* build a pattern matching string
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param array $pattern even keys are strings, odd are patterns (% and _)
|
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
|
||||
* @param string $field optional field name that is being matched against
|
||||
* (might be required when emulating ILIKE)
|
||||
*
|
||||
* @return string SQL pattern
|
||||
*/
|
||||
public function matchPattern($pattern, $operator = null, $field = null)
|
||||
{
|
||||
$match = '';
|
||||
if ( ! is_null($operator)) {
|
||||
$field = is_null($field) ? '' : $field.' ';
|
||||
$operator = strtoupper($operator);
|
||||
switch ($operator) {
|
||||
// case insensitive
|
||||
case 'ILIKE':
|
||||
$match = $field.'ILIKE ';
|
||||
break;
|
||||
// case sensitive
|
||||
case 'LIKE':
|
||||
$match = $field.'LIKE ';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Expression_Pgsql_Exception('not a supported operator type:'. $operator);
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
foreach ($pattern as $key => $value) {
|
||||
if ($key % 2) {
|
||||
$match.= $value;
|
||||
} else {
|
||||
$match.= $this->conn->escapePattern($this->conn->escape($value));
|
||||
}
|
||||
}
|
||||
$match.= "'";
|
||||
$match.= $this->patternEscapeString();
|
||||
return $match;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Expression_Driver');
|
||||
|
||||
/**
|
||||
* Doctrine_Expression_Sqlite
|
||||
*
|
||||
|
@ -28,134 +28,10 @@ Doctrine::autoload('Doctrine_Expression_Driver');
|
|||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Remove
|
||||
*/
|
||||
class Doctrine_Expression_Sqlite extends Doctrine_Expression_Driver
|
||||
{
|
||||
/**
|
||||
* Returns the md5 sum of the data that SQLite's md5() function receives.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return string
|
||||
*/
|
||||
public static function md5Impl($data)
|
||||
{
|
||||
return md5($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modules of the data that SQLite's mod() function receives.
|
||||
*
|
||||
* @param integer $dividend
|
||||
* @param integer $divisor
|
||||
* @return string
|
||||
*/
|
||||
public static function modImpl($dividend, $divisor)
|
||||
{
|
||||
return $dividend % $divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* locate
|
||||
* returns the position of the first occurrence of substring $substr in string $str that
|
||||
* SQLite's locate() function receives
|
||||
*
|
||||
* @param string $substr literal string to find
|
||||
* @param string $str literal string
|
||||
* @return string
|
||||
*/
|
||||
public static function locateImpl($substr, $str)
|
||||
{
|
||||
return strpos($str, $substr);
|
||||
}
|
||||
public static function sha1Impl($str)
|
||||
{
|
||||
return sha1($str);
|
||||
}
|
||||
public static function ltrimImpl($str)
|
||||
{
|
||||
return ltrim($str);
|
||||
}
|
||||
public static function rtrimImpl($str)
|
||||
{
|
||||
return rtrim($str);
|
||||
}
|
||||
public static function trimImpl($str)
|
||||
{
|
||||
return trim($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the regular expression operator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function regexp()
|
||||
{
|
||||
return 'RLIKE';
|
||||
}
|
||||
|
||||
/**
|
||||
* soundex
|
||||
* Returns a string to call a function to compute the
|
||||
* soundex encoding of a string
|
||||
*
|
||||
* The string "?000" is returned if the argument is NULL.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string SQL soundex function with given parameter
|
||||
*/
|
||||
public function soundex($value)
|
||||
{
|
||||
return 'SOUNDEX(' . $value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to call a variable with the current timestamp inside an SQL statement
|
||||
* There are three special variables for current date and time.
|
||||
*
|
||||
* @return string sqlite function as string
|
||||
*/
|
||||
public function now($type = 'timestamp')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'time':
|
||||
return 'time(\'now\')';
|
||||
case 'date':
|
||||
return 'date(\'now\')';
|
||||
case 'timestamp':
|
||||
default:
|
||||
return 'datetime(\'now\')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get random value inside an SQL statement
|
||||
*
|
||||
* @return string to generate float between 0 and 1
|
||||
*/
|
||||
public function random()
|
||||
{
|
||||
return '((RANDOM() + 2147483648) / 4294967296)';
|
||||
}
|
||||
|
||||
/**
|
||||
* return string to call a function to get a substring inside an SQL statement
|
||||
*
|
||||
* Note: Not SQL92, but common functionality.
|
||||
*
|
||||
* SQLite only supports the 2 parameter variant of this function
|
||||
*
|
||||
* @param string $value an sql string literal or column name/alias
|
||||
* @param integer $position where to start the substring portion
|
||||
* @param integer $length the substring portion length
|
||||
* @return string SQL substring function with given parameters
|
||||
*/
|
||||
public function substring($value, $position, $length = null)
|
||||
{
|
||||
if ($length !== null) {
|
||||
return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')';
|
||||
}
|
||||
return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
* @version $Revision: 3192 $
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @deprecated
|
||||
*/
|
||||
class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
|
||||
{
|
||||
|
|
|
@ -196,7 +196,8 @@ class Doctrine_Import extends Doctrine_Connection_Module
|
|||
*
|
||||
* @param string $directory
|
||||
* @param array $databases
|
||||
* @return array the names of the imported classes
|
||||
* @return array the names of the imported classes
|
||||
* @todo ORM stuff
|
||||
*/
|
||||
public function importSchema($directory, array $databases = array(), array $options = array())
|
||||
{
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
* Null object: Null valued of a field or empty association that has already been loaded.
|
||||
* On access, the database is not queried.
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Null
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @todo Really needed? Remove.
|
||||
* @todo Remove.
|
||||
*/
|
||||
interface Doctrine_Overloadable {
|
||||
/**
|
||||
|
|
|
@ -197,13 +197,13 @@ abstract class Doctrine_Query_Production
|
|||
*
|
||||
* @return string Sql piece
|
||||
*/
|
||||
public function buildSql()
|
||||
/*public function buildSql()
|
||||
{
|
||||
$className = get_class($this);
|
||||
$methodName = substr($className, strrpos($className, '_'));
|
||||
|
||||
$this->_sqlBuilder->$methodName($this);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -73,7 +73,7 @@ class Doctrine_Query_Production_Atom extends Doctrine_Query_Production
|
|||
|
||||
public function buildSql()
|
||||
{
|
||||
$conn = $this->_parser->getSqlBuilder()->getConnection();
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
switch ($this->_type) {
|
||||
case 'param':
|
||||
|
@ -86,7 +86,7 @@ class Doctrine_Query_Production_Atom extends Doctrine_Query_Production
|
|||
break;
|
||||
|
||||
default:
|
||||
$stringQuoting = $conn->getProperty('string_quoting');
|
||||
$stringQuoting = $conn->getDatabasePlatform()->getProperty('string_quoting');
|
||||
return $stringQuoting['start']
|
||||
. $conn->quote($this->_value, $this->_type)
|
||||
. $stringQuoting['end'];
|
||||
|
|
|
@ -75,12 +75,7 @@ class Doctrine_Query_Production_IdentificationVariableDeclaration extends Doctri
|
|||
$queryComponent = $parserResult->getQueryComponent($this->_rangeVariableDeclaration);
|
||||
|
||||
// Retrieving connection
|
||||
$conn = $this->_parser->getSqlBuilder()->getConnection();
|
||||
$manager = Doctrine_Manager::getInstance();
|
||||
|
||||
if ($manager->hasConnectionForComponent($queryComponent['metadata']->getClassName())) {
|
||||
$conn = $manager->getConnectionForComponent($queryComponent['metadata']->getClassName());
|
||||
}
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
$str = $conn->quoteIdentifier($queryComponent['metadata']->getTableName()) . ' '
|
||||
. $conn->quoteIdentifier($parserResult->getTableAliasFromComponentAlias($this->_rangeVariableDeclaration));
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @todo Merge into DatabasePlatform.
|
||||
*/
|
||||
abstract class Doctrine_Query_SqlBuilder
|
||||
{
|
||||
|
@ -83,198 +84,4 @@ abstract class Doctrine_Query_SqlBuilder
|
|||
|
||||
// End of Common SQL generations
|
||||
|
||||
|
||||
|
||||
/** The following is just test/draft code for now. */
|
||||
|
||||
/*private $_sql;
|
||||
private $_conditionalTerms = array();
|
||||
private $_conditionalFactors = array();
|
||||
private $_conditionalPrimaries = array();
|
||||
private $_variableDeclaration = array();
|
||||
private $_expressions = array();
|
||||
private $_deleteClause;
|
||||
private $_whereClause;
|
||||
|
||||
public function visitVariableDeclaration($variableDeclaration)
|
||||
{
|
||||
echo " VariableDeclaration ";
|
||||
// Basic handy variables
|
||||
$parserResult = $variableDeclaration->getParser()->getParserResult();
|
||||
$queryComponent = $parserResult->getQueryComponent($variableDeclaration->getComponentAlias());
|
||||
|
||||
// Retrieving connection
|
||||
$manager = Doctrine_EntityManagerFactory::getManager();
|
||||
$conn = $manager->getConnection();
|
||||
|
||||
$this->_variableDeclaration[] = $conn->quoteIdentifier($queryComponent['metadata']->getTableName()) . ' '
|
||||
. $conn->quoteIdentifier($parserResult->getTableAliasFromComponentAlias(
|
||||
$variableDeclaration->getComponentAlias()));
|
||||
}
|
||||
|
||||
public function visitDeleteClause($deleteClause)
|
||||
{
|
||||
echo " DeleteClause ";
|
||||
$this->_deleteClause = 'DELETE FROM ' . array_pop($this->_variableDeclaration);
|
||||
}
|
||||
|
||||
public function visitDeleteStatement($deleteStatement)
|
||||
{
|
||||
echo " DeleteStatement ";
|
||||
$this->_sql = $this->_deleteClause;
|
||||
if ($this->_whereClause) {
|
||||
$this->_sql .= $this->_whereClause;
|
||||
} else {
|
||||
$this->_sql .= " WHERE 1 = 1";
|
||||
}
|
||||
}
|
||||
|
||||
public function visitWhereClause($whereClause)
|
||||
{
|
||||
echo " WhereClause ";
|
||||
if ($this->_expressions) {
|
||||
$this->_whereClause = ' WHERE ' . array_pop($this->_expressions);
|
||||
}
|
||||
}
|
||||
|
||||
public function visitConditionalExpression($conditionalExpression)
|
||||
{
|
||||
echo " ConditionalExpression ";
|
||||
$count = count($conditionalExpression->getConditionalTerms());
|
||||
$terms = array();
|
||||
for ($i=0; $i<$count; $i++) {
|
||||
$terms[] = array_pop($this->_conditionalTerms);
|
||||
}
|
||||
|
||||
$this->_expressions[] = implode(' OR ', $terms);
|
||||
}
|
||||
|
||||
public function visitSimpleConditionalExpression($simpleConditionalExpression)
|
||||
{
|
||||
//var_dump($this->_expressions);
|
||||
echo " SimpleConditionalExpression ";
|
||||
$rightExpr = array_pop($this->_expressions);
|
||||
$leftExpr = array_pop($this->_expressions);
|
||||
$this->_expressions[] = $leftExpr . ' ' . $rightExpr;
|
||||
}
|
||||
|
||||
public function visitConditionalPrimary($conditionalPrimary)
|
||||
{
|
||||
echo " ConditionalPrimary ";
|
||||
if ($this->_expressions) {
|
||||
$this->_conditionalPrimaries[] = '(' . array_pop($this->_expressions) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
public function visitConditionalTerm($conditionalTerm)
|
||||
{
|
||||
echo " ConditionalTerm ";
|
||||
$count = count($conditionalTerm->getConditionalFactors());
|
||||
$factors = array();
|
||||
for ($i=0; $i<$count; $i++) {
|
||||
$factors[] = array_pop($this->_conditionalFactors);
|
||||
}
|
||||
|
||||
$this->_conditionalTerms[] = implode(' AND ', $factors);
|
||||
}
|
||||
|
||||
public function visitConditionalFactor($conditionalFactor)
|
||||
{
|
||||
echo " ConditionalFactor ";
|
||||
if ($this->_conditionalPrimaries) {
|
||||
$this->_conditionalFactors[] = 'NOT ' . array_pop($this->_conditionalPrimaries);
|
||||
}
|
||||
}
|
||||
|
||||
public function visitBetweenExpression($betweenExpression)
|
||||
{
|
||||
$this->_expressions[] = (($betweenExpression->getNot()) ? 'NOT ' : '') . 'BETWEEN '
|
||||
. array_pop($this->_expressions) . ' AND ' . array_pop($this->_expressions);
|
||||
}
|
||||
|
||||
public function visitLikeExpression($likeExpression)
|
||||
{
|
||||
$this->_expressions[] = (($likeExpression->getNot()) ? 'NOT ' : '') . 'LIKE ' .
|
||||
array_pop($this->_expressions)
|
||||
. (($likeExpression->getEscapeString() !== null) ? ' ESCAPE ' . $likeExpression->getEscapeString() : '');
|
||||
}
|
||||
|
||||
public function visitInExpression($inExpression)
|
||||
{
|
||||
$count = count($inExpression->getAtoms());
|
||||
$atoms = array();
|
||||
for ($i=0; $i<$count; $i++) {
|
||||
$atoms[] = array_pop($this->_expressions);
|
||||
}
|
||||
|
||||
$this->_expressions[] = (($inExpression->getNot()) ? 'NOT ' : '') . 'IN ('
|
||||
. (($inExpression->getSubselect() !== null) ? array_pop($this->_expressions) :
|
||||
implode(', ', $atoms))
|
||||
. ')';
|
||||
}
|
||||
|
||||
public function visitNullComparisonExpression($nullComparisonExpression)
|
||||
{
|
||||
$this->_expressions[] = 'IS ' . (($nullComparisonExpression->getNot()) ? 'NOT ' : '') . 'NULL';
|
||||
}
|
||||
|
||||
public function visitAtom($atom)
|
||||
{
|
||||
$conn = $atom->getParser()->getSqlBuilder()->getConnection();
|
||||
switch ($atom->getType()) {
|
||||
case 'param':
|
||||
$this->_expressions[] = $atom->getValue();
|
||||
break;
|
||||
case 'integer':
|
||||
case 'float':
|
||||
$this->_expressions[] = $conn->quote($atom->getValue(), $atom->getType());
|
||||
break;
|
||||
default:
|
||||
$stringQuoting = $this->_conn->getProperty('string_quoting');
|
||||
$this->_expressions[] = $stringQuoting['start']
|
||||
. $conn->quote($this->_value, $this->_type)
|
||||
. $stringQuoting['end'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function visitPathExpression($pathExpression)
|
||||
{
|
||||
echo " PathExpression ";
|
||||
// Basic handy variables
|
||||
$parserResult = $pathExpression->getParser()->getParserResult();
|
||||
|
||||
// Retrieving connection
|
||||
$manager = Doctrine_EntityManagerFactory::getManager();
|
||||
$conn = $manager->getConnection();
|
||||
|
||||
// Looking for queryComponent to fetch
|
||||
$queryComponent = $parserResult->getQueryComponent($pathExpression->getComponentAlias());
|
||||
|
||||
// Generating the SQL piece
|
||||
$str = $parserResult->getTableAliasFromComponentAlias($pathExpression->getComponentAlias()) . '.'
|
||||
. $queryComponent['metadata']->getColumnName($pathExpression->getFieldName());
|
||||
|
||||
$this->_expressions[] = $conn->quoteIdentifier($str);
|
||||
}
|
||||
|
||||
public function visitComparisonExpression($comparisonExpression)
|
||||
{
|
||||
echo " ComparisonExpression ";
|
||||
|
||||
$expr = $comparisonExpression->getOperator() . ' ';
|
||||
if ($comparisonExpression->getIsSubselect()) {
|
||||
$expr .= '(' . array_pop($this->_expressions) . ')';
|
||||
} else {
|
||||
$expr .= array_pop($this->_expressions);
|
||||
}
|
||||
$this->_expressions[] = $expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getSql()
|
||||
{
|
||||
return $this->_sql;
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -35,14 +35,7 @@ class Doctrine_Query_SqlExecutor_SingleTableDeleteUpdate extends Doctrine_Query_
|
|||
{
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
{
|
||||
parent::__construct($AST);
|
||||
|
||||
/*if ($AST instanceof Doctrine_Query_Production_DeleteStatement) {
|
||||
$builder = new Doctrine_Query_SqlBuilder_MySql(Doctrine_EntityManagerFactory::getManager());
|
||||
$AST->accept($builder);
|
||||
echo PHP_EOL . "SQL:" . $builder->getSql() . PHP_EOL . PHP_EOL;
|
||||
}*/
|
||||
|
||||
parent::__construct($AST);
|
||||
$this->_sqlStatements = $AST->buildSql();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,9 @@
|
|||
* Handles transaction savepoint and isolation abstraction
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @package Doctrine
|
||||
* @subpackage Transaction
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
|
@ -56,24 +55,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
* transaction.
|
||||
*/
|
||||
protected $_nestingLevel = 0;
|
||||
|
||||
/**
|
||||
* @var integer $_internalNestingLevel The current internal nesting level of this transaction.
|
||||
* "Internal" means transactions started by Doctrine itself.
|
||||
* Therefore the internal nesting level is always
|
||||
* lower or equal to the overall nesting level.
|
||||
* A level of 0 means there is currently no active
|
||||
* transaction that was initiated by Doctrine itself.
|
||||
* @todo package:orm. I guess the DBAL does not start transactions on its own?
|
||||
*/
|
||||
protected $_internalNestingLevel = 0;
|
||||
|
||||
/**
|
||||
* @var array $invalid an array containing all invalid records within this transaction
|
||||
* @todo What about a more verbose name? $invalidRecords?
|
||||
* package:orm
|
||||
*/
|
||||
protected $invalid = array();
|
||||
|
||||
/**
|
||||
* @var array $savepoints an array containing all savepoints
|
||||
|
@ -81,33 +62,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
protected $savePoints = array();
|
||||
|
||||
/**
|
||||
* @var array $_collections an array of Doctrine_Collection objects that were affected during the Transaction
|
||||
* @todo package:orm
|
||||
*/
|
||||
protected $_collections = array();
|
||||
|
||||
/**
|
||||
* addCollection
|
||||
* adds a collection in the internal array of collections
|
||||
*
|
||||
* at the end of each commit this array is looped over and
|
||||
* of every collection Doctrine then takes a snapshot in order
|
||||
* to keep the collections up to date with the database
|
||||
*
|
||||
* @param Doctrine_Collection $coll a collection to be added
|
||||
* @return Doctrine_Transaction this object
|
||||
* @todo package:orm
|
||||
*/
|
||||
public function addCollection(Doctrine_Collection $coll)
|
||||
{
|
||||
$this->_collections[] = $coll;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* getState
|
||||
* returns the state of this transaction module.
|
||||
* Returns the state of this transaction module.
|
||||
*
|
||||
* @see Doctrine_Connection_Transaction::STATE_* constants
|
||||
* @return integer the connection state
|
||||
|
@ -116,49 +71,18 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
{
|
||||
switch ($this->_nestingLevel) {
|
||||
case 0:
|
||||
return Doctrine_Transaction::STATE_SLEEP;
|
||||
return self::STATE_SLEEP;
|
||||
break;
|
||||
case 1:
|
||||
return Doctrine_Transaction::STATE_ACTIVE;
|
||||
return self::STATE_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
return Doctrine_Transaction::STATE_BUSY;
|
||||
return self::STATE_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* addInvalid
|
||||
* adds record into invalid records list
|
||||
*
|
||||
* @param Doctrine_Entity $record
|
||||
* @return boolean false if record already existed in invalid records list,
|
||||
* otherwise true
|
||||
* @todo package:orm
|
||||
*/
|
||||
public function addInvalid(Doctrine_Entity $record)
|
||||
{
|
||||
if (in_array($record, $this->invalid, true)) {
|
||||
return false;
|
||||
}
|
||||
$this->invalid[] = $record;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the invalid records
|
||||
*
|
||||
* @return array An array of invalid records
|
||||
* @todo package:orm
|
||||
*/
|
||||
public function getInvalid()
|
||||
{
|
||||
return $this->invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransactionLevel
|
||||
* get the current transaction nesting level
|
||||
* Gets the current transaction nesting level.
|
||||
*
|
||||
* @return integer
|
||||
* @todo Name suggestion: getNestingLevel(). $transaction->getTransactionLevel() looks odd.
|
||||
|
@ -167,21 +91,8 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
{
|
||||
return $this->_nestingLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* getInternalTransactionLevel
|
||||
* get the current internal transaction nesting level
|
||||
*
|
||||
* @return integer
|
||||
* @todo package:orm. I guess the DBAL does not start transactions itself?
|
||||
*/
|
||||
public function getInternalTransactionLevel()
|
||||
{
|
||||
return $this->_internalNestingLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* beginTransaction
|
||||
* Start a transaction or set a savepoint.
|
||||
*
|
||||
* if trying to set a savepoint and there is no active transaction
|
||||
|
@ -195,40 +106,33 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
* @param string $savepoint name of a savepoint to set
|
||||
* @throws Doctrine_Transaction_Exception if the transaction fails at database level
|
||||
* @return integer current transaction nesting level
|
||||
* @todo Name suggestion: begin(). $transaction->beginTransaction() looks odd.
|
||||
*/
|
||||
public function beginTransaction($savepoint = null)
|
||||
public function begin($savepoint = null)
|
||||
{
|
||||
$this->conn->connect();
|
||||
|
||||
$listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
//$listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
|
||||
if ( ! is_null($savepoint)) {
|
||||
$this->savePoints[] = $savepoint;
|
||||
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_CREATE);
|
||||
|
||||
$listener->preSavepointCreate($event);
|
||||
|
||||
if ( ! $event->skipOperation) {
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_CREATE);
|
||||
//$listener->preSavepointCreate($event);
|
||||
//if ( ! $event->skipOperation) {
|
||||
$this->createSavePoint($savepoint);
|
||||
}
|
||||
|
||||
$listener->postSavepointCreate($event);
|
||||
//}
|
||||
//$listener->postSavepointCreate($event);
|
||||
} else {
|
||||
if ($this->_nestingLevel == 0) {
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::TX_BEGIN);
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::TX_BEGIN);
|
||||
//$listener->preTransactionBegin($event);
|
||||
|
||||
$listener->preTransactionBegin($event);
|
||||
|
||||
if ( ! $event->skipOperation) {
|
||||
//if ( ! $event->skipOperation) {
|
||||
try {
|
||||
$this->_doBeginTransaction();
|
||||
} catch (Exception $e) {
|
||||
throw new Doctrine_Transaction_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
$listener->postTransactionBegin($event);
|
||||
//}
|
||||
//$listener->postTransactionBegin($event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,8 +142,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* commit
|
||||
* Commit the database changes done during a transaction that is in
|
||||
* Commits the database changes done during a transaction that is in
|
||||
* progress or release a savepoint. This function may only be called when
|
||||
* auto-committing is disabled, otherwise it will fail.
|
||||
*
|
||||
|
@ -258,60 +161,35 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
|
||||
$this->conn->connect();
|
||||
|
||||
$listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
//$listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
|
||||
if ( ! is_null($savepoint)) {
|
||||
$this->_nestingLevel -= $this->removeSavePoints($savepoint);
|
||||
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_COMMIT);
|
||||
|
||||
$listener->preSavepointCommit($event);
|
||||
|
||||
if ( ! $event->skipOperation) {
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_COMMIT);
|
||||
//$listener->preSavepointCommit($event);
|
||||
//if ( ! $event->skipOperation) {
|
||||
$this->releaseSavePoint($savepoint);
|
||||
}
|
||||
|
||||
$listener->postSavepointCommit($event);
|
||||
} else {
|
||||
|
||||
if ($this->_nestingLevel == 1 || $this->_internalNestingLevel == 1) {
|
||||
if ( ! empty($this->invalid)) {
|
||||
if ($this->_internalNestingLevel == 1) {
|
||||
$tmp = $this->invalid;
|
||||
$this->invalid = array();
|
||||
throw new Doctrine_Validator_Exception($tmp);
|
||||
}
|
||||
}
|
||||
if ($this->_nestingLevel == 1) {
|
||||
// take snapshots of all collections used within this transaction
|
||||
foreach ($this->_collections as $coll) {
|
||||
$coll->takeSnapshot();
|
||||
}
|
||||
$this->_collections = array();
|
||||
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT);
|
||||
|
||||
$listener->preTransactionCommit($event);
|
||||
if ( ! $event->skipOperation) {
|
||||
$this->_doCommit();
|
||||
}
|
||||
$listener->postTransactionCommit($event);
|
||||
}
|
||||
//}
|
||||
//$listener->postSavepointCommit($event);
|
||||
} else {
|
||||
if ($this->_nestingLevel == 1) {
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT);
|
||||
//$listener->preTransactionCommit($event);
|
||||
//if ( ! $event->skipOperation) {
|
||||
$this->_doCommit();
|
||||
//}
|
||||
//$listener->postTransactionCommit($event);
|
||||
}
|
||||
|
||||
if ($this->_nestingLevel > 0) {
|
||||
$this->_nestingLevel--;
|
||||
}
|
||||
if ($this->_internalNestingLevel > 0) {
|
||||
$this->_internalNestingLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* rollback
|
||||
* Cancel any database changes done during a transaction or since a specific
|
||||
* savepoint that is in progress. This function may only be called when
|
||||
* auto-committing is disabled, otherwise it will fail. Therefore, a new
|
||||
|
@ -332,8 +210,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
|
||||
$this->conn->connect();
|
||||
|
||||
if ($this->_internalNestingLevel > 1 || $this->_nestingLevel > 1) {
|
||||
$this->_internalNestingLevel--;
|
||||
if ($this->_nestingLevel > 1) {
|
||||
$this->_nestingLevel--;
|
||||
return false;
|
||||
}
|
||||
|
@ -342,34 +219,31 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
|
||||
if ( ! is_null($savepoint)) {
|
||||
$this->_nestingLevel -= $this->removeSavePoints($savepoint);
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_ROLLBACK);
|
||||
$listener->preSavepointRollback($event);
|
||||
if ( ! $event->skipOperation) {
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_ROLLBACK);
|
||||
//$listener->preSavepointRollback($event);
|
||||
//if ( ! $event->skipOperation) {
|
||||
$this->rollbackSavePoint($savepoint);
|
||||
}
|
||||
$listener->postSavepointRollback($event);
|
||||
//}
|
||||
//$listener->postSavepointRollback($event);
|
||||
} else {
|
||||
$event = new Doctrine_Event($this, Doctrine_Event::TX_ROLLBACK);
|
||||
$listener->preTransactionRollback($event);
|
||||
|
||||
if ( ! $event->skipOperation) {
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::TX_ROLLBACK);
|
||||
//$listener->preTransactionRollback($event);
|
||||
//if ( ! $event->skipOperation) {
|
||||
$this->_nestingLevel = 0;
|
||||
$this->_internalNestingLevel = 0;
|
||||
try {
|
||||
$this->_doRollback();
|
||||
} catch (Exception $e) {
|
||||
throw new Doctrine_Transaction_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
$listener->postTransactionRollback($event);
|
||||
//}
|
||||
//$listener->postTransactionRollback($event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* releaseSavePoint
|
||||
* creates a new savepoint
|
||||
* Creates a new savepoint.
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to create
|
||||
* @return void
|
||||
|
@ -380,8 +254,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* releaseSavePoint
|
||||
* releases given savepoint
|
||||
* Releases given savepoint.
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to release
|
||||
* @return void
|
||||
|
@ -392,8 +265,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* rollbackSavePoint
|
||||
* releases given savepoint
|
||||
* Performs a rollback to a specified savepoint.
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to rollback to
|
||||
* @return void
|
||||
|
@ -428,7 +300,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* removeSavePoints
|
||||
* removes a savepoint from the internal savePoints array of this transaction object
|
||||
* and all its children savepoints
|
||||
*
|
||||
|
@ -458,8 +329,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* setIsolation
|
||||
*
|
||||
* Set the transacton isolation level.
|
||||
* (implemented by the connection drivers)
|
||||
*
|
||||
|
@ -485,9 +354,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
}
|
||||
|
||||
/**
|
||||
* getTransactionIsolation
|
||||
*
|
||||
* fetches the current session transaction isolation level
|
||||
* Fetches the current session transaction isolation level.
|
||||
*
|
||||
* note: some drivers may support setting the transaction isolation level
|
||||
* but not fetching it
|
||||
|
@ -499,18 +366,5 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
|
|||
public function getIsolation()
|
||||
{
|
||||
throw new Doctrine_Transaction_Exception('Fetching transaction isolation level not supported by this driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a transaction.
|
||||
*
|
||||
* This method must only be used by Doctrine itself to initiate transactions.
|
||||
* Userland-code must use {@link beginTransaction()}.
|
||||
*/
|
||||
public function beginInternalTransaction($savepoint = null)
|
||||
{
|
||||
$this->_internalNestingLevel++;
|
||||
return $this->beginTransaction($savepoint);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
#namespace Doctrine::DBAL::Transactions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @package Doctrine
|
||||
* @subpackage Transaction
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
|
@ -33,11 +33,11 @@ Doctrine::autoload('Doctrine_Transaction');
|
|||
class Doctrine_Transaction_Firebird extends Doctrine_Transaction
|
||||
{
|
||||
/**
|
||||
* createSavepoint
|
||||
* creates a new savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to set
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function createSavePoint($savepoint)
|
||||
{
|
||||
|
@ -47,11 +47,11 @@ class Doctrine_Transaction_Firebird extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* releaseSavePoint
|
||||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to release
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function releaseSavePoint($savepoint)
|
||||
{
|
||||
|
@ -61,11 +61,11 @@ class Doctrine_Transaction_Firebird extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* rollbackSavePoint
|
||||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to rollback to
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function rollbackSavePoint($savepoint)
|
||||
{
|
||||
|
@ -89,7 +89,8 @@ class Doctrine_Transaction_Firebird extends Doctrine_Transaction
|
|||
*
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level or unknown wait option
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function setIsolation($isolation, $options = array()) {
|
||||
switch ($isolation) {
|
||||
|
|
|
@ -18,14 +18,12 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @package Doctrine
|
||||
* @subpackage Transaction
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
|
|
|
@ -47,7 +47,8 @@ class Doctrine_Transaction_Mssql extends Doctrine_Transaction
|
|||
* @link http://msdn2.microsoft.com/en-us/library/ms173763.aspx
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level or unknown wait option
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function setIsolation($isolation, $options = array()) {
|
||||
switch ($isolation) {
|
||||
|
@ -67,7 +68,9 @@ class Doctrine_Transaction_Mssql extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* Performs the rollback.
|
||||
* Performs the rollback.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _doRollback()
|
||||
{
|
||||
|
@ -75,7 +78,9 @@ class Doctrine_Transaction_Mssql extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* Performs the commit.
|
||||
* Performs the commit.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _doCommit()
|
||||
{
|
||||
|
@ -83,7 +88,9 @@ class Doctrine_Transaction_Mssql extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* Begins a database transaction.
|
||||
* Begins a database transaction.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _doBeginTransaction()
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
|
@ -33,11 +33,11 @@ Doctrine::autoload('Doctrine_Transaction');
|
|||
class Doctrine_Transaction_Oracle extends Doctrine_Transaction
|
||||
{
|
||||
/**
|
||||
* createSavepoint
|
||||
* creates a new savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to set
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function createSavePoint($savepoint)
|
||||
{
|
||||
|
@ -47,11 +47,11 @@ class Doctrine_Transaction_Oracle extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* releaseSavePoint
|
||||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to release
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function releaseSavePoint($savepoint)
|
||||
{
|
||||
|
@ -60,11 +60,11 @@ class Doctrine_Transaction_Oracle extends Doctrine_Transaction
|
|||
}
|
||||
|
||||
/**
|
||||
* rollbackSavePoint
|
||||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to rollback to
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function rollbackSavePoint($savepoint)
|
||||
{
|
||||
|
@ -83,7 +83,8 @@ class Doctrine_Transaction_Oracle extends Doctrine_Transaction
|
|||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function setIsolation($isolation)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
|
@ -38,7 +38,8 @@ class Doctrine_Transaction_Pgsql extends Doctrine_Transaction
|
|||
* creates a new savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to set
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function createSavePoint($savepoint)
|
||||
{
|
||||
|
@ -52,7 +53,8 @@ class Doctrine_Transaction_Pgsql extends Doctrine_Transaction
|
|||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to release
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function releaseSavePoint($savepoint)
|
||||
{
|
||||
|
@ -66,7 +68,8 @@ class Doctrine_Transaction_Pgsql extends Doctrine_Transaction
|
|||
* releases given savepoint
|
||||
*
|
||||
* @param string $savepoint name of a savepoint to rollback to
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
protected function rollbackSavePoint($savepoint)
|
||||
{
|
||||
|
@ -85,7 +88,8 @@ class Doctrine_Transaction_Pgsql extends Doctrine_Transaction
|
|||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level or unknown wait option
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function setIsolation($isolation)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Transaction');
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
|
@ -42,7 +42,8 @@ class Doctrine_Transaction_Sqlite extends Doctrine_Transaction
|
|||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level
|
||||
* @return void
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function setIsolation($isolation)
|
||||
{
|
||||
|
|
51
tests/Orm/Internal/CommitOrderCalculatorTest.php
Normal file
51
tests/Orm/Internal/CommitOrderCalculatorTest.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
require_once 'lib/DoctrineTestInit.php';
|
||||
|
||||
/**
|
||||
* Tests of the commit order calculation.
|
||||
*
|
||||
* IMPORTANT: When writing tests here consider that a lot of graph constellations
|
||||
* can have many valid orderings, so you may want to build a graph that has only
|
||||
* 1 valid order to simplify your tests.
|
||||
*/
|
||||
class Orm_Internal_CommitOrderCalculatorTest extends Doctrine_OrmTestCase
|
||||
{
|
||||
private $_calc;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_calc = new Doctrine_Internal_CommitOrderCalculator();
|
||||
}
|
||||
|
||||
private function _createNodes(array $names)
|
||||
{
|
||||
$nodes = array();
|
||||
foreach ($names as $name) {
|
||||
$node = new Doctrine_Internal_CommitOrderNode($name, $this->_calc);
|
||||
$nodes[$name] = $node;
|
||||
$this->_calc->addNode($node->getClass(), $node);
|
||||
}
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
public function testCommitOrdering1()
|
||||
{
|
||||
$nodes = $this->_createNodes(array("node1", "node2", "node3", "node4", "node5"));
|
||||
|
||||
$nodes['node1']->before($nodes['node2']);
|
||||
$nodes['node2']->before($nodes['node3']);
|
||||
$nodes['node3']->before($nodes['node4']);
|
||||
$nodes['node5']->before($nodes['node1']);
|
||||
|
||||
shuffle($nodes); // some randomness
|
||||
|
||||
$sorted = $this->_calc->getCommitOrder();
|
||||
|
||||
// There is only 1 valid ordering for this constellation
|
||||
$correctOrder = array("node5", "node1", "node2", "node3", "node4");
|
||||
$this->assertSame($correctOrder, $sorted);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||
private $_persisterMock;
|
||||
// The EntityManager mock that provides the mock persister
|
||||
private $_emMock;
|
||||
private $_platformMock;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -32,9 +33,17 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||
$this->_user->username = 'romanb';
|
||||
|
||||
$this->_connectionMock = new Doctrine_ConnectionMock(array());
|
||||
$this->_sequenceMock = $this->_connectionMock->getSequenceManager();
|
||||
$this->_platformMock = new Doctrine_DatabasePlatformMock();
|
||||
$this->_emMock = new Doctrine_EntityManagerMock($this->_connectionMock);
|
||||
$this->_persisterMock = $this->_emMock->getEntityPersister("ForumUser");
|
||||
$this->_sequenceMock = new Doctrine_SequenceMock($this->_connectionMock);
|
||||
|
||||
$this->_connectionMock->setSequenceManager($this->_sequenceMock);
|
||||
$this->_connectionMock->setDatabasePlatform($this->_platformMock);
|
||||
|
||||
$this->_persisterMock = new Doctrine_EntityPersisterMock(
|
||||
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
|
||||
$this->_emMock->setEntityPersister($this->_persisterMock);
|
||||
|
||||
$this->_unitOfWork = $this->_emMock->getUnitOfWork();
|
||||
}
|
||||
|
||||
|
@ -105,7 +114,7 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
|||
// should have an id
|
||||
$this->assertTrue(is_numeric($this->_user->id));
|
||||
|
||||
// Now lets check whether a subsequence commit() does anything
|
||||
// Now lets check whether a subsequent commit() does anything
|
||||
|
||||
$this->_persisterMock->reset();
|
||||
|
||||
|
|
|
@ -1,20 +1,46 @@
|
|||
<?php
|
||||
|
||||
require_once 'lib/mocks/Doctrine_SequenceMock.php';
|
||||
require_once 'lib/mocks/Doctrine_DatabasePlatformMock.php';
|
||||
|
||||
class Doctrine_ConnectionMock extends Doctrine_Connection
|
||||
{
|
||||
protected $_driverName = 'Mysql';
|
||||
protected $_driverName = 'Mock';
|
||||
private $_sequenceModuleMock;
|
||||
private $_platformMock;
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSequenceManager()
|
||||
{
|
||||
if ( ! $this->_sequenceModuleMock) {
|
||||
$this->_sequenceModuleMock = new Doctrine_SequenceMock($this);
|
||||
}
|
||||
return $this->_sequenceModuleMock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return $this->_platformMock;
|
||||
}
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function setDatabasePlatform($platform)
|
||||
{
|
||||
$this->_platformMock = $platform;
|
||||
}
|
||||
|
||||
public function setSequenceManager($seqManager)
|
||||
{
|
||||
$this->_sequenceModuleMock = $seqManager;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
9
tests/lib/mocks/Doctrine_DatabasePlatformMock.php
Normal file
9
tests/lib/mocks/Doctrine_DatabasePlatformMock.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Doctrine_DatabasePlatformMock extends Doctrine_DatabasePlatform
|
||||
{
|
||||
public function getNativeDeclaration($field) {}
|
||||
public function getPortableDeclaration(array $field) {}
|
||||
}
|
||||
|
||||
?>
|
|
@ -6,7 +6,6 @@ class Doctrine_EntityManagerMock extends Doctrine_EntityManager
|
|||
{
|
||||
private $_persisterMock;
|
||||
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
|
@ -15,11 +14,15 @@ class Doctrine_EntityManagerMock extends Doctrine_EntityManager
|
|||
*/
|
||||
public function getEntityPersister($entityName)
|
||||
{
|
||||
if ( ! $this->_persisterMock) {
|
||||
$this->_persisterMock = new Doctrine_EntityPersisterMock($this, $this->getClassMetadata($entityName));
|
||||
}
|
||||
return $this->_persisterMock;
|
||||
}
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function setEntityPersister($persister)
|
||||
{
|
||||
$this->_persisterMock = $persister;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -28,6 +28,8 @@ class Doctrine_SequenceMock extends Doctrine_Sequence
|
|||
return $this->_sequenceNumber;
|
||||
}
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_sequenceNumber = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue