Expr.php 16.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<?php
/*
 *  $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\ORM\Query;

/**
 * This class is used to generate DQL expressions via a set of PHP static functions
 *
27 28 29 30 31 32 33
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link    www.doctrine-project.org
 * @since   2.0
 * @version $Revision$
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
34
 * @todo Rename: ExpressionBuilder
35 36 37
 */
class Expr
{
38
    /**
39 40 41
     * Creates a conjunction of the given boolean expressions.
     * 
     * Example:
42 43 44
     *
     *     [php]
     *     // (u.type = ?1) AND (u.role = ?2)
45
     *     $expr->andX('u.type = ?1', 'u.role = ?2'));
46 47 48 49 50
     *
     * @param mixed $x Optional clause. Defaults = null, but requires
     *                 at least one defined when converting to string.
     * @return Expr\Andx
     */
51
    public function andX($x = null)
52
    {
53
        return new Expr\Andx(func_get_args());
54 55
    }

56
    /**
57 58 59
     * Creates a disjunction of the given boolean expressions.
     * 
     * Example:
60 61 62
     *
     *     [php]
     *     // (u.type = ?1) OR (u.role = ?2)
63
     *     $q->where($q->expr()->orX('u.type = ?1', 'u.role = ?2'));
64 65 66 67 68
     *
     * @param mixed $x Optional clause. Defaults = null, but requires
     *                 at least one defined when converting to string.
     * @return Expr\Orx
     */
69
    public function orX($x = null)
70
    {
71
        return new Expr\Orx(func_get_args());
72
    }
73
    
74
    /**
75 76 77 78
     * Creates an ASCending order expression.
     * 
     * @param $sort
     * @return OrderBy
79
     */
80
    public function asc($expr)
81
    {
82
        return new Expr\OrderBy($expr, 'ASC');
83
    }
84
    
85
    /**
86 87 88 89
     * Creates a DESCending order expression.
     * 
     * @param $sort
     * @return OrderBy
90
     */
91
    public function desc($expr)
92
    {
93
        return new Expr\OrderBy($expr, 'DESC');
94
    }
95

96
    /**
97 98
     * Creates an equality comparison expression with the given arguments.
     * 
99 100 101 102 103
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> = <right expr>. Example:
     *
     *     [php]
     *     // u.id = ?1
104
     *     $expr->eq('u.id', '?1');
105 106 107 108 109
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
110
    public function eq($x, $y)
111
    {
112
        return new Expr\Comparison($x, Expr\Comparison::EQ, $y);
113 114
    }

115 116 117 118 119 120 121
    /**
     * Creates an instance of Expr\Comparison, with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> <> <right expr>. Example:
     *
     *     [php]
     *     // u.id <> ?1
122
     *     $q->where($q->expr()->neq('u.id', '?1'));
123 124 125 126 127
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
128
    public function neq($x, $y)
129
    {
130
        return new Expr\Comparison($x, Expr\Comparison::NEQ, $y);
131 132
    }

133 134 135 136 137 138 139
    /**
     * Creates an instance of Expr\Comparison, with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> < <right expr>. Example:
     *
     *     [php]
     *     // u.id < ?1
140
     *     $q->where($q->expr()->lt('u.id', '?1'));
141 142 143 144 145
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
146
    public function lt($x, $y)
147
    {
148
        return new Expr\Comparison($x, Expr\Comparison::LT, $y);
149 150
    }

151 152 153 154 155 156 157
    /**
     * Creates an instance of Expr\Comparison, with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> <= <right expr>. Example:
     *
     *     [php]
     *     // u.id <= ?1
158
     *     $q->where($q->expr()->lte('u.id', '?1'));
159 160 161 162 163
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
164
    public function lte($x, $y)
165
    {
166
        return new Expr\Comparison($x, Expr\Comparison::LTE, $y);
167 168
    }

169 170 171 172 173 174 175
    /**
     * Creates an instance of Expr\Comparison, with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> > <right expr>. Example:
     *
     *     [php]
     *     // u.id > ?1
176
     *     $q->where($q->expr()->gt('u.id', '?1'));
177 178 179 180 181
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
182
    public function gt($x, $y)
183
    {
184
        return new Expr\Comparison($x, Expr\Comparison::GT, $y);
185 186
    }

187 188 189 190 191 192 193
    /**
     * Creates an instance of Expr\Comparison, with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> >= <right expr>. Example:
     *
     *     [php]
     *     // u.id >= ?1
194
     *     $q->where($q->expr()->gte('u.id', '?1'));
195 196 197 198 199
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Comparison
     */
200
    public function gte($x, $y)
201
    {
202
        return new Expr\Comparison($x, Expr\Comparison::GTE, $y);
203 204
    }

205 206 207 208 209 210
    /**
     * Creates an instance of AVG() function, with the given argument.
     *
     * @param mixed $x Argument to be used in AVG() function.
     * @return Expr\Func
     */
211
    public function avg($x)
212
    {
213
        return new Expr\Func('AVG', array($x));
214 215
    }

216 217 218 219 220 221
    /**
     * Creates an instance of MAX() function, with the given argument.
     *
     * @param mixed $x Argument to be used in MAX() function.
     * @return Expr\Func
     */
222
    public function max($x)
223
    {
224
        return new Expr\Func('MAX', array($x));
225 226
    }

227 228 229 230 231 232
    /**
     * Creates an instance of MIN() function, with the given argument.
     *
     * @param mixed $x Argument to be used in MIN() function.
     * @return Expr\Func
     */
233
    public function min($x)
234
    {
235
        return new Expr\Func('MIN', array($x));
236 237
    }

238 239 240 241 242 243
    /**
     * Creates an instance of COUNT() function, with the given argument.
     *
     * @param mixed $x Argument to be used in COUNT() function.
     * @return Expr\Func
     */
244
    public function count($x)
245
    {
246
        return new Expr\Func('COUNT', array($x));
247 248
    }

249 250 251 252 253 254
    /**
     * Creates an instance of COUNT(DISTINCT) function, with the given argument.
     *
     * @param mixed $x Argument to be used in COUNT(DISTINCT) function.
     * @return string
     */
255
    public function countDistinct($x)
256
    {
257
        return 'COUNT(DISTINCT ' . implode(', ', func_get_args()) . ')';
258 259
    }

260 261 262 263 264 265
    /**
     * Creates an instance of EXISTS() function, with the given DQL Subquery.
     *
     * @param mixed $subquery DQL Subquery to be used in EXISTS() function.
     * @return Expr\Func
     */
266
    public function exists($subquery)
267
    {
268
        return new Expr\Func('EXISTS', array($subquery));
269 270
    }

271 272 273 274 275 276
    /**
     * Creates an instance of ALL() function, with the given DQL Subquery.
     *
     * @param mixed $subquery DQL Subquery to be used in ALL() function.
     * @return Expr\Func
     */
277
    public function all($subquery)
278
    {
279
        return new Expr\Func('ALL', array($subquery));
280 281
    }

282
    /**
283
     * Creates a SOME() function expression with the given DQL subquery.
284 285 286 287
     *
     * @param mixed $subquery DQL Subquery to be used in SOME() function.
     * @return Expr\Func
     */
288
    public function some($subquery)
289
    {
290
        return new Expr\Func('SOME', array($subquery));
291 292
    }

293
    /**
294
     * Creates an ANY() function expression with the given DQL subquery.
295 296 297 298
     *
     * @param mixed $subquery DQL Subquery to be used in ANY() function.
     * @return Expr\Func
     */
299
    public function any($subquery)
300
    {
301
        return new Expr\Func('ANY', array($subquery));
302 303
    }

304
    /**
305
     * Creates a negation expression of the given restriction.
306 307 308 309
     *
     * @param mixed $restriction Restriction to be used in NOT() function.
     * @return Expr\Func
     */
310
    public function not($restriction)
311
    {
312
        return new Expr\Func('NOT', array($restriction));
313 314
    }

315
    /**
316
     * Creates an ABS() function expression with the given argument.
317 318 319 320
     *
     * @param mixed $x Argument to be used in ABS() function.
     * @return Expr\Func
     */
321
    public function abs($x)
322
    {
323
        return new Expr\Func('ABS', array($x));
324 325
    }

326 327
    /**
     * Creates a product mathematical expression with the given arguments.
328
     * 
329 330 331 332 333
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> * <right expr>. Example:
     *
     *     [php]
     *     // u.salary * u.percentAnualSalaryIncrease
334
     *     $q->expr()->prod('u.salary', 'u.percentAnualSalaryIncrease')
335 336 337 338 339
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Math
     */
340
    public function prod($x, $y)
341
    {
342
        return new Expr\Math($x, '*', $y);
343 344
    }

345 346 347 348 349 350 351
    /**
     * Creates a difference mathematical expression with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> - <right expr>. Example:
     *
     *     [php]
     *     // u.monthlySubscriptionCount - 1
352
     *     $q->expr()->diff('u.monthlySubscriptionCount', '1')
353 354 355 356 357
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Math
     */
358
    public function diff($x, $y)
359
    {
360
        return new Expr\Math($x, '-', $y);
361 362
    }

363 364 365 366 367 368 369
    /**
     * Creates a sum mathematical expression with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> + <right expr>. Example:
     *
     *     [php]
     *     // u.numChildren + 1
370
     *     $q->expr()->diff('u.numChildren', '1')
371 372 373 374 375
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Math
     */
376
    public function sum($x, $y)
377
    {
378
        return new Expr\Math($x, '+', $y);
379 380
    }

381 382 383 384 385 386
    /**
     * Creates a quotient mathematical expression with the given arguments.
     * First argument is considered the left expression and the second is the right expression.
     * When converted to string, it will generated a <left expr> / <right expr>. Example:
     *
     *     [php]
387 388
     *     // u.total / u.period
     *     $expr->quot('u.total', 'u.period')
389 390 391 392 393
     *
     * @param mixed $x Left expression
     * @param mixed $y Right expression
     * @return Expr\Math
     */
394
    public function quot($x, $y)
395
    {
396
        return new Expr\Math($x, '/', $y);
397 398
    }

399
    /**
400
     * Creates a SQRT() function expression with the given argument.
401 402 403 404
     *
     * @param mixed $x Argument to be used in SQRT() function.
     * @return Expr\Func
     */
405
    public function sqrt($x)
406
    {
407
        return new Expr\Func('SQRT', array($x));
408 409
    }

410
    /**
411
     * Creates an IN() expression with the given arguments.
412 413 414 415 416
     *
     * @param string $x Field in string format to be restricted by IN() function
     * @param mixed $y Argument to be used in IN() function.
     * @return Expr\Func
     */
417
    public function in($x, $y)
418
    {
419 420 421 422 423 424 425
        if (is_array($y)) {
            foreach ($y as &$literal) {
                if ( ! ($literal instanceof Expr\Literal)) {
                    $literal = $this->_quoteLiteral($literal);
                }
            }
        }
426
        return new Expr\Func($x . ' IN', (array) $y);
427 428
    }

429
    /**
430
     * Creates a NOT IN() expression with the given arguments.
431 432 433 434 435
     *
     * @param string $x Field in string format to be restricted by NOT IN() function
     * @param mixed $y Argument to be used in NOT IN() function.
     * @return Expr\Func
     */
436
    public function notIn($x, $y)
437
    {
438
        return new Expr\Func($x . ' NOT IN', (array) $y);
439 440
    }

441
    /**
442
     * Creates a LIKE() comparison expression with the given arguments.
443 444 445 446 447
     *
     * @param string $x Field in string format to be inspected by LIKE() comparison.
     * @param mixed $y Argument to be used in LIKE() comparison.
     * @return Expr\Comparison
     */
448
    public function like($x, $y)
449
    {
450
        return new Expr\Comparison($x, 'LIKE', $y);
451 452
    }

453
    /**
454
     * Creates a CONCAT() function expression with the given arguments.
455 456 457 458 459
     *
     * @param mixed $x First argument to be used in CONCAT() function.
     * @param mixed $x Second argument to be used in CONCAT() function.
     * @return Expr\Func
     */
460
    public function concat($x, $y)
461
    {
462
        return new Expr\Func('CONCAT', array($x, $y));
463 464
    }

465
    /**
466
     * Creates a SUBSTRING() function expression with the given arguments.
467
     *
468
     * @param mixed $x Argument to be used as string to be cropped by SUBSTRING() function.
469 470 471 472
     * @param integer $from Initial offset to start cropping string. May accept negative values.
     * @param integer $len Length of crop. May accept negative values.
     * @return Expr\Func
     */
473
    public function substring($x, $from, $len)
474
    {
475
        return new Expr\Func('SUBSTRING', array($x, $from, $len));
476 477
    }

478
    /**
479
     * Creates a LOWER() function expression with the given argument.
480 481
     *
     * @param mixed $x Argument to be used in LOWER() function.
482
     * @return Expr\Func A LOWER function expression.
483
     */
484
    public function lower($x)
485
    {
486
        return new Expr\Func('LOWER', array($x));
487 488
    }

489
    /**
490
     * Creates an UPPER() function expression with the given argument.
491
     *
492 493
     * @param mixed $x Argument to be used in UPPER() function.
     * @return Expr\Func An UPPER function expression.
494
     */
495
    public function upper($x)
496
    {
497
        return new Expr\Func('UPPER', array($x));
498 499
    }

500
    /**
501
     * Creates a LENGTH() function expression with the given argument.
502 503
     *
     * @param mixed $x Argument to be used as argument of LENGTH() function.
504
     * @return Expr\Func A LENGTH function expression.
505
     */
506
    public function length($x)
507
    {
508
        return new Expr\Func('LENGTH', array($x));
509 510
    }

511
    /**
512
     * Creates a literal expression of the given argument.
513 514
     *
     * @param mixed $literal Argument to be converted to literal.
515
     * @return Expr\Literal
516
     */
517
    public function literal($literal)
518 519 520 521 522 523 524 525 526 527 528
    {
        return new Expr\Literal($this->_quoteLiteral($literal));
    }
    
    /**
     * Quotes a literal value, if necessary, according to the DQL syntax.
     * 
     * @param mixed $literal The literal value.
     * @return string
     */
    private function _quoteLiteral($literal)
529
    {
530 531 532
        if (is_numeric($literal)) {
            return (string) $literal;
        } else {
533
            return "'" . str_replace("'", "''", $literal) . "'";
534
        }
535 536
    }

537 538 539 540 541 542
    /**
     * Creates an instance of BETWEEN() function, with the given argument.
     *
     * @param mixed $val Valued to be inspected by range values.
     * @param integer $x Starting range value to be used in BETWEEN() function.
     * @param integer $y End point value to be used in BETWEEN() function.
543
     * @return Expr\Func A BETWEEN expression.
544
     */
545
    public function between($val, $x, $y)
546
    {
547
        return $val . ' BETWEEN ' . $x . ' AND ' . $y;
548 549
    }

550 551 552 553
    /**
     * Creates an instance of TRIM() function, with the given argument.
     *
     * @param mixed $x Argument to be used as argument of TRIM() function.
554
     * @return Expr\Func a TRIM expression.
555
     */
556
    public function trim($x)
557
    {
558
        return new Expr\Func('TRIM', $x);
559
    }
560
}