00001 <?php
00027 require_once 'Zend/Db/Adapter/Abstract.php';
00028
00032 require_once 'Zend/Db/Expr.php';
00033
00034
00044 class Zend_Db_Select
00045 {
00046
00047 const DISTINCT = 'distinct';
00048 const COLUMNS = 'columns';
00049 const FROM = 'from';
00050 const UNION = 'union';
00051 const WHERE = 'where';
00052 const GROUP = 'group';
00053 const HAVING = 'having';
00054 const ORDER = 'order';
00055 const LIMIT_COUNT = 'limitcount';
00056 const LIMIT_OFFSET = 'limitoffset';
00057 const FOR_UPDATE = 'forupdate';
00058
00059 const INNER_JOIN = 'inner join';
00060 const LEFT_JOIN = 'left join';
00061 const RIGHT_JOIN = 'right join';
00062 const FULL_JOIN = 'full join';
00063 const CROSS_JOIN = 'cross join';
00064 const NATURAL_JOIN = 'natural join';
00065
00066 const SQL_WILDCARD = '*';
00067 const SQL_SELECT = 'SELECT';
00068 const SQL_UNION = 'UNION';
00069 const SQL_UNION_ALL = 'UNION ALL';
00070 const SQL_FROM = 'FROM';
00071 const SQL_WHERE = 'WHERE';
00072 const SQL_DISTINCT = 'DISTINCT';
00073 const SQL_GROUP_BY = 'GROUP BY';
00074 const SQL_ORDER_BY = 'ORDER BY';
00075 const SQL_HAVING = 'HAVING';
00076 const SQL_FOR_UPDATE = 'FOR UPDATE';
00077 const SQL_AND = 'AND';
00078 const SQL_AS = 'AS';
00079 const SQL_OR = 'OR';
00080 const SQL_ON = 'ON';
00081 const SQL_ASC = 'ASC';
00082 const SQL_DESC = 'DESC';
00083
00089 protected $_bind = array();
00090
00096 protected $_adapter;
00097
00105 protected static $_partsInit = array(
00106 self::DISTINCT => false,
00107 self::COLUMNS => array(),
00108 self::UNION => array(),
00109 self::FROM => array(),
00110 self::WHERE => array(),
00111 self::GROUP => array(),
00112 self::HAVING => array(),
00113 self::ORDER => array(),
00114 self::LIMIT_COUNT => null,
00115 self::LIMIT_OFFSET => null,
00116 self::FOR_UPDATE => false
00117 );
00118
00124 protected static $_joinTypes = array(
00125 self::INNER_JOIN,
00126 self::LEFT_JOIN,
00127 self::RIGHT_JOIN,
00128 self::FULL_JOIN,
00129 self::CROSS_JOIN,
00130 self::NATURAL_JOIN,
00131 );
00132
00138 protected static $_unionTypes = array(
00139 self::SQL_UNION,
00140 self::SQL_UNION_ALL
00141 );
00142
00149 protected $_parts = array();
00150
00156 protected $_tableCols = array();
00157
00163 public function __construct(Zend_Db_Adapter_Abstract $adapter)
00164 {
00165 $this->_adapter = $adapter;
00166 $this->_parts = self::$_partsInit;
00167 }
00168
00174 public function getBind()
00175 {
00176 return $this->_bind;
00177 }
00178
00185 public function bind($bind)
00186 {
00187 $this->_bind = $bind;
00188
00189 return $this;
00190 }
00191
00198 public function distinct($flag = true)
00199 {
00200 $this->_parts[self::DISTINCT] = (bool) $flag;
00201 return $this;
00202 }
00203
00228 public function from($name, $cols = '*', $schema = null)
00229 {
00230 return $this->_join(self::FROM, $name, null, $cols, $schema);
00231 }
00232
00243 public function columns($cols = '*', $correlationName = null)
00244 {
00245 if ($correlationName === null && count($this->_parts[self::FROM])) {
00246 $correlationName = current(array_keys($this->_parts[self::FROM]));
00247 }
00248
00249 if (!array_key_exists($correlationName, $this->_parts[self::FROM])) {
00253 require_once 'Zend/Db/Select/Exception.php';
00254 throw new Zend_Db_Select_Exception("No table has been specified for the FROM clause");
00255 }
00256
00257 $this->_tableCols($correlationName, $cols);
00258
00259 return $this;
00260 }
00261
00271 public function union($select = array(), $type = self::SQL_UNION)
00272 {
00273 if (!is_array($select)) {
00274 $select = array();
00275 }
00276
00277 if (!in_array($type, self::$_unionTypes)) {
00278 require_once 'Zend/Db/Select/Exception.php';
00279 throw new Zend_Db_Select_Exception("Invalid union type '{$type}'");
00280 }
00281
00282 foreach ($select as $target) {
00283 $this->_parts[self::UNION][] = array($target, $type);
00284 }
00285
00286 return $this;
00287 }
00288
00301 public function join($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
00302 {
00303 return $this->joinInner($name, $cond, $cols, $schema);
00304 }
00305
00322 public function joinInner($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
00323 {
00324 return $this->_join(self::INNER_JOIN, $name, $cond, $cols, $schema);
00325 }
00326
00343 public function joinLeft($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
00344 {
00345 return $this->_join(self::LEFT_JOIN, $name, $cond, $cols, $schema);
00346 }
00347
00365 public function joinRight($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
00366 {
00367 return $this->_join(self::RIGHT_JOIN, $name, $cond, $cols, $schema);
00368 }
00369
00387 public function joinFull($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
00388 {
00389 return $this->_join(self::FULL_JOIN, $name, $cond, $cols, $schema);
00390 }
00391
00404 public function joinCross($name, $cols = self::SQL_WILDCARD, $schema = null)
00405 {
00406 return $this->_join(self::CROSS_JOIN, $name, null, $cols, $schema);
00407 }
00408
00424 public function joinNatural($name, $cols = self::SQL_WILDCARD, $schema = null)
00425 {
00426 return $this->_join(self::NATURAL_JOIN, $name, null, $cols, $schema);
00427 }
00428
00461 public function where($cond, $value = null, $type = null)
00462 {
00463 $this->_parts[self::WHERE][] = $this->_where($cond, $value, $type, true);
00464
00465 return $this;
00466 }
00467
00480 public function orWhere($cond, $value = null, $type = null)
00481 {
00482 $this->_parts[self::WHERE][] = $this->_where($cond, $value, $type, false);
00483
00484 return $this;
00485 }
00486
00493 public function group($spec)
00494 {
00495 if (!is_array($spec)) {
00496 $spec = array($spec);
00497 }
00498
00499 foreach ($spec as $val) {
00500 if (preg_match('/\(.*\)/', (string) $val)) {
00501 $val = new Zend_Db_Expr($val);
00502 }
00503 $this->_parts[self::GROUP][] = $val;
00504 }
00505
00506 return $this;
00507 }
00508
00520 public function having($cond)
00521 {
00522 if (func_num_args() > 1) {
00523 $val = func_get_arg(1);
00524 $cond = $this->_adapter->quoteInto($cond, $val);
00525 }
00526
00527 if ($this->_parts[self::HAVING]) {
00528 $this->_parts[self::HAVING][] = self::SQL_AND . " ($cond)";
00529 } else {
00530 $this->_parts[self::HAVING][] = "($cond)";
00531 }
00532
00533 return $this;
00534 }
00535
00547 public function orHaving($cond)
00548 {
00549 if (func_num_args() > 1) {
00550 $val = func_get_arg(1);
00551 $cond = $this->_adapter->quoteInto($cond, $val);
00552 }
00553
00554 if ($this->_parts[self::HAVING]) {
00555 $this->_parts[self::HAVING][] = self::SQL_OR . " ($cond)";
00556 } else {
00557 $this->_parts[self::HAVING][] = "($cond)";
00558 }
00559
00560 return $this;
00561 }
00562
00569 public function order($spec)
00570 {
00571 if (!is_array($spec)) {
00572 $spec = array($spec);
00573 }
00574
00575
00576 foreach ($spec as $val) {
00577 if ($val instanceof Zend_Db_Expr) {
00578 $expr = $val->__toString();
00579 if (empty($expr)) {
00580 continue;
00581 }
00582 $this->_parts[self::ORDER][] = $val;
00583 } else {
00584 if (empty($val)) {
00585 continue;
00586 }
00587 $direction = self::SQL_ASC;
00588 if (preg_match('/(.*\W)(' . self::SQL_ASC . '|' . self::SQL_DESC . ')\b/si', $val, $matches)) {
00589 $val = trim($matches[1]);
00590 $direction = $matches[2];
00591 }
00592 if (preg_match('/\(.*\)/', $val)) {
00593 $val = new Zend_Db_Expr($val);
00594 }
00595 $this->_parts[self::ORDER][] = array($val, $direction);
00596 }
00597 }
00598
00599 return $this;
00600 }
00601
00609 public function limit($count = null, $offset = null)
00610 {
00611 $this->_parts[self::LIMIT_COUNT] = (int) $count;
00612 $this->_parts[self::LIMIT_OFFSET] = (int) $offset;
00613 return $this;
00614 }
00615
00623 public function limitPage($page, $rowCount)
00624 {
00625 $page = ($page > 0) ? $page : 1;
00626 $rowCount = ($rowCount > 0) ? $rowCount : 1;
00627 $this->_parts[self::LIMIT_COUNT] = (int) $rowCount;
00628 $this->_parts[self::LIMIT_OFFSET] = (int) $rowCount * ($page - 1);
00629 return $this;
00630 }
00631
00638 public function forUpdate($flag = true)
00639 {
00640 $this->_parts[self::FOR_UPDATE] = (bool) $flag;
00641 return $this;
00642 }
00643
00651 public function getPart($part)
00652 {
00653 $part = strtolower($part);
00654 if (!array_key_exists($part, $this->_parts)) {
00655 require_once 'Zend/Db/Select/Exception.php';
00656 throw new Zend_Db_Select_Exception("Invalid Select part '$part'");
00657 }
00658 return $this->_parts[$part];
00659 }
00660
00668 public function query($fetchMode = null, $bind = array())
00669 {
00670 if (!empty($bind)) {
00671 $this->bind($bind);
00672 }
00673
00674 $stmt = $this->_adapter->query($this);
00675 if ($fetchMode == null) {
00676 $fetchMode = $this->_adapter->getFetchMode();
00677 }
00678 $stmt->setFetchMode($fetchMode);
00679 return $stmt;
00680 }
00681
00687 public function assemble()
00688 {
00689 $sql = self::SQL_SELECT;
00690 foreach (array_keys(self::$_partsInit) as $part) {
00691 $method = '_render' . ucfirst($part);
00692 if (method_exists($this, $method)) {
00693 $sql = $this->$method($sql);
00694 }
00695 }
00696 return $sql;
00697 }
00698
00705 public function reset($part = null)
00706 {
00707 if ($part == null) {
00708 $this->_parts = self::$_partsInit;
00709 } else if (array_key_exists($part, self::$_partsInit)) {
00710 $this->_parts[$part] = self::$_partsInit[$part];
00711 }
00712 return $this;
00713 }
00714
00721 public function getAdapter()
00722 {
00723 return $this->_adapter;
00724 }
00725
00742 protected function _join($type, $name, $cond, $cols, $schema = null)
00743 {
00744 if (!in_array($type, self::$_joinTypes) && $type != self::FROM) {
00748 require_once 'Zend/Db/Select/Exception.php';
00749 throw new Zend_Db_Select_Exception("Invalid join type '$type'");
00750 }
00751
00752 if (count($this->_parts[self::UNION])) {
00753 require_once 'Zend/Db/Select/Exception.php';
00754 throw new Zend_Db_Select_Exception("Invalid use of table with " . self::SQL_UNION);
00755 }
00756
00757 if (empty($name)) {
00758 $correlationName = $tableName = '';
00759 } else if (is_array($name)) {
00760
00761 foreach ($name as $_correlationName => $_tableName) {
00762 if (is_string($_correlationName)) {
00763
00764 $tableName = $_tableName;
00765 $correlationName = $_correlationName;
00766 } else {
00767
00768 $tableName = $_tableName;
00769 $correlationName = $this->_uniqueCorrelation($tableName);
00770 }
00771 break;
00772 }
00773 } else if ($name instanceof Zend_Db_Expr|| $name instanceof Zend_Db_Select) {
00774 $tableName = $name;
00775 $correlationName = $this->_uniqueCorrelation('t');
00776 } else if (preg_match('/^(.+)\s+AS\s+(.+)$/i', $name, $m)) {
00777 $tableName = $m[1];
00778 $correlationName = $m[2];
00779 } else {
00780 $tableName = $name;
00781 $correlationName = $this->_uniqueCorrelation($tableName);
00782 }
00783
00784
00785 if (!is_object($tableName) && false !== strpos($tableName, '.')) {
00786 list($schema, $tableName) = explode('.', $tableName);
00787 }
00788
00789 $lastFromCorrelationName = null;
00790 if (!empty($correlationName)) {
00791 if (array_key_exists($correlationName, $this->_parts[self::FROM])) {
00795 require_once 'Zend/Db/Select/Exception.php';
00796 throw new Zend_Db_Select_Exception("You cannot define a correlation name '$correlationName' more than once");
00797 }
00798
00799 if ($type == self::FROM) {
00800
00801 $tmpFromParts = $this->_parts[self::FROM];
00802 $this->_parts[self::FROM] = array();
00803
00804 while ($tmpFromParts) {
00805 $currentCorrelationName = key($tmpFromParts);
00806 if ($tmpFromParts[$currentCorrelationName]['joinType'] != self::FROM) {
00807 break;
00808 }
00809 $lastFromCorrelationName = $currentCorrelationName;
00810 $this->_parts[self::FROM][$currentCorrelationName] = array_shift($tmpFromParts);
00811 }
00812 } else {
00813 $tmpFromParts = array();
00814 }
00815 $this->_parts[self::FROM][$correlationName] = array(
00816 'joinType' => $type,
00817 'schema' => $schema,
00818 'tableName' => $tableName,
00819 'joinCondition' => $cond
00820 );
00821 while ($tmpFromParts) {
00822 $currentCorrelationName = key($tmpFromParts);
00823 $this->_parts[self::FROM][$currentCorrelationName] = array_shift($tmpFromParts);
00824 }
00825 }
00826
00827
00828 if ($type == self::FROM && $lastFromCorrelationName == null) {
00829 $lastFromCorrelationName = true;
00830 }
00831 $this->_tableCols($correlationName, $cols, $lastFromCorrelationName);
00832
00833 return $this;
00834 }
00835
00861 public function _joinUsing($type, $name, $cond, $cols = '*', $schema = null)
00862 {
00863 if (empty($this->_parts[self::FROM])) {
00864 require_once 'Zend/Db/Select/Exception.php';
00865 throw new Zend_Db_Select_Exception("You can only perform a joinUsing after specifying a FROM table");
00866 }
00867
00868 $join = $this->_adapter->quoteIdentifier(key($this->_parts[self::FROM]), true);
00869 $from = $this->_adapter->quoteIdentifier($this->_uniqueCorrelation($name), true);
00870
00871 $cond1 = $from . '.' . $cond;
00872 $cond2 = $join . '.' . $cond;
00873 $cond = $cond1 . ' = ' . $cond2;
00874
00875 return $this->_join($type, $name, $cond, $cols, $schema);
00876 }
00877
00884 private function _uniqueCorrelation($name)
00885 {
00886 if (is_array($name)) {
00887 $c = end($name);
00888 } else {
00889
00890 $dot = strrpos($name,'.');
00891 $c = ($dot === false) ? $name : substr($name, $dot+1);
00892 }
00893 for ($i = 2; array_key_exists($c, $this->_parts[self::FROM]); ++$i) {
00894 $c = $name . '_' . (string) $i;
00895 }
00896 return $c;
00897 }
00898
00908 protected function _tableCols($correlationName, $cols, $afterCorrelationName = null)
00909 {
00910 if (!is_array($cols)) {
00911 $cols = array($cols);
00912 }
00913
00914 if ($correlationName == null) {
00915 $correlationName = '';
00916 }
00917
00918 $columnValues = array();
00919
00920 foreach (array_filter($cols) as $alias => $col) {
00921 $currentCorrelationName = $correlationName;
00922 if (is_string($col)) {
00923
00924 if (preg_match('/^(.+)\s+' . self::SQL_AS . '\s+(.+)$/i', $col, $m)) {
00925 $col = $m[1];
00926 $alias = $m[2];
00927 }
00928
00929 if (preg_match('/\(.*\)/', $col)) {
00930 $col = new Zend_Db_Expr($col);
00931 } elseif (preg_match('/(.+)\.(.+)/', $col, $m)) {
00932 $currentCorrelationName = $m[1];
00933 $col = $m[2];
00934 }
00935 }
00936 $columnValues[] = array($currentCorrelationName, $col, is_string($alias) ? $alias : null);
00937 }
00938
00939 if ($columnValues) {
00940
00941
00942 if ($afterCorrelationName === true || is_string($afterCorrelationName)) {
00943 $tmpColumns = $this->_parts[self::COLUMNS];
00944 $this->_parts[self::COLUMNS] = array();
00945 } else {
00946 $tmpColumns = array();
00947 }
00948
00949
00950 if (is_string($afterCorrelationName)) {
00951 while ($tmpColumns) {
00952 $this->_parts[self::COLUMNS][] = $currentColumn = array_shift($tmpColumns);
00953 if ($currentColumn[0] == $afterCorrelationName) {
00954 break;
00955 }
00956 }
00957 }
00958
00959
00960 foreach ($columnValues as $columnValue) {
00961 array_push($this->_parts[self::COLUMNS], $columnValue);
00962 }
00963
00964
00965 while ($tmpColumns) {
00966 array_push($this->_parts[self::COLUMNS], array_shift($tmpColumns));
00967 }
00968 }
00969 }
00970
00980 protected function _where($condition, $value = null, $type = null, $bool = true)
00981 {
00982 if (count($this->_parts[self::UNION])) {
00983 require_once 'Zend/Db/Select/Exception.php';
00984 throw new Zend_Db_Select_Exception("Invalid use of where clause with " . self::SQL_UNION);
00985 }
00986
00987 if ($value !== null) {
00988 $condition = $this->_adapter->quoteInto($condition, $value, $type);
00989 }
00990
00991 $cond = "";
00992 if ($this->_parts[self::WHERE]) {
00993 if ($bool === true) {
00994 $cond = self::SQL_AND . ' ';
00995 } else {
00996 $cond = self::SQL_OR . ' ';
00997 }
00998 }
00999
01000 return $cond . "($condition)";
01001 }
01002
01006 protected function _getDummyTable()
01007 {
01008 return array();
01009 }
01010
01017 protected function _getQuotedSchema($schema = null)
01018 {
01019 if ($schema === null) {
01020 return null;
01021 }
01022 return $this->_adapter->quoteIdentifier($schema, true) . '.';
01023 }
01024
01032 protected function _getQuotedTable($tableName, $correlationName = null)
01033 {
01034 return $this->_adapter->quoteTableAs($tableName, $correlationName, true);
01035 }
01036
01043 protected function _renderDistinct($sql)
01044 {
01045 if ($this->_parts[self::DISTINCT]) {
01046 $sql .= ' ' . self::SQL_DISTINCT;
01047 }
01048
01049 return $sql;
01050 }
01051
01058 protected function _renderColumns($sql)
01059 {
01060 if (!count($this->_parts[self::COLUMNS])) {
01061 return null;
01062 }
01063
01064 $columns = array();
01065 foreach ($this->_parts[self::COLUMNS] as $columnEntry) {
01066 list($correlationName, $column, $alias) = $columnEntry;
01067 if ($column instanceof Zend_Db_Expr) {
01068 $columns[] = $this->_adapter->quoteColumnAs($column, $alias, true);
01069 } else {
01070 if ($column == self::SQL_WILDCARD) {
01071 $column = new Zend_Db_Expr(self::SQL_WILDCARD);
01072 $alias = null;
01073 }
01074 if (empty($correlationName)) {
01075 $columns[] = $this->_adapter->quoteColumnAs($column, $alias, true);
01076 } else {
01077 $columns[] = $this->_adapter->quoteColumnAs(array($correlationName, $column), $alias, true);
01078 }
01079 }
01080 }
01081
01082 return $sql .= ' ' . implode(', ', $columns);
01083 }
01084
01091 protected function _renderFrom($sql)
01092 {
01093
01094
01095
01096
01097 if (empty($this->_parts[self::FROM])) {
01098 $this->_parts[self::FROM] = $this->_getDummyTable();
01099 }
01100
01101 $from = array();
01102
01103 foreach ($this->_parts[self::FROM] as $correlationName => $table) {
01104 $tmp = '';
01105
01106 $joinType = ($table['joinType'] == self::FROM) ? self::INNER_JOIN : $table['joinType'];
01107
01108
01109 if (! empty($from)) {
01110 $tmp .= ' ' . strtoupper($joinType) . ' ';
01111 }
01112
01113 $tmp .= $this->_getQuotedSchema($table['schema']);
01114 $tmp .= $this->_getQuotedTable($table['tableName'], $correlationName);
01115
01116
01117 if (!empty($from) && ! empty($table['joinCondition'])) {
01118 $tmp .= ' ' . self::SQL_ON . ' ' . $table['joinCondition'];
01119 }
01120
01121
01122 $from[] = $tmp;
01123 }
01124
01125
01126 if (!empty($from)) {
01127 $sql .= ' ' . self::SQL_FROM . ' ' . implode("\n", $from);
01128 }
01129
01130 return $sql;
01131 }
01132
01139 protected function _renderUnion($sql)
01140 {
01141 if ($this->_parts[self::UNION]) {
01142 $parts = count($this->_parts[self::UNION]);
01143 foreach ($this->_parts[self::UNION] as $cnt => $union) {
01144 list($target, $type) = $union;
01145 if ($target instanceof Zend_Db_Select) {
01146 $target = $target->assemble();
01147 }
01148 $sql .= $target;
01149 if ($cnt < $parts - 1) {
01150 $sql .= ' ' . $type . ' ';
01151 }
01152 }
01153 }
01154
01155 return $sql;
01156 }
01157
01164 protected function _renderWhere($sql)
01165 {
01166 if ($this->_parts[self::FROM] && $this->_parts[self::WHERE]) {
01167 $sql .= ' ' . self::SQL_WHERE . ' ' . implode(' ', $this->_parts[self::WHERE]);
01168 }
01169
01170 return $sql;
01171 }
01172
01179 protected function _renderGroup($sql)
01180 {
01181 if ($this->_parts[self::FROM] && $this->_parts[self::GROUP]) {
01182 $group = array();
01183 foreach ($this->_parts[self::GROUP] as $term) {
01184 $group[] = $this->_adapter->quoteIdentifier($term, true);
01185 }
01186 $sql .= ' ' . self::SQL_GROUP_BY . ' ' . implode(",\n\t", $group);
01187 }
01188
01189 return $sql;
01190 }
01191
01198 protected function _renderHaving($sql)
01199 {
01200 if ($this->_parts[self::FROM] && $this->_parts[self::HAVING]) {
01201 $sql .= ' ' . self::SQL_HAVING . ' ' . implode(' ', $this->_parts[self::HAVING]);
01202 }
01203
01204 return $sql;
01205 }
01206
01213 protected function _renderOrder($sql)
01214 {
01215 if ($this->_parts[self::ORDER]) {
01216 $order = array();
01217 foreach ($this->_parts[self::ORDER] as $term) {
01218 if (is_array($term)) {
01219 if(is_numeric($term[0]) && strval(intval($term[0])) == $term[0]) {
01220 $order[] = (int)trim($term[0]) . ' ' . $term[1];
01221 } else {
01222 $order[] = $this->_adapter->quoteIdentifier($term[0], true) . ' ' . $term[1];
01223 }
01224 } else if (is_numeric($term) && strval(intval($term)) == $term) {
01225 $order[] = (int)trim($term);
01226 } else {
01227 $order[] = $this->_adapter->quoteIdentifier($term, true);
01228 }
01229 }
01230 $sql .= ' ' . self::SQL_ORDER_BY . ' ' . implode(', ', $order);
01231 }
01232
01233 return $sql;
01234 }
01235
01242 protected function _renderLimitoffset($sql)
01243 {
01244 $count = 0;
01245 $offset = 0;
01246
01247 if (!empty($this->_parts[self::LIMIT_OFFSET])) {
01248 $offset = (int) $this->_parts[self::LIMIT_OFFSET];
01249 $count = PHP_INT_MAX;
01250 }
01251
01252 if (!empty($this->_parts[self::LIMIT_COUNT])) {
01253 $count = (int) $this->_parts[self::LIMIT_COUNT];
01254 }
01255
01256
01257
01258
01259 if ($count > 0) {
01260 $sql = trim($this->_adapter->limit($sql, $count, $offset));
01261 }
01262
01263 return $sql;
01264 }
01265
01272 protected function _renderForupdate($sql)
01273 {
01274 if ($this->_parts[self::FOR_UPDATE]) {
01275 $sql .= ' ' . self::SQL_FOR_UPDATE;
01276 }
01277
01278 return $sql;
01279 }
01280
01290 public function __call($method, array $args)
01291 {
01292 $matches = array();
01293
01300 if (preg_match('/^join([a-zA-Z]*?)Using$/', $method, $matches)) {
01301 $type = strtolower($matches[1]);
01302 if ($type) {
01303 $type .= ' join';
01304 if (!in_array($type, self::$_joinTypes)) {
01305 require_once 'Zend/Db/Select/Exception.php';
01306 throw new Zend_Db_Select_Exception("Unrecognized method '$method()'");
01307 }
01308 if (in_array($type, array(self::CROSS_JOIN, self::NATURAL_JOIN))) {
01309 require_once 'Zend/Db/Select/Exception.php';
01310 throw new Zend_Db_Select_Exception("Cannot perform a joinUsing with method '$method()'");
01311 }
01312 } else {
01313 $type = self::INNER_JOIN;
01314 }
01315 array_unshift($args, $type);
01316 return call_user_func_array(array($this, '_joinUsing'), $args);
01317 }
01318
01319 require_once 'Zend/Db/Select/Exception.php';
01320 throw new Zend_Db_Select_Exception("Unrecognized method '$method()'");
01321 }
01322
01328 public function __toString()
01329 {
01330 try {
01331 $sql = $this->assemble();
01332 } catch (Exception $e) {
01333 trigger_error($e->getMessage(), E_USER_WARNING);
01334 $sql = '';
01335 }
01336 return (string)$sql;
01337 }
01338
01339 }