diff --git a/common.php b/common.php index f7898ed..b0fb0b5 100644 --- a/common.php +++ b/common.php @@ -74,6 +74,25 @@ function db_filter($array, $index) // -------------------------------------------------------------------------- +/** + * Create a snake_case string from camelCase + * + * @see http://stackoverflow.com/questions/1993721/how-to-convert-camelcase-to-camel-case + * + * @param string $input + * @return string + */ +function from_camel_case($input) { + preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches); + $ret = $matches[0]; + foreach ($ret as &$match) { + $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match); + } + return implode('_', $ret); +} + +// -------------------------------------------------------------------------- + /** * Zip a set of arrays together on common keys * diff --git a/core/abstract/abstract_driver.php b/core/abstract/abstract_driver.php index 6df590b..e4e6abf 100644 --- a/core/abstract/abstract_driver.php +++ b/core/abstract/abstract_driver.php @@ -254,25 +254,6 @@ abstract class Abstract_Driver extends \PDO implements Driver_Interface { // -------------------------------------------------------------------------- - /** - * Sets the table prefix on the passed string - * - * @param string $str - * @return string - */ - protected function _prefix($str) - { - // Don't prefix an already prefixed table - if (strpos($str, $this->table_prefix) !== FALSE) - { - return $str; - } - - return $this->table_prefix.$str; - } - - // -------------------------------------------------------------------------- - /** * Surrounds the string with the databases identifier escape characters * @@ -318,30 +299,6 @@ abstract class Abstract_Driver extends \PDO implements Driver_Interface { } - // -------------------------------------------------------------------------- - - /** - * Helper method for quote_ident - * - * @param mixed $str - * @return mixed - */ - public function _quote($str) - { - // Check that the current value is a string, - // and is not already quoted before quoting - // that value, otherwise, return the original value - return ( - strpos($str, $this->escape_char) !== 0 - && strrpos($str, $this->escape_char) !== 0 - && is_string($str) - && ! is_numeric($str) - ) - ? "{$this->escape_char}{$str}{$this->escape_char}" - : $str; - - } - // ------------------------------------------------------------------------- /** @@ -405,7 +362,7 @@ abstract class Abstract_Driver extends \PDO implements Driver_Interface { // ------------------------------------------------------------------------- /** - * Return list of function for the current database + * Return list of functions for the current database * * @return array */ @@ -554,18 +511,6 @@ abstract class Abstract_Driver extends \PDO implements Driver_Interface { return NULL; } - // ------------------------------------------------------------------------- - // ! Abstract public functions to implement in child classes - // ------------------------------------------------------------------------- - - /** - * Empty the passed table - * - * @param string $table - * @return void - */ - abstract public function truncate($table); - // -------------------------------------------------------------------------- /** @@ -603,5 +548,61 @@ abstract class Abstract_Driver extends \PDO implements Driver_Interface { return array($sql, $vals); } + + // -------------------------------------------------------------------------- + + /** + * Helper method for quote_ident + * + * @param mixed $str + * @return mixed + */ + public function _quote($str) + { + // Check that the current value is a string, + // and is not already quoted before quoting + // that value, otherwise, return the original value + return ( + strpos($str, $this->escape_char) !== 0 + && strrpos($str, $this->escape_char) !== 0 + && is_string($str) + && ! is_numeric($str) + ) + ? "{$this->escape_char}{$str}{$this->escape_char}" + : $str; + + } + + // -------------------------------------------------------------------------- + + /** + * Sets the table prefix on the passed string + * + * @param string $str + * @return string + */ + protected function _prefix($str) + { + // Don't prefix an already prefixed table + if (strpos($str, $this->table_prefix) !== FALSE) + { + return $str; + } + + return $this->table_prefix.$str; + } + + // ------------------------------------------------------------------------- + // ! Abstract public functions to implement in child classes + // ------------------------------------------------------------------------- + + /** + * Empty the passed table + * + * @param string $table + * @return void + */ + abstract public function truncate($table); + } // End of db_pdo.php \ No newline at end of file diff --git a/core/connection_manager.php b/core/connection_manager.php index bb4dcef..587be38 100644 --- a/core/connection_manager.php +++ b/core/connection_manager.php @@ -84,7 +84,6 @@ final class Connection_Manager { */ public static function get_instance() { - // @codeCoverageIgnoreStart if (self::$instance === null) { @@ -115,11 +114,9 @@ final class Connection_Manager { { return end($this->connections); } - else - { - // You should actually connect before trying to get a connection... - throw new \InvalidArgumentException("The specified connection does not exist"); - } + + // You should actually connect before trying to get a connection... + throw new \InvalidArgumentException("The specified connection does not exist"); } // -------------------------------------------------------------------------- diff --git a/core/interfaces/driver_interface.php b/core/interfaces/driver_interface.php index 98835af..426fb94 100644 --- a/core/interfaces/driver_interface.php +++ b/core/interfaces/driver_interface.php @@ -33,6 +33,16 @@ interface Driver_Interface { */ public function __construct($dsn, $username=NULL, $password=NULL, array $driver_options = array()); + /** + * Simplifies prepared statements for database queries + * + * @param string $sql + * @param array $data + * @return \PDOStatement | FALSE + * @throws \InvalidArgumentException + */ + public function prepare_query($sql, $data); + /** * Begin a transaction * @@ -100,6 +110,21 @@ interface Driver_Interface { */ public function get_columns($table); + /** + * Retrieve list of data types for the database + * + * @return array + */ + public function get_types(); + + /** + * Retrieve indexes for the table + * + * @param string $table + * @return array + */ + public function get_indexes($table); + /** * Retrieve foreign keys for the table * @@ -115,6 +140,14 @@ interface Driver_Interface { */ public function get_tables(); + /** + * Retrieves an array of non-user-created tables for + * the connection/database + * + * @return array + */ + public function get_system_tables(); + /** * Return list of dbs for the current connection, if possible * @@ -122,6 +155,41 @@ interface Driver_Interface { */ public function get_dbs(); + /** + * Return list of views for the current database + * + * @return array + */ + public function get_views(); + + /** + * Return list of sequences for the current database, if they exist + * + * @return array + */ + public function get_sequences(); + + /** + * Return list of functions for the current database + * + * @return array + */ + public function get_functions(); + + /** + * Return list of stored procedures for the current database + * + * @return array + */ + public function get_procedures(); + + /** + * Return list of triggers for the current database + * + * @return array + */ + public function get_triggers(); + /** * Surrounds the string with the databases identifier escape characters * @@ -169,5 +237,37 @@ interface Driver_Interface { * @return array */ public function driver_query($query, $filtered_index=TRUE); + + /** + * Returns number of rows affected by an INSERT, UPDATE, DELETE type query + * + * @return int + */ + public function affected_rows(); + + /** + * Return the number of rows returned for a SELECT query + * @see http://us3.php.net/manual/en/pdostatement.rowcount.php#87110 + * + * @return int + */ + public function num_rows(); + + /** + * Prefixes a table if it is not already prefixed + * + * @param string $table + * @return string + */ + public function prefix_table($table); + + /** + * Create sql for batch insert + * + * @param string $table + * @param array $data + * @return array + */ + public function insert_batch($table, $data=array()); } // End of driver_interface.php diff --git a/core/query_builder.php b/core/query_builder.php index 1e2fba8..bb99016 100644 --- a/core/query_builder.php +++ b/core/query_builder.php @@ -1315,14 +1315,26 @@ class Query_Builder implements Query_Builder_Interface { */ public function __call($name, $params) { - if (method_exists($this->db, $name)) + // Allow camel-case method calls + $snake_name = \from_camel_case($name); + + foreach(array($this, $this->db) as $object) { - return call_user_func_array(array($this->db, $name), $params); + foreach(array($name, $snake_name) as $method_name) + { + if (method_exists($object, $method_name)) + { + return call_user_func_array(array($object, $method_name), $params); + } + } + } throw new \BadMethodCallException("Method does not exist"); } + // -------------------------------------------------------------------------- + /** * Convert the prepared statement into readable sql * diff --git a/drivers/firebird/firebird_driver.php b/drivers/firebird/firebird_driver.php index c241c6e..3a0ea70 100644 --- a/drivers/firebird/firebird_driver.php +++ b/drivers/firebird/firebird_driver.php @@ -134,12 +134,14 @@ class Firebird extends Abstract_Driver { * Empty a database table * * @param string $table + * @return \PDOStatement */ public function truncate($table) { // Firebird lacks a truncate command $sql = 'DELETE FROM '.$this->quote_table($table); $this->statement = $this->query($sql); + return $this->statement; } // -------------------------------------------------------------------------- diff --git a/tests/core/db_qb_test.php b/tests/core/db_qb_test.php index 465c1ff..e83b5a2 100644 --- a/tests/core/db_qb_test.php +++ b/tests/core/db_qb_test.php @@ -267,6 +267,25 @@ abstract class QBTest extends Query_TestCase { $this->assertIsA($query, 'PDOStatement'); } + // -------------------------------------------------------------------------- + + public function testGroupCamelCase() + { + $query = $this->db->select('id, key as k, val') + ->from('test') + ->groupStart() + ->where('id >', 1) + ->where('id <', 900) + ->groupEnd() + ->orNotGroupStart() + ->where('id =', 0) + ->groupEnd() + ->limit(2, 1) + ->get(); + + $this->assertIsA($query, 'PDOStatement'); + } + // -------------------------------------------------------------------------- // ! Where In tests // --------------------------------------------------------------------------