# Coverage for Doctrine_Query_Abstract

Back to coverage report

1 | <?php
2 | /*
3 | * $Id: Query.php 1393 2007-05-19 17:49:16Z zYne $
4 | *
5 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | *
17 | * This software consists of voluntary contributions made by many individuals
18 | * and is licensed under the LGPL. For more information, see
19 | * <http://www.phpdoctrine.org>.
20 | */
21 | Doctrine::autoload('Doctrine_Hydrate');
22 | /**
23 | * Doctrine_Query_Abstract
24 | *
25 | * @package Doctrine
26 | * @subpackage Query
27 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
28 | * @link www.phpdoctrine.org
29 | * @since 1.0
30 | * @version $Revision: 1393 $
31 | * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
32 | * @todo See {@link Doctrine_Query}
33 | */
34 | abstract class Doctrine_Query_Abstract
35 | {
36 | /**
37 | * QUERY TYPE CONSTANTS
38 | */
39 |
40 | /**
41 | * constant for SELECT queries
42 | */
43 | const SELECT = 0;
44 |
45 | /**
46 | * constant for DELETE queries
47 | */
48 | const DELETE = 1;
49 |
50 | /**
51 | * constant for UPDATE queries
52 | */
53 | const UPDATE = 2;
54 |
55 | /**
56 | * constant for INSERT queries
57 | */
58 | const INSERT = 3;
59 |
60 | /**
61 | * constant for CREATE queries
62 | */
63 | const CREATE = 4;
64 |
65 | /** @todo document the query states (and the transitions between them). */
66 | /**
67 | * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts.
68 | */
69 | const STATE_CLEAN = 1;
70 |
71 | /**
72 | * A query object is in state DIRTY when it has DQL parts that have not yet been
73 | * parsed/processed.
74 | */
75 | const STATE_DIRTY = 2;
76 |
77 | /**
78 | * A query is in DIRECT state when ... ?
79 | */
80 | const STATE_DIRECT = 3;
81 |
82 | /**
83 | * A query object is on LOCKED state when ... ?
84 | */
85 | const STATE_LOCKED = 4;
86 |
87 | /**
88 | * @var array Table alias map. Keys are SQL aliases and values DQL aliases.
89 | */
90 | protected $_tableAliasMap = array();
91 |
92 | /**
93 | * @var Doctrine_View The view object used by this query, if any.
94 | */
95 | protected $_view;
96 |
97 | /**
98 | * @var integer $_state The current state of this query.
99 | */
100 | protected $_state = Doctrine_Query::STATE_CLEAN;
101 |
102 | /**
103 | * @var array $params The parameters of this query.
104 | */
105 | protected $_params = array('where' => array(),
106 | 'set' => array(),
107 | 'having' => array());
108 |
109 | /* Caching properties */
110 | /**
111 | * @var Doctrine_Cache_Interface The cache driver used for caching result sets.
112 | */
113 | protected $_resultCache;
114 | /**
115 | * @var boolean $_expireResultCache A boolean value that indicates whether or not
116 | * expire the result cache.
117 | */
118 | protected $_expireResultCache = false;
119 | protected $_resultCacheTTL;
120 |
121 | /**
122 | * @var Doctrine_Cache_Interface The cache driver used for caching queries.
123 | */
124 | protected $_queryCache;
125 | protected $_expireQueryCache = false;
126 | protected $_queryCacheTTL;
127 |
128 |
129 | /**
130 | * @var Doctrine_Connection The connection used by this query object.
131 | */
132 | protected $_conn;
133 |
134 |
135 | /**
136 | * @var array $_sqlParts The SQL query string parts. Filled during the DQL parsing process.
137 | */
138 | protected $_sqlParts = array(
139 | 'select' => array(),
140 | 'distinct' => false,
141 | 'forUpdate' => false,
142 | 'from' => array(),
143 | 'set' => array(),
144 | 'join' => array(),
145 | 'where' => array(),
146 | 'groupby' => array(),
147 | 'having' => array(),
148 | 'orderby' => array(),
149 | 'limit' => false,
150 | 'offset' => false,
151 | );
152 |
153 | /**
154 | * @var array $_dqlParts an array containing all DQL query parts
155 | */
156 | protected $_dqlParts = array(
157 | 'from' => array(),
158 | 'select' => array(),
159 | 'forUpdate' => false,
160 | 'set' => array(),
161 | 'join' => array(),
162 | 'where' => array(),
163 | 'groupby' => array(),
164 | 'having' => array(),
165 | 'orderby' => array(),
166 | 'limit' => array(),
167 | 'offset' => array(),
168 | );
169 |
170 |
171 | /**
172 | * @var array $_queryComponents Two dimensional array containing the components of this query,
173 | * informations about their relations and other related information.
174 | * The components are constructed during query parsing.
175 | *
176 | * Keys are component aliases and values the following:
177 | *
178 | * table table object associated with given alias
179 | *
180 | * relation the relation object owned by the parent
181 | *
182 | * parent the alias of the parent
183 | *
184 | * agg the aggregates of this component
185 | *
186 | * map the name of the column / aggregate value this
187 | * component is mapped to a collection
188 | */
189 | protected $_queryComponents = array();
190 |
191 | /**
192 | * @var integer $type the query type
193 | *
194 | * @see Doctrine_Query::* constants
195 | */
196 | protected $_type = self::SELECT;
197 |
198 | /**
199 | * @var Doctrine_Hydrator The hydrator object used to hydrate query results.
200 | */
201 | protected $_hydrator;
202 |
203 | /**
204 | * @var Doctrine_Query_Tokenizer The tokenizer that is used during the query parsing process.
205 | */
206 | protected $_tokenizer;
207 |
208 | /**
209 | * @var Doctrine_Query_Parser The parser that is used for query parsing.
210 | */
211 | protected $_parser;
212 |
213 | /**
214 | * @var array $_tableAliasSeeds A simple array keys representing table aliases and values
215 | * table alias seeds. The seeds are used for generating short table
216 | * aliases.
217 | */
218 | protected $_tableAliasSeeds = array();
219 |
220 | /**
221 | * @var array $_options an array of options
222 | */
223 | protected $_options = array(
224 | 'fetchMode' => Doctrine::FETCH_RECORD
225 | );
226 |
227 | /**
228 | * @var array $_enumParams an array containing the keys of the parameters that should be enumerated
229 | */
230 | protected $_enumParams = array();
231 |
232 | /**
233 | * @var boolean
234 | */
235 | protected $_isLimitSubqueryUsed = false;
236 |
237 |
238 | /**
239 | * Constructor.
240 | *
241 | * @param Doctrine_Connection The connection object the query will use.
242 | * @param Doctrine_Hydrator_Abstract The hydrator that will be used for generating result sets.
243 | */
244 | public function __construct(Doctrine_Connection $connection = null,
245 | Doctrine_Hydrator_Abstract $hydrator = null)
246 | {
247 | if ($connection === null) {
248 | $connection = Doctrine_Manager::getInstance()->getCurrentConnection();
249 | }
250 | if ($hydrator === null) {
251 | $hydrator = new Doctrine_Hydrator();
252 | }
253 | $this->_conn = $connection;
254 | $this->_hydrator = $hydrator;
255 | $this->_tokenizer = new Doctrine_Query_Tokenizer();
256 | }
257 |
258 | /**
259 | * setOption
260 | *
261 | * @param string $name option name
262 | * @param string $value option value
263 | * @return Doctrine_Query this object
264 | */
265 | public function setOption($name, $value)
266 | {
267 | if ( ! isset($this->_options[$name])) {
268 | throw new Doctrine_Query_Exception('Unknown option ' . $name);
269 | }
270 | $this->_options[$name] = $value;
271 | }
272 |
273 | /**
274 | * hasTableAlias
275 | * whether or not this object has given tableAlias
276 | *
277 | * @param string $tableAlias the table alias to be checked
278 | * @return boolean true if this object has given alias, otherwise false
279 | * @deprecated
280 | */
281 | public function hasTableAlias($sqlTableAlias)
282 | {
283 | return $this->hasSqlTableAlias($sqlTableAlias);
284 | }
285 |
286 | /**
287 | * hasSqlTableAlias
288 | * whether or not this object has given tableAlias
289 | *
290 | * @param string $tableAlias the table alias to be checked
291 | * @return boolean true if this object has given alias, otherwise false
292 | */
293 | public function hasSqlTableAlias($sqlTableAlias)
294 | {
295 | return (isset($this->_tableAliasMap[$sqlTableAlias]));
296 | }
297 |
298 | /**
299 | * getTableAliases
300 | * returns all table aliases
301 | *
302 | * @return array table aliases as an array
303 | * @deprecated
304 | */
305 | public function getTableAliases()
306 | {
307 | return $this->getTableAliasMap();
308 | }
309 |
310 | /**
311 | * getTableAliasMap
312 | * returns all table aliases
313 | *
314 | * @return array table aliases as an array
315 | */
316 | public function getTableAliasMap()
317 | {
318 | return $this->_tableAliasMap;
319 | }
320 |
321 | /**
322 | * getQueryPart
323 | * gets a query part from the query part array
324 | *
325 | * @param string $name the name of the query part to be set
326 | * @param string $part query part string
327 | * @throws Doctrine_Query_Exception if trying to set unknown query part
328 | * @return Doctrine_Query_Abstract this object
329 | * @deprecated
330 | */
331 | public function getQueryPart($part)
332 | {
333 | return $this->getSqlQueryPart($part);
334 | }
335 |
336 | /**
337 | * getSqlQueryPart
338 | * gets an SQL query part from the SQL query part array
339 | *
340 | * @param string $name the name of the query part to be set
341 | * @param string $part query part string
342 | * @throws Doctrine_Query_Exception if trying to set unknown query part
343 | * @return Doctrine_Hydrate this object
344 | */
345 | public function getSqlQueryPart($part)
346 | {
347 | if ( ! isset($this->_sqlParts[$part])) {
348 | throw new Doctrine_Query_Exception('Unknown SQL query part ' . $part);
349 | }
350 | return $this->_sqlParts[$part];
351 | }
352 |
353 | /**
354 | * setQueryPart
355 | * sets a query part in the query part array
356 | *
357 | * @param string $name the name of the query part to be set
358 | * @param string $part query part string
359 | * @throws Doctrine_Query_Exception if trying to set unknown query part
360 | * @return Doctrine_Hydrate this object
361 | * @deprecated
362 | */
363 | public function setQueryPart($name, $part)
364 | {
365 | return $this->setSqlQueryPart($name, $part);
366 | }
367 |
368 | /**
369 | * setSqlQueryPart
370 | * sets an SQL query part in the SQL query part array
371 | *
372 | * @param string $name the name of the query part to be set
373 | * @param string $part query part string
374 | * @throws Doctrine_Query_Exception if trying to set unknown query part
375 | * @return Doctrine_Hydrate this object
376 | */
377 | public function setSqlQueryPart($name, $part)
378 | {
379 | if ( ! isset($this->_sqlParts[$name])) {
380 | throw new Doctrine_Query_Exception('Unknown query part ' . $name);
381 | }
382 |
383 | if ($name !== 'limit' && $name !== 'offset') {
384 | if (is_array($part)) {
385 | $this->_sqlParts[$name] = $part;
386 | } else {
387 | $this->_sqlParts[$name] = array($part);
388 | }
389 | } else {
390 | $this->_sqlParts[$name] = $part;
391 | }
392 |
393 | return $this;
394 | }
395 |
396 | /**
397 | * addQueryPart
398 | * adds a query part in the query part array
399 | *
400 | * @param string $name the name of the query part to be added
401 | * @param string $part query part string
402 | * @throws Doctrine_Query_Exception if trying to add unknown query part
403 | * @return Doctrine_Hydrate this object
404 | * @deprecated
405 | */
406 | public function addQueryPart($name, $part)
407 | {
408 | return $this->addSqlQueryPart($name, $part);
409 | }
410 |
411 | /**
412 | * addSqlQueryPart
413 | * adds an SQL query part to the SQL query part array
414 | *
415 | * @param string $name the name of the query part to be added
416 | * @param string $part query part string
417 | * @throws Doctrine_Query_Exception if trying to add unknown query part
418 | * @return Doctrine_Hydrate this object
419 | */
420 | public function addSqlQueryPart($name, $part)
421 | {
422 | if ( ! isset($this->_sqlParts[$name])) {
423 | throw new Doctrine_Query_Exception('Unknown query part ' . $name);
424 | }
425 | if (is_array($part)) {
426 | $this->_sqlParts[$name] = array_merge($this->_sqlParts[$name], $part);
427 | } else {
428 | $this->_sqlParts[$name][] = $part;
429 | }
430 | return $this;
431 | }
432 |
433 | /**
434 | * removeQueryPart
435 | * removes a query part from the query part array
436 | *
437 | * @param string $name the name of the query part to be removed
438 | * @throws Doctrine_Query_Exception if trying to remove unknown query part
439 | * @return Doctrine_Hydrate this object
440 | * @deprecated
441 | */
442 | public function removeQueryPart($name)
443 | {
444 | return $this->removeSqlQueryPart($name);
445 | }
446 |
447 | /**
448 | * removeSqlQueryPart
449 | * removes a query part from the query part array
450 | *
451 | * @param string $name the name of the query part to be removed
452 | * @throws Doctrine_Query_Exception if trying to remove unknown query part
453 | * @return Doctrine_Hydrate this object
454 | */
455 | public function removeSqlQueryPart($name)
456 | {
457 | try {
458 | if ( ! isset($this->_sqlParts[$name])) {
459 | throw new Doctrine_Query_Exception('Unknown query part ' . $name);
460 | }}
461 | catch (Exception $e) {echo $e->getTraceAsString(); echo "<br /><br /><br />";}
462 |
463 | if ($name == 'limit' || $name == 'offset') {
464 | $this->_sqlParts[$name] = false;
465 | } else {
466 | $this->_sqlParts[$name] = array();
467 | }
468 | return $this;
469 | }
470 |
471 | /**
472 | * setView
473 | * sets a database view this query object uses
474 | * this method should only be called internally by doctrine
475 | *
476 | * @param Doctrine_View $view database view
477 | * @return void
478 | */
479 | public function setView(Doctrine_View $view)
480 | {
481 | $this->_view = $view;
482 | }
483 |
484 | /**
485 | * getView
486 | * returns the view associated with this query object (if any)
487 | *
488 | * @return Doctrine_View the view associated with this query object
489 | */
490 | public function getView()
491 | {
492 | return $this->_view;
493 | }
494 |
495 | /**
496 | * limitSubqueryUsed
497 | *
498 | * @return boolean
499 | */
500 | public function isLimitSubqueryUsed()
501 | {
502 | return $this->_isLimitSubqueryUsed;
503 | }
504 |
505 | /**
506 | * convertEnums
507 | * convert enum parameters to their integer equivalents
508 | *
509 | * @return array converted parameter array
510 | */
511 | public function convertEnums($params)
512 | {
513 | foreach ($this->_enumParams as $key => $values) {
514 | if (isset($params[$key])) {
515 | if ( ! empty($values)) {
516 | $params[$key] = $values[0]->enumIndex($values[1], $params[$key]);
517 | }
518 | }
519 | }
520 | return $params;
521 | }
522 |
523 | /**
524 | * applyInheritance
525 | * applies column aggregation inheritance to DQL / SQL query
526 | *
527 | * @return string
528 | */
529 | public function applyInheritance()
530 | {
531 | // get the inheritance maps
532 | $array = array();
533 |
534 | foreach ($this->_queryComponents as $componentAlias => $data) {
535 | $tableAlias = $this->getSqlTableAlias($componentAlias);
536 | $array[$tableAlias][] = $data['table']->inheritanceMap;
537 | }
538 |
539 | // apply inheritance maps
540 | $str = '';
541 | $c = array();
542 |
543 | $index = 0;
544 | foreach ($array as $tableAlias => $maps) {
545 | $a = array();
546 |
547 | // don't use table aliases if the query isn't a select query
548 | if ($this->_type !== Doctrine_Query::SELECT) {
549 | $tableAlias = '';
550 | } else {
551 | $tableAlias .= '.';
552 | }
553 |
554 | foreach ($maps as $map) {
555 | $b = array();
556 | foreach ($map as $field => $value) {
557 | $identifier = $this->_conn->quoteIdentifier($tableAlias . $field);
558 |
559 | if ($index > 0) {
560 | $b[] = '(' . $identifier . ' = ' . $this->_conn->quote($value)
561 | . ' OR ' . $identifier . ' IS NULL)';
562 | } else {
563 | $b[] = $identifier . ' = ' . $this->_conn->quote($value);
564 | }
565 | }
566 |
567 | if ( ! empty($b)) {
568 | $a[] = implode(' AND ', $b);
569 | }
570 | }
571 |
572 | if ( ! empty($a)) {
573 | $c[] = implode(' AND ', $a);
574 | }
575 | $index++;
576 | }
577 |
578 | $str .= implode(' AND ', $c);
579 |
580 | return $str;
581 | }
582 |
583 | /**
584 | * getTableAlias
585 | * some database such as Oracle need the identifier lengths to be < ~30 chars
586 | * hence Doctrine creates as short identifier aliases as possible
587 | *
588 | * this method is used for the creation of short table aliases, its also
589 | * smart enough to check if an alias already exists for given component (componentAlias)
590 | *
591 | * @param string $componentAlias the alias for the query component to search table alias for
592 | * @param string $tableName the table name from which the table alias is being created
593 | * @return string the generated / fetched short alias
594 | * @deprecated
595 | */
596 | public function getTableAlias($componentAlias, $tableName = null)
597 | {
598 | return $this->getSqlTableAlias($componentAlias, $tableName);
599 | }
600 |
601 | /**
602 | * getSqlTableAlias
603 | * some database such as Oracle need the identifier lengths to be < ~30 chars
604 | * hence Doctrine creates as short identifier aliases as possible
605 | *
606 | * this method is used for the creation of short table aliases, its also
607 | * smart enough to check if an alias already exists for given component (componentAlias)
608 | *
609 | * @param string $componentAlias the alias for the query component to search table alias for
610 | * @param string $tableName the table name from which the table alias is being created
611 | * @return string the generated / fetched short alias
612 | */
613 | public function getSqlTableAlias($componentAlias, $tableName = null)
614 | {
615 | $alias = array_search($componentAlias, $this->_tableAliasMap);
616 |
617 | if ($alias !== false) {
618 | return $alias;
619 | }
620 |
621 | if ($tableName === null) {
622 | throw new Doctrine_Query_Exception("Couldn't get short alias for " . $componentAlias);
623 | }
624 |
625 | return $this->generateTableAlias($componentAlias, $tableName);
626 | }
627 |
628 | /**
629 | * generateNewTableAlias
630 | * generates a new alias from given table alias
631 | *
632 | * @param string $tableAlias table alias from which to generate the new alias from
633 | * @return string the created table alias
634 | * @deprecated
635 | */
636 | public function generateNewTableAlias($oldAlias)
637 | {
638 | return $this->generateNewSqlTableAlias($oldAlias);
639 | }
640 |
641 | /**
642 | * generateNewSqlTableAlias
643 | * generates a new alias from given table alias
644 | *
645 | * @param string $tableAlias table alias from which to generate the new alias from
646 | * @return string the created table alias
647 | */
648 | public function generateNewSqlTableAlias($oldAlias)
649 | {
650 | if (isset($this->_tableAliasMap[$oldAlias])) {
651 | // generate a new alias
652 | $name = substr($oldAlias, 0, 1);
653 | $i = ((int) substr($oldAlias, 1));
654 |
655 | if ($i == 0) {
656 | $i = 1;
657 | }
658 |
659 | $newIndex = ($this->_tableAliasSeeds[$name] + $i);
660 |
661 | return $name . $newIndex;
662 | }
663 |
664 | return $oldAlias;
665 | }
666 |
667 | /**
668 | * getTableAliasSeed
669 | * returns the alias seed for given table alias
670 | *
671 | * @param string $tableAlias table alias that identifies the alias seed
672 | * @return integer table alias seed
673 | * @deprecated
674 | */
675 | public function getTableAliasSeed($sqlTableAlias)
676 | {
677 | return $this->getSqlTableAliasSeed($sqlTableAlias);
678 | }
679 |
680 | /**
681 | * getSqlTableAliasSeed
682 | * returns the alias seed for given table alias
683 | *
684 | * @param string $tableAlias table alias that identifies the alias seed
685 | * @return integer table alias seed
686 | */
687 | public function getSqlTableAliasSeed($sqlTableAlias)
688 | {
689 | if ( ! isset($this->_tableAliasSeeds[$sqlTableAlias])) {
690 | return 0;
691 | }
692 | return $this->_tableAliasSeeds[$sqlTableAlias];
693 | }
694 |
695 | /**
696 | * hasAliasDeclaration
697 | * whether or not this object has a declaration for given component alias
698 | *
699 | * @param string $componentAlias the component alias the retrieve the declaration from
700 | * @return boolean
701 | */
702 | public function hasAliasDeclaration($componentAlias)
703 | {
704 | return isset($this->_queryComponents[$componentAlias]);
705 | }
706 |
707 | /**
708 | * getAliasDeclaration
709 | * get the declaration for given component alias
710 | *
711 | * @param string $componentAlias the component alias the retrieve the declaration from
712 | * @return array the alias declaration
713 | * @deprecated
714 | */
715 | public function getAliasDeclaration($componentAlias)
716 | {
717 | return $this->getQueryComponent($componentAlias);
718 | }
719 |
720 | /**
721 | * getQueryComponent
722 | * get the declaration for given component alias
723 | *
724 | * @param string $componentAlias the component alias the retrieve the declaration from
725 | * @return array the alias declaration
726 | */
727 | public function getQueryComponent($componentAlias)
728 | {
729 | if ( ! isset($this->_queryComponents[$componentAlias])) {
730 | throw new Doctrine_Query_Exception('Unknown component alias ' . $componentAlias);
731 | }
732 |
733 | return $this->_queryComponents[$componentAlias];
734 | }
735 |
736 | /**
737 | * copyAliases
738 | * copy aliases from another Hydrate object
739 | *
740 | * this method is needed by DQL subqueries which need the aliases
741 | * of the parent query
742 | *
743 | * @param Doctrine_Hydrate $query the query object from which the
744 | * aliases are copied from
745 | * @return Doctrine_Hydrate this object
746 | */
747 | public function copyAliases(Doctrine_Query_Abstract $query)
748 | {
749 | $this->_tableAliasMap = $query->_tableAliasMap;
750 | $this->_queryComponents = $query->_queryComponents;
751 | $this->_tableAliasSeeds = $query->_tableAliasSeeds;
752 | return $this;
753 | }
754 |
755 | /**
756 | * getRootAlias
757 | * returns the alias of the the root component
758 | *
759 | * @return array
760 | */
761 | public function getRootAlias()
762 | {
763 | if ( ! $this->_queryComponents) {
764 | $this->getSql();
765 | }
766 | reset($this->_queryComponents);
767 |
768 | return key($this->_queryComponents);
769 | }
770 |
771 | /**
772 | * getRootDeclaration
773 | * returns the root declaration
774 | *
775 | * @return array
776 | */
777 | public function getRootDeclaration()
778 | {
779 | $map = reset($this->_queryComponents);
780 | return $map;
781 | }
782 |
783 | /**
784 | * getRoot
785 | * returns the root component for this object
786 | *
787 | * @return Doctrine_Table root components table
788 | */
789 | public function getRoot()
790 | {
791 | $map = reset($this->_queryComponents);
792 |
793 | if ( ! isset($map['table'])) {
794 | throw new Doctrine_Query_Exception('Root component not initialized.');
795 | }
796 |
797 | return $map['table'];
798 | }
799 |
800 | /**
801 | * generateTableAlias
802 | * generates a table alias from given table name and associates
803 | * it with given component alias
804 | *
805 | * @param string $componentAlias the component alias to be associated with generated table alias
806 | * @param string $tableName the table name from which to generate the table alias
807 | * @return string the generated table alias
808 | * @deprecated
809 | */
810 | public function generateTableAlias($componentAlias, $tableName)
811 | {
812 | return $this->generateSqlTableAlias($componentAlias, $tableName);
813 | }
814 |
815 | /**
816 | * generateSqlTableAlias
817 | * generates a table alias from given table name and associates
818 | * it with given component alias
819 | *
820 | * @param string $componentAlias the component alias to be associated with generated table alias
821 | * @param string $tableName the table name from which to generate the table alias
822 | * @return string the generated table alias
823 | */
824 | public function generateSqlTableAlias($componentAlias, $tableName)
825 | {
826 | $char = strtolower(substr($tableName, 0, 1));
827 |
828 | $alias = $char;
829 |
830 | if ( ! isset($this->_tableAliasSeeds[$alias])) {
831 | $this->_tableAliasSeeds[$alias] = 1;
832 | }
833 |
834 | while (isset($this->_tableAliasMap[$alias])) {
835 | if ( ! isset($this->_tableAliasSeeds[$alias])) {
836 | $this->_tableAliasSeeds[$alias] = 1;
837 | }
838 | $alias = $char . ++$this->_tableAliasSeeds[$alias];
839 | }
840 |
841 | $this->_tableAliasMap[$alias] = $componentAlias;
842 |
843 | return $alias;
844 | }
845 |
846 | /**
847 | * getComponentAlias
848 | * get component alias associated with given table alias
849 | *
850 | * @param string $sqlTableAlias the SQL table alias that identifies the component alias
851 | * @return string component alias
852 | */
853 | public function getComponentAlias($sqlTableAlias)
854 | {
855 | if ( ! isset($this->_tableAliasMap[$sqlTableAlias])) {
856 | throw new Doctrine_Query_Exception('Unknown table alias ' . $sqlTableAlias);
857 | }
858 | return $this->_tableAliasMap[$sqlTableAlias];
859 | }
860 |
861 | /**
862 | * _execute
863 | *
864 | * @param array $params
865 | * @return PDOStatement The executed PDOStatement.
866 | */
867 | protected function _execute($params)
868 | {
869 | $params = $this->_conn->convertBooleans($params);
870 |
871 | if ( ! $this->_view) {
872 | if ($this->_queryCache || $this->_conn->getAttribute(Doctrine::ATTR_QUERY_CACHE)) {
873 | $queryCacheDriver = $this->getQueryCacheDriver();
874 | // calculate hash for dql query
875 | $dql = $this->getDql();
876 | $hash = md5($dql . 'DOCTRINE_QUERY_CACHE_SALT');
877 | $cached = $queryCacheDriver->fetch($hash);
878 | if ($cached) {
879 | $query = $this->_constructQueryFromCache($cached);
880 | } else {
881 | $query = $this->getSqlQuery($params);
882 | $serializedQuery = $this->getCachedForm($query);
883 | $queryCacheDriver->save($hash, $serializedQuery, $this->_queryCacheTTL);
884 | }
885 | } else {
886 | $query = $this->getSqlQuery($params);
887 | }
888 | } else {
889 | $query = $this->_view->getSelectSql();
890 | }
891 |
892 | $params = $this->convertEnums($params);
893 |
894 | if ($this->isLimitSubqueryUsed() &&
895 | $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME) !== 'mysql') {
896 | $params = array_merge($params, $params);
897 | }
898 |
899 | if ($this->_type !== self::SELECT) {
900 | return $this->_conn->exec($query, $params);
901 | }
902 |
903 | $stmt = $this->_conn->execute($query, $params);
904 | return $stmt;
905 | }
906 |
907 | /**
908 | * execute
909 | * executes the query and populates the data set
910 | *
911 | * @param string $params
912 | * @return Doctrine_Collection the root collection
913 | */
914 | public function execute($params = array(), $hydrationMode = null)
915 | {
916 | $params = array_merge($this->_params['set'],
917 | $this->_params['where'],
918 | $this->_params['having'],
919 | $params);
920 |
921 | if ($this->_resultCache) {
922 | $cacheDriver = $this->getResultCacheDriver();
923 |
924 | $dql = $this->getDql();
925 | // calculate hash for dql query
926 | $hash = md5($dql . var_export($params, true));
927 |
928 | $cached = ($this->_expireResultCache) ? false : $cacheDriver->fetch($hash);
929 |
930 | if ($cached === false) {
931 | // cache miss
932 | $stmt = $this->_execute($params);
933 | $this->_hydrator->setQueryComponents($this->_queryComponents);
934 | $result = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap,
935 | Doctrine::HYDRATE_ARRAY);
936 |
937 | $cached = $this->getCachedForm($result);
938 | $cacheDriver->save($hash, $cached, $this->_resultCacheTTL);
939 | return $result;
940 | } else {
941 | return $this->_constructQueryFromCache($cached);
942 | }
943 | } else {
944 | $stmt = $this->_execute($params);
945 |
946 | if (is_integer($stmt)) {
947 | return $stmt;
948 | }
949 |
950 | $this->_hydrator->setQueryComponents($this->_queryComponents);
951 | return $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap, $hydrationMode);
952 | }
953 | }
954 |
955 | /**
956 | * Constructs the query from the cached form.
957 | *
958 | * @param string The cached query, in a serialized form.
959 | * @return array The custom component that was cached together with the essential
960 | * query data. This can be either a result set (result caching)
961 | * or an SQL query string (query caching).
962 | */
963 | protected function _constructQueryFromCache($cached)
964 | {
965 | $cached = unserialize($cached);
966 | $this->_tableAliasMap = $cached[2];
967 | $customComponent = $cached[0];
968 |
969 | $queryComponents = array();
970 | $cachedComponents = $cached[1];
971 | foreach ($cachedComponents as $alias => $components) {
972 | $e = explode('.', $components[0]);
973 | if (count($e) === 1) {
974 | $queryComponents[$alias]['table'] = $this->_conn->getTable($e[0]);
975 | } else {
976 | $queryComponents[$alias]['parent'] = $e[0];
977 | $queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getRelation($e[1]);
978 | $queryComponents[$alias]['table'] = $queryComponents[$alias]['relation']->getTable();
979 | }
980 | if (isset($v[1])) {
981 | $queryComponents[$alias]['agg'] = $components[1];
982 | }
983 | if (isset($v[2])) {
984 | $queryComponents[$alias]['map'] = $components[2];
985 | }
986 | }
987 | $this->_queryComponents = $queryComponents;
988 |
989 | return $customComponent;
990 | }
991 |
992 | /**
993 | * getCachedForm
994 | * returns the cached form of this query for given resultSet
995 | *
996 | * @param array $resultSet
997 | * @return string serialized string representation of this query
998 | */
999 | public function getCachedForm($customComponent = null)
1000 | {
1001 | $componentInfo = array();
1002 |
1003 | foreach ($this->getQueryComponents() as $alias => $components) {
1004 | if ( ! isset($components['parent'])) {
1005 | $componentInfo[$alias][] = $components['table']->getComponentName();
1006 | } else {
1007 | $componentInfo[$alias][] = $components['parent'] . '.' . $components['relation']->getAlias();
1008 | }
1009 | if (isset($components['agg'])) {
1010 | $componentInfo[$alias][] = $components['agg'];
1011 | }
1012 | if (isset($components['map'])) {
1013 | $componentInfo[$alias][] = $components['map'];
1014 | }
1015 | }
1016 |
1017 | return serialize(array($customComponent, $componentInfo, $this->getTableAliasMap()));
1018 | }
1019 |
1020 | /**
1021 | * addSelect
1022 | * adds fields to the SELECT part of the query
1023 | *
1024 | * @param string $select Query SELECT part
1025 | * @return Doctrine_Query
1026 | */
1027 | public function addSelect($select)
1028 | {
1029 | return $this->_addDqlQueryPart('select', $select, true);
1030 | }
1031 |
1032 | /**
1033 | * addTableAlias
1034 | * adds an alias for table and associates it with given component alias
1035 | *
1036 | * @param string $componentAlias the alias for the query component associated with given tableAlias
1037 | * @param string $tableAlias the table alias to be added
1038 | * @return Doctrine_Hydrate
1039 | * @deprecated
1040 | */
1041 | public function addTableAlias($tableAlias, $componentAlias)
1042 | {
1043 | return $this->addSqlTableAlias($tableAlias, $componentAlias);
1044 | }
1045 |
1046 | /**
1047 | * addSqlTableAlias
1048 | * adds an SQL table alias and associates it a component alias
1049 | *
1050 | * @param string $componentAlias the alias for the query component associated with given tableAlias
1051 | * @param string $tableAlias the table alias to be added
1052 | * @return Doctrine_Query_Abstract
1053 | */
1054 | public function addSqlTableAlias($sqlTableAlias, $componentAlias)
1055 | {
1056 | $this->_tableAliasMap[$sqlTableAlias] = $componentAlias;
1057 | return $this;
1058 | }
1059 |
1060 | /**
1061 | * addFrom
1062 | * adds fields to the FROM part of the query
1063 | *
1064 | * @param string $from Query FROM part
1065 | * @return Doctrine_Query
1066 | */
1067 | public function addFrom($from)
1068 | {
1069 | return $this->_addDqlQueryPart('from', $from, true);
1070 | }
1071 |
1072 | /**
1073 | * addWhere
1074 | * adds conditions to the WHERE part of the query
1075 | *
1076 | * @param string $where Query WHERE part
1077 | * @param mixed $params an array of parameters or a simple scalar
1078 | * @return Doctrine_Query
1079 | */
1080 | public function addWhere($where, $params = array())
1081 | {
1082 | if (is_array($params)) {
1083 | $this->_params['where'] = array_merge($this->_params['where'], $params);
1084 | } else {
1085 | $this->_params['where'][] = $params;
1086 | }
1087 | return $this->_addDqlQueryPart('where', $where, true);
1088 | }
1089 |
1090 | /**
1091 | * whereIn
1092 | * adds IN condition to the query WHERE part
1093 | *
1094 | * @param string $expr the operand of the IN
1095 | * @param mixed $params an array of parameters or a simple scalar
1096 | * @param boolean $not whether or not to use NOT in front of IN
1097 | * @return Doctrine_Query
1098 | */
1099 | public function whereIn($expr, $params = array(), $not = false)
1100 | {
1101 | $params = (array) $params;
1102 | $a = array();
1103 | foreach ($params as $k => $value) {
1104 | if ($value instanceof Doctrine_Expression) {
1105 | $value = $value->getSql();
1106 | unset($params[$k]);
1107 | } else {
1108 | $value = '?';
1109 | }
1110 | $a[] = $value;
1111 | }
1112 |
1113 | $this->_params['where'] = array_merge($this->_params['where'], $params);
1114 |
1115 | $where = $expr . ($not === true ? ' NOT ':'') . ' IN (' . implode(', ', $a) . ')';
1116 |
1117 | return $this->_addDqlQueryPart('where', $where, true);
1118 | }
1119 |
1120 | /**
1121 | * whereNotIn
1122 | * adds NOT IN condition to the query WHERE part
1123 | *
1124 | * @param string $expr the operand of the NOT IN
1125 | * @param mixed $params an array of parameters or a simple scalar
1126 | * @return Doctrine_Query
1127 | */
1128 | public function whereNotIn($expr, $params = array())
1129 | {
1130 | return $this->whereIn($expr, $params, true);
1131 | }
1132 |
1133 | /**
1134 | * addGroupBy
1135 | * adds fields to the GROUP BY part of the query
1136 | *
1137 | * @param string $groupby Query GROUP BY part
1138 | * @return Doctrine_Query
1139 | */
1140 | public function addGroupBy($groupby)
1141 | {
1142 | return $this->_addDqlQueryPart('groupby', $groupby, true);
1143 | }
1144 |
1145 | /**
1146 | * addHaving
1147 | * adds conditions to the HAVING part of the query
1148 | *
1149 | * @param string $having Query HAVING part
1150 | * @param mixed $params an array of parameters or a simple scalar
1151 | * @return Doctrine_Query
1152 | */
1153 | public function addHaving($having, $params = array())
1154 | {
1155 | if (is_array($params)) {
1156 | $this->_params['having'] = array_merge($this->_params['having'], $params);
1157 | } else {
1158 | $this->_params['having'][] = $params;
1159 | }
1160 | return $this->_addDqlQueryPart('having', $having, true);
1161 | }
1162 |
1163 | /**
1164 | * addOrderBy
1165 | * adds fields to the ORDER BY part of the query
1166 | *
1167 | * @param string $orderby Query ORDER BY part
1168 | * @return Doctrine_Query
1169 | */
1170 | public function addOrderBy($orderby)
1171 | {
1172 | return $this->_addDqlQueryPart('orderby', $orderby, true);
1173 | }
1174 |
1175 | /**
1176 | * select
1177 | * sets the SELECT part of the query
1178 | *
1179 | * @param string $select Query SELECT part
1180 | * @return Doctrine_Query
1181 | */
1182 | public function select($select)
1183 | {
1184 | return $this->_addDqlQueryPart('select', $select);
1185 | }
1186 |
1187 | /**
1188 | * distinct
1189 | * Makes the query SELECT DISTINCT.
1190 | *
1191 | * @param bool $flag Whether or not the SELECT is DISTINCT (default true).
1192 | * @return Doctrine_Query
1193 | */
1194 | public function distinct($flag = true)
1195 | {
1196 | $this->_sqlParts['distinct'] = (bool) $flag;
1197 | return $this;
1198 | }
1199 |
1200 | /**
1201 | * forUpdate
1202 | * Makes the query SELECT FOR UPDATE.
1203 | *
1204 | * @param bool $flag Whether or not the SELECT is FOR UPDATE (default true).
1205 | * @return Doctrine_Query
1206 | */
1207 | public function forUpdate($flag = true)
1208 | {
1209 | $this->_sqlParts[self::FOR_UPDATE] = (bool) $flag;
1210 | return $this;
1211 | }
1212 |
1213 | /**
1214 | * delete
1215 | * sets the query type to DELETE
1216 | *
1217 | * @return Doctrine_Query
1218 | */
1219 | public function delete()
1220 | {
1221 | $this->_type = self::DELETE;
1222 | return $this;
1223 | }
1224 |
1225 | /**
1226 | * update
1227 | * sets the UPDATE part of the query
1228 | *
1229 | * @param string $update Query UPDATE part
1230 | * @return Doctrine_Query
1231 | */
1232 | public function update($update)
1233 | {
1234 | $this->_type = self::UPDATE;
1235 | return $this->_addDqlQueryPart('from', $update);
1236 | }
1237 |
1238 | /**
1239 | * set
1240 | * sets the SET part of the query
1241 | *
1242 | * @param string $update Query UPDATE part
1243 | * @return Doctrine_Query
1244 | */
1245 | public function set($key, $value, $params = null)
1246 | {
1247 | if (is_array($key)) {
1248 | foreach ($key as $k => $v) {
1249 | $this->set($k, '?', array($v));
1250 | }
1251 | return $this;
1252 | } else {
1253 | if ($params !== null) {
1254 | if (is_array($params)) {
1255 | $this->_params['set'] = array_merge($this->_params['set'], $params);
1256 | } else {
1257 | $this->_params['set'][] = $params;
1258 | }
1259 | }
1260 | return $this->_addDqlQueryPart('set', $key . ' = ' . $value, true);
1261 | }
1262 | }
1263 |
1264 | /**
1265 | * from
1266 | * sets the FROM part of the query
1267 | *
1268 | * @param string $from Query FROM part
1269 | * @return Doctrine_Query
1270 | */
1271 | public function from($from)
1272 | {
1273 | return $this->_addDqlQueryPart('from', $from);
1274 | }
1275 |
1276 | /**
1277 | * innerJoin
1278 | * appends an INNER JOIN to the FROM part of the query
1279 | *
1280 | * @param string $join Query INNER JOIN
1281 | * @return Doctrine_Query
1282 | */
1283 | public function innerJoin($join)
1284 | {
1285 | return $this->_addDqlQueryPart('from', 'INNER JOIN ' . $join, true);
1286 | }
1287 |
1288 | /**
1289 | * leftJoin
1290 | * appends a LEFT JOIN to the FROM part of the query
1291 | *
1292 | * @param string $join Query LEFT JOIN
1293 | * @return Doctrine_Query
1294 | */
1295 | public function leftJoin($join)
1296 | {
1297 | return $this->_addDqlQueryPart('from', 'LEFT JOIN ' . $join, true);
1298 | }
1299 |
1300 | /**
1301 | * groupBy
1302 | * sets the GROUP BY part of the query
1303 | *
1304 | * @param string $groupby Query GROUP BY part
1305 | * @return Doctrine_Query
1306 | */
1307 | public function groupBy($groupby)
1308 | {
1309 | return $this->_addDqlQueryPart('groupby', $groupby);
1310 | }
1311 |
1312 | /**
1313 | * where
1314 | * sets the WHERE part of the query
1315 | *
1316 | * @param string $join Query WHERE part
1317 | * @param mixed $params an array of parameters or a simple scalar
1318 | * @return Doctrine_Query
1319 | */
1320 | public function where($where, $params = array())
1321 | {
1322 | $this->_params['where'] = array();
1323 | if (is_array($params)) {
1324 | $this->_params['where'] = $params;
1325 | } else {
1326 | $this->_params['where'][] = $params;
1327 | }
1328 |
1329 | return $this->_addDqlQueryPart('where', $where);
1330 | }
1331 |
1332 | /**
1333 | * having
1334 | * sets the HAVING part of the query
1335 | *
1336 | * @param string $having Query HAVING part
1337 | * @param mixed $params an array of parameters or a simple scalar
1338 | * @return Doctrine_Query
1339 | */
1340 | public function having($having, $params = array())
1341 | {
1342 | $this->_params['having'] = array();
1343 | if (is_array($params)) {
1344 | $this->_params['having'] = $params;
1345 | } else {
1346 | $this->_params['having'][] = $params;
1347 | }
1348 |
1349 | return $this->_addDqlQueryPart('having', $having);
1350 | }
1351 |
1352 | /**
1353 | * orderBy
1354 | * sets the ORDER BY part of the query
1355 | *
1356 | * @param string $orderby Query ORDER BY part
1357 | * @return Doctrine_Query
1358 | */
1359 | public function orderBy($orderby)
1360 | {
1361 | return $this->_addDqlQueryPart('orderby', $orderby);
1362 | }
1363 |
1364 | /**
1365 | * limit
1366 | * sets the Query query limit
1367 | *
1368 | * @param integer $limit limit to be used for limiting the query results
1369 | * @return Doctrine_Query
1370 | */
1371 | public function limit($limit)
1372 | {
1373 | return $this->_addDqlQueryPart('limit', $limit);
1374 | }
1375 |
1376 | /**
1377 | * offset
1378 | * sets the Query query offset
1379 | *
1380 | * @param integer $offset offset to be used for paginating the query
1381 | * @return Doctrine_Query
1382 | */
1383 | public function offset($offset)
1384 | {
1385 | return $this->_addDqlQueryPart('offset', $offset);
1386 | }
1387 |
1388 | /**
1389 | * getSql
1390 | * shortcut for {@link getSqlQuery()}.
1391 | *
1392 | * @return string sql query string
1393 | */
1394 | public function getSql()
1395 | {
1396 | return $this->getSqlQuery();
1397 | }
1398 |
1399 | /**
1400 | * clear
1401 | * resets all the variables
1402 | *
1403 | * @return void
1404 | */
1405 | protected function clear()
1406 | {
1407 | $this->_sqlParts = array(
1408 | 'select' => array(),
1409 | 'distinct' => false,
1410 | 'forUpdate' => false,
1411 | 'from' => array(),
1412 | 'set' => array(),
1413 | 'join' => array(),
1414 | 'where' => array(),
1415 | 'groupby' => array(),
1416 | 'having' => array(),
1417 | 'orderby' => array(),
1418 | 'limit' => false,
1419 | 'offset' => false,
1420 | );
1421 | }
1422 |
1423 | public function setHydrationMode($hydrationMode)
1424 | {
1425 | $this->_hydrator->setHydrationMode($hydrationMode);
1426 | return $this;
1427 | }
1428 |
1429 | /**
1430 | * @deprecated
1431 | */
1432 | public function getAliasMap()
1433 | {
1434 | return $this->_queryComponents;
1435 | }
1436 |
1437 | /**
1438 | * Gets the components of this query.
1439 | */
1440 | public function getQueryComponents()
1441 | {
1442 | return $this->_queryComponents;
1443 | }
1444 |
1445 | /**
1446 | * Return the SQL parts.
1447 | *
1448 | * @return array The parts
1449 | * @deprecated
1450 | */
1451 | public function getParts()
1452 | {
1453 | return $this->getSqlParts();
1454 | }
1455 |
1456 | /**
1457 | * Return the SQL parts.
1458 | *
1459 | * @return array The parts
1460 | */
1461 | public function getSqlParts()
1462 | {
1463 | return $this->_sqlParts;
1464 | }
1465 |
1466 | /**
1467 | * getType
1468 | *
1469 | * returns the type of this query object
1470 | * by default the type is Doctrine_Query_Abstract::SELECT but if update() or delete()
1471 | * are being called the type is Doctrine_Query_Abstract::UPDATE and Doctrine_Query_Abstract::DELETE,
1472 | * respectively
1473 | *
1474 | * @see Doctrine_Query_Abstract::SELECT
1475 | * @see Doctrine_Query_Abstract::UPDATE
1476 | * @see Doctrine_Query_Abstract::DELETE
1477 | *
1478 | * @return integer return the query type
1479 | */
1480 | public function getType()
1481 | {
1482 | return $this->_type;
1483 | }
1484 |
1485 | /**
1486 | * useCache
1487 | *
1488 | * @param Doctrine_Cache_Interface|bool $driver cache driver
1489 | * @param integer $timeToLive how long the cache entry is valid
1490 | * @return Doctrine_Hydrate this object
1491 | * @deprecated Use useResultCache()
1492 | */
1493 | public function useCache($driver = true, $timeToLive = null)
1494 | {
1495 | return $this->useResultCache($driver, $timeToLive);
1496 | }
1497 |
1498 | /**
1499 | * useResultCache
1500 | *
1501 | * @param Doctrine_Cache_Interface|bool $driver cache driver
1502 | * @param integer $timeToLive how long the cache entry is valid
1503 | * @return Doctrine_Hydrate this object
1504 | */
1505 | public function useResultCache($driver = true, $timeToLive = null)
1506 | {
1507 | if ($driver !== null && $driver !== true && ! ($driver instanceOf Doctrine_Cache_Interface)){
1508 | $msg = 'First argument should be instance of Doctrine_Cache_Interface or null.';
1509 | throw new Doctrine_Query_Exception($msg);
1510 | }
1511 | $this->_resultCache = $driver;
1512 |
1513 | return $this->setResultCacheLifeSpan($timeToLive);
1514 | }
1515 |
1516 | /**
1517 | * useQueryCache
1518 | *
1519 | * @param Doctrine_Cache_Interface|bool $driver cache driver
1520 | * @param integer $timeToLive how long the cache entry is valid
1521 | * @return Doctrine_Hydrate this object
1522 | */
1523 | public function useQueryCache(Doctrine_Cache_Interface $driver, $timeToLive = null)
1524 | {
1525 | $this->_queryCache = $driver;
1526 | return $this->setQueryCacheLifeSpan($timeToLive);
1527 | }
1528 |
1529 | /**
1530 | * expireCache
1531 | *
1532 | * @param boolean $expire whether or not to force cache expiration
1533 | * @return Doctrine_Hydrate this object
1534 | * @deprecated Use expireResultCache()
1535 | */
1536 | public function expireCache($expire = true)
1537 | {
1538 | return $this->expireResultCache($expire);
1539 | }
1540 |
1541 | /**
1542 | * expireCache
1543 | *
1544 | * @param boolean $expire whether or not to force cache expiration
1545 | * @return Doctrine_Hydrate this object
1546 | */
1547 | public function expireResultCache($expire = true)
1548 | {
1549 | $this->_expireResultCache = true;
1550 | return $this;
1551 | }
1552 |
1553 | /**
1554 | * expireQueryCache
1555 | *
1556 | * @param boolean $expire whether or not to force cache expiration
1557 | * @return Doctrine_Hydrate this object
1558 | */
1559 | public function expireQueryCache($expire = true)
1560 | {
1561 | $this->_expireQueryCache = true;
1562 | return $this;
1563 | }
1564 |
1565 | /**
1566 | * setCacheLifeSpan
1567 | *
1568 | * @param integer $timeToLive how long the cache entry is valid
1569 | * @return Doctrine_Hydrate this object
1570 | * @deprecated Use setResultCacheLifeSpan()
1571 | */
1572 | public function setCacheLifeSpan($timeToLive)
1573 | {
1574 | return $this->setResultCacheLifeSpan($timeToLive);
1575 | }
1576 |
1577 | /**
1578 | * setResultCacheLifeSpan
1579 | *
1580 | * @param integer $timeToLive how long the cache entry is valid
1581 | * @return Doctrine_Hydrate this object
1582 | */
1583 | public function setResultCacheLifeSpan($timeToLive)
1584 | {
1585 | if ($timeToLive !== null) {
1586 | $timeToLive = (int) $timeToLive;
1587 | }
1588 | $this->_resultCacheTTL = $timeToLive;
1589 |
1590 | return $this;
1591 | }
1592 |
1593 | /**
1594 | * setQueryCacheLifeSpan
1595 | *
1596 | * @param integer $timeToLive how long the cache entry is valid
1597 | * @return Doctrine_Hydrate this object
1598 | */
1599 | public function setQueryCacheLifeSpan($timeToLive)
1600 | {
1601 | if ($timeToLive !== null) {
1602 | $timeToLive = (int) $timeToLive;
1603 | }
1604 | $this->_queryCacheTTL = $timeToLive;
1605 |
1606 | return $this;
1607 | }
1608 |
1609 | /**
1610 | * getCacheDriver
1611 | * returns the cache driver associated with this object
1612 | *
1613 | * @return Doctrine_Cache_Interface|boolean|null cache driver
1614 | * @deprecated Use getResultCacheDriver()
1615 | */
1616 | public function getCacheDriver()
1617 | {
1618 | return $this->getResultCacheDriver();
1619 | }
1620 |
1621 | /**
1622 | * getResultCacheDriver
1623 | * returns the cache driver used for caching result sets
1624 | *
1625 | * @return Doctrine_Cache_Interface|boolean|null cache driver
1626 | */
1627 | public function getResultCacheDriver()
1628 | {
1629 | if ($this->_resultCache instanceof Doctrine_Cache_Interface) {
1630 | return $this->_resultCache;
1631 | } else {
1632 | return $this->_conn->getResultCacheDriver();
1633 | }
1634 | }
1635 |
1636 | /**
1637 | * getQueryCacheDriver
1638 | * returns the cache driver used for caching queries
1639 | *
1640 | * @return Doctrine_Cache_Interface|boolean|null cache driver
1641 | */
1642 | public function getQueryCacheDriver()
1643 | {
1644 | if ($this->_queryCache instanceof Doctrine_Cache_Interface) {
1645 | return $this->_queryCache;
1646 | } else {
1647 | return $this->_conn->getQueryCacheDriver();
1648 | }
1649 | }
1650 |
1651 | /**
1652 | * getConnection
1653 | *
1654 | * @return Doctrine_Connection
1655 | */
1656 | public function getConnection()
1657 | {
1658 | return $this->_conn;
1659 | }
1660 |
1661 | /**
1662 | * Adds a DQL part to the internal parts collection.
1663 | *
1664 | * @param string $queryPartName The name of the query part.
1665 | * @param string $queryPart The actual query part to add.
1666 | * @param boolean $append Whether to append $queryPart to already existing
1667 | * parts under the same $queryPartName. Defaults to FALSE
1668 | * (previously added parts with the same name get overridden).
1669 | */
1670 | protected function _addDqlQueryPart($queryPartName, $queryPart, $append = false)
1671 | {
1672 | if ($append) {
1673 | $this->_dqlParts[$queryPartName][] = $queryPart;
1674 | } else {
1675 | $this->_dqlParts[$queryPartName] = array($queryPart);
1676 | }
1677 |
1678 | $this->_state = Doctrine_Query::STATE_DIRTY;
1679 | return $this;
1680 | }
1681 |
1682 | /**
1683 | * _processDqlQueryPart
1684 | * parses given query part
1685 | *
1686 | * @param string $queryPartName the name of the query part
1687 | * @param array $queryParts an array containing the query part data
1688 | * @return Doctrine_Query this object
1689 | * @todo Better description. "parses given query part" ??? Then wheres the difference
1690 | * between process/parseQueryPart? I suppose this does something different.
1691 | */
1692 | protected function _processDqlQueryPart($queryPartName, $queryParts)
1693 | {
1694 | $this->removeSqlQueryPart($queryPartName);
1695 |
1696 | if (is_array($queryParts) && ! empty($queryParts)) {
1697 | foreach ($queryParts as $queryPart) {
1698 | $parser = $this->_getParser($queryPartName);
1699 | $sql = $parser->parse($queryPart);
1700 | if (isset($sql)) {
1701 | if ($queryPartName == 'limit' || $queryPartName == 'offset') {
1702 | $this->setSqlQueryPart($queryPartName, $sql);
1703 | } else {
1704 | $this->addSqlQueryPart($queryPartName, $sql);
1705 | }
1706 | }
1707 | }
1708 | }
1709 | }
1710 |
1711 | /**
1712 | * _getParser
1713 | * parser lazy-loader
1714 | *
1715 | * @throws Doctrine_Query_Exception if unknown parser name given
1716 | * @return Doctrine_Query_Part
1717 | * @todo Doc/Description: What is the parameter for? Which parsers are available?
1718 | */
1719 | protected function _getParser($name)
1720 | {
1721 | if ( ! isset($this->_parsers[$name])) {
1722 | $class = 'Doctrine_Query_' . ucwords(strtolower($name));
1723 |
1724 | Doctrine::autoload($class);
1725 |
1726 | if ( ! class_exists($class)) {
1727 | throw new Doctrine_Query_Exception('Unknown parser ' . $name);
1728 | }
1729 |
1730 | $this->_parsers[$name] = new $class($this, $this->_tokenizer);
1731 | }
1732 |
1733 | return $this->_parsers[$name];
1734 | }
1735 |
1736 | /**
1737 | * Gets the SQL query that corresponds to this query object.
1738 | * The returned SQL syntax depends on the connection driver that is used
1739 | * by this query object at the time of this method call.
1740 | *
1741 | * @param array $params
1742 | */
1743 | abstract public function getSqlQuery($params = array());
1744 |
1745 | /**
1746 | * parseDqlQuery
1747 | * parses a dql query
1748 | *
1749 | * @param string $query query to be parsed
1750 | * @return Doctrine_Query_Abstract this object
1751 | */
1752 | abstract public function parseDqlQuery($query);
1753 |
1754 | /**
1755 | * @deprecated
1756 | */
1757 | public function parseQuery($query)
1758 | {
1759 | return $this->parseDqlQuery($query);
1760 | }
1761 |
1762 | /**
1763 | * @deprecated
1764 | */
1765 | public function getQuery($params = array())
1766 | {
1767 | return $this->getSqlQuery($params);
1768 | }
1769 | }