Skip to content

Commit

Permalink
Continuing connection refactoring.
Browse files Browse the repository at this point in the history
Changing the logic from adapter to wrapper for the actual PDO
connection.
  • Loading branch information
fzaninotto committed Nov 5, 2011
1 parent a35dab3 commit 44e911b
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 356 deletions.
5 changes: 3 additions & 2 deletions src/Propel/Runtime/Adapter/AbstractAdapter.php
Expand Up @@ -16,6 +16,7 @@
use Propel\Runtime\Util\PropelColumnTypes;
use Propel\Runtime\Util\PropelDateTime;
use Propel\Runtime\Query\Criteria;
use Propel\Runtime\Connection\PdoConnection;

use \PDO;
use \PDOStatement;
Expand Down Expand Up @@ -120,7 +121,7 @@ public function getConnection($conparams)
}
}

$con = new PDO($dsn, $user, $password, $driver_options);
$con = new PdoConnection($dsn, $user, $password, $driver_options);
$this->initConnection($con, isset($conparams['settings']) && is_array($conparams['settings']) ? $conparams['settings'] : array());

return $con;
Expand Down Expand Up @@ -308,7 +309,7 @@ public function isGetIdAfterInsert()

/**
* Gets the generated ID (either last ID for autoincrement or next sequence ID).
*
* @param PDO $con
* @param string $name
*
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Runtime/Connection/ConnectionInterface.php
Expand Up @@ -124,7 +124,7 @@ public function prepare($statement, $driver_options = array());
* successfully prepares, FALSE otherwise.
* @throws ConnectionException depending on error handling.
*/
public function query($statement);
public function query();

This comment has been minimized.

Copy link
@willdurand

willdurand Nov 5, 2011

It's an interface, you can (have to) avoid visibility keywords as all methods will be public and it's the default visibility in PHP.

This comment has been minimized.

Copy link
@fzaninotto

fzaninotto Nov 6, 2011

Author Owner

Fixed in 00249b8


/**
* Quotes a string for use in a query.
Expand Down
189 changes: 189 additions & 0 deletions src/Propel/Runtime/Connection/PdoConnection.php
@@ -0,0 +1,189 @@
<?php

/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/

namespace Propel\Runtime\Connection;

use Propel\Runtime\Connection\ConnectionInterface;
use Propel\Runtime\Exception\PropelException;

use \PDO;

/**
* Connection wrapping around a PDO connection that provides the basic fixes to PDO that are required by Propel.
*
*/
class PdoConnection extends PDO implements ConnectionInterface
{
protected $useDebug = false;

/**
* Attribute to use to set whether to cache prepared statements.
*/
const PROPEL_ATTR_CACHE_PREPARES = -1;

/**
* Cache of prepared statements (PDOStatement) keyed by md5 of SQL.
*
* @var array [md5(sql) => PDOStatement]
*/
protected $preparedStatements = array();

/**
* Whether to cache prepared statements.
*
* @var boolean
*/
protected $cachePreparedStatements = false;

/**
* The default value for runtime config item "debugpdo.logging.methods".
*
* @var array
*/
protected static $defaultLogMethods = array(
'exec',
'query',
'statement_execute',
);

/**
* Sets a connection attribute.
*
* This is overridden here to provide support for setting Propel-specific attributes too.
*
* @param integer $attribute The attribute to set (e.g. PropelPDO::PROPEL_ATTR_CACHE_PREPARES).
* @param mixed $value The attribute value.
*/
public function setAttribute($attribute, $value)
{
if (is_string($attribute) && strpos($attribute, '::') === false) {
$attribute = '\PDO::' . $attribute;
if (!defined($attribute)) {
throw new PropelException(sprintf('Invalid PDO option/attribute name specified: "%s"', $attribute));
}
$attribute = constant($attribute);
}
switch($attribute) {
case self::PROPEL_ATTR_CACHE_PREPARES:
$this->cachePreparedStatements = $value;
break;
default:
parent::setAttribute($attribute, $value);
}
}

/**
* Gets a connection attribute.
*
* This is overridden here to provide support for setting Propel-specific attributes too.
*
* @param integer $attribute The attribute to get (e.g. PropelPDO::PROPEL_ATTR_CACHE_PREPARES).
* @return mixed
*/
public function getAttribute($attribute)
{
switch($attribute) {
case self::PROPEL_ATTR_CACHE_PREPARES:
return $this->cachePreparedStatements;
break;
default:
return parent::getAttribute($attribute);
}
}

/**
* Proxy to PDO::prepare()
* Add query caching support if the PropelPDO::PROPEL_ATTR_CACHE_PREPARES was set to true.
*
* @param string $sql This must be a valid SQL statement for the target database server.
* @param array $driver_options One $array or more key => value pairs to set attribute values
* for the PDOStatement object that this method returns.
*
* @return PDOStatement
*/
public function prepare($sql, $driver_options = array())
{
if ($this->cachePreparedStatements) {
if (!isset($this->preparedStatements[$sql])) {
$return = parent::prepare($sql, $driver_options);
$this->preparedStatements[$sql] = $return;
} else {
$return = $this->preparedStatements[$sql];
}
} else {
$return = parent::prepare($sql, $driver_options);
}

return $return;
}

/**
* Clears any stored prepared statements for this connection.
*/
public function clearStatementCache()
{
$this->preparedStatements = array();
}

/**
* Configures the PDOStatement class for this connection.
*
* @param string $class
* @param boolean $suppressError Whether to suppress an exception if the statement class cannot be set.
*
* @throws PropelException if the statement class cannot be set (and $suppressError is false).
*/
protected function configureStatementClass($class = '\PDOStatement', $suppressError = true)
{
// extending PDOStatement is only supported with non-persistent connections
if (!$this->getAttribute(PDO::ATTR_PERSISTENT)) {
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($class, array($this)));
} elseif (!$suppressError) {
throw new PropelException('Extending PDOStatement is not supported with persistent connections.');
}
}

/**
* Returns the number of queries this DebugPDO instance has performed on the database connection.
*
* When using DebugPDOStatement as the statement class, any queries by DebugPDOStatement instances
* are counted as well.
*
* @throws PropelException if persistent connection is used (since unable to override PDOStatement in that case).
* @return integer
*/
public function getQueryCount()
{
// extending PDOStatement is not supported with persistent connections
if ($this->getAttribute(PDO::ATTR_PERSISTENT)) {
throw new PropelException('Extending PDOStatement is not supported with persistent connections. Count would be inaccurate, because we cannot count the PDOStatment::execute() calls. Either don\'t use persistent connections or don\'t call PropelPDO::getQueryCount()');
}

return parent::getQueryCount();
}


/**
* Enable or disable the query debug features
*
* @param boolean $value True to enable debug (default), false to disable it
*/
public function useDebug($value = true)
{
if ($value) {
$this->configureStatementClass('\Propel\Runtime\Connection\DebugPDOStatement', true);
} else {
// reset query logging
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('\PDOStatement'));
}
$this->clearStatementCache();
}

}

0 comments on commit 44e911b

Please sign in to comment.