Parsed join conditions fixes #2
This commit is contained in:
parent
6a89b48fe8
commit
90c6760196
@ -29,21 +29,21 @@ abstract class DB_PDO extends PDO {
|
|||||||
* @var mixed
|
* @var mixed
|
||||||
*/
|
*/
|
||||||
protected $statement;
|
protected $statement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Character to escape identifiers
|
* Character to escape identifiers
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $escape_char = '"';
|
protected $escape_char = '"';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to sql sub class
|
* Reference to sql sub class
|
||||||
*
|
*
|
||||||
* @var Object
|
* @var Object
|
||||||
*/
|
*/
|
||||||
public $sql;
|
public $sql;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to util sub class
|
* Reference to util sub class
|
||||||
*
|
*
|
||||||
@ -62,11 +62,11 @@ abstract class DB_PDO extends PDO {
|
|||||||
public function __construct($dsn, $username=NULL, $password=NULL, $driver_options=array())
|
public function __construct($dsn, $username=NULL, $password=NULL, $driver_options=array())
|
||||||
{
|
{
|
||||||
parent::__construct($dsn, $username, $password, $driver_options);
|
parent::__construct($dsn, $username, $password, $driver_options);
|
||||||
|
|
||||||
// Load the sql class for the driver
|
// Load the sql class for the driver
|
||||||
$class = get_class($this)."_sql";
|
$class = get_class($this)."_sql";
|
||||||
$this->sql = new $class();
|
$this->sql = new $class();
|
||||||
|
|
||||||
// Load the util class for the driver
|
// Load the util class for the driver
|
||||||
$class = get_class($this)."_util";
|
$class = get_class($this)."_util";
|
||||||
$this->util = new $class($this);
|
$this->util = new $class($this);
|
||||||
@ -210,7 +210,7 @@ abstract class DB_PDO extends PDO {
|
|||||||
{
|
{
|
||||||
return array_map(array($this, 'quote_ident'), $ident);
|
return array_map(array($this, 'quote_ident'), $ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the string is already quoted, return the string
|
// If the string is already quoted, return the string
|
||||||
if (($pos = strpos($ident, $this->escape_char)) !== FALSE && $pos === 0)
|
if (($pos = strpos($ident, $this->escape_char)) !== FALSE && $pos === 0)
|
||||||
{
|
{
|
||||||
@ -223,9 +223,9 @@ abstract class DB_PDO extends PDO {
|
|||||||
// Return the re-compiled string
|
// Return the re-compiled string
|
||||||
return implode('.', array_map(array($this, '_quote'), $hiers));
|
return implode('.', array_map(array($this, '_quote'), $hiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for quote_ident
|
* Helper method for quote_ident
|
||||||
*
|
*
|
||||||
@ -238,7 +238,7 @@ abstract class DB_PDO extends PDO {
|
|||||||
{
|
{
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "{$this->escape_char}{$str}{$this->escape_char}";
|
return "{$this->escape_char}{$str}{$this->escape_char}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,9 +366,9 @@ abstract class DB_PDO extends PDO {
|
|||||||
{
|
{
|
||||||
return $this->driver_query($this->sql->system_table_list());
|
return $this->driver_query($this->sql->system_table_list());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve column information for the current database table
|
* Retrieve column information for the current database table
|
||||||
*
|
*
|
||||||
@ -379,9 +379,9 @@ abstract class DB_PDO extends PDO {
|
|||||||
{
|
{
|
||||||
return $this->driver_query($this->sql->column_list($table), FALSE);
|
return $this->driver_query($this->sql->column_list($table), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve list of data types for the database
|
* Retrieve list of data types for the database
|
||||||
*
|
*
|
||||||
@ -408,7 +408,7 @@ abstract class DB_PDO extends PDO {
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return predefined data
|
// Return predefined data
|
||||||
if (is_array($sql))
|
if (is_array($sql))
|
||||||
{
|
{
|
||||||
@ -422,7 +422,7 @@ abstract class DB_PDO extends PDO {
|
|||||||
|
|
||||||
return ($filtered_index) ? db_filter($all, 0) : $all;
|
return ($filtered_index) ? db_filter($all, 0) : $all;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -432,8 +432,8 @@ abstract class DB_PDO extends PDO {
|
|||||||
*/
|
*/
|
||||||
public function num_rows()
|
public function num_rows()
|
||||||
{
|
{
|
||||||
return isset($this->statement) && is_object($this->statement)
|
return isset($this->statement) && is_object($this->statement)
|
||||||
? $this->statement->rowCount()
|
? $this->statement->rowCount()
|
||||||
: FALSE;
|
: FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,35 +52,35 @@ class Query_Builder {
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $select_string;
|
private $select_string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiled 'from' clause
|
* Compiled 'from' clause
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $from_string;
|
private $from_string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiled arguments for insert / update
|
* Compiled arguments for insert / update
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $set_string;
|
private $set_string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order by clause
|
* Order by clause
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $order_string;
|
private $order_string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group by clause
|
* Group by clause
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $group_string;
|
private $group_string;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! SQL Clause Arrays
|
// ! SQL Clause Arrays
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -91,21 +91,21 @@ class Query_Builder {
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $set_array_keys;
|
private $set_array_keys;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key/val pairs for order by clause
|
* Key/val pairs for order by clause
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $order_array;
|
private $order_array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key/val pairs for group by clause
|
* Key/val pairs for group by clause
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $group_array;
|
private $group_array;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! Other Class vars
|
// ! Other Class vars
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -123,7 +123,7 @@ class Query_Builder {
|
|||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $limit;
|
private $limit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value for offset in limit string
|
* Value for offset in limit string
|
||||||
*
|
*
|
||||||
@ -138,7 +138,7 @@ class Query_Builder {
|
|||||||
*/
|
*/
|
||||||
public $sql;
|
public $sql;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query component order mapping
|
* Query component order mapping
|
||||||
* for complex select queries
|
* for complex select queries
|
||||||
*
|
*
|
||||||
@ -153,7 +153,7 @@ class Query_Builder {
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $query_map;
|
private $query_map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map for having clause
|
* Map for having clause
|
||||||
*
|
*
|
||||||
@ -161,6 +161,13 @@ class Query_Builder {
|
|||||||
*/
|
*/
|
||||||
private $having_map;
|
private $having_map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query parser to safely escape conditions
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
private $parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience property for connection management
|
* Convenience property for connection management
|
||||||
*
|
*
|
||||||
@ -179,33 +186,33 @@ class Query_Builder {
|
|||||||
if (is_array($params))
|
if (is_array($params))
|
||||||
{
|
{
|
||||||
$p = new stdClass();
|
$p = new stdClass();
|
||||||
|
|
||||||
foreach($params as $k => $v)
|
foreach($params as $k => $v)
|
||||||
{
|
{
|
||||||
$p->$k = $v;
|
$p->$k = $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = $p;
|
$params = $p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the connection work with 'conn_db' or 'database'
|
// Let the connection work with 'conn_db' or 'database'
|
||||||
if (isset($params->database))
|
if (isset($params->database))
|
||||||
{
|
{
|
||||||
$params->conn_db = $params->database;
|
$params->conn_db = $params->database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$params->type = strtolower($params->type);
|
$params->type = strtolower($params->type);
|
||||||
$dbtype = ($params->type !== 'postgresql') ? $params->type : 'pgsql';
|
$dbtype = ($params->type !== 'postgresql') ? $params->type : 'pgsql';
|
||||||
|
|
||||||
$dsn = '';
|
$dsn = '';
|
||||||
|
|
||||||
// Add the driver type to the dsn
|
// Add the driver type to the dsn
|
||||||
if ($dbtype !== 'firebird' && $dbtype !== 'sqlite')
|
if ($dbtype !== 'firebird' && $dbtype !== 'sqlite')
|
||||||
{
|
{
|
||||||
$dsn = strtolower($dbtype).':'.$dsn;
|
$dsn = strtolower($dbtype).':'.$dsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the class exists
|
// Make sure the class exists
|
||||||
if ( ! class_exists($dbtype))
|
if ( ! class_exists($dbtype))
|
||||||
{
|
{
|
||||||
@ -227,7 +234,7 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
$dsn .= ";port={$params->port}";
|
$dsn .= ";port={$params->port}";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
@ -238,9 +245,9 @@ class Query_Builder {
|
|||||||
$dsn = "{$params->host}:{$params->file}";
|
$dsn = "{$params->host}:{$params->file}";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Create the database connection
|
// Create the database connection
|
||||||
if ( ! empty($params->user))
|
if ( ! empty($params->user))
|
||||||
@ -263,6 +270,8 @@ class Query_Builder {
|
|||||||
$this->conn_name = $params->name;
|
$this->conn_name = $params->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instantiate the Query Parser
|
||||||
|
$this->parser = new Query_Parser();
|
||||||
|
|
||||||
// Make things just slightly shorter
|
// Make things just slightly shorter
|
||||||
$this->sql =& $this->db->sql;
|
$this->sql =& $this->db->sql;
|
||||||
@ -314,9 +323,9 @@ class Query_Builder {
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to simplify select_ methods
|
* Method to simplify select_ methods
|
||||||
*
|
*
|
||||||
@ -328,16 +337,16 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
// Escape the identifiers
|
// Escape the identifiers
|
||||||
$field = $this->quote_ident($field);
|
$field = $this->quote_ident($field);
|
||||||
|
|
||||||
$as = ($as !== FALSE)
|
$as = ($as !== FALSE)
|
||||||
? $this->quote_ident($as)
|
? $this->quote_ident($as)
|
||||||
: $field;
|
: $field;
|
||||||
|
|
||||||
return "({$field}) AS {$as} ";
|
return "({$field}) AS {$as} ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the maximum value of a field from a query
|
* Selects the maximum value of a field from a query
|
||||||
*
|
*
|
||||||
@ -351,9 +360,9 @@ class Query_Builder {
|
|||||||
$this->select_string .= $this->sql->max().$this->_select($field, $as);
|
$this->select_string .= $this->sql->max().$this->_select($field, $as);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the minimum value of a field from a query
|
* Selects the minimum value of a field from a query
|
||||||
*
|
*
|
||||||
@ -362,14 +371,14 @@ class Query_Builder {
|
|||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function select_min($field, $as=FALSE)
|
public function select_min($field, $as=FALSE)
|
||||||
{
|
{
|
||||||
// Create the select string
|
// Create the select string
|
||||||
$this->select_string .= $this->sql->min().$this->_select($field, $as);
|
$this->select_string .= $this->sql->min().$this->_select($field, $as);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the average value of a field from a query
|
* Selects the average value of a field from a query
|
||||||
*
|
*
|
||||||
@ -383,9 +392,9 @@ class Query_Builder {
|
|||||||
$this->select_string .= $this->sql->avg().$this->_select($field, $as);
|
$this->select_string .= $this->sql->avg().$this->_select($field, $as);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the sum of a field from a query
|
* Selects the sum of a field from a query
|
||||||
*
|
*
|
||||||
@ -401,7 +410,7 @@ class Query_Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the 'distinct' keyword to a query
|
* Adds the 'distinct' keyword to a query
|
||||||
*
|
*
|
||||||
@ -413,7 +422,7 @@ class Query_Builder {
|
|||||||
$this->select_string = $this->sql->distinct() . $this->select_string;
|
$this->select_string = $this->sql->distinct() . $this->select_string;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -440,7 +449,7 @@ class Query_Builder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! 'Like' methods
|
// ! 'Like' methods
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify 'like' methods
|
* Simplify 'like' methods
|
||||||
*
|
*
|
||||||
@ -470,19 +479,19 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
$val = "%{$val}%";
|
$val = "%{$val}%";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->query_map[] = array(
|
$this->query_map[] = array(
|
||||||
'type' => 'like',
|
'type' => 'like',
|
||||||
'conjunction' => (empty($this->query_map)) ? ' WHERE ' : " {$conj} ",
|
'conjunction' => (empty($this->query_map)) ? ' WHERE ' : " {$conj} ",
|
||||||
'string' => $l
|
'string' => $l
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add to the values array
|
// Add to the values array
|
||||||
$this->values[] = $val;
|
$this->values[] = $val;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -542,11 +551,11 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
return $this->_like($field, $val, $pos, 'NOT LIKE', 'OR');
|
return $this->_like($field, $val, $pos, 'NOT LIKE', 'OR');
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! Having methods
|
// ! Having methods
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify building having clauses
|
* Simplify building having clauses
|
||||||
*
|
*
|
||||||
@ -558,7 +567,7 @@ class Query_Builder {
|
|||||||
private function _having($key, $val=array(), $conj='AND')
|
private function _having($key, $val=array(), $conj='AND')
|
||||||
{
|
{
|
||||||
$where = $this->_where($key, $val);
|
$where = $this->_where($key, $val);
|
||||||
|
|
||||||
// Create key/value placeholders
|
// Create key/value placeholders
|
||||||
foreach($where as $f => &$val)
|
foreach($where as $f => &$val)
|
||||||
{
|
{
|
||||||
@ -577,12 +586,12 @@ class Query_Builder {
|
|||||||
'string' => $item
|
'string' => $item
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a 'Having' clause
|
* Generates a 'Having' clause
|
||||||
*
|
*
|
||||||
@ -594,9 +603,9 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
return $this->_having($key, $val, 'AND');
|
return $this->_having($key, $val, 'AND');
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a 'Having' clause prefixed with 'OR'
|
* Generates a 'Having' clause prefixed with 'OR'
|
||||||
*
|
*
|
||||||
@ -642,9 +651,9 @@ class Query_Builder {
|
|||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify generating where string
|
* Simplify generating where string
|
||||||
*
|
*
|
||||||
@ -679,9 +688,9 @@ class Query_Builder {
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify where_in methods
|
* Simplify where_in methods
|
||||||
*
|
*
|
||||||
@ -708,7 +717,7 @@ class Query_Builder {
|
|||||||
'conjunction' => ( ! empty($this->query_map)) ? " {$conj} " : ' WHERE ',
|
'conjunction' => ( ! empty($this->query_map)) ? " {$conj} " : ' WHERE ',
|
||||||
'string' => $string
|
'string' => $string
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,7 +810,7 @@ class Query_Builder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! Other Query Modifier methods
|
// ! Other Query Modifier methods
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets values for inserts / updates / deletes
|
* Sets values for inserts / updates / deletes
|
||||||
*
|
*
|
||||||
@ -837,7 +846,7 @@ class Query_Builder {
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -850,15 +859,26 @@ class Query_Builder {
|
|||||||
*/
|
*/
|
||||||
public function join($table, $condition, $type='')
|
public function join($table, $condition, $type='')
|
||||||
{
|
{
|
||||||
// TODO make able to handle operators without spaces
|
|
||||||
|
|
||||||
$table = implode(" ", array_map(array($this->db, 'quote_ident'), explode(' ', trim($table))));
|
$table = implode(" ", array_map(array($this->db, 'quote_ident'), explode(' ', trim($table))));
|
||||||
//$condition = preg_replace('`(\W)`', " $1 ", $condition);
|
|
||||||
$cond_array = explode(' ', trim($condition));
|
|
||||||
$cond_array = array_map('trim', $cond_array);
|
|
||||||
|
|
||||||
$condition = $table . ' ON ' . $this->quote_ident($cond_array[0]) . $cond_array[1] .
|
$parser = new query_parser();
|
||||||
' ' . $this->quote_ident($cond_array[2]);
|
|
||||||
|
// Parse out the join condition
|
||||||
|
$parts = $parser->parse_join($condition);
|
||||||
|
$count = count($parts['identifiers']);
|
||||||
|
|
||||||
|
// Go through and quote the identifiers
|
||||||
|
for($i=0; $i <= $count; $i++)
|
||||||
|
{
|
||||||
|
if (in_array($parts['combined'][$i], $parts['identifiers']) && ! is_numeric($parts['combined'][$i]))
|
||||||
|
{
|
||||||
|
$parts['combined'][$i] = $this->quote_ident($parts['combined'][$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed_condition = implode(' ', $parts['combined']);
|
||||||
|
|
||||||
|
$condition = $table . ' ON ' . $parsed_condition;
|
||||||
|
|
||||||
$this->query_map[] = array(
|
$this->query_map[] = array(
|
||||||
'type' => 'join',
|
'type' => 'join',
|
||||||
@ -1022,7 +1042,7 @@ class Query_Builder {
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ! Query execution methods
|
// ! Query execution methods
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -1070,7 +1090,7 @@ class Query_Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convience method for get() with a where clause
|
* Convience method for get() with a where clause
|
||||||
*
|
*
|
||||||
@ -1084,13 +1104,13 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
// Create the where clause
|
// Create the where clause
|
||||||
$this->where($where);
|
$this->where($where);
|
||||||
|
|
||||||
// Return the result
|
// Return the result
|
||||||
return $this->get($table, $limit, $offset);
|
return $this->get($table, $limit, $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreive the number of rows in the selected table
|
* Retreive the number of rows in the selected table
|
||||||
*
|
*
|
||||||
@ -1103,9 +1123,9 @@ class Query_Builder {
|
|||||||
$res = $this->query($sql);
|
$res = $this->query($sql);
|
||||||
return (int) count($res->fetchAll());
|
return (int) count($res->fetchAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the number of results for the generated query - used
|
* Retrieve the number of results for the generated query - used
|
||||||
* in place of the get() method
|
* in place of the get() method
|
||||||
@ -1120,7 +1140,7 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
$this->from($table);
|
$this->from($table);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = $this->_compile();
|
$sql = $this->_compile();
|
||||||
|
|
||||||
// Do prepared statements for anything involving a "where" clause
|
// Do prepared statements for anything involving a "where" clause
|
||||||
@ -1136,12 +1156,12 @@ class Query_Builder {
|
|||||||
|
|
||||||
// Reset for next query
|
// Reset for next query
|
||||||
$this->_reset();
|
$this->_reset();
|
||||||
|
|
||||||
$rows = $result->fetchAll();
|
$rows = $result->fetchAll();
|
||||||
|
|
||||||
return (int) count($rows);
|
return (int) count($rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1276,7 +1296,7 @@ class Query_Builder {
|
|||||||
|
|
||||||
// Set empty arrays
|
// Set empty arrays
|
||||||
$this->values = array();
|
$this->values = array();
|
||||||
|
|
||||||
// Set select string as an empty string, for proper handling
|
// Set select string as an empty string, for proper handling
|
||||||
// of the 'distinct' keyword
|
// of the 'distinct' keyword
|
||||||
$this->select_string = '';
|
$this->select_string = '';
|
||||||
@ -1295,7 +1315,7 @@ class Query_Builder {
|
|||||||
private function _compile($type='', $table='')
|
private function _compile($type='', $table='')
|
||||||
{
|
{
|
||||||
$sql = '';
|
$sql = '';
|
||||||
|
|
||||||
$table = $this->quote_ident($table);
|
$table = $this->quote_ident($table);
|
||||||
|
|
||||||
switch($type)
|
switch($type)
|
||||||
@ -1324,7 +1344,7 @@ class Query_Builder {
|
|||||||
{
|
{
|
||||||
$sql .= $this->group_string;
|
$sql .= $this->group_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the having string
|
// Set the having string
|
||||||
if ( ! empty($this->having_map))
|
if ( ! empty($this->having_map))
|
||||||
{
|
{
|
||||||
@ -1350,7 +1370,7 @@ class Query_Builder {
|
|||||||
case "insert":
|
case "insert":
|
||||||
$param_count = count($this->set_array_keys);
|
$param_count = count($this->set_array_keys);
|
||||||
$params = array_fill(0, $param_count, '?');
|
$params = array_fill(0, $param_count, '?');
|
||||||
$sql = "INSERT INTO {$table} ("
|
$sql = "INSERT INTO {$table} ("
|
||||||
. implode(', ', $this->set_array_keys) .
|
. implode(', ', $this->set_array_keys) .
|
||||||
') VALUES ('.implode(', ', $params).')';
|
') VALUES ('.implode(', ', $params).')';
|
||||||
break;
|
break;
|
||||||
@ -1382,7 +1402,7 @@ class Query_Builder {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//echo $sql . '<br />';
|
//echo $sql . '<br />';
|
||||||
|
|
||||||
return $sql;
|
return $sql;
|
||||||
|
@ -27,9 +27,9 @@ class Query_Parser {
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $match_patterns = array(
|
private $match_patterns = array(
|
||||||
'function' => '`([a-zA-Z0-9_]+\((.*?)\))`',
|
'function' => '([a-zA-Z0-9_]+\((.*?)\))',
|
||||||
'identifier' => '`([a-zA-Z0-9"_-]+\.?)+`',
|
'identifier' => '([a-zA-Z0-9_-]+\.?)+',
|
||||||
'operator' => '`=|AND|&&?|~|\|\|?|\^|/|>=?|<=?|-|%|OR|\+|NOT|\!=?|<>|XOR`'
|
'operator' => '=|AND|&&?|~|\|\|?|\^|/|>=?|<=?|-|%|OR|\+|NOT|\!=?|<>|XOR'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,6 +41,7 @@ class Query_Parser {
|
|||||||
'functions' => array(),
|
'functions' => array(),
|
||||||
'identifiers' => array(),
|
'identifiers' => array(),
|
||||||
'operators' => array(),
|
'operators' => array(),
|
||||||
|
'combined' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,9 +51,57 @@ class Query_Parser {
|
|||||||
*/
|
*/
|
||||||
public function __construct($sql = '')
|
public function __construct($sql = '')
|
||||||
{
|
{
|
||||||
preg_match_all($this->match_patterns['function'], $sql, $this->matches['functions'], PREG_SET_ORDER);
|
// Get sql clause components
|
||||||
preg_match_all($this->match_patterns['identifier'], $sql, $this->matches['identifiers'], PREG_SET_ORDER);
|
preg_match_all('`'.$this->match_patterns['function'].'`', $sql, $this->matches['functions'], PREG_SET_ORDER);
|
||||||
preg_match_all($this->match_patterns['operator'], $sql, $this->matches['operators'], PREG_SET_ORDER);
|
preg_match_all('`'.$this->match_patterns['identifier'].'`', $sql, $this->matches['identifiers'], PREG_SET_ORDER);
|
||||||
|
preg_match_all('`'.$this->match_patterns['operator'].'`', $sql, $this->matches['operators'], PREG_SET_ORDER);
|
||||||
|
|
||||||
|
// Get everything at once for ordering
|
||||||
|
$full_pattern = '`'.$this->match_patterns['function'].'+|'.$this->match_patterns['identifier'].'|('.$this->match_patterns['operator'].')+`i';
|
||||||
|
preg_match_all($full_pattern, $sql, $this->matches['combined'], PREG_SET_ORDER);
|
||||||
|
|
||||||
|
// Go through the matches, and get the most relevant matches
|
||||||
|
$this->matches = array_map(array($this, 'filter_array'), $this->matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public parser method for seting the parse string
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function parse_join($sql)
|
||||||
|
{
|
||||||
|
$this->__construct($sql);
|
||||||
|
return $this->matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a more useful match array
|
||||||
|
*
|
||||||
|
* @param array
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function filter_array($array)
|
||||||
|
{
|
||||||
|
$new_array = array();
|
||||||
|
|
||||||
|
foreach($array as $row)
|
||||||
|
{
|
||||||
|
if (is_array($row))
|
||||||
|
{
|
||||||
|
$new_array[] = $row[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$new_array[] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $new_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the Query Parser
|
||||||
|
*/
|
||||||
class QPTest extends UnitTestCase {
|
class QPTest extends UnitTestCase {
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@ -22,16 +25,33 @@ class QPTest extends UnitTestCase {
|
|||||||
|
|
||||||
public function TestGeneric()
|
public function TestGeneric()
|
||||||
{
|
{
|
||||||
$this->parser->__construct('table1.field1=table2.field2');
|
$matches = $this->parser->parse_join('table1.field1=table2.field2');
|
||||||
|
$this->assertIdentical($matches['combined'], array(
|
||||||
|
'table1.field1', '=', 'table2.field2'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
//echo '<pre>'.print_r($this->parser->matches, TRUE).'</pre>';
|
public function TestGeneric2()
|
||||||
|
{
|
||||||
|
$matches = $this->parser->parse_join('db1.table1.field1!=db2.table2.field2');
|
||||||
|
$this->assertIdentical($matches['combined'], array(
|
||||||
|
'db1.table1.field1','!=','db2.table2.field2'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function TestWUnderscore()
|
||||||
|
{
|
||||||
|
$matches = $this->parser->parse_join('table_1.field1 = tab_le2.field_2');
|
||||||
|
$this->assertIdentical($matches['combined'], array(
|
||||||
|
'table_1.field1', '=', 'tab_le2.field_2'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function TestFunction()
|
public function TestFunction()
|
||||||
{
|
{
|
||||||
$this->parser->__construct('table1.field1 > SUM(3+5)');
|
$matches = $this->parser->parse_join('table1.field1 > SUM(3+5)');
|
||||||
|
$this->assertIdentical($matches['combined'], array(
|
||||||
//echo '<pre>'.print_r($this->parser->matches, TRUE).'</pre>';
|
'table1.field1', '>', 'SUM(3+5)'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user