diff --git a/README.md b/README.md index 675acdb..83d31af 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Create a connection array or object similar to this: The parameters required depend on the database. ### Running Queries -Query uses the same interface as CodeIgniter's [Active Record class](http://codeigniter.com/user_guide/database/active_record.html). However, it does not implement the `select_` methods, `count_all_results`, `distinct`, `having`, `or_having`, `insert_batch`, `update_batch`, or `count_all` methods. +Query uses the same interface as CodeIgniter's [Active Record class](http://codeigniter.com/user_guide/database/active_record.html). However, it does not implement the `count_all_results`, `distinct`, `having`, `or_having`, `insert_batch`, `update_batch`, or `count_all` methods. #### Retrieving Results diff --git a/classes/db_pdo.php b/classes/db_pdo.php index 9839852..90f8560 100644 --- a/classes/db_pdo.php +++ b/classes/db_pdo.php @@ -27,6 +27,11 @@ abstract class DB_PDO extends PDO { /** * PDO constructor wrapper + * + * @param string $dsn + * @param string $username + * @param string $password + * @param array $driver_options */ public function __construct($dsn, $username=NULL, $password=NULL, $driver_options=array()) { @@ -35,7 +40,9 @@ abstract class DB_PDO extends PDO { $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } - // ------------------------------------------------------------------------- + // -------------------------------------------------------------------------- + // ! Concrete functions that can be overridden in child classes + // -------------------------------------------------------------------------- /** * Simplifies prepared statements for database queries @@ -327,9 +334,8 @@ abstract class DB_PDO extends PDO { return $this->driver_query($this->sql->system_table_list()); } - // ------------------------------------------------------------------------- - // ! Abstract public functions to override in child classes + // ! Abstract public functions to implement in child classes // ------------------------------------------------------------------------- /** diff --git a/classes/db_sql.php b/classes/db_sql.php index b85f293..45b6a60 100644 --- a/classes/db_sql.php +++ b/classes/db_sql.php @@ -67,6 +67,18 @@ abstract class DB_SQL { return ' AVG'; } + // -------------------------------------------------------------------------- + + /** + * Get the 'sum' keyword + * + * @return string + */ + public function sum() + { + return ' SUM'; + } + // -------------------------------------------------------------------------- // ! Abstract Methods // -------------------------------------------------------------------------- diff --git a/classes/query_builder.php b/classes/query_builder.php index 98f07e9..cb92099 100644 --- a/classes/query_builder.php +++ b/classes/query_builder.php @@ -38,7 +38,7 @@ class Query_Builder { private $limit, $offset; - // Alias to $this->db->sql + // Alias to $this->sql private $sql; // Query component order mapping @@ -59,7 +59,7 @@ class Query_Builder { /** * Constructor * - * @param object $conn_name - the name of the connection/parameters + * @param object $params - the connection parametere */ public function __construct($params) { @@ -111,9 +111,6 @@ class Query_Builder { break; } - // Set the charset - //$dsn .= ";charset=utf-8"; - // Create the database connection if ( ! empty($params->user)) { @@ -180,6 +177,102 @@ class Query_Builder { return $this; } + + // -------------------------------------------------------------------------- + + /** + * Selects the maximum value of a field from a query + * + * @param string $field + * @param string $as + * @return $this + */ + public function select_max($field, $as=FALSE) + { + // Escape the identifiers + $field = $this->quote_ident($field); + + $as = ($as !== FALSE) + ? $this->quote_ident($as) + : $field; + + // Create the select string + $this->select_string = $this->sql->max()."({$field}) AS {$as} "; + + return $this; + } + + // -------------------------------------------------------------------------- + + /** + * Selects the minimum value of a field from a query + * + * @param string $field + * @param string $as + * @return $this + */ + public function select_min($field, $as=FALSE) + { + // Escape the identifiers + $field = $this->quote_ident($field); + + $as = ($as !== FALSE) + ? $this->quote_ident($as) + : $field; + + // Create the select string + $this->select_string = $this->sql->min()."({$field}) AS {$as} "; + + return $this; + } + + // -------------------------------------------------------------------------- + + /** + * Selects the average value of a field from a query + * + * @param string $field + * @param string $as + * @return $this + */ + public function select_avg($field, $as=FALSE) + { + // Escape the identifiers + $field = $this->quote_ident($field); + + $as = ($as !== FALSE) + ? $this->quote_ident($as) + : $field; + + // Create the select string + $this->select_string = $this->sql->avg()."({$field}) AS {$as} "; + + return $this; + } + + // -------------------------------------------------------------------------- + + /** + * Selects the sum of a field from a query + * + * @param string $field + * @param string $as + * @return $this + */ + public function select_sum($field, $as=FALSE) + { + // Escape the identifiers + $field = $this->quote_ident($field); + + $as = ($as !== FALSE) + ? $this->quote_ident($as) + : $field; + + // Create the select string + $this->select_string = $this->sql->sum()."({$field}) AS {$as} "; + + return $this; + } // -------------------------------------------------------------------------- @@ -218,7 +311,7 @@ class Query_Builder { */ public function like($field, $val, $pos='both') { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); // Add the like string into the order map $l = $field. ' LIKE ?'; @@ -260,7 +353,7 @@ class Query_Builder { */ public function or_like($field, $val, $pos='both') { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); // Add the like string into the order map $l = $field. ' LIKE ?'; @@ -302,7 +395,7 @@ class Query_Builder { */ public function not_like($field, $val, $pos='both') { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); // Add the like string into the order map $l = $field. ' NOT LIKE ?'; @@ -344,7 +437,7 @@ class Query_Builder { */ public function or_not_like($field, $val, $pos='both') { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); // Add the like string into the order map $l = $field. ' NOT LIKE ?'; @@ -430,7 +523,7 @@ class Query_Builder { // is an operator such as >, <, !=, etc. $f_array = explode(' ', trim($f)); - $item = $this->db->quote_ident($f_array[0]); + $item = $this->quote_ident($f_array[0]); // Simple key value, or an operator $item .= (count($f_array === 1)) ? '= ?' : " {$f_array[1]} ?"; @@ -469,11 +562,11 @@ class Query_Builder { // Simple key = val if (count($f_array) === 1) { - $item = $this->db->quote_ident($f_array[0]) . '= ?'; + $item = $this->quote_ident($f_array[0]) . '= ?'; } else // Other operators { - $item = $this->db->quote_ident($f_array[0]) . " {$f_array[1]} ?"; + $item = $this->quote_ident($f_array[0]) . " {$f_array[1]} ?"; } // Put in the query map for select statements @@ -498,7 +591,7 @@ class Query_Builder { */ public function where_in($field, $val=array()) { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); $params = array_fill(0, count($val), '?'); foreach($val as $v) @@ -528,7 +621,7 @@ class Query_Builder { */ public function or_where_in($field, $val=array()) { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); $params = array_fill(0, count($val), '?'); foreach($val as $v) @@ -558,7 +651,7 @@ class Query_Builder { */ public function where_not_in($field, $val=array()) { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); $params = array_fill(0, count($val), '?'); foreach($val as $v) @@ -588,7 +681,7 @@ class Query_Builder { */ public function or_where_not_in($field, $val=array()) { - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); $params = array_fill(0, count($val), '?'); foreach($val as $v) @@ -627,8 +720,8 @@ class Query_Builder { $cond_array = explode(' ', trim($condition)); $cond_array = array_map('trim', $cond_array); - $condition = $table . ' ON ' . $this->db->quote_ident($cond_array[0]) . $cond_array[1] . - ' ' . $this->db->quote_ident($cond_array[2]); + $condition = $table . ' ON ' . $this->quote_ident($cond_array[0]) . $cond_array[1] . + ' ' . $this->quote_ident($cond_array[2]); $this->query_map[] = array( 'type' => 'join', @@ -655,7 +748,7 @@ class Query_Builder { } else { - $this->group_array[] = $this->db->quote_ident($field); + $this->group_array[] = $this->quote_ident($field); } $this->group_string = ' GROUP BY ' . implode(', ', $this->group_array); @@ -681,7 +774,7 @@ class Query_Builder { } // Set fields for later manipulation - $field = $this->db->quote_ident($field); + $field = $this->quote_ident($field); $this->order_array[$field] = $type; $order_clauses = array(); @@ -825,12 +918,12 @@ class Query_Builder { // Do prepared statements for anything involving a "where" clause if ( ! empty($this->query_map)) { - $result = $this->db->prepare_execute($sql, $this->values); + $result = $this->prepare_execute($sql, $this->values); } else { // Otherwise, a simple query will do. - $result = $this->db->query($sql); + $result = $this->query($sql); } // Reset for next query @@ -878,7 +971,7 @@ class Query_Builder { $sql = $this->_compile("insert", $table); - $res = $this->db->prepare_execute($sql, $this->values); + $res = $this->prepare_execute($sql, $this->values); $this->_reset(); @@ -904,7 +997,7 @@ class Query_Builder { $sql = $this->_compile('update', $table); - $res = $this->db->prepare_execute($sql, $this->values); + $res = $this->prepare_execute($sql, $this->values); $this->_reset(); @@ -932,7 +1025,7 @@ class Query_Builder { // Create the SQL and parameters $sql = $this->_compile("delete", $table); - $res = $this->db->prepare_execute($sql, $this->values); + $res = $this->prepare_execute($sql, $this->values); $this->_reset(); @@ -1090,13 +1183,13 @@ class Query_Builder { case "insert": $param_count = count($this->set_array); $params = array_fill(0, $param_count, '?'); - $sql = 'INSERT INTO '. $this->db->quote_ident($table) . + $sql = 'INSERT INTO '. $this->quote_ident($table) . ' (' . implode(', ', $this->set_array_keys) . ') VALUES ('.implode(', ', $params).')'; break; case "update": - $sql = 'UPDATE '.$this->db->quote_ident($table). ' SET '. $this->set_string; + $sql = 'UPDATE '.$this->quote_ident($table). ' SET '. $this->set_string; // Set the where string if ( ! empty($this->query_map)) @@ -1109,7 +1202,7 @@ class Query_Builder { break; case "delete": - $sql = 'DELETE FROM '.$this->db->quote_ident($table); + $sql = 'DELETE FROM '.$this->quote_ident($table); // Set the where string if ( ! empty($this->query_map)) diff --git a/tests/databases/firebird/firebird-qb.php b/tests/databases/firebird/firebird-qb.php index ba26ee5..2c1f2f8 100644 --- a/tests/databases/firebird/firebird-qb.php +++ b/tests/databases/firebird/firebird-qb.php @@ -76,6 +76,46 @@ class FirebirdQBTest extends QBTest { $this->assertIsA($query, 'Firebird_Result'); } + function TestSelectMax() + { + if (empty($this->db)) return; + + $query = $this->db->select_max('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'Firebird_Result'); + } + + function TestSelectMin() + { + if (empty($this->db)) return; + + $query = $this->db->select_min('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'Firebird_Result'); + } + + function TestSelectAvg() + { + if (empty($this->db)) return; + + $query = $this->db->select_avg('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'Firebird_Result'); + } + + function TestSelectSum() + { + if (empty($this->db)) return; + + $query = $this->db->select_sum('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'Firebird_Result'); + } + function TestGetWhere() { if (empty($this->db)) return; diff --git a/tests/db_files/FB_TEST_DB.FDB b/tests/db_files/FB_TEST_DB.FDB index 9f4ec82..3674a55 100755 Binary files a/tests/db_files/FB_TEST_DB.FDB and b/tests/db_files/FB_TEST_DB.FDB differ diff --git a/tests/parent.php b/tests/parent.php index 2f644c7..d0e2f3c 100644 --- a/tests/parent.php +++ b/tests/parent.php @@ -107,6 +107,46 @@ abstract class QBTest extends UnitTestCase { $this->assertIsA($query, 'PDOStatement'); } + function TestSelectMax() + { + if (empty($this->db)) return; + + $query = $this->db->select_max('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'PDOStatement'); + } + + function TestSelectMin() + { + if (empty($this->db)) return; + + $query = $this->db->select_min('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'PDOStatement'); + } + + function TestSelectAvg() + { + if (empty($this->db)) return; + + $query = $this->db->select_avg('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'PDOStatement'); + } + + function TestSelectSum() + { + if (empty($this->db)) return; + + $query = $this->db->select_sum('id', 'di') + ->get('create_test'); + + $this->assertIsA($query, 'PDOStatement'); + } + function TestGetWhere() { if (empty($this->db)) return;