`

抽取个sql生成器工具 -- 摘自 fuelphp1.1 版本

 
阅读更多
<?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-Stable-1.1.19.8.zip"压缩包中,主要包含的是CKettle的源代码和相关资源,这为我们提供了深入理解其工作原理和自定义功能的机会。 "CKettle.tar"是压缩包中的主要文件,这是一个Linux/Unix系统中常见的...

    flume-ng-sql-source-release-1.5.2.zip

    Flume-ng-sql-source是Apache Flume的一个扩展插件,主要功能是允许用户从各种数据库中抽取数据并将其传输到其他目的地,如Apache Kafka。在本案例中,我们讨论的是版本1.5.2的发布包,即"flume-ng-sql-source-...

    apache-any23-core-1.1.zip

    这个"apache-any23-core-1.1.zip"文件包含了Apache Any23的核心组件,版本号为1.1。该压缩包主要服务于那些需要处理和理解语义Web数据的开发者。 Apache Any23的核心功能主要分为以下几个方面: 1. **数据抽取**:...

    数据集: 快递单中抽取关键信息【一】----基于BiGRU+CR+预训练的词向量优化

    博客链接:...快递单中抽取关键信息【一】----基于BiGRU+CR+预训练的词向量优化

    flume-ng-sql-source-1.5.2

    Flume-ng-sql-source-1.5.2是Apache Flume的一个扩展,它允许Flume从SQL数据库中收集数据。Apache Flume是一个分布式、可靠且可用于有效聚合、移动大量日志数据的系统。"ng"代表"next generation",表明这是Flume的...

    SQL脚本生成工具

    综上所述,SQL脚本生成工具是数据库管理员、开发人员和系统架构师不可或缺的工具,它们通过自动化和智能化的方式,极大地简化了数据库管理、迁移和版本控制的工作流程,提高了整个团队的生产力。在实际使用中,选择...

    【全程复习方略】2014-2015学年高中数学 1.1 从普查到抽样课时提升作业 北师大版必修3

    描述中的第4题D选项中,从每个班随机抽取5名学生调查近视眼情况,体现了随机性和全面性,因此更具代表性。 6. **抽样方法的选择** - 描述中的第7题,对于“青少年上网问题”的专题,由于涉及个人隐私,抽样调查...

    实现ORACLE与SQLSERVER数据库间的数据抽取与转换工具

    本文将探讨如何实现一个工具,用于在Oracle和SQL Server数据库之间进行数据的抽取与转换。Oracle是广受欢迎的关系型数据库管理系统,而SQL Server是微软公司推出的另一款强大的数据库平台。在不同的数据库系统间进行...

    中文实体关系抽取数据集 Chinese-Literature-NER-RE-Dataset

    基于几个可用的NER和RE数据集定义了7个实体标签和9个关系标签。实体(Entity):每个实体都由带有多个属性的T标签标识。关系(Relation):每个关系由R标签标识,该标签可以具有多个属性。

    晚会抽奖系统

    时出现重复数字的错误,V1.1之前版本无此错误 ~感谢石路街道的领导提醒:) 2011-01-08 增加了可选滚动姓名的功能 配置 m_name=[]; 即可 2011-01-08 增加双击数字单独重抽时的提示选项“此号码在以后的环节是否还有...

    Kettle SQL server驱动jtds-1.3.1.zip

    一旦配置完成,Kettle就能够执行SQL查询、数据抽取、转换和加载等操作。 总结来说,Kettle通过使用JDBC驱动程序(如jTDS)来与SQL Server建立连接。当遇到找不到驱动的错误时,可以下载并正确配置相应的驱动库。...

    年会抽奖软件-免费版V1.1.1211

    该软件的版本号“V1.1.1211”暗示了这是一个经过多次迭代和改进的稳定版本,发布日期可能为12月11日。通常,软件的版本号表示其功能、性能和错误修复的更新程度,1.1可能是主要和次要版本,而1211可能是特定的构建或...

    从SQL脚本抽取数据库表名小工具.zip

    针对这一需求,有一个名为"从SQL脚本抽取数据库表名小工具.zip"的压缩包,它包含了一个Python小工具,专门用于从SQL脚本中高效地提取出所有引用的表名。 这个Python小工具的核心功能是利用正则表达式(Regular ...

    基于java的开发源码-最快速的Java代码生成器 rapid-generator.zip

    【标题】"基于Java的开发源码-最快速的Java代码生成器 rapid-generator.zip" 提供的是一个名为 "rapid-generator" 的工具,该工具专为Java开发者设计,旨在加速开发过程,通过自动化代码生成来提高效率。这个工具的...

    SQL面试经典版-整理篇

    - Integration Services (SSIS):ETL工具,用于数据抽取、转换和加载。 - Analysis Services (SSAS) 和 Reporting Services (SSRS):商业智能解决方案,提供数据建模和报表生成。 在面试准备过程中,应熟悉以上...

    flume-ng-sql-source-1.4.3.jar

    在1.4.3版本中,Flume-ng-sql-source实现了对SQL源的集成,使得用户能够直接从关系型数据库中采集数据。这个功能极大地扩展了Flume的应用场景,尤其是在大数据环境中,对于实时或者近实时的数据流处理,能够方便地将...

    OGG增量抽取Oracle业务数据到kafka-部署手册.doc

    OGG增量抽取Oracle业务数据到kafka部署手册 OGG(Oracle GoldenGate)是一种数据集成工具,用于实时集成和复制数据 zwischen Oracle 数据库和 Kafka 消息队列。下面是 OGG 增量抽取 Oracle 业务数据到 Kafka 的部署...

    001 SQL数据库提取器-例1.zip_数据提取器

    总的来说,"001 SQL数据库提取器-例1" 提供了一个直观易用的平台,使得数据提取不再是一项繁琐的任务。通过熟练掌握并运用这款工具,我们可以更好地发掘数据中的价值,驱动业务发展,助力信息时代的创新。

    通过SSIS导入数据(SQL Server2005-->Oracle11g)

    在数据集成和迁移场景中,SQL Server Integration Services (SSIS) 是一种非常强大的工具,它允许用户轻松地从不同的数据源抽取、转换和加载数据。本文将详细介绍如何利用SSIS将数据从SQL Server 2005迁移到Oracle ...

    SQL 随机抽取数据

    `NEWID()`函数是SQL Server中的一个内置函数,用于生成一个新的唯一标识符(Unique Identifier),即`uniqueidentifier`类型的值。这个值每次调用时都会不同,并且在整个数据库系统中都是唯一的。这使得`NEWID()`...

Global site tag (gtag.js) - Google Analytics