From 846e68acc412fade69a7b81a5873c840b476bf80 Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Wed, 26 Mar 2014 20:49:33 -0400 Subject: [PATCH] Add interface for pdo drivers to enforce the same interface on the Firebird driver --- classes/{db_pdo.php => abstract_driver.php} | 4 +- classes/idriver.php | 132 +++++++++++++++++++ classes/query_builder.php | 138 +++++++++----------- drivers/firebird/firebird_driver.php | 129 ++++++++++++++---- drivers/mysql/mysql_driver.php | 8 +- drivers/pgsql/pgsql_driver.php | 6 +- drivers/sqlite/sqlite_driver.php | 13 +- drivers/sqlite/sqlite_sql.php | 18 +-- tests/databases/firebird/FirebirdQBTest.php | 6 +- 9 files changed, 326 insertions(+), 128 deletions(-) rename classes/{db_pdo.php => abstract_driver.php} (99%) create mode 100644 classes/idriver.php diff --git a/classes/db_pdo.php b/classes/abstract_driver.php similarity index 99% rename from classes/db_pdo.php rename to classes/abstract_driver.php index 74645d4..06f4bae 100644 --- a/classes/db_pdo.php +++ b/classes/abstract_driver.php @@ -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; diff --git a/classes/idriver.php b/classes/idriver.php new file mode 100644 index 0000000..98d6c68 --- /dev/null +++ b/classes/idriver.php @@ -0,0 +1,132 @@ +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)) diff --git a/drivers/firebird/firebird_driver.php b/drivers/firebird/firebird_driver.php index 23084c7..43489a4 100644 --- a/drivers/firebird/firebird_driver.php +++ b/drivers/firebird/firebird_driver.php @@ -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 diff --git a/drivers/mysql/mysql_driver.php b/drivers/mysql/mysql_driver.php index 01bf027..75c36d0 100644 --- a/drivers/mysql/mysql_driver.php +++ b/drivers/mysql/mysql_driver.php @@ -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); } diff --git a/drivers/pgsql/pgsql_driver.php b/drivers/pgsql/pgsql_driver.php index 075d376..92aaf0a 100644 --- a/drivers/pgsql/pgsql_driver.php +++ b/drivers/pgsql/pgsql_driver.php @@ -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); } diff --git a/drivers/sqlite/sqlite_driver.php b/drivers/sqlite/sqlite_driver.php index 4798b08..ace0f3a 100644 --- a/drivers/sqlite/sqlite_driver.php +++ b/drivers/sqlite/sqlite_driver.php @@ -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 diff --git a/drivers/sqlite/sqlite_sql.php b/drivers/sqlite/sqlite_sql.php index 2db729a..9721d14 100644 --- a/drivers/sqlite/sqlite_sql.php +++ b/drivers/sqlite/sqlite_sql.php @@ -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 * diff --git a/tests/databases/firebird/FirebirdQBTest.php b/tests/databases/firebird/FirebirdQBTest.php index 183c588..8efc6d3 100644 --- a/tests/databases/firebird/FirebirdQBTest.php +++ b/tests/databases/firebird/FirebirdQBTest.php @@ -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); }