📄 select.php
字号:
<?php/** * Zend Framework * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://framework.zend.com/license/new-bsd * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * * @category Zend * @package Zend_Db * @subpackage Select * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id: Select.php 163 2008-01-14 04:40:16Z matt $ *//** * @see Zend_Db_Adapter_Abstract */require_once 'Zend/Db/Adapter/Abstract.php';/** * @see Zend_Db_Expr */require_once 'Zend/Db/Expr.php';/** * Class for SQL SELECT generation and results. * * @category Zend * @package Zend_Db * @subpackage Select * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */class Zend_Db_Select{ const DISTINCT = 'distinct'; const FOR_UPDATE = 'forupdate'; const COLUMNS = 'columns'; const FROM = 'from'; const WHERE = 'where'; const GROUP = 'group'; const HAVING = 'having'; const ORDER = 'order'; const LIMIT_COUNT = 'limitcount'; const LIMIT_OFFSET = 'limitoffset'; const INNER_JOIN = 'inner join'; const LEFT_JOIN = 'left join'; const RIGHT_JOIN = 'right join'; const FULL_JOIN = 'full join'; const CROSS_JOIN = 'cross join'; const NATURAL_JOIN = 'natural join'; /** * Zend_Db_Adapter_Abstract object. * * @var Zend_Db_Adapter_Abstract */ protected $_adapter; /** * The initial values for the $_parts array. * * @var array */ protected static $_partsInit = array( self::DISTINCT => false, self::FOR_UPDATE => false, self::COLUMNS => array(), self::FROM => array(), self::WHERE => array(), self::GROUP => array(), self::HAVING => array(), self::ORDER => array(), self::LIMIT_COUNT => null, self::LIMIT_OFFSET => null, ); /** * The component parts of a SELECT statement. * Initialized to the $_partsInit array in the constructor. * * @var array */ protected $_parts = array(); /** * Tracks which columns are being select from each table and join. * * @var array */ protected $_tableCols = array(); /** * Class constructor * * @param Zend_Db_Adapter_Abstract $adapter */ public function __construct(Zend_Db_Adapter_Abstract $adapter) { $this->_adapter = $adapter; $this->_parts = self::$_partsInit; } /** * Converts this object to an SQL SELECT string. * * @return string This object as a SELECT string. */ public function __toString() { // initial SELECT [DISTINCT] [FOR UPDATE] $sql = 'SELECT'; if ($this->_parts[self::DISTINCT]) { $sql .= ' DISTINCT'; } if ($this->_parts[self::FOR_UPDATE]) { $sql .= ' FOR UPDATE'; } $sql .= "\n\t"; // add columns $columns = array(); foreach ($this->_parts[self::COLUMNS] as $columnEntry) { list($correlationName, $column, $alias) = $columnEntry; if ($column instanceof Zend_Db_Expr) { $columns[] = $this->_adapter->quoteColumnAs($column, $alias, true); } else { if ($column == '*') { $column = new Zend_Db_Expr('*'); $alias = null; } if (empty($correlationName)) { $columns[] = $this->_adapter->quoteColumnAs($column, $alias, true); } else { $columns[] = $this->_adapter->quoteColumnAs(array($correlationName, $column), $alias, true); } } } $sql .= implode(",\n\t", $columns); // from these joined tables if ($this->_parts[self::FROM]) { $from = array(); foreach ($this->_parts[self::FROM] as $correlationName => $table) { $tmp = ''; if (empty($from)) { // Add schema if available if (null !== $table['schema']) { $tmp .= $this->_adapter->quoteIdentifier($table['schema'], true) . '.'; } // First table is named alone ignoring join information $tmp .= $this->_adapter->quoteTableAs($table['tableName'], $correlationName, true); } else { // Subsequent tables may have joins if (! empty($table['joinType'])) { $tmp .= ' ' . strtoupper($table['joinType']) . ' '; } // Add schema if available if (null !== $table['schema']) { $tmp .= $this->_adapter->quoteIdentifier($table['schema'], true) . '.'; } $tmp .= $this->_adapter->quoteTableAs($table['tableName'], $correlationName, true); if (! empty($table['joinCondition'])) { $tmp .= ' ON ' . $table['joinCondition']; } } // add the table name and condition // add to the list $from[] = $tmp; } // add the list of all joins if (!empty($from)) { $sql .= "\nFROM " . implode("\n", $from); } // with these where conditions if ($this->_parts[self::WHERE]) { $sql .= "\nWHERE\n\t"; $sql .= implode("\n\t", $this->_parts[self::WHERE]); } // grouped by these columns if ($this->_parts[self::GROUP]) { $sql .= "\nGROUP BY\n\t"; $l = array(); foreach ($this->_parts[self::GROUP] as $term) { $l[] = $this->_adapter->quoteIdentifier($term, true); } $sql .= implode(",\n\t", $l); } // having these conditions if ($this->_parts[self::HAVING]) { $sql .= "\nHAVING\n\t"; $sql .= implode("\n\t", $this->_parts[self::HAVING]); } } // ordered by these columns if ($this->_parts[self::ORDER]) { $sql .= "\nORDER BY\n\t"; $l = array(); foreach ($this->_parts[self::ORDER] as $term) { if (is_array($term)) { $l[] = $this->_adapter->quoteIdentifier($term[0], true) . ' ' . $term[1]; } else { $l[] = $this->_adapter->quoteIdentifier($term, true); } } $sql .= implode(",\n\t", $l); } // determine offset $count = 0; $offset = 0; if (!empty($this->_parts[self::LIMIT_OFFSET])) { $offset = (int) $this->_parts[self::LIMIT_OFFSET]; // this should be reduced to the max integer PHP can support $count = intval(9223372036854775807); } // determine count if (!empty($this->_parts[self::LIMIT_COUNT])) { $count = (int) $this->_parts[self::LIMIT_COUNT]; } // add limits clause if ($count > 0) { $sql .= "\n"; $sql = trim($this->_adapter->limit($sql, $count, $offset)); } return $sql; } /** * Makes the query SELECT DISTINCT. * * @param bool $flag Whether or not the SELECT is DISTINCT (default true). * @return Zend_Db_Select This Zend_Db_Select object. */ public function distinct($flag = true) { $this->_parts[self::DISTINCT] = (bool) $flag; return $this; } /** * Makes the query SELECT FOR UPDATE. * * @param bool $flag Whether or not the SELECT is FOR UPDATE (default true). * @return Zend_Db_Select This Zend_Db_Select object. */ public function forUpdate($flag = true) { $this->_parts[self::FOR_UPDATE] = (bool) $flag; return $this; } /** * Adds a FROM table and optional columns to the query. * * The first parameter $name can be a simple string, in which case the * correlation name is generated automatically. If you want to specify * the correlation name, the first parameter must be an associative * array in which the key is the physical table name, and the value is * the correlation name. For example, array('table' => 'alias'). * The correlation name is prepended to all columns fetched for this * table. * * The second parameter can be a single string or Zend_Db_Expr object, * or else an array of strings or Zend_Db_Expr objects. * * The first parameter can be null or an empty string, in which case * no correlation name is generated or prepended to the columns named * in the second parameter. * * @param array|string|Zend_Db_Expr $name The table name or an associative array relating table name to * correlation name. * @param array|string|Zend_Db_Expr $cols The columns to select from this table. * @param string $schema The schema name to specify, if any. * @return Zend_Db_Select This Zend_Db_Select object. */ public function from($name, $cols = '*', $schema = null) { return $this->joinInner($name, null, $cols, $schema); } /** * Populate the {@link $_parts} 'join' key * * Does the dirty work of populating the join key. * * The $name and $cols parameters follow the same logic * as described in the from() method. * * @param null|string $type Type of join; inner, left, and null are currently supported * @param array|string|Zend_Db_Expr $name Table name * @param string $cond Join on this condition * @param array|string $cols The columns to select from the joined table * @param string $schema The database name to specify, if any. * @return Zend_Db_Select This Zend_Db_Select object * @throws Zend_Db_Select_Exception */ protected function _join($type, $name, $cond, $cols, $schema = null) { $joinTypes = array(self::INNER_JOIN, self::LEFT_JOIN, self::RIGHT_JOIN, self::FULL_JOIN, self::CROSS_JOIN, self::NATURAL_JOIN); if (!in_array($type, $joinTypes)) { /** * @see Zend_Db_Select_Exception */ require_once 'Zend/Db/Select/Exception.php'; throw new Zend_Db_Select_Exception("Invalid join type '$type'"); } if (empty($name)) { $correlationName = $tableName = ''; } else if (is_array($name)) { // Must be array($correlationName => $tableName) or array($ident, ...) foreach ($name as $_correlationName => $_tableName) { if (is_string($_correlationName)) { // We assume the key is the correlation name and value is the table name $tableName = $_tableName; $correlationName = $_correlationName; } else { // We assume just an array of identifiers, with no correlation name $tableName = $name; $correlationName = $this->_uniqueCorrelation($tableName); } break; } } else if ($name instanceof Zend_Db_Expr) { $tableName = $name; $correlationName = $this->_uniqueCorrelation('t'); } else if (preg_match('/^(.+)\s+AS\s+(.+)$/i', $name, $m)) { $tableName = $m[1]; $correlationName = $m[2]; } else { $tableName = $name; $correlationName = $this->_uniqueCorrelation($tableName); } // Schema from table name overrides schema argument if (false !== strpos($tableName, '.')) { list($schema, $tableName) = explode('.', $tableName); } if (!empty($correlationName)) { if (array_key_exists($correlationName, $this->_parts[self::FROM])) { /** * @see Zend_Db_Select_Exception */ require_once 'Zend/Db/Select/Exception.php'; throw new Zend_Db_Select_Exception("You cannot define a correlation name '$correlationName' more than once"); } $this->_parts[self::FROM][$correlationName] = array( 'joinType' => $type, 'schema' => $schema, 'tableName' => $tableName, 'joinCondition' => $cond ); } // add to the columns from this joined table $this->_tableCols($correlationName, $cols); return $this; } /** * Generate a unique correlation name * * @param string|array $name A qualified identifier. * @return string A unique correlation name. */ private function _uniqueCorrelation($name) { if (is_array($name)) { $c = end($name); } else { // Extract just the last name of a qualified table name $dot = strrpos($name,'.'); $c = ($dot === false) ? $name : substr($name, $dot+1); } for ($i = 2; array_key_exists($c, $this->_parts[self::FROM]); ++$i) { $c = $name . '_' . (string) $i; } return $c; } /** * Adds a JOIN table and columns to the query. * * The $name and $cols parameters follow the same logic * as described in the from() method. * * @param array|string|Zend_Db_Expr $name The table name. * @param string $cond Join on this condition. * @param array|string $cols The columns to select from the joined table. * @param string $schema The database name to specify, if any. * @return Zend_Db_Select This Zend_Db_Select object. */ public function join($name, $cond, $cols = '*', $schema = null) { return $this->joinInner($name, $cond, $cols); } /** * Add an INNER JOIN table and colums to the query * Rows in both tables are matched according to the expression * in the $cond argument. The result set is comprised * of all cases where rows from the left table match
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -