PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/Database/src/sqlabstraction/expression.php

https://github.com/Yannix/zetacomponents
PHP | 1109 lines | 412 code | 73 blank | 624 comment | 36 complexity | 2bf02f1d0d2b0032251279006a9030ab MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcQueryExpression class.
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package Database
  23. * @version //autogentag//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. */
  26. /**
  27. * The ezcQueryExpression class is used to create database independent SQL expression.
  28. *
  29. * The QueryExpression class is usually used through the 'expr' variable in
  30. * one of the Select, Insert, Update or Delete classes.
  31. *
  32. * Note that the methods for logical or and and are
  33. * named lOr and lAnd respectively. This is because and and or are reserved names
  34. * in PHP and can not be used in method names.
  35. *
  36. * @package Database
  37. * @version //autogentag//
  38. * @mainclass
  39. */
  40. class ezcQueryExpression
  41. {
  42. /**
  43. * A pointer to the database handler to use for this query.
  44. *
  45. * @var PDO
  46. */
  47. protected $db;
  48. /**
  49. * The column and table name aliases.
  50. *
  51. * Format: array('alias' => 'realName')
  52. * @var array(string=>string)
  53. */
  54. private $aliases = null;
  55. /**
  56. * The flag that switch quoting mode for
  57. * values provided by user in miscelaneous SQL functions.
  58. *
  59. * @var boolean
  60. */
  61. protected $quoteValues = true;
  62. /**
  63. * Contains an interval map from generic intervals to MySQL native intervals.
  64. *
  65. * @var array(string=>string)
  66. */
  67. protected $intervalMap = array(
  68. 'SECOND' => 'SECOND',
  69. 'MINUTE' => 'MINUTE',
  70. 'HOUR' => 'HOUR',
  71. 'DAY' => 'DAY',
  72. 'MONTH' => 'MONTH',
  73. 'YEAR' => 'YEAR',
  74. );
  75. /**
  76. * Constructs an empty ezcQueryExpression
  77. *
  78. * @param PDO $db
  79. * @param array(string=>string) $aliases
  80. */
  81. public function __construct( PDO $db, array $aliases = array() )
  82. {
  83. $this->db = $db;
  84. if ( !empty( $aliases ) )
  85. {
  86. $this->aliases = $aliases;
  87. }
  88. }
  89. /**
  90. * Sets the aliases $aliases for this object.
  91. *
  92. * The aliases can be used to substitute the column and table names with more
  93. * friendly names. E.g PersistentObject uses it to allow using property and class
  94. * names instead of column and table names.
  95. *
  96. * @param array(string=>string) $aliases
  97. * @return void
  98. */
  99. public function setAliases( array $aliases )
  100. {
  101. $this->aliases = $aliases;
  102. }
  103. /**
  104. * Returns true if this object has aliases.
  105. *
  106. * @return bool
  107. */
  108. public function hasAliases()
  109. {
  110. return $this->aliases !== null ? true : false;
  111. }
  112. /**
  113. * Returns the correct identifier for the alias $alias.
  114. *
  115. * If the alias does not exists in the list of aliases
  116. * it is returned unchanged.
  117. *
  118. * @param string $alias
  119. * @return string
  120. */
  121. protected function getIdentifier( $alias )
  122. {
  123. $aliasParts = explode( '.', $alias );
  124. $identifiers = array();
  125. // If the alias consists of one part, then we just look it up in the
  126. // array. If we find it, we use it, otherwise we return the name as-is
  127. // and assume it's just a column name. The alias target can be a fully
  128. // qualified name (table.column).
  129. if ( count( $aliasParts ) == 1 )
  130. {
  131. if ( $this->aliases !== null &&
  132. array_key_exists( $alias, $this->aliases ) )
  133. {
  134. $alias = $this->aliases[$alias];
  135. }
  136. return $alias;
  137. }
  138. // If the passed name consist of two parts, we need to check all parts
  139. // of the passed-in name for aliases, because an alias can be made for
  140. // both a table name and a column name. For each element we try to find
  141. // whether we have an alias mapping. Unlike the above case, the alias
  142. // target can in this case *not* consist of a fully qualified name as
  143. // this would introduce another part of the name (with two dots).
  144. for ( $i = 0; $i < count( $aliasParts ); $i++ )
  145. {
  146. if ( $this->aliases !== null &&
  147. array_key_exists( $aliasParts[$i], $this->aliases ) )
  148. {
  149. // We only use the found alias if the alias target is not a fully
  150. // qualified name (table.column).
  151. $tmpAlias = $this->aliases[$aliasParts[$i]];
  152. if ( count( explode( '.', $tmpAlias ) ) === 1 )
  153. {
  154. $aliasParts[$i] = $this->aliases[$aliasParts[$i]];
  155. }
  156. }
  157. }
  158. $alias = join( '.', $aliasParts );
  159. return $alias;
  160. }
  161. /**
  162. * Returns the correct identifiers for the aliases found in $aliases.
  163. *
  164. * This method is similar to getIdentifier except that it works on an array.
  165. *
  166. * @param array(string) $aliasList
  167. * @return array(string)
  168. */
  169. protected function getIdentifiers( array $aliasList )
  170. {
  171. if ( $this->aliases !== null )
  172. {
  173. foreach ( $aliasList as $key => $alias )
  174. {
  175. $aliasList[$key] = $this->getIdentifier( $alias );
  176. }
  177. }
  178. return $aliasList;
  179. }
  180. /**
  181. * Sets the mode of quoting for parameters passed
  182. * to SQL functions and operators.
  183. *
  184. * Quoting mode is set to ON by default.
  185. * $q->expr->in( 'column1', 'Hello', 'world' ) will
  186. * produce SQL "column1 IN ( 'Hello', 'world' )"
  187. * ( note quotes in SQL ).
  188. *
  189. * User must execute setValuesQuoting( false ) before call
  190. * to function where quoting of parameters is not desirable.
  191. * Example:
  192. * <code>
  193. * $q->expr->setValuesQuoting( false );
  194. * $q->expr->in( 'column1', 'SELECT * FROM table' )
  195. * </code>
  196. * This will produce SQL "column1 IN ( SELECT * FROM table )".
  197. *
  198. * Quoting mode will remain unchanged until next call
  199. * to setValuesQuoting().
  200. *
  201. * @param boolean $doQuoting - flag that switch quoting.
  202. * @return void
  203. */
  204. public function setValuesQuoting( $doQuoting )
  205. {
  206. $this->quoteValues = $doQuoting;
  207. }
  208. /**
  209. * Returns the SQL to bind logical expressions together using a logical or.
  210. *
  211. * lOr() accepts an arbitrary number of parameters. Each parameter
  212. * must contain a logical expression or an array with logical expressions.
  213. *
  214. * Example:
  215. * <code>
  216. * $q = ezcDbInstance::get()->createSelectQuery();
  217. * $e = $q->expr;
  218. * $q->select( '*' )->from( 'table' )
  219. * ->where( $e->lOr( $e->eq( 'id', $q->bindValue( 1 ) ),
  220. * $e->eq( 'id', $q->bindValue( 2 ) ) ) );
  221. * </code>
  222. *
  223. * @throws ezcDbAbstractionException if called with no parameters.
  224. * @return string a logical expression
  225. */
  226. public function lOr()
  227. {
  228. $args = func_get_args();
  229. if ( count( $args ) < 1 )
  230. {
  231. throw new ezcQueryVariableParameterException( 'lOr', count( $args ), 1 );
  232. }
  233. $elements = ezcQuerySelect::arrayFlatten( $args );
  234. if ( count( $elements ) == 1 )
  235. {
  236. return $elements[0];
  237. }
  238. else
  239. {
  240. return '( ' . join( ' OR ', $elements ) . ' )';
  241. }
  242. }
  243. /**
  244. * Returns the SQL to bind logical expressions together using a logical and.
  245. *
  246. * lAnd() accepts an arbitrary number of parameters. Each parameter
  247. * must contain a logical expression or an array with logical expressions.
  248. *
  249. * Example:
  250. * <code>
  251. * $q = ezcDbInstance::get()->createSelectQuery();
  252. * $e = $q->expr;
  253. * $q->select( '*' )->from( 'table' )
  254. * ->where( $e->lAnd( $e->eq( 'id', $q->bindValue( 1 ) ),
  255. * $e->eq( 'id', $q->bindValue( 2 ) ) ) );
  256. * </code>
  257. *
  258. * @throws ezcDbAbstractionException if called with no parameters.
  259. * @return string a logical expression
  260. */
  261. public function lAnd()
  262. {
  263. $args = func_get_args();
  264. if ( count( $args ) < 1 )
  265. {
  266. throw new ezcQueryVariableParameterException( 'lAnd', count( $args ), 1 );
  267. }
  268. $elements = ezcQuerySelect::arrayFlatten( $args );
  269. if ( count( $elements ) == 1 )
  270. {
  271. return $elements[0];
  272. }
  273. else
  274. {
  275. return '( ' . join( ' AND ', $elements ) . ' )';
  276. }
  277. }
  278. /**
  279. * Returns the SQL for a logical not, negating the $expression.
  280. *
  281. * Example:
  282. * <code>
  283. * $q = ezcDbInstance::get()->createSelectQuery();
  284. * $e = $q->expr;
  285. * $q->select( '*' )->from( 'table' )
  286. * ->where( $e->eq( 'id', $e->not( 'null' ) ) );
  287. * </code>
  288. *
  289. * @param string $expression
  290. * @return string a logical expression
  291. */
  292. public function not( $expression )
  293. {
  294. $expression = $this->getIdentifier( $expression );
  295. return "NOT ( {$expression} )";
  296. }
  297. // math
  298. /**
  299. * Returns the SQL to perform the same mathematical operation over an array
  300. * of values or expressions.
  301. *
  302. * basicMath() accepts an arbitrary number of parameters. Each parameter
  303. * must contain a value or an expression or an array with values or
  304. * expressions.
  305. *
  306. * @throws ezcDbAbstractionException if called with no parameters.
  307. * @param string $type the type of operation, can be '+', '-', '*' or '/'.
  308. * @param string|array(string) $...
  309. * @return string an expression
  310. */
  311. private function basicMath( $type )
  312. {
  313. $args = func_get_args();
  314. $elements = ezcQuerySelect::arrayFlatten( array_slice( $args, 1 ) );
  315. $elements = $this->getIdentifiers( $elements );
  316. if ( count( $elements ) < 1 )
  317. {
  318. throw new ezcQueryVariableParameterException( $type, count( $args ), 1 );
  319. }
  320. if ( count( $elements ) == 1 )
  321. {
  322. return $elements[0];
  323. }
  324. else
  325. {
  326. return '( ' . join( " $type ", $elements ) . ' )';
  327. }
  328. }
  329. /**
  330. * Returns the SQL to add values or expressions together.
  331. *
  332. * add() accepts an arbitrary number of parameters. Each parameter
  333. * must contain a value or an expression or an array with values or
  334. * expressions.
  335. *
  336. * Example:
  337. * <code>
  338. * $q = ezcDbInstance::get()->createSelectQuery();
  339. * $q->select( '*' )->from( 'table' )
  340. * ->where( $q->expr->add( 'id', 2 ) );
  341. * </code>
  342. *
  343. * @throws ezcDbAbstractionException if called with no parameters.
  344. * @param string|array(string) $...
  345. * @return string an expression
  346. */
  347. public function add()
  348. {
  349. $args = func_get_args();
  350. return $this->basicMath( '+', $args );
  351. }
  352. /**
  353. * Returns the SQL to subtract values or expressions from eachother.
  354. *
  355. * subtract() accepts an arbitrary number of parameters. Each parameter
  356. * must contain a value or an expression or an array with values or
  357. * expressions.
  358. *
  359. * Example:
  360. * <code>
  361. * $q = ezcDbInstance::get()->createSelectQuery();
  362. * $q->select( '*' )->from( 'table' )
  363. * ->where( $q->expr->subtract( 'id', 2 ) );
  364. * </code>
  365. *
  366. * @throws ezcDbAbstractionException if called with no parameters.
  367. * @param string|array(string) $...
  368. * @return string an expression
  369. */
  370. public function sub()
  371. {
  372. $args = func_get_args();
  373. return $this->basicMath( '-', $args );
  374. }
  375. /**
  376. * Returns the SQL to multiply values or expressions by eachother.
  377. *
  378. * multiply() accepts an arbitrary number of parameters. Each parameter
  379. * must contain a value or an expression or an array with values or
  380. * expressions.
  381. *
  382. * Example:
  383. * <code>
  384. * $q = ezcDbInstance::get()->createSelectQuery();
  385. * $q->select( '*' )->from( 'table' )
  386. * ->where( $q->expr->multiply( 'id', 2 ) );
  387. * </code>
  388. *
  389. * @throws ezcDbAbstractionException if called with no parameters.
  390. * @param string|array(string) $...
  391. * @return string an expression
  392. */
  393. public function mul()
  394. {
  395. $args = func_get_args();
  396. return $this->basicMath( '*', $args );
  397. }
  398. /**
  399. * Returns the SQL to divide values or expressions by eachother.
  400. *
  401. * divide() accepts an arbitrary number of parameters. Each parameter
  402. * must contain a value or an expression or an array with values or
  403. * expressions.
  404. *
  405. * Example:
  406. * <code>
  407. * $q = ezcDbInstance::get()->createSelectQuery();
  408. * $q->select( '*' )->from( 'table' )
  409. * ->where( $q->expr->divide( 'id', 2 ) );
  410. * </code>
  411. *
  412. * @throws ezcDbAbstractionException if called with no parameters.
  413. * @param string|array(string) $...
  414. * @return string an expression
  415. */
  416. public function div()
  417. {
  418. $args = func_get_args();
  419. return $this->basicMath( '/', $args );
  420. }
  421. /**
  422. * Returns the SQL to check if two values are equal.
  423. *
  424. * Example:
  425. * <code>
  426. * $q = ezcDbInstance::get()->createSelectQuery();
  427. * $q->select( '*' )->from( 'table' )
  428. * ->where( $q->expr->eq( 'id', $q->bindValue( 1 ) ) );
  429. * </code>
  430. *
  431. * @param string $value1 logical expression to compare
  432. * @param string $value2 logical expression to compare with
  433. * @return string logical expression
  434. */
  435. public function eq( $value1, $value2 )
  436. {
  437. $value1 = $this->getIdentifier( $value1 );
  438. $value2 = $this->getIdentifier( $value2 );
  439. return "{$value1} = {$value2}";
  440. }
  441. /**
  442. * Returns the SQL to check if two values are unequal.
  443. *
  444. * Example:
  445. * <code>
  446. * $q = ezcDbInstance::get()->createSelectQuery();
  447. * $q->select( '*' )->from( 'table' )
  448. * ->where( $q->expr->neq( 'id', $q->bindValue( 1 ) ) );
  449. * </code>
  450. *
  451. * @param string $value1 logical expression to compare
  452. * @param string $value2 logical expression to compare with
  453. * @return string logical expression
  454. */
  455. public function neq( $value1, $value2 )
  456. {
  457. $value1 = $this->getIdentifier( $value1 );
  458. $value2 = $this->getIdentifier( $value2 );
  459. return "{$value1} <> {$value2}";
  460. }
  461. /**
  462. * Returns the SQL to check if one value is greater than another value.
  463. *
  464. * Example:
  465. * <code>
  466. * $q = ezcDbInstance::get()->createSelectQuery();
  467. * $q->select( '*' )->from( 'table' )
  468. * ->where( $q->expr->gt( 'id', $q->bindValue( 1 ) ) );
  469. * </code>
  470. *
  471. * @param string $value1 logical expression to compare
  472. * @param string $value2 logical expression to compare with
  473. * @return string logical expression
  474. */
  475. public function gt( $value1, $value2 )
  476. {
  477. $value1 = $this->getIdentifier( $value1 );
  478. $value2 = $this->getIdentifier( $value2 );
  479. return "{$value1} > {$value2}";
  480. }
  481. /**
  482. * Returns the SQL to check if one value is greater than or equal to
  483. * another value.
  484. *
  485. * Example:
  486. * <code>
  487. * $q = ezcDbInstance::get()->createSelectQuery();
  488. * $q->select( '*' )->from( 'table' )
  489. * ->where( $q->expr->gte( 'id', $q->bindValue( 1 ) ) );
  490. * </code>
  491. *
  492. * @param string $value1 logical expression to compare
  493. * @param string $value2 logical expression to compare with
  494. * @return string logical expression
  495. */
  496. public function gte( $value1, $value2 )
  497. {
  498. $value1 = $this->getIdentifier( $value1 );
  499. $value2 = $this->getIdentifier( $value2 );
  500. return "{$value1} >= {$value2}";
  501. }
  502. /**
  503. * Returns the SQL to check if one value is less than another value.
  504. *
  505. * Example:
  506. * <code>
  507. * $q = ezcDbInstance::get()->createSelectQuery();
  508. * $q->select( '*' )->from( 'table' )
  509. * ->where( $q->expr->lt( 'id', $q->bindValue( 1 ) ) );
  510. * </code>
  511. *
  512. * @param string $value1 logical expression to compare
  513. * @param string $value2 logical expression to compare with
  514. * @return string logical expression
  515. */
  516. public function lt( $value1, $value2 )
  517. {
  518. $value1 = $this->getIdentifier( $value1 );
  519. $value2 = $this->getIdentifier( $value2 );
  520. return "{$value1} < {$value2}";
  521. }
  522. /**
  523. * Returns the SQL to check if one value is less than or equal to
  524. * another value.
  525. *
  526. * Example:
  527. * <code>
  528. * $q = ezcDbInstance::get()->createSelectQuery();
  529. * $q->select( '*' )->from( 'table' )
  530. * ->where( $q->expr->lte( 'id', $q->bindValue( 1 ) ) );
  531. * </code>
  532. *
  533. * @param string $value1 logical expression to compare
  534. * @param string $value2 logical expression to compare with
  535. * @return string logical expression
  536. */
  537. public function lte( $value1, $value2 )
  538. {
  539. $value1 = $this->getIdentifier( $value1 );
  540. $value2 = $this->getIdentifier( $value2 );
  541. return "{$value1} <= {$value2}";
  542. }
  543. /**
  544. * Returns the SQL to check if a value is one in a set of
  545. * given values..
  546. *
  547. * in() accepts an arbitrary number of parameters. The first parameter
  548. * must always specify the value that should be matched against. Successive
  549. * parameters must contain a logical expression or an array with logical
  550. * expressions. These expressions will be matched against the first
  551. * parameter.
  552. *
  553. * Example:
  554. * <code>
  555. * $q->select( '*' )->from( 'table' )
  556. * ->where( $q->expr->in( 'id', 1, 2, 3 ) );
  557. * </code>
  558. *
  559. * Optimization note: Call setQuotingValues( false ) before using in() with
  560. * big lists of numeric parameters. This avoid redundant quoting of numbers
  561. * in resulting SQL query and saves time of converting strings to
  562. * numbers inside RDBMS.
  563. *
  564. * @throws ezcQueryVariableParameterException if called with less than two
  565. * parameters.
  566. * @throws ezcQueryInvalidParameterException if the 2nd parameter is an
  567. * empty array.
  568. * @param string $column the value that should be matched against
  569. * @param string|array(string) $... values that will be matched against $column
  570. * @return string logical expression
  571. */
  572. public function in( $column )
  573. {
  574. $args = func_get_args();
  575. if ( count( $args ) < 2 )
  576. {
  577. throw new ezcQueryVariableParameterException( 'in', count( $args ), 2 );
  578. }
  579. if ( is_array( $args[1] ) && count( $args[1] ) == 0 )
  580. {
  581. throw new ezcQueryInvalidParameterException( 'in', 2, 'an empty array', 'a non-empty array' );
  582. }
  583. $values = ezcQuerySelect::arrayFlatten( array_slice( $args, 1 ) );
  584. $column = $this->getIdentifier( $column );
  585. // Special handling of sub selects to avoid double braces
  586. if ( count( $values ) === 1 && $values[0] instanceof ezcQuerySubSelect )
  587. {
  588. return "{$column} IN " . $values[0]->getQuery();
  589. }
  590. $values = $this->getIdentifiers( $values );
  591. if ( count( $values ) == 0 )
  592. {
  593. throw new ezcQueryVariableParameterException( 'in', count( $args ), 2 );
  594. }
  595. if ( $this->quoteValues )
  596. {
  597. foreach ( $values as $key => $value )
  598. {
  599. switch ( true )
  600. {
  601. case $value instanceof ezcQuerySubSelect:
  602. $values[$key] = $value->getQuery(); // fix for PHP 5.1.6 because typecasting to string not working there.
  603. break;
  604. case is_int( $value ):
  605. case is_float( $value ):
  606. $values[$key] = (string) $value;
  607. break;
  608. default:
  609. $values[$key] = $this->db->quote( $value );
  610. }
  611. }
  612. }
  613. return "{$column} IN ( " . join( ', ', $values ) . ' )';
  614. }
  615. /**
  616. * Returns SQL that checks if a expression is null.
  617. *
  618. * Example:
  619. * <code>
  620. * $q = ezcDbInstance::get()->createSelectQuery();
  621. * $q->select( '*' )->from( 'table' )
  622. * ->where( $q->expr->isNull( 'id' ) );
  623. * </code>
  624. *
  625. * @param string $expression the expression that should be compared to null
  626. * @return string logical expression
  627. */
  628. public function isNull( $expression )
  629. {
  630. $expression = $this->getIdentifier( $expression );
  631. return "{$expression} IS NULL";
  632. }
  633. /**
  634. * Returns SQL that checks if an expression evaluates to a value between
  635. * two values.
  636. *
  637. * The parameter $expression is checked if it is between $value1 and $value2.
  638. *
  639. * Note: There is a slight difference in the way BETWEEN works on some databases.
  640. * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
  641. * independence you should avoid using between().
  642. *
  643. * Example:
  644. * <code>
  645. * $q = ezcDbInstance::get()->createSelectQuery();
  646. * $q->select( '*' )->from( 'table' )
  647. * ->where( $q->expr->between( 'id', $q->bindValue( 1 ), $q->bindValue( 5 ) ) );
  648. * </code>
  649. *
  650. * @param string $expression the value to compare to
  651. * @param string $value1 the lower value to compare with
  652. * @param string $value2 the higher value to compare with
  653. * @return string logical expression
  654. */
  655. public function between( $expression, $value1, $value2 )
  656. {
  657. $expression = $this->getIdentifier( $expression );
  658. $value1 = $this->getIdentifier( $value1 );
  659. $value2 = $this->getIdentifier( $value2 );
  660. return "{$expression} BETWEEN {$value1} AND {$value2}";
  661. }
  662. /**
  663. * Match a partial string in a column.
  664. *
  665. * Like will look for the pattern in the column given. Like accepts
  666. * the wildcards '_' matching a single character and '%' matching
  667. * any number of characters.
  668. *
  669. * @param string $expression the name of the expression to match on
  670. * @param string $pattern the pattern to match with.
  671. */
  672. public function like( $expression, $pattern )
  673. {
  674. $expression = $this->getIdentifier( $expression );
  675. return "{$expression} LIKE {$pattern}";
  676. }
  677. // aggregate functions
  678. /**
  679. * Returns the average value of a column
  680. *
  681. * @param string $column the column to use
  682. * @return string
  683. */
  684. public function avg( $column )
  685. {
  686. $column = $this->getIdentifier( $column );
  687. return "AVG( {$column} )";
  688. }
  689. /**
  690. * Returns the number of rows (without a NULL value) of a column
  691. *
  692. * If a '*' is used instead of a column the number of selected rows
  693. * is returned.
  694. *
  695. * @param string $column the column to use
  696. * @return string
  697. */
  698. public function count( $column )
  699. {
  700. $column = $this->getIdentifier( $column );
  701. return "COUNT( {$column} )";
  702. }
  703. /**
  704. * Returns the highest value of a column
  705. *
  706. * @param string $column the column to use
  707. * @return string
  708. */
  709. public function max( $column )
  710. {
  711. $column = $this->getIdentifier( $column );
  712. return "MAX( {$column} )";
  713. }
  714. /**
  715. * Returns the lowest value of a column
  716. *
  717. * @param string $column the column to use
  718. * @return string
  719. */
  720. public function min( $column )
  721. {
  722. $column = $this->getIdentifier( $column );
  723. return "MIN( {$column} )";
  724. }
  725. /**
  726. * Returns the total sum of a column
  727. *
  728. * @param string $column the column to use
  729. * @return string
  730. */
  731. public function sum( $column )
  732. {
  733. $column = $this->getIdentifier( $column );
  734. return "SUM( {$column} )";
  735. }
  736. // scalar functions
  737. /**
  738. * Returns the md5 sum of $column.
  739. *
  740. * Note: Not SQL92, but common functionality
  741. *
  742. * @param string $column
  743. * @return string
  744. */
  745. public function md5( $column )
  746. {
  747. $column = $this->getIdentifier( $column );
  748. return "MD5( {$column} )";
  749. }
  750. /**
  751. * Returns the length of text field $column
  752. *
  753. * @param string $column
  754. * @return string
  755. */
  756. public function length( $column )
  757. {
  758. $column = $this->getIdentifier( $column );
  759. return "LENGTH( {$column} )";
  760. }
  761. /**
  762. * Rounds a numeric field to the number of decimals specified.
  763. *
  764. * @param string $column
  765. * @param int $decimals
  766. * @return string
  767. */
  768. public function round( $column, $decimals )
  769. {
  770. $column = $this->getIdentifier( $column );
  771. return "ROUND( {$column}, {$decimals} )";
  772. }
  773. /**
  774. * Returns the remainder of the division operation
  775. * $expression1 / $expression2.
  776. *
  777. * @param string $expression1
  778. * @param string $expression2
  779. * @return string
  780. */
  781. public function mod( $expression1, $expression2 )
  782. {
  783. $expression1 = $this->getIdentifier( $expression1 );
  784. $expression2 = $this->getIdentifier( $expression2 );
  785. return "MOD( {$expression1}, {$expression2} )";
  786. }
  787. /**
  788. * Returns the current system date and time in the database internal
  789. * format.
  790. *
  791. * @return string
  792. */
  793. public function now()
  794. {
  795. return "NOW()";
  796. }
  797. // string functions
  798. /**
  799. * Returns part of a string.
  800. *
  801. * Note: Not SQL92, but common functionality.
  802. *
  803. * @param string $value the target $value the string or the string column.
  804. * @param int $from extract from this characeter.
  805. * @param int $len extract this amount of characters.
  806. * @return string sql that extracts part of a string.
  807. */
  808. public function subString( $value, $from, $len = null )
  809. {
  810. $value = $this->getIdentifier( $value );
  811. if ( $len === null )
  812. {
  813. return "substring( {$value} from {$from} )";
  814. }
  815. else
  816. {
  817. $len = $this->getIdentifier( $len );
  818. return "substring( {$value} from {$from} for {$len} )";
  819. }
  820. }
  821. /**
  822. * Returns a series of strings concatinated
  823. *
  824. * concat() accepts an arbitrary number of parameters. Each parameter
  825. * must contain an expression or an array with expressions.
  826. *
  827. * @param string|array(string) $... strings that will be concatinated.
  828. */
  829. public function concat()
  830. {
  831. $args = func_get_args();
  832. $cols = ezcQuerySelect::arrayFlatten( $args );
  833. if ( count( $cols ) < 1 )
  834. {
  835. throw new ezcQueryVariableParameterException( 'concat', count( $args ), 1 );
  836. }
  837. $cols = $this->getIdentifiers( $cols );
  838. return "CONCAT( " . join( ', ', $cols ) . ' )';
  839. }
  840. /**
  841. * Returns the SQL to locate the position of the first occurrence of a substring
  842. *
  843. * @param string $substr
  844. * @param string $value
  845. * @return string
  846. */
  847. public function position( $substr, $value )
  848. {
  849. $value = $this->getIdentifier( $value );
  850. return "LOCATE( '{$substr}', {$value} )";
  851. }
  852. /**
  853. * Returns the SQL to change all characters to lowercase
  854. *
  855. * @param string $value
  856. * @return string
  857. */
  858. public function lower( $value )
  859. {
  860. $value = $this->getIdentifier( $value );
  861. return "LOWER( {$value} )";
  862. }
  863. /**
  864. * Returns the SQL to change all characters to uppercase
  865. *
  866. * @param string $value
  867. * @return string
  868. */
  869. public function upper( $value )
  870. {
  871. $value = $this->getIdentifier( $value );
  872. return "UPPER( {$value} )";
  873. }
  874. /**
  875. * Returns the SQL to calculate the next lowest integer value from the number.
  876. *
  877. * @param string $number
  878. * @return string
  879. */
  880. public function floor( $number )
  881. {
  882. $number = $this->getIdentifier( $number );
  883. return " FLOOR( {$number} ) ";
  884. }
  885. /**
  886. * Returns the SQL to calculate the next highest integer value from the number.
  887. *
  888. * @param string $number
  889. * @return string
  890. */
  891. public function ceil( $number )
  892. {
  893. $number = $this->getIdentifier( $number );
  894. return " CEIL( {$number} ) ";
  895. }
  896. /**
  897. * Returns the SQL that performs the bitwise AND on two values.
  898. *
  899. * @param string $value1
  900. * @param string $value2
  901. * @return string
  902. */
  903. public function bitAnd( $value1, $value2 )
  904. {
  905. $value1 = $this->getIdentifier( $value1 );
  906. $value2 = $this->getIdentifier( $value2 );
  907. return "( {$value1} & {$value2} )";
  908. }
  909. /**
  910. * Returns the SQL that performs the bitwise OR on two values.
  911. *
  912. * @param string $value1
  913. * @param string $value2
  914. * @return string
  915. */
  916. public function bitOr( $value1, $value2 )
  917. {
  918. $value1 = $this->getIdentifier( $value1 );
  919. $value2 = $this->getIdentifier( $value2 );
  920. return "( {$value1} | {$value2} )";
  921. }
  922. /**
  923. * Returns the SQL that performs the bitwise XOR on two values.
  924. *
  925. * @param string $value1
  926. * @param string $value2
  927. * @return string
  928. */
  929. public function bitXor( $value1, $value2 )
  930. {
  931. $value1 = $this->getIdentifier( $value1 );
  932. $value2 = $this->getIdentifier( $value2 );
  933. return "( {$value1} ^ {$value2} )";
  934. }
  935. /**
  936. * Returns the SQL that converts a timestamp value to a unix timestamp.
  937. *
  938. * @param string $column
  939. * @return string
  940. */
  941. public function unixTimestamp( $column )
  942. {
  943. $column = $this->getIdentifier( $column );
  944. return " UNIX_TIMESTAMP( {$column} ) ";
  945. }
  946. /**
  947. * Returns the SQL that subtracts an interval from a timestamp value.
  948. *
  949. * @param string $column
  950. * @param numeric $expr
  951. * @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
  952. * @return string
  953. */
  954. public function dateSub( $column, $expr, $type )
  955. {
  956. $type = $this->intervalMap[$type];
  957. $column = $this->getIdentifier( $column );
  958. return " {$column} - INTERVAL {$expr} {$type} ";
  959. }
  960. /**
  961. * Returns the SQL that adds an interval to a timestamp value.
  962. *
  963. * @param string $column
  964. * @param numeric $expr
  965. * @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
  966. * @return string
  967. */
  968. public function dateAdd( $column, $expr, $type )
  969. {
  970. $type = $this->intervalMap[$type];
  971. $column = $this->getIdentifier( $column );
  972. return " {$column} + INTERVAL {$expr} {$type} ";
  973. }
  974. /**
  975. * Returns the SQL that extracts parts from a timestamp value.
  976. *
  977. * @param string $column The column to operate on
  978. * @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
  979. * @return string
  980. */
  981. public function dateExtract( $column, $type )
  982. {
  983. $type = $this->intervalMap[$type];
  984. $column = $this->getIdentifier( $column );
  985. return " EXTRACT( {$type} FROM {$column} ) ";
  986. }
  987. /**
  988. * Returns a searched CASE statement.
  989. *
  990. * Accepts an arbitrary number of parameters.
  991. * The first parameter (array) must always be specified, the last
  992. * parameter (string) specifies the ELSE result.
  993. *
  994. * Example:
  995. * <code>
  996. * $q = ezcDbInstance::get()->createSelectQuery();
  997. * $q->select(
  998. * $q->expr->searchedCase(
  999. * array( $q->expr->gte( 'column1', 20 ), 'column1' )
  1000. * , array( $q->expr->gte( 'column2', 50 ), 'column2' )
  1001. * , 'column3'
  1002. * )
  1003. * )
  1004. * ->from( 'table' );
  1005. * </code>
  1006. *
  1007. * @throws ezcQueryVariableParameterException
  1008. * @return string
  1009. */
  1010. public function searchedCase()
  1011. {
  1012. $args = func_get_args();
  1013. if ( count( $args ) === 0 )
  1014. {
  1015. throw new ezcQueryVariableParameterException( 'searchedCase', count( $args ), 1 );
  1016. }
  1017. $expr = ' CASE';
  1018. foreach ( $args as $arg )
  1019. {
  1020. if ( is_array( $arg ) && count( $arg ) == 2 )
  1021. {
  1022. $column1 = $this->getIdentifier( $arg[0] );
  1023. $column2 = $this->getIdentifier( $arg[1] );
  1024. $expr .= " WHEN {$column1} THEN {$column2}";
  1025. }
  1026. else if ( is_scalar( $arg ) )
  1027. {
  1028. $column = $this->getIdentifier( $arg );
  1029. $expr .= " ELSE {$column}";
  1030. }
  1031. }
  1032. $expr .= ' END ';
  1033. return $expr;
  1034. }
  1035. }
  1036. ?>