Add interface for pdo drivers to enforce the same interface on the Firebird driver

This commit is contained in:
Timothy Warren 2014-03-26 20:49:33 -04:00
parent 56c061a7d1
commit 846e68acc4
9 changed files with 326 additions and 128 deletions

View File

@ -21,7 +21,7 @@
* @package Query
* @subpackage Query
*/
abstract class DB_PDO extends PDO {
abstract class Abstract_Driver extends PDO implements idriver {
// Reference to the last executed query
protected $statement;
@ -49,7 +49,7 @@ abstract class DB_PDO extends PDO {
* @param string $password
* @param array $driver_options
*/
public function __construct($dsn, $username=NULL, $password=NULL, $driver_options=array())
public function __construct($dsn, $username=NULL, $password=NULL, array $driver_options=array())
{
// Set PDO to display errors as exceptions
$driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;

132
classes/idriver.php Normal file
View File

@ -0,0 +1,132 @@
<?php
/**
* Query
*
* Free Query Builder / Database Abstraction Layer
*
* @package Query
* @author Timothy J. Warren
* @copyright Copyright (c) 2012 - 2014
* @link https://github.com/aviat4ion/Query
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
/**
* PDO Interface to implement for database drivers
*/
interface idriver {
/**
* Constructor/Connection method
*
* @param string $dsn
* @param [string] $username
* @param [string] $password
* @param [array] $driver_options
* @return void
*/
public function __construct($dsn, $username=NULL, $password=NULL, array $driver_options = array());
/**
* Begin a transaction
*
* @return bool
*/
public function beginTransaction();
/**
* Commit a transaction
*
* @return bool
*/
public function commit();
/**
* Return the current error code
*
* @return mixed
*/
public function errorCode();
/**
* Return information about the current error
*
* @return array
*/
public function errorInfo();
/**
* Execute an SQL statement and return the number of affected rows
*
* @param string $statement
* @return int
*/
public function exec($statement);
/**
* Get a connection attribute for the current db driver
*
* @param int $attribute
* @returm mixed
*/
public function getAttribute($attribute);
/**
* Check if currently in a transaction
*
* @return bool
*/
public function inTransaction();
/**
* Returns the id of the last row inserted into the database
*
* @param [string] $name
* @return string
*/
public function lastInsertId($name = NULL);
/**
* Prepare a statement for execution
*
* @param string $statement
* @param [array] $driver_options
* @return PDOStatement
*/
public function prepare($statement, $driver_options = array());
/**
* Executes an sql statement
*
* @param string $statement
* @return PDOStatement
*/
public function query();
/**
* Quotes a string for use in a query
*
* @param string $string
* @param [int] $parameter_type
* #return string
*/
public function quote($string, $parameter_type = PDO::PARAM_STRING);
/**
* Rollback a transaction
*
* @return bool
*/
public function rollback();
/**
* Set a connection attribute
* @param int $attribute
* @param mixed $value
* @return bool
*/
public function setAttribute($attribute, $value);
}
// End of idriver.php

View File

@ -27,7 +27,7 @@ class Query_Builder implements iQuery_Builder {
// --------------------------------------------------------------------------
// Compiled 'select' clause
protected $select_string;
protected $select_string = '';
// Compiled 'from' clause
protected $from_string;
@ -46,13 +46,13 @@ class Query_Builder implements iQuery_Builder {
// --------------------------------------------------------------------------
// Keys for insert/update statement
protected $set_array_keys;
protected $set_array_keys = array();
// Key/val pairs for order by clause
protected $order_array;
protected $order_array = array();
// Key/val pairs for group by clause
protected $group_array;
protected $group_array = array();
// --------------------------------------------------------------------------
// ! Other Class vars
@ -94,7 +94,7 @@ class Query_Builder implements iQuery_Builder {
public $queries;
// Whether to do only an explain on the query
protected $explain = FALSE;
protected $explain;
// Subclass instances
public $db;
@ -969,15 +969,7 @@ class Query_Builder implements iQuery_Builder {
$this->limit($limit, $offset);
}
// Do prepared statements for anything involving a "where" clause
if ( ! empty($this->query_map) || ! empty($this->having_map))
{
return $this->_run("get", $table);
}
else
{
return $this->_run("get", $table, TRUE);
}
return $this->_run("get", $table);
}
// --------------------------------------------------------------------------
@ -1032,16 +1024,8 @@ class Query_Builder implements iQuery_Builder {
$this->from($table);
}
// Do prepared statements for anything involving a "where" clause
if ( ! empty($this->query_map))
{
$result = $this->_run('get', $table);
}
else
{
// Otherwise, a simple query will do.
$result = $this->_run('get', $table, TRUE);
}
$result = $this->_run('get', $table);
$rows = $result->fetchAll();
@ -1084,7 +1068,7 @@ class Query_Builder implements iQuery_Builder {
if ( ! is_null($sql))
{
return $this->_run('', $table, FALSE, $sql, $data);
return $this->_run('', $table, $sql, $data);
}
return NULL;
@ -1228,23 +1212,37 @@ class Query_Builder implements iQuery_Builder {
*/
public function reset_query()
{
foreach($this as $name => $var)
$null_properties = array(
'select_string',
'from_string',
'set_string',
'order_string',
'group_string',
'limit',
'offset',
'explain'
);
$array_properties = array(
'set_array_keys',
'order_array',
'group_array',
'values',
'where_values',
'query_map',
'having_map'
);
// Reset strings and booleans
foreach($null_properties as $var)
{
$skip = array('db','sql','queries','table_prefix','parser','conn_name');
$this->$var = NULL;
}
// Skip properties that are needed for every query
if (in_array($name, $skip)) continue;
// Nothing query-generation related is safe!
$this->$name = NULL;
// Set empty arrays
$this->values = array();
$this->query_map = array();
// Set select string as an empty string, for proper handling
// of the 'distinct' keyword
$this->select_string = '';
// Reset arrays
foreach($array_properties as $var)
{
$this->$var = array();
}
}
@ -1255,12 +1253,11 @@ class Query_Builder implements iQuery_Builder {
*
* @param string $type
* @param string $table
* @param bool $simple
* @param string $sql
* @param mixed $vals
* @return mixed
*/
protected function _run($type, $table, $simple=FALSE, $sql=NULL, $vals=NULL)
protected function _run($type, $table, $sql=NULL, $vals=NULL)
{
if (is_null($sql))
{
@ -1276,7 +1273,7 @@ class Query_Builder implements iQuery_Builder {
$start_time = microtime(TRUE);
if ($simple)
if (empty($vals))
{
$res = $this->db->query($sql);
}
@ -1347,37 +1344,32 @@ class Query_Builder implements iQuery_Builder {
*/
protected function _compile_type($type='', $table='')
{
$table = $this->db->quote_table($table);
switch($type)
if ($type === 'insert')
{
default:
case "get":
$sql = "SELECT * \nFROM {$this->from_string}";
$param_count = count($this->set_array_keys);
$params = array_fill(0, $param_count, '?');
$sql = "INSERT INTO {$table} ("
. implode(',', $this->set_array_keys)
. ")\nVALUES (".implode(',', $params).')';
}
elseif ($type === 'update')
{
$sql = "UPDATE {$table}\nSET {$this->set_string}";
}
elseif ($type === 'delete')
{
$sql = "DELETE FROM {$table}";
}
else // GET queries
{
$sql = "SELECT * \nFROM {$this->from_string}";
// Set the select string
if ( ! empty($this->select_string))
{
// Replace the star with the selected fields
$sql = str_replace('*', $this->select_string, $sql);
}
break;
case "insert":
$param_count = count($this->set_array_keys);
$params = array_fill(0, $param_count, '?');
$sql = "INSERT INTO {$table} ("
. implode(',', $this->set_array_keys) .
")\nVALUES (".implode(',', $params).')';
break;
case "update":
$sql = "UPDATE {$table}\nSET {$this->set_string}";
break;
case "delete":
$sql = "DELETE FROM {$table}";
break;
// Set the select string
if ( ! empty($this->select_string))
{
// Replace the star with the selected fields
$sql = str_replace('*', $this->select_string, $sql);
}
}
return $sql;
@ -1395,7 +1387,7 @@ class Query_Builder implements iQuery_Builder {
protected function _compile($type='', $table='')
{
// Get the base clause for the query
$sql = $this->_compile_type($type, $table);
$sql = $this->_compile_type($type, $this->db->quote_table($table));
// Set the where clause
if ( ! empty($this->query_map))

View File

@ -21,7 +21,7 @@
* @package Query
* @subpackage Drivers
*/
class Firebird extends DB_PDO {
class Firebird extends Abstract_Driver {
/**
* Reference to the last query executed
@ -29,22 +29,22 @@ class Firebird extends DB_PDO {
* @var object
*/
protected $statement = NULL;
/**
* Reference to the resource returned by
* the last query executed
*
* @var resource
*/
protected $statement_link;
protected $statement_link = NULL;
/**
* Reference to the current transaction
*
* @var resource
*/
protected $trans;
protected $trans = NULL;
/**
* Reference to the connection resource
*
@ -60,29 +60,29 @@ class Firebird extends DB_PDO {
* @param string $pass
* @param array $options
*/
public function __construct($dbpath, $user='SYSDBA', $pass='masterkey', $options = array())
public function __construct($dbpath, $user='SYSDBA', $pass='masterkey', array $options = array())
{
if (isset($options[PDO::ATTR_PERSISTENT]) && $options[PDO::ATTR_PERSISTENT] == TRUE)
{
$this->conn = fbird_pconnect($dbpath, $user, $pass, 'utf-8', 0);
}
else
else
{
$this->conn = fbird_connect($dbpath, $user, $pass, 'utf-8', 0);
$this->conn = fbird_connect($dbpath, $user, $pass, 'utf-8', 0);
}
// Throw an exception to make this match other pdo classes
if ( ! is_resource($this->conn)) throw new PDOException(fbird_errmsg(), fbird_errcode(), NULL);
// Load these classes here because this
// driver does not call the constructor
// of DB_PDO, which defines these two
// of DB_PDO, which defines these two
// class variables for the other drivers
// Load the sql class
$class = __CLASS__."_sql";
$this->sql = new $class();
// Load the util class
$class = __CLASS__."_util";
$this->util = new $class($this);
@ -104,6 +104,63 @@ class Firebird extends DB_PDO {
// --------------------------------------------------------------------------
/**
* Execute an sql statement and return number of affected rows
*
* @param string $sql
* @return int
*/
public function exec($sql)
{
if (empty($sql)) throw new PDOException("Exec method requires an sql query!", 0, NULL);
$query = (isset($this->trans))
? fbird_query($this->trans, $sql)
: fbird_query($this->conn, $sql);
return fbird_affected_rows($query);
}
// --------------------------------------------------------------------------
/**
* Implement for compatibility with PDO
*
* @param int $attribute
* @return mixed
*/
public function getAttribute($attribute)
{
return NULL;
}
// --------------------------------------------------------------------------
/**
* Return whether the current statement is in a transaction
*
* @return bool
*/
public function inTransaction()
{
return ! is_null($this->trans);
}
// --------------------------------------------------------------------------
/**
* Returns the last value of the specified generator
*
* @param string $name
* @return mixed
*/
public function lastInsertId($name = NULL)
{
return fbird_gen_id($name, 0, $this->conn);
}
// --------------------------------------------------------------------------
/**
* Wrapper public function to better match PDO
*
@ -111,10 +168,11 @@ class Firebird extends DB_PDO {
* @return Firebird_Result
* @throws PDOException
*/
public function query($sql)
public function query($sql = '')
{
if (empty($sql)) throw new PDOException("Query method requires an sql query!", 0, NULL);
$this->statement_link = (isset($this->trans))
? fbird_query($this->trans, $sql)
: fbird_query($this->conn, $sql);
@ -122,7 +180,7 @@ class Firebird extends DB_PDO {
// Throw the error as a exception
$err_string = fbird_errmsg() . "Last query:" . $this->last_query;
if ($this->statement_link === FALSE) throw new PDOException($err_string, fbird_errcode(), NULL);
$this->statement = new FireBird_Result($this->statement_link);
return $this->statement;
@ -138,7 +196,7 @@ class Firebird extends DB_PDO {
* @return Firebird_Result
* @throws PDOException
*/
public function prepare($query, $options=NULL)
public function prepare($query, $options=array())
{
$this->statement_link = fbird_prepare($this->conn, $query);
@ -171,7 +229,9 @@ class Firebird extends DB_PDO {
*/
public function commit()
{
return fbird_commit($this->trans);
$res = fbird_commit($this->trans);
$this->trans = NULL;
return $res;
}
// --------------------------------------------------------------------------
@ -183,7 +243,22 @@ class Firebird extends DB_PDO {
*/
public function rollBack()
{
return fbird_rollback($this->trans);
$res = fbird_rollback($this->trans);
$this->trans = NULL;
return $res;
}
// --------------------------------------------------------------------------
/**
* Set a connection attribute
* @param int $attribute
* @param mixed $value
* @return bool
*/
public function setAttribute($attribute, $value)
{
return FALSE;
}
// --------------------------------------------------------------------------
@ -200,7 +275,7 @@ class Firebird extends DB_PDO {
$query = $this->prepare($sql);
// Set the statement in the class variable for easy later access
$this->statement_link =& $query;
$this->statement_link =& $query;
return $query->execute($args);
}
@ -214,7 +289,7 @@ class Firebird extends DB_PDO {
* @param int $param_type
* @return string
*/
public function quote($str, $param_type = NULL)
public function quote($str, $param_type = PDO::PARAM_STR)
{
if(is_numeric($str))
{
@ -238,11 +313,11 @@ class Firebird extends DB_PDO {
return array(0, $code, $msg);
}
// --------------------------------------------------------------------------
/**
* Method to emulate PDO->errorCode
* Method to emulate PDO->errorCode
*
* @return array
*/
@ -266,10 +341,10 @@ class Firebird extends DB_PDO {
// the firebird database
return NULL;
}
// --------------------------------------------------------------------------
/**
/**
* Create sql for batch insert
*
* @param string $table

View File

@ -19,7 +19,7 @@
* @package Query
* @subpackage Drivers
*/
class MySQL extends DB_PDO {
class MySQL extends Abstract_Driver {
/**
* Set the backtick as the MySQL escape character
@ -36,7 +36,7 @@ class MySQL extends DB_PDO {
* @param string $password
* @param array $options
*/
public function __construct($dsn, $username=null, $password=null, $options=array())
public function __construct($dsn, $username=null, $password=null, array $options=array())
{
// Set the charset to UTF-8
if (defined('PDO::MYSQL_ATTR_INIT_COMMAND'))
@ -45,9 +45,9 @@ class MySQL extends DB_PDO {
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF-8 COLLATE 'UTF-8'",
));
}
if (strpos($dsn, 'mysql') === FALSE) $dsn = 'mysql:'.$dsn;
parent::__construct($dsn, $username, $password, $options);
}

View File

@ -19,7 +19,7 @@
* @package Query
* @subpackage Drivers
*/
class PgSQL extends DB_PDO {
class PgSQL extends Abstract_Driver {
/**
* Connect to a PosgreSQL database
@ -29,10 +29,10 @@ class PgSQL extends DB_PDO {
* @param string $password
* @param array $options
*/
public function __construct($dsn, $username=null, $password=null, $options=array())
public function __construct($dsn, $username=null, $password=null, array $options=array())
{
if (strpos($dsn, 'pgsql') === FALSE) $dsn = 'pgsql:'.$dsn;
parent::__construct($dsn, $username, $password, $options);
}

View File

@ -19,7 +19,7 @@
* @package Query
* @subpackage Drivers
*/
class SQLite extends DB_PDO {
class SQLite extends Abstract_Driver {
/**
* Reference to the last executed sql query
@ -34,9 +34,10 @@ class SQLite extends DB_PDO {
* @param string $dsn
* @param string $user
* @param string $pass
* @param array $driver_options
*/
public function __construct($dsn, $user=NULL, $pass=NULL)
{
public function __construct($dsn, $user=NULL, $pass=NULL, array $driver_options=array())
{
// DSN is simply `sqlite:/path/to/db`
parent::__construct("sqlite:{$dsn}", $user, $pass);
}
@ -87,10 +88,10 @@ class SQLite extends DB_PDO {
// that is of any importance.
return array('sqlite_master');
}
// --------------------------------------------------------------------------
/**
/**
* Create sql for batch insert
*
* @param string $table

View File

@ -33,14 +33,14 @@ class SQLite_SQL implements iDB_SQL {
{
if ( ! is_numeric($offset))
{
return $sql." LIMIT {$limit}";
return $sql."\nLIMIT {$limit}";
}
return $sql." LIMIT {$offset}, {$limit}";
return $sql."\nLIMIT {$limit} OFFSET {$offset}";
}
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
@ -63,7 +63,7 @@ class SQLite_SQL implements iDB_SQL {
{
return ' RANDOM()';
}
// --------------------------------------------------------------------------
/**
@ -166,9 +166,9 @@ SQL;
{
return NULL;
}
// --------------------------------------------------------------------------
/**
* SQL to show list of field types
*
@ -178,9 +178,9 @@ SQL;
{
return array('INTEGER', 'REAL', 'TEXT', 'BLOB');
}
// --------------------------------------------------------------------------
/**
* SQL to show infromation about columns in a table
*

View File

@ -33,12 +33,10 @@ class FirebirdQBTest extends QBTest {
$params->alias = 'fire';
$params->type = 'firebird';
$params->file = $dbpath;
$params->host = 'localhost';
$params->user = 'sysdba';
$params->host = '127.0.0.1';
$params->user = 'SYSDBA';
$params->pass = 'masterkey';
$params->prefix = 'create_';
$params->options = array();
$params->options[PDO::ATTR_PERSISTENT] = TRUE;
$this->db = Query($params);
}