diff options
Diffstat (limited to 'modules/database/classes/driver/pdo')
-rw-r--r-- | modules/database/classes/driver/pdo/db.php | 137 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/query.php | 448 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/result.php | 45 |
3 files changed, 362 insertions, 268 deletions
diff --git a/modules/database/classes/driver/pdo/db.php b/modules/database/classes/driver/pdo/db.php index 69a7457..5b81d66 100644 --- a/modules/database/classes/driver/pdo/db.php +++ b/modules/database/classes/driver/pdo/db.php @@ -4,23 +4,24 @@ * PDO Database implementation. * @package Database */ -class DB_PDO_Driver extends DB{ +class DB_PDO_Driver extends DB +{ /** * Connection object * @var PDO * @access public - * @link http://php.net/manual/en/class.pdo.php + * @link http://php.net/manual/en/class.pdo.php */ - public $conn; - - /** + public $conn; + + /** * Type of the database, e.g. mysql, pgsql etc. * @var string * @access public */ - public $db_type; - + public $db_type; + /** * Initializes database connection * @@ -28,17 +29,18 @@ class DB_PDO_Driver extends DB{ * @return void * @access public */ - public function __construct($config) { - $this->conn = new PDO( - Config::get("database.{$config}.connection"), - Config::get("database.{$config}.user",''), - Config::get("database.{$config}.password",'') - ); - $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->db_type = strtolower(str_replace('PDO_', '', $this->conn->getAttribute(PDO::ATTR_DRIVER_NAME))); - if($this->db_type!='sqlite') - $this->conn->exec("SET NAMES utf8"); - } + public function __construct($config) + { + $this->conn = new PDO( + Config::get("database.{$config}.connection"), Config::get("database.{$config}.user", ''), Config::get("database.{$config}.password", '') + ); + $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->db_type = strtolower(str_replace('PDO_', '', $this->conn->getAttribute(PDO::ATTR_DRIVER_NAME))); + if ($this->db_type != 'sqlite') + { + $this->conn->exec("SET NAMES utf8"); + } + } /** * Builds a new Query implementation @@ -46,11 +48,12 @@ class DB_PDO_Driver extends DB{ * @param string $type Query type. Available types: select,update,insert,delete,count * @return Query_PDO_Driver Returns a PDO implementation of a Query. * @access public - * @see Query_Database + * @see Query_Database */ - public function build_query($type) { - return new Query_PDO_Driver($this,$type); - } + public function build_query($type) + { + return new Query_PDO_Driver($this, $type); + } /** * Gets the id of the last inserted row. @@ -58,39 +61,52 @@ class DB_PDO_Driver extends DB{ * @return mixed Row id * @access public */ - public function get_insert_id() { - if ($this->db_type == 'pgsql') - return $this->execute('SELECT lastval() as id')->current()->id; - return $this->conn->lastInsertId(); - } - - /** + public function get_insert_id() + { + if ($this->db_type == 'pgsql') + { + return $this->execute('SELECT lastval() as id')->current()->id; + } + return $this->conn->lastInsertId(); + } + + /** * Gets column names for the specified table * - * @param string $table Name of the table to get columns from + * @param string $table Name of the table to get columns from * @return array Array of column names * @access public */ - public function list_columns($table) { - $columns=array(); - if ($this->db_type == 'mysql') { - $table_desc = $this->execute("DESCRIBE `$table`"); - foreach($table_desc as $column) - $columns[]=$column->Field; - } - if ($this->db_type == 'pgsql') { - $table_desc = $this->execute("select column_name from information_schema.columns where table_name = '{$table}' and table_catalog=current_database();"); - foreach($table_desc as $column) - $columns[]=$column->column_name; - } - if ($this->db_type == 'sqlite') { - $table_desc = $this->execute("PRAGMA table_info('$table')"); - foreach($table_desc as $column) - $columns[]=$column->name; - } - return $columns; - } - + public function list_columns($table) + { + $columns = array(); + if ($this->db_type == 'mysql') + { + $table_desc = $this->execute("DESCRIBE `$table`"); + foreach ($table_desc as $column) + { + $columns[] = $column->Field; + } + } + if ($this->db_type == 'pgsql') + { + $table_desc = $this->execute("select column_name from information_schema.columns where table_name = '{$table}' and table_catalog=current_database();"); + foreach ($table_desc as $column) + { + $columns[] = $column->column_name; + } + } + if ($this->db_type == 'sqlite') + { + $table_desc = $this->execute("PRAGMA table_info('$table')"); + foreach ($table_desc as $column) + { + $columns[] = $column->name; + } + } + return $columns; + } + /** * Executes a prepared statement query * @@ -99,14 +115,17 @@ class DB_PDO_Driver extends DB{ * @return Result_PDO_Driver PDO implementation of a database result * @access public * @throws Exception If the query resulted in an error - * @see Database_Result + * @see Database_Result */ - public function execute($query, $params = array()) { - $cursor = $this->conn->prepare($query); - if (!$cursor->execute($params)) { - $error = $cursor->errorInfo(); - throw new Exception("Database error:\n".$error[2]." \n in query:\n{$query}"); - } - return new Result_PDO_Driver($cursor); - } + public function execute($query, $params = array()) + { + $cursor = $this->conn->prepare($query); + if (!$cursor->execute($params)) + { + $error = $cursor->errorInfo(); + throw new Exception("Database error:\n".$error[2]." \n in query:\n{$query}"); + } + return new Result_PDO_Driver($cursor); + } + }
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/query.php b/modules/database/classes/driver/pdo/query.php index f23e28b..d37e459 100644 --- a/modules/database/classes/driver/pdo/query.php +++ b/modules/database/classes/driver/pdo/query.php @@ -4,22 +4,23 @@ * PDO implementation of the database Query * @package Database */ -class Query_PDO_Driver extends Query_Database { - - /** +class Query_PDO_Driver extends Query_Database +{ + + /** * Type of the database, e.g. mysql, pgsql etc. * @var string * @access public */ - protected $_db_type; - - /** + protected $_db_type; + + /** * Character to use for quoting fields * @var string * @access public */ - protected $_quote; - + protected $_quote; + /** * Creates a new query object, checks which driver we are using and set the character used for quoting * @@ -27,188 +28,247 @@ class Query_PDO_Driver extends Query_Database { * @param string $type Query type. Available types: select, update, insert, delete, count * @return void * @access public - * @see Query_Database::__construct() + * @see Query_Database::__construct() */ - public function __construct($db, $type) { - parent::__construct($db, $type); - $this->_db_type = $this->_db->db_type; - $this->_quote=$this->_db_type=='mysql'?'`':'"'; - } - + public function __construct($db, $type) + { + parent::__construct($db, $type); + $this->_db_type = $this->_db->db_type; + $this->_quote = $this->_db_type == 'mysql' ? '`' : '"'; + } + /** * Puts quotes around a string * * @param string $str String to be enclosed in quotes * @return string String surrounded with quotes * @access protected - */ - protected function quote($str) { - return $this->_quote.$str.$this->_quote; - } - + */ + protected function quote($str) + { + return $this->_quote.$str.$this->_quote; + } + /** * If a string is passed escapes a field by enclosing it in specified quotes. - * If you pass an Expression_Database object the value will be inserted into the query unescaped + * If you pass an Expression_Database object the value will be inserted into the query unescaped * * @param mixed $field Field to be escaped or an Expression_Database object - * if the field must not be escaped + * if the field must not be escaped * @return string Escaped field representation * @access public - * @see Expression_Database + * @see Expression_Database */ - public function escape_field($field) { - if (is_object($field) && get_class($field) == 'Expression_Database') - return $field->value; - $field = explode('.', $field); - if (count($field) == 1) - array_unshift($field,$this->last_alias()); - $str = $this->quote($field[0]).'.'; - if (trim($field[1]) == '*') - return $str.'*'; - return $str.$this->quote($field[1]); - } - + public function escape_field($field) + { + if (is_object($field) && get_class($field) == 'Expression_Database') + { + return $field->value; + } + $field = explode('.', $field); + if (count($field) == 1) + { + array_unshift($field, $this->last_alias()); + } + $str = $this->quote($field[0]).'.'; + if (trim($field[1]) == '*') + { + return $str.'*'; + } + return $str.$this->quote($field[1]); + } + /** * Replaces the value with ? and appends it to the parameters array - * If you pass an Expression_Database object the value will be inserted into the query unescaped + * If you pass an Expression_Database object the value will be inserted into the query unescaped * @param mixed $val Value to be escaped or an Expression_Database object - * if the value must not be escaped + * if the value must not be escaped * @param array &$params Reference to parameters array * @return string Escaped value representation * @access public */ - public function escape_value($val,&$params) { - if (is_object($val) && get_class($val) == 'Expression_Database') - return $val->value; - $params[] = $val; - return '?'; - } - + public function escape_value($val, &$params) + { + if (is_object($val) && get_class($val) == 'Expression_Database') + { + return $val->value; + } + $params[] = $val; + return '?'; + } + /** * Builds a query and fills the $params array with parameter values * * @return array An array with a prepared query string and an array of parameters * @access public */ - public function query() { - - $query = ''; - $params = array(); - if ($this->_type == 'insert') { - $query.= "INSERT INTO {$this->quote($this->_table)} "; - if (empty($this->_data) && $this->_db_type == 'pgsql'){ - $query.= "DEFAULT VALUES "; - }else{ - $columns = ''; - $values = ''; - $first = true; - foreach($this->_data as $key => $val) { - if (!$first) { - $values.= ', '; - $columns.= ', '; - }else { - $first=false; - } - $columns.= $this->quote($key); - $values.=$this->escape_value($val,$params); - } - $query.= "({$columns}) VALUES({$values})"; - } - }else{ - if ($this->_type == 'select'){ - $query.= "SELECT "; - if($this->_fields==null){ - $query.= "* "; - }else{ - $first = true; - foreach($this->_fields as $f) { - if (!$first) { - $query.=", "; - }else { - $first = false; - } - if(is_array($f)){ - $query.= "{$this->escape_field($f[0])} AS {$f[1]} "; - }else { - $query.= "{$this->escape_field($f)} "; - } - } - } - $query.= "FROM {$this->quote($this->_table)} "; - } - if ($this->_type == 'count') { - $query.= "SELECT COUNT(*) as {$this->quote('count')} FROM {$this->quote($this->_table)} "; - } - if ($this->_type == 'delete') { - if($this->_db_type!='sqlite'){ - $query.= "DELETE {$this->last_alias()}.* FROM {$this->quote($this->_table)} "; - }else { - if (!empty($this->_joins)) - throw new Exception("SQLite doesn't support deleting a table with JOIN in the query"); - $query.= "DELETE FROM {$this->quote($this->_table)} "; - } - } - if($this->_type=='update'){ - $query.= "UPDATE {$this->quote($this->_table)} SET "; - $first = true; - foreach($this->_data as $key=>$val){ - if (!$first) { - $query.=", "; - }else { - $first=false; - } - $query.= "{$this->quote($key)} = {$this->escape_value($val,$params)}"; - } - $query.= " "; - } - - foreach($this->_joins as $join) { - $table = $join[0]; - if (is_array($table)){ - $table = "{$this->quote($table[0])} as {$this->quote($table[1])}"; - }else { - $table="{$this->quote($table)}"; - } - $query.= strtoupper($join[1])." JOIN {$table} ON {$this->get_condition_query($join[2],$params,true,true)} "; - } + public function query() + { + + $query = ''; + $params = array(); + if ($this->_type == 'insert') + { + $query.= "INSERT INTO {$this->quote($this->_table)} "; + if (empty($this->_data) && $this->_db_type == 'pgsql') + { + $query.= "DEFAULT VALUES "; + } + else + { + $columns = ''; + $values = ''; + $first = true; + foreach ($this->_data as $key => $val) + { + if (!$first) + { + $values .= ', '; + $columns .= ', '; + } + else + { + $first = false; + } + $columns .= $this->quote($key); + $values .= $this->escape_value($val, $params); + } + $query .= "({$columns}) VALUES({$values})"; + } + } + else + { + if ($this->_type == 'select') + { + $query .= "SELECT "; + if ($this->_fields == null) + { + $query .= "* "; + } + else + { + $first = true; + foreach ($this->_fields as $f) + { + if (!$first) + { + $query .= ", "; + } + else + { + $first = false; + } + if (is_array($f)) + { + $query .= "{$this->escape_field($f[0])} AS {$f[1]} "; + } + else + { + $query .= "{$this->escape_field($f)} "; + } + } + } + $query .= "FROM {$this->quote($this->_table)} "; + } + if ($this->_type == 'count') + { + $query .= "SELECT COUNT(*) as {$this->quote('count')} FROM {$this->quote($this->_table)} "; + } + if ($this->_type == 'delete') + { + if ($this->_db_type != 'sqlite') + { + $query .= "DELETE {$this->last_alias()}.* FROM {$this->quote($this->_table)} "; + } + else + { + if (!empty($this->_joins)) + { + throw new Exception("SQLite doesn't support deleting a table with JOIN in the query"); + } + $query .= "DELETE FROM {$this->quote($this->_table)} "; + } + } + if ($this->_type == 'update') + { + $query .= "UPDATE {$this->quote($this->_table)} SET "; + $first = true; + foreach ($this->_data as $key => $val) + { + if (!$first) + { + $query .= ", "; + } + else + { + $first = false; + } + $query .= "{$this->quote($key)} = {$this->escape_value($val, $params)}"; + } + $query .= " "; + } + + foreach ($this->_joins as $join) + { + $table = $join[0]; + if (is_array($table)) + { + $table = "{$this->quote($table[0])} as {$this->quote($table[1])}"; + } + else + { + $table = "{$this->quote($table)}"; + } + $query .= strtoupper($join[1])." JOIN {$table} ON {$this->get_condition_query($join[2], $params, true, true)} "; + } - if (!empty($this->_conditions)) { - $query.="WHERE {$this->get_condition_query($this->_conditions,$params,true)} "; - } - if (($this->_type == 'select' || $this->_type == 'count') && $this->_group_by!=null) { - $query.="GROUP BY {$this->escape_field($this->_group_by)} "; - } - if (($this->_type == 'select' || $this->_type == 'count') && !empty($this->_having)) { - $query.="HAVING {$this->get_condition_query($this->_having,$params,true)} "; - } - - if ($this->_type == 'select' && !empty($this->_orderby)) { - $query.="ORDER BY "; - $first = true; - foreach($this->_orderby as $order) { - if (!$first) { - $query.=','; - }else { - $first=false; - } - $query.= $this->escape_field($order[0])." "; - if (isset($order[1])) { - $dir = strtoupper($order[1]); - $query.=$dir." "; - } - } - } - if($this->_type != 'count'){ - if ($this->_limit != null) - $query.= "LIMIT {$this->_limit} "; - if ($this->_offset != null) - $query.= "OFFSET {$this->_offset} "; - } - - } - - return array($query,$params); - } + if (!empty($this->_conditions)) + { + $query .= "WHERE {$this->get_condition_query($this->_conditions, $params, true)} "; + } + if (($this->_type == 'select' || $this->_type == 'count') && $this->_group_by != null) + { + $query .= "GROUP BY {$this->escape_field($this->_group_by)} "; + } + if (($this->_type == 'select' || $this->_type == 'count') && !empty($this->_having)) + { + $query .= "HAVING {$this->get_condition_query($this->_having, $params, true)} "; + } + + if ($this->_type == 'select' && !empty($this->_orderby)) + { + $query .= "ORDER BY "; + $first = true; + foreach ($this->_orderby as $order) + { + if (!$first) + { + $query .= ','; + } + else + { + $first = false; + } + $query .= $this->escape_field($order[0])." "; + if (isset($order[1])) + { + $dir = strtoupper($order[1]); + $query .= $dir." "; + } + } + } + if ($this->_type != 'count') + { + if ($this->_limit != null) + $query .= "LIMIT {$this->_limit} "; + if ($this->_offset != null) + $query .= "OFFSET {$this->_offset} "; + } + } + + return array($query, $params); + } /** * Recursively parses conditions array into a query string @@ -216,41 +276,47 @@ class Query_PDO_Driver extends Query_Database { * @param array $p Element of the cobditions array * @param array &$params Reference to parameters array * @param boolean $skip_first_operator Flag to skip the first logical operator in a query - * to prevent AND or OR to be at the beginning of the query + * to prevent AND or OR to be at the beginning of the query * @param boolean $value_is_field Flag if the the value in the logical operations should - * be treated as a field. E.g. for joins where the fields are - * compared between themselves and not with actual values + * be treated as a field. E.g. for joins where the fields are + * compared between themselves and not with actual values * @return string String representation of the conditions * @access public * @throws Exception If condition cannot be parsed */ - public function get_condition_query($p,&$params,$skip_first_operator,$value_is_field=false) { - if (isset($p['field'])) { - if ($value_is_field){ - $param = $this->escape_field($p['value']); - }else { - $param = $this->escape_value($p['value'],$params); - } - return $this->escape_field($p['field']).' '.$p['operator'].' '.$param; - } - if (isset($p['logic'])) { - return ($skip_first_operator?'':strtoupper($p['logic']).' ') - .$this->get_condition_query($p['conditions'],$params,false,$value_is_field); - } - - $conds = ''; - $skip=$skip_first_operator||(count($p) > 1); - foreach($p as $q) { - $conds.=$this->get_condition_query($q,$params,$skip,$value_is_field).' '; - $skip=false; - } - if (count($p) > 1 && !$skip_first_operator) - return "( ".$conds.")"; - return $conds; - - throw new Exception("Cannot parse condition:\n".var_export($p,true)); - } + public function get_condition_query($p, &$params, $skip_first_operator, $value_is_field = false) + { + if (isset($p['field'])) + { + if ($value_is_field) + { + $param = $this->escape_field($p['value']); + } + else + { + $param = $this->escape_value($p['value'], $params); + } + return $this->escape_field($p['field']).' '.$p['operator'].' '.$param; + } + if (isset($p['logic'])) + { + return ($skip_first_operator ? '' : strtoupper($p['logic']).' ').$this->get_condition_query($p['conditions'], $params, false, $value_is_field); + } + $conds = ''; + $skip = $skip_first_operator || (count($p) > 1); + foreach ($p as $q) + { + $conds .= $this->get_condition_query($q, $params, $skip, $value_is_field).' '; + $skip = false; + } + if (count($p) > 1 && !$skip_first_operator) + { + return "( ".$conds.")"; + } + return $conds; + throw new Exception("Cannot parse condition:\n".var_export($p, true)); + } }
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/result.php b/modules/database/classes/driver/pdo/result.php index 3c96b4c..d64c479 100644 --- a/modules/database/classes/driver/pdo/result.php +++ b/modules/database/classes/driver/pdo/result.php @@ -4,7 +4,8 @@ * Database result implementation for PDO * @package Database */ -class Result_PDO_Driver extends Result_Database { +class Result_PDO_Driver extends Result_Database +{ /** * Initializes new result object @@ -12,11 +13,12 @@ class Result_PDO_Driver extends Result_Database { * @param PDOStatement $stmt PDO Statement * @return void * @access public - * @link http://php.net/manual/en/class.pdostatement.php + * @link http://php.net/manual/en/class.pdostatement.php */ - public function __construct($stmt) { - $this->_result = $stmt; - } + public function __construct($stmt) + { + $this->_result = $stmt; + } /** * Throws exception if rewind is attempted. @@ -25,25 +27,32 @@ class Result_PDO_Driver extends Result_Database { * @access public * @throws Exception If rewind is attempted */ - public function rewind() { - if($this->_position>0) - throw new Exception('PDO statement cannot be rewound for unbuffered queries'); + public function rewind() + { + if ($this->_position > 0) + { + throw new Exception('PDO statement cannot be rewound for unbuffered queries'); + } } - + /** * Iterates to the next row in the result set * * @return void * @access public */ - public function next() { - $this->check_fetched(); - $this->_row = $this->_result->fetchObject(); - if ($this->_row) { - $this->_position++; - }else { - $this->_result->closeCursor(); - } + public function next() + { + $this->check_fetched(); + $this->_row = $this->_result->fetchObject(); + if ($this->_row) + { + $this->_position++; + } + else + { + $this->_result->closeCursor(); + } } - + }
\ No newline at end of file |