<?php
/**
* Sql 创造者类
*
* @author 色色
*/
class SqlCreator {
// 查询类型
const DB_SELECT = 1;
const DB_INSERT = 2;
const DB_UPDATE = 3;
const DB_DELETE = 4;
/**
* 返回 Expr Sql 创建器对象
*
* @param string $expr
*
* @return SqlCreator_Query_Expression
*/
static function newExpr($expr){
return new SqlCreator_Query_Expression($expr);
}
/**
* 返回 Insert Sql 创建器对象
*
* @param Core_DB $dbo
* @param string $table
* @param array $columns
*
* @return SqlCreator_Query_Builder_Insert
*/
static function newInsert(Core_DB $dbo,$table = NULL, array $columns = NULL){
return new SqlCreator_Query_Builder_Insert($dbo,$table,$columns);
}
/**
* 返回 Insert Sql 创建器对象
*
* @param Core_DB $dbo
* @param string $table
*
* @return SqlCreator_Query_Builder_Update
*/
static function newUpdate(Core_DB $dbo,$table = NULL){
return new SqlCreator_Query_Builder_Update($dbo,$table);
}
/**
* 返回 Delete Sql 创建器对象
*
* @param Core_DB $dbo
* @param string $table
*
* @return SqlCreator_Query_Builder_Delete
*/
static function newDelete(Core_DB $dbo,$table = NULL){
return new SqlCreator_Query_Builder_Delete($dbo,$table);
}
/**
* 返回 Select Sql 创建器对象
*
* @param Core_DB $dbo
* @param array $columns
*
* @return SqlCreator_Query_Builder_Select
*/
static function newSelect(Core_DB $dbo,array $columns = NULL){
return new SqlCreator_Query_Builder_Select($dbo,$columns);
}
/**
* 返回 Join Sql 创建器对象
*
* @param Core_DB $dbo
* @param string $table
* @param string $type INNER, RIGHT, LEFT, etc
*
* @return SqlCreator_Query_Builder_Join
*/
static function newJoin(Core_DB $dbo,$table, $type = NULL){
return new SqlCreator_Query_Builder_Join($dbo,$table, $type);
}
}
class SqlCreatorException extends Exception {}
class SqlCreator_Query_Expression
{
// Raw expression string
protected $_value;
/**
* Sets the expression string.
*
* $expression = new SqlCreator_Query_Expression('COUNT(users.id)');
*/
function __construct($value)
{
// Set the expression string
$this->_value = $value;
}
/**
* Get the expression value as a string.
*
* $sql = $expression->value();
*
* @return string
*/
function value()
{
return (string) $this->_value;
}
function __toString()
{
return $this->value();
}
}
class SqlCreator_Query
{
/**
* @var Core_DB
*/
protected $_dbo = NULL;
/**
* @var int Query type
*/
protected $_type;
/**
* @var string SQL statement
*/
protected $_sql;
/**
* @var array Quoted query parameters
*/
protected $_parameters = array();
/**
* Creates a new SQL query of the specified type.
*
* @param Core_DB $dbo
* @param string query string
* @param integer query type
*/
function __construct(Core_DB $dbo,$sql, $type = null)
{
$this->_dbo = $dbo;
$this->_type = $type;
$this->_sql = $sql;
}
final function __toString()
{
return $this->compile();
}
/**
* Get the type of the query.
*
* @return integer
*/
function type()
{
return $this->_type;
}
/**
* Set the value of a parameter in the query.
*
* @param string parameter key to replace
* @param mixed value to use
*
* @return SqlCreator_Query
*/
function param($param, $value)
{
// Add or overload a new parameter
$this->_parameters[$param] = $value;
return $this;
}
/**
* Bind a variable to a parameter in the query.
*
* @param string parameter key to replace
* @param mixed variable to use
*
* @return SqlCreator_Query
*/
function bind($param, & $var)
{
// Bind a value to a variable
$this->_parameters[$param] =& $var;
return $this;
}
/**
* Add multiple parameters to the query.
*
* @param array list of parameters
*
* @return SqlCreator_Query
*/
function parameters(array $params)
{
// Merge the new parameters in
$this->_parameters = $params + $this->_parameters;
return $this;
}
/**
* Compile the SQL query and return it. Replaces any parameters with their
* given values.
*
* @param mixed Database instance or instance name
*
* @return string
*/
function compile()
{
// Import the SQL locally
$sql = $this->_sql;
if ( ! empty($this->_parameters))
{
// Quote all of the values
$values = array_map(array($this, '__quote__'), $this->_parameters);
// Replace the values in the SQL
$sql = strtr($sql, $values);
}
return trim($sql);
}
/**
* Quote a value for an SQL query.
*
* Objects passed to this function will be converted to strings.
* [Database_Expression] objects will use the value of the expression.
* [Database_Query] objects will be compiled and converted to a sub-query.
* All other objects will be converted using the `__toString` method.
*
* @param mixed any value to quote
* @return string
*/
function __quote__($value)
{
if ($value === null)
{
return 'null';
}
elseif ($value === true)
{
return "'1'";
}
elseif ($value === false)
{
return "'0'";
}
elseif (is_object($value))
{
if ($value instanceof SqlCreator_Query)
{
// Create a sub-query
return '('.$value->compile().')';
}
elseif ($value instanceof SqlCreator_Query_Expression)
{
// Use a raw expression
return $value->value();
}
else
{
// Convert the object to a string
return $this->__quote__((string) $value);
}
}
elseif (is_array($value))
{
return '('.implode(', ', array_map(array($this, '__quote__'), $value)).')';
}
elseif (is_int($value))
{
return (int) $value;
}
elseif (is_float($value))
{
// Convert to non-locale aware float to prevent possible commas
return sprintf('%F', $value);
}
return $this->_dbo->qstr($value);
}
/**
* Quote a database table name and adds the table prefix if needed.
*
* @param mixed table name or array(table, alias)
* @return string
*/
function __quote_table__($value)
{
// Assign the table by reference from the value
if (is_array($value))
{
$table =& $value[0];
// // Attach table prefix to alias
// $value[1] = $this->table_prefix().$value[1];
}
else
{
$table =& $value;
}
// deal with the sub-query objects first
if ($table instanceof SqlCreator_Query)
{
// Create a sub-query
$table = '('.$table->compile().')';
}
elseif (is_string($table))
{
if (strpos($table, '.') === false)
{
// Add the table prefix for tables
// $table = $this->__quote_identifier__($this->table_prefix().$table);
}
else
{
// Split the identifier into the individual parts
$parts = explode('.', $table);
// if ($prefix = $this->table_prefix())
// {
// // Get the offset of the table name, 2nd-to-last part
// // This works for databases that can have 3 identifiers (Postgre)
// if (($offset = count($parts)) == 2)
// {
// $offset = 1;
// }
// else
// {
// $offset = $offset - 2;
// }
//
// // Add the table prefix to the table name
// $parts[$offset] = $prefix.$parts[$offset];
// }
// Quote each of the parts
$table = implode('.', array_map(array($this, '__quote_identifier__'), $parts));
}
}
// process the alias if present
if (is_array($value))
{
// Separate the column and alias
list ($value, $alias) = $value;
return $value.' AS '.$this->__quote_identifier__($alias);
}
else
{
// return the value
return $value;
}
}
/**
* Quote a database identifier, such as a column name. Adds the
* table prefix to the identifier if a table name is present.
*
* Objects passed to this function will be converted to strings.
* [Database_Expression] objects will use the value of the expression.
* [Database_Query] objects will be compiled and converted to a sub-query.
* All other objects will be converted using the `__toString` method.
*
* @param mixed any identifier
* @return string
*/
function __quote_identifier__($value)
{
if ($value === '*')
{
return $value;
}
elseif (is_object($value))
{
if ($value instanceof SqlCreator_Query)
{
// Create a sub-query
return '('.$value->compile().')';
}
elseif ($value instanceof SqlCreator_Query_Expression)
{
// Use a raw expression
return $value->value();
}
else
{
// Convert the object to a string
return $this->__quote_identifier__((string) $value);
}
}
elseif (is_array($value))
{
// Separate the column and alias
list ($value, $alias) = $value;
return $this->__quote_identifier__($value).' AS '.$this->__quote_identifier__($alias);
}
if (strpos($value, '"') !== false)
{
// Quote the column in FUNC("ident") identifiers
return preg_replace('/"(.+?)"/e', '$this->__quote_identifier__("$1")', $value);
}
elseif (strpos($value, '.') !== false)
{
// Split the identifier into the individual parts
$parts = explode('.', $value);
// if ($prefix = $this->table_prefix())
// {
// // Get the offset of the table name, 2nd-to-last part
// // This works for databases that can have 3 identifiers (Postgre)
// $offset = count($parts) - 2;
//
// // Add the table prefix to the table name
// $parts[$offset] = $prefix.$parts[$offset];
// }
// Quote each of the parts
return implode('.', array_map(array($this, '__quote_identifier__'), $parts));
}
else
{
return '`'.$value.'`';
}
}
}
abstract class SqlCreator_Query_Builder extends SqlCreator_Query
{
/**
* Compiles an array of JOIN statements into an SQL partial.
*
* @param array join statements
* @return string
*/
protected function _compile_join(array $joins)
{
$statements = array();
foreach ($joins as $join)
{
// Compile each of the join statements
$statements[] = $join->compile();
}
return implode(' ', $statements);
}
/**
* Compiles an array of conditions into an SQL partial. Used for WHERE
* and HAVING.
*
* @param array condition statements
* @return string
*/
protected function _compile_conditions(array $conditions)
{
$last_condition = NULL;
$sql = '';
foreach ($conditions as $group)
{
// Process groups of conditions
foreach ($group as $logic => $condition)
{
if ($condition === '(')
{
if ( ! empty($sql) AND $last_condition !== '(')
{
// Include logic operator
$sql .= ' '.$logic.' ';
}
$sql .= '(';
}
elseif ($condition === ')')
{
$sql .= ')';
}
else
{
if ( ! empty($sql) AND $last_condition !== '(')
{
// Add the logic operator
$sql .= ' '.$logic.' ';
}
// Split the condition
list($column, $op, $value) = $condition;
if ($value === NULL)
{
if ($op === '=')
{
// Convert "val = NULL" to "val IS NULL"
$op = 'IS';
}
elseif ($op === '!=')
{
// Convert "val != NULL" to "valu IS NOT NULL"
$op = 'IS NOT';
}
}
// Database operators are always uppercase
$op = strtoupper($op);
if ($op === 'BETWEEN' AND is_array($value))
{
// BETWEEN always has exactly two arguments
list($min, $max) = $value;
if (is_string($min) AND array_key_exists($min, $this->_parameters))
{
// Set the parameter as the minimum
$min = $this->_parameters[$min];
}
if (is_string($max) AND array_key_exists($max, $this->_parameters))
{
// Set the parameter as the maximum
$max = $this->_parameters[$max];
}
// Quote the min and max value
$value = $this->__quote__($min).' AND '.$this->__quote__($max);
}
else
{
if (is_string($value) AND array_key_exists($value, $this->_parameters))
{
// Set the parameter as the value
$value = $this->_parameters[$value];
}
// Quote the entire value normally
$value = $this->__quote__($value);
}
// Append the statement to the query
$sql .= $this->__quote_identifier__($column).' '.$op.' '.$value;
}
$last_condition = $condition;
}
}
return $sql;
}
/**
* Compiles an array of set values into an SQL partial. Used for UPDATE.
*
* @param array updated values
* @return string
*/
protected function _compile_set(array $values)
{
$set = array();
foreach ($values as $group)
{
// Split the set
list ($column, $value) = $group;
// Quote the column name
$column = $this->__quote_identifier__($column);
if (is_string($value) AND array_key_exists($value, $this->_parameters))
{
// Use the parameter value
$value = $this->_parameters[$value];
}
$set[$column] = $column.' = '.$this->__quote__($value);
}
return implode(', ', $set);
}
/**
* Compiles an array of ORDER BY statements into an SQL partial.
*
* @param array sorting columns
* @return string
*/
protected function _compile_order_by(array $columns)
{
$sort = array();
foreach ($columns as $group)
{
list ($column, $direction) = $group;
if ( ! empty($direction))
{
// Make the direction uppercase
$direction = ' '.strtoupper($direction);
}
$sort[] = $this->__quote_identifier__($column).$direction;
}
return 'ORDER BY '.implode(', ', $sort);
}
/**
* Reset the current builder status.
*
* @return SqlCreator_Query_Builder
*/
abstract function reset();
}
abstract class SqlCreator_Query_Builder_Where extends SqlCreator_Query_Builder
{
// WHERE ...
protected $_where = array();
// ORDER BY ...
protected $_order_by = array();
// LIMIT ...
protected $_limit = NULL;
/**
* Alias of and_where()
*
* @return SqlCreator_Query_Builder_Where
*/
function where()
{
$args = func_get_args();
return call_user_func_array(array($this, 'and_where'), $args);
}
/**
* Creates a new "AND WHERE" condition for the query.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column value
*
* @return SqlCreator_Query_Builder_Where
*/
function and_where($column, $op = null, $value = null)
{
if (is_array($column))
{
foreach ($column as $key => $val)
{
if (is_array($val))
{
$this->and_where($val[0], $val[1], $val[2]);
}
else
{
$this->and_where($key, '=', $val);
}
}
}
else
{
if(func_num_args() === 2)
{
$value = $op;
$op = '=';
}
$this->_where[] = array('AND' => array($column, $op, $value));
}
return $this;
}
/**
* Creates a new "OR WHERE" condition for the query.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column value
*
* @return SqlCreator_Query_Builder_Where
*/
function or_where($column, $op = null, $value = null)
{
if (is_array($column))
{
foreach ($column as $key => $val)
{
if (is_array($val))
{
$this->or_where($val[0], $val[1], $val[2]);
}
else
{
$this->or_where($key, '=', $val);
}
}
}
else
{
if(func_num_args() === 2)
{
$value = $op;
$op = '=';
}
$this->_where[] = array('OR' => array($column, $op, $value));
}
return $this;
}
/**
* Alias of and_where_open()
*
* @return SqlCreator_Query_Builder_Where
*/
function where_open()
{
return $this->and_where_open();
}
/**
* Opens a new "AND WHERE (...)" grouping.
*
* @return SqlCreator_Query_Builder_Where
*/
function and_where_open()
{
$this->_where[] = array('AND' => '(');
return $this;
}
/**
* Opens a new "OR WHERE (...)" grouping.
*
* @return SqlCreator_Query_Builder_Where
*/
function or_where_open()
{
$this->_where[] = array('OR' => '(');
return $this;
}
/**
* Closes an open "AND WHERE (...)" grouping.
*
* @return SqlCreator_Query_Builder_Where
*/
function where_close()
{
return $this->and_where_close();
}
/**
* Closes an open "AND WHERE (...)" grouping.
*
* @return SqlCreator_Query_Builder_Where
*/
function and_where_close()
{
$this->_where[] = array('AND' => ')');
return $this;
}
/**
* Closes an open "OR WHERE (...)" grouping.
*
* @return SqlCreator_Query_Builder_Where
*/
function or_where_close()
{
$this->_where[] = array('OR' => ')');
return $this;
}
/**
* Applies sorting with "ORDER BY ..."
*
* @param mixed column name or array($column, $alias) or object
* @param string direction of sorting
* @return SqlCreator_Query_Builder_Where
*/
function order_by($column, $direction = NULL)
{
$this->_order_by[] = array($column, $direction);
return $this;
}
/**
* Return up to "LIMIT ..." results
*
* @param integer maximum results to return
*
* @return SqlCreator_Query_Builder_Where
*/
function limit($number)
{
$this->_limit = (int) $number;
return $this;
}
}
class SqlCreator_Query_Builder_Insert extends SqlCreator_Query_Builder
{
// INSERT INTO ...
protected $_table;
// (...)
protected $_columns = array();
// VALUES (...)
protected $_values = array();
/**
* Set the table and columns for an insert.
*
* @param Core_DB $dbo
* @param string $table
* @param array $columns
*/
function __construct(Core_DB $dbo,$table = NULL, array $columns = NULL)
{
if ($table)
{
$this->_table = $table;
}
if ($columns)
{
// Set the column names
$this->_columns = $columns;
}
// Start the query with no SQL
return parent::__construct($dbo,'', SqlCreator::DB_INSERT);
}
/**
* Sets the table to insert into.
*
* @param string $table
* @return SqlCreator_Query_Builder_Insert
*/
function table($table)
{
$this->_table = $table;
return $this;
}
/**
* Set the columns that will be inserted.
*
* @param array column names
* @return SqlCreator_Query_Builder_Insert
*/
function columns(array $columns)
{
$this->_columns = array_merge($this->_columns, $columns);
return $this;
}
/**
* Adds or overwrites values. Multiple value sets can be added.
*
* @param array values list
* @return SqlCreator_Query_Builder_Insert
*/
function values(array $values)
{
if ( ! is_array($this->_values))
{
throw new SqlCreatorException('INSERT INTO ... SELECT statements cannot be combined with INSERT INTO ... VALUES');
}
// Get all of the passed values
$values = func_get_args();
$this->_values = array_merge($this->_values, $values);
return $this;
}
/**
* This is a wrapper function for calling columns() and values().
*
* @param array column value pairs
* @return SqlCreator_Query_Builder_Insert
*/
function set(array $pairs)
{
$this->columns(array_keys($pairs));
$this->values($pairs);
return $this;
}
/**
* Use a sub-query to for the inserted values.
*
* @param SqlCreator_Query $query 必须是 SqlCreator::DB_SELECT类型的对象
*
* @return SqlCreator_Query_Builder_Insert
*/
function select(SqlCreator_Query $query)
{
if ($query->type() !== SqlCreator::DB_SELECT)
{
throw new SqlCreatorException('Only SELECT queries can be combined with INSERT queries');
}
$this->_values = $query;
return $this;
}
/**
* Compile the SQL query and return it.
*
* @return string
*/
function compile()
{
// Start an insertion query
$query = 'INSERT INTO '.$this->__quote_table__($this->_table);
// Add the column names
$query .= ' ('.implode(', ', array_map(array($this, '__quote_identifier__'), $this->_columns)).') ';
if (is_array($this->_values))
{
// Callback for quoting values
$quote = array($this, '__quote__');
$groups = array();
foreach ($this->_values as $group)
{
foreach ($group as $i => $value)
{
if (is_string($value) AND isset($this->_parameters[$value]))
{
// Use the parameter value
$group[$i] = $this->_parameters[$value];
}
}
$groups[] = '('.implode(', ', array_map($quote, $group)).')';
}
// Add the values
$query .= 'VALUES '.implode(', ', $groups);
}
else
{
// Add the sub-query
$query .= (string) $this->_values;
}
return $query;
}
/**
* @return SqlCreator_Query_Builder_Insert
*/
function reset()
{
$this->_table = NULL;
$this->_columns =
$this->_values = array();
$this->_parameters = array();
return $this;
}
}
class SqlCreator_Query_Builder_Update extends SqlCreator_Query_Builder_Where
{
// UPDATE ...
protected $_table;
// SET ...
protected $_set = array();
// JOIN ...
protected $_join = array();
/**
* Set the table for a update.
*
* @param string $table
*/
function __construct(Core_DB $dbo,$table = NULL)
{
if ($table)
{
$this->_table = $table;
}
// Start the query with no SQL
return parent::__construct($dbo,'', SqlCreator::DB_UPDATE);
}
/**
* Sets the table to update.
*
* @param string $table
* @return SqlCreator_Query_Builder_Update
*/
function table($table)
{
$this->_table = $table;
return $this;
}
/**
* Set the values to update with an associative array.
*
* @param array associative (column => value) list
* @return SqlCreator_Query_Builder_Update
*/
function set(array $pairs)
{
foreach ($pairs as $column => $value)
{
$this->_set[] = array($column, $value);
}
return $this;
}
/**
* Set the value of a single column.
*
* @param string $table
* @param mixed column value
* @return SqlCreator_Query_Builder_Update
*/
function value($column, $value)
{
$this->_set[] = array($column, $value);
return $this;
}
/**
* Compile the SQL query and return it.
*
* @return string
*/
function compile()
{
// Start an update query
$query = 'UPDATE '.$this->__quote_table__($this->_table);
if ( ! empty($this->_join))
{
// Add tables to join
$query .= ' '.$this->_compile_join($this->_join);
}
// Add the columns to update
$query .= ' SET '.$this->_compile_set($this->_set);
if ( ! empty($this->_where))
{
// Add selection conditions
$query .= ' WHERE '.$this->_compile_conditions($this->_where);
}
if ($this->_limit !== NULL)
{
// Add limiting
$query .= ' LIMIT '.$this->_limit;
}
return $query;
}
function reset()
{
$this->_table = NULL;
$this->_set =
$this->_where = array();
$this->_limit = NULL;
$this->_parameters = array();
return $this;
}
/**
* Adds addition tables to "JOIN ...".
*
* @param string $table
* @param string join type (LEFT, RIGHT, INNER, etc)
*
* @return SqlCreator_Query_Builder_Update
*/
function join($table, $type = NULL)
{
$this->_join[] = $this->_last_join = new SqlCreator_Query_Builder_Join($this->_dbo,$table, $type);
return $this;
}
/**
* Adds "ON ..." conditions for the last created JOIN statement.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column name or array($column, $alias) or object
*
* @return SqlCreator_Query_Builder_Update
*/
function on($c1, $op, $c2)
{
$this->_last_join->on($c1, $op, $c2);
return $this;
}
}
class SqlCreator_Query_Builder_Delete extends SqlCreator_Query_Builder_Where
{
// DELETE FROM ...
protected $_table;
/**
* Set the table for a delete.
*
* @param string $table
*/
function __construct(Core_DB $dbo,$table = NULL)
{
if ($table)
{
$this->_table = $table;
}
// Start the query with no SQL
return parent::__construct($dbo,'', SqlCreator::DB_DELETE);
}
/**
* Sets the table to delete from.
*
* @param string $table
* @return SqlCreator_Query_Builder_Delete
*/
function table($table)
{
$this->_table = $table;
return $this;
}
/**
* Compile the SQL query and return it.
*
* @param mixed SqlCreator instance or instance name
* @return string
*/
function compile()
{
// Start a deletion query
$query = 'DELETE FROM '.$this->__quote_table__($this->_table);
if ( ! empty($this->_where))
{
// Add deletion conditions
$query .= ' WHERE '.$this->_compile_conditions($this->_where);
}
if ( ! empty($this->_order_by))
{
// Add sorting
$query .= ' '.$this->_compile_order_by($this->_order_by);
}
if ($this->_limit !== NULL)
{
// Add limiting
$query .= ' LIMIT '.$this->_limit;
}
return $query;
}
function reset()
{
$this->_table = NULL;
$this->_where = array();
$this->_parameters = array();
return $this;
}
}
class SqlCreator_Query_Builder_Join extends SqlCreator_Query_Builder
{
// Type of JOIN
protected $_type;
// JOIN ...
protected $_table;
// ON ...
protected $_on = array();
/**
* Creates a new JOIN statement for a table. Optionally, the type of JOIN
* can be specified as the second parameter.
*
* @param mixed column name or array($column, $alias) or object
* @param string type of JOIN: INNER, RIGHT, LEFT, etc
*/
function __construct(Core_DB $dbo,$table, $type = NULL)
{
$this->_dbo = $dbo;
// Set the table to JOIN on
$this->_table = $table;
if ($type !== NULL)
{
// Set the JOIN type
$this->_type = (string) $type;
}
}
/**
* Adds a new condition for joining.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column name or array($column, $alias) or object
* @return SqlCreator_Query_Builder_Join
*/
function on($c1, $op, $c2)
{
$this->_on[] = array($c1, $op, $c2);
return $this;
}
/**
* Compile the SQL partial for a JOIN statement and return it.
*
* @param mixed SqlCreator instance or instance name
* @return string
*/
function compile()
{
if ($this->_type)
{
$sql = strtoupper($this->_type).' JOIN';
}
else
{
$sql = 'JOIN';
}
// Quote the table name that is being joined
$sql .= ' '.$this->__quote_table__($this->_table).' ON ';
$conditions = array();
foreach ($this->_on as $condition)
{
// Split the condition
list($c1, $op, $c2) = $condition;
if ($op)
{
// Make the operator uppercase and spaced
$op = ' '.strtoupper($op);
}
// Quote each of the identifiers used for the condition
$conditions[] = $this->__quote_identifier__($c1).$op.' '.$this->__quote_identifier__($c2);
}
// Concat the conditions "... AND ..."
$sql .= '('.implode(' AND ', $conditions).')';
return $sql;
}
function reset()
{
$this->_type =
$this->_table = NULL;
$this->_on = array();
}
}
class SqlCreator_Query_Builder_Select extends SqlCreator_Query_Builder_Where
{
// SELECT ...
protected $_select = array();
// DISTINCT
protected $_distinct = FALSE;
// FROM ...
protected $_from = array();
// JOIN ...
protected $_join = array();
// GROUP BY ...
protected $_group_by = array();
// HAVING ...
protected $_having = array();
// OFFSET ...
protected $_offset = NULL;
// The last JOIN statement created
protected $_last_join;
/**
* Sets the initial columns to select from.
*
* @param array column list
*/
function __construct(Core_DB $dbo,array $columns = NULL)
{
if ( ! empty($columns))
{
// Set the initial columns
$this->_select = $columns;
}
// Start the query with no actual SQL statement
parent::__construct($dbo,'', SqlCreator::DB_SELECT);
}
/**
* Enables or disables selecting only unique columns using "SELECT DISTINCT"
*
* @param boolean enable or disable distinct columns
* @return SqlCreator_Query_Builder_Select
*/
function distinct($value = true)
{
$this->_distinct = (bool) $value;
return $this;
}
/**
* Choose the columns to select from.
*
* @param mixed column name or array($column, $alias) or object
* @param ...
* @return SqlCreator_Query_Builder_Select
*/
function select($columns = NULL)
{
$columns = func_get_args();
$this->_select = array_merge($this->_select, $columns);
return $this;
}
/**
* Choose the columns to select from, using an array.
*
* @param array list of column names or aliases
* @return SqlCreator_Query_Builder_Select
*/
function select_array(array $columns)
{
$this->_select = array_merge($this->_select, $columns);
return $this;
}
/**
* Choose the tables to select "FROM ..."
*
* @param string $table
* @param ...
* @return SqlCreator_Query_Builder_Select
*/
function from($tables)
{
$tables = func_get_args();
$this->_from = array_merge($this->_from, $tables);
return $this;
}
/**
* Adds addition tables to "JOIN ...".
*
* @param mixed column name or array($column, $alias) or object
* @param string join type (LEFT, RIGHT, INNER, etc)
* @return SqlCreator_Query_Builder_Select
*/
function join($table, $type = NULL)
{
$this->_join[] = $this->_last_join = new SqlCreator_Query_Builder_Join($this->_dbo,$table, $type);
return $this;
}
/**
* Adds "ON ..." conditions for the last created JOIN statement.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column name or array($column, $alias) or object
* @return SqlCreator_Query_Builder_Select
*/
function on($c1, $op, $c2)
{
$this->_last_join->on($c1, $op, $c2);
return $this;
}
/**
* Creates a "GROUP BY ..." filter.
*
* @param mixed column name or array($column, $alias) or object
* @return SqlCreator_Query_Builder_Select
*/
function group_by($columns)
{
$columns = func_get_args();
$this->_group_by = array_merge($this->_group_by, $columns);
return $this;
}
/**
* Alias of and_having()
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column value
*
* @return SqlCreator_Query_Builder_Select
*/
function having($column, $op, $value = NULL)
{
return $this->and_having($column, $op, $value);
}
/**
* Creates a new "AND HAVING" condition for the query.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column value
*
* @return SqlCreator_Query_Builder_Select
*/
function and_having($column, $op, $value = NULL)
{
$this->_having[] = array('AND' => array($column, $op, $value));
return $this;
}
/**
* Creates a new "OR HAVING" condition for the query.
*
* @param mixed column name or array($column, $alias) or object
* @param string logic operator
* @param mixed column value
*
* @return SqlCreator_Query_Builder_Select
*/
function or_having($column, $op, $value = NULL)
{
$this->_having[] = array('OR' => array($column, $op, $value));
return $this;
}
/**
* Alias of and_having_open()
*
* @return SqlCreator_Query_Builder_Select
*/
function having_open()
{
return $this->and_having_open();
}
/**
* Opens a new "AND HAVING (...)" grouping.
*
* @return SqlCreator_Query_Builder_Select
*/
function and_having_open()
{
$this->_having[] = array('AND' => '(');
return $this;
}
/**
* Opens a new "OR HAVING (...)" grouping.
*
* @return SqlCreator_Query_Builder_Select
*/
function or_having_open()
{
$this->_having[] = array('OR' => '(');
return $this;
}
/**
* Closes an open "AND HAVING (...)" grouping.
*
* @return SqlCreator_Query_Builder_Select
*/
function having_close()
{
return $this->and_having_close();
}
/**
* Closes an open "AND HAVING (...)" grouping.
*
* @return SqlCreator_Query_Builder_Select
*/
function and_having_close()
{
$this->_having[] = array('AND' => ')');
return $this;
}
/**
* Closes an open "OR HAVING (...)" grouping.
*
* @return SqlCreator_Query_Builder_Select
*/
function or_having_close()
{
$this->_having[] = array('OR' => ')');
return $this;
}
/**
* Start returning results after "OFFSET ..."
*
* @param integer starting result number
*
* @return SqlCreator_Query_Builder_Select
*/
function offset($number)
{
$this->_offset = (int) $number;
return $this;
}
/**
* Compile the SQL query and return it.
*
* @return string
*/
function compile()
{
// Callback to quote identifiers
$quote_ident = array($this, '__quote_identifier__');
// Callback to quote tables
$quote_table = array($this, '__quote_table__');
// Start a selection query
$query = 'SELECT ';
if ($this->_distinct === TRUE)
{
// Select only unique results
$query .= 'DISTINCT ';
}
if (empty($this->_select))
{
// Select all columns
$query .= '*';
}
else
{
// Select all columns
$query .= implode(', ', array_unique(array_map($quote_ident, $this->_select)));
}
if ( ! empty($this->_from))
{
// Set tables to select from
$query .= ' FROM '.implode(', ', array_unique(array_map($quote_table, $this->_from)));
}
if ( ! empty($this->_join))
{
// Add tables to join
$query .= ' '.$this->_compile_join($this->_join);
}
if ( ! empty($this->_where))
{
// Add selection conditions
$query .= ' WHERE '.$this->_compile_conditions($this->_where);
}
if ( ! empty($this->_group_by))
{
// Add sorting
$query .= ' GROUP BY '.implode(', ', array_map($quote_ident, $this->_group_by));
}
if ( ! empty($this->_having))
{
// Add filtering conditions
$query .= ' HAVING '.$this->_compile_conditions($this->_having);
}
if ( ! empty($this->_order_by))
{
// Add sorting
$query .= ' '.$this->_compile_order_by($this->_order_by);
}
if ($this->_limit !== NULL)
{
// Add limiting
$query .= ' LIMIT '.$this->_limit;
}
if ($this->_offset !== NULL)
{
// Add offsets
$query .= ' OFFSET '.$this->_offset;
}
return $query;
}
function reset()
{
$this->_select =
$this->_from =
$this->_join =
$this->_where =
$this->_group_by =
$this->_having =
$this->_order_by = array();
$this->_distinct = FALSE;
$this->_limit =
$this->_offset =
$this->_last_join = NULL;
$this->_parameters = array();
return $this;
}
}
分享到:
相关推荐
在"CKettle-Stable-1.1.19.8.zip"压缩包中,主要包含的是CKettle的源代码和相关资源,这为我们提供了深入理解其工作原理和自定义功能的机会。 "CKettle.tar"是压缩包中的主要文件,这是一个Linux/Unix系统中常见的...
Flume-ng-sql-source是Apache Flume的一个扩展插件,主要功能是允许用户从各种数据库中抽取数据并将其传输到其他目的地,如Apache Kafka。在本案例中,我们讨论的是版本1.5.2的发布包,即"flume-ng-sql-source-...
这个"apache-any23-core-1.1.zip"文件包含了Apache Any23的核心组件,版本号为1.1。该压缩包主要服务于那些需要处理和理解语义Web数据的开发者。 Apache Any23的核心功能主要分为以下几个方面: 1. **数据抽取**:...
博客链接:...快递单中抽取关键信息【一】----基于BiGRU+CR+预训练的词向量优化
Flume-ng-sql-source-1.5.2是Apache Flume的一个扩展,它允许Flume从SQL数据库中收集数据。Apache Flume是一个分布式、可靠且可用于有效聚合、移动大量日志数据的系统。"ng"代表"next generation",表明这是Flume的...
综上所述,SQL脚本生成工具是数据库管理员、开发人员和系统架构师不可或缺的工具,它们通过自动化和智能化的方式,极大地简化了数据库管理、迁移和版本控制的工作流程,提高了整个团队的生产力。在实际使用中,选择...
描述中的第4题D选项中,从每个班随机抽取5名学生调查近视眼情况,体现了随机性和全面性,因此更具代表性。 6. **抽样方法的选择** - 描述中的第7题,对于“青少年上网问题”的专题,由于涉及个人隐私,抽样调查...
本文将探讨如何实现一个工具,用于在Oracle和SQL Server数据库之间进行数据的抽取与转换。Oracle是广受欢迎的关系型数据库管理系统,而SQL Server是微软公司推出的另一款强大的数据库平台。在不同的数据库系统间进行...
基于几个可用的NER和RE数据集定义了7个实体标签和9个关系标签。实体(Entity):每个实体都由带有多个属性的T标签标识。关系(Relation):每个关系由R标签标识,该标签可以具有多个属性。
时出现重复数字的错误,V1.1之前版本无此错误 ~感谢石路街道的领导提醒:) 2011-01-08 增加了可选滚动姓名的功能 配置 m_name=[]; 即可 2011-01-08 增加双击数字单独重抽时的提示选项“此号码在以后的环节是否还有...
一旦配置完成,Kettle就能够执行SQL查询、数据抽取、转换和加载等操作。 总结来说,Kettle通过使用JDBC驱动程序(如jTDS)来与SQL Server建立连接。当遇到找不到驱动的错误时,可以下载并正确配置相应的驱动库。...
该软件的版本号“V1.1.1211”暗示了这是一个经过多次迭代和改进的稳定版本,发布日期可能为12月11日。通常,软件的版本号表示其功能、性能和错误修复的更新程度,1.1可能是主要和次要版本,而1211可能是特定的构建或...
针对这一需求,有一个名为"从SQL脚本抽取数据库表名小工具.zip"的压缩包,它包含了一个Python小工具,专门用于从SQL脚本中高效地提取出所有引用的表名。 这个Python小工具的核心功能是利用正则表达式(Regular ...
【标题】"基于Java的开发源码-最快速的Java代码生成器 rapid-generator.zip" 提供的是一个名为 "rapid-generator" 的工具,该工具专为Java开发者设计,旨在加速开发过程,通过自动化代码生成来提高效率。这个工具的...
- Integration Services (SSIS):ETL工具,用于数据抽取、转换和加载。 - Analysis Services (SSAS) 和 Reporting Services (SSRS):商业智能解决方案,提供数据建模和报表生成。 在面试准备过程中,应熟悉以上...
在1.4.3版本中,Flume-ng-sql-source实现了对SQL源的集成,使得用户能够直接从关系型数据库中采集数据。这个功能极大地扩展了Flume的应用场景,尤其是在大数据环境中,对于实时或者近实时的数据流处理,能够方便地将...
OGG增量抽取Oracle业务数据到kafka部署手册 OGG(Oracle GoldenGate)是一种数据集成工具,用于实时集成和复制数据 zwischen Oracle 数据库和 Kafka 消息队列。下面是 OGG 增量抽取 Oracle 业务数据到 Kafka 的部署...
总的来说,"001 SQL数据库提取器-例1" 提供了一个直观易用的平台,使得数据提取不再是一项繁琐的任务。通过熟练掌握并运用这款工具,我们可以更好地发掘数据中的价值,驱动业务发展,助力信息时代的创新。
在数据集成和迁移场景中,SQL Server Integration Services (SSIS) 是一种非常强大的工具,它允许用户轻松地从不同的数据源抽取、转换和加载数据。本文将详细介绍如何利用SSIS将数据从SQL Server 2005迁移到Oracle ...
`NEWID()`函数是SQL Server中的一个内置函数,用于生成一个新的唯一标识符(Unique Identifier),即`uniqueidentifier`类型的值。这个值每次调用时都会不同,并且在整个数据库系统中都是唯一的。这使得`NEWID()`...