SqliteDialectTrait.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <?php
  2. /**
  3. * PHP Version 5.4
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since CakePHP(tm) v 3.0.0
  15. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  16. */
  17. namespace Cake\Database\Dialect;
  18. use Cake\Database\ExpressionInterface;
  19. use Cake\Database\Expression\FunctionExpression;
  20. use Cake\Database\Query;
  21. use Cake\Database\SqlDialectTrait;
  22. trait SqliteDialectTrait {
  23. use SqlDialectTrait;
  24. /**
  25. * String used to start a database identifier quoting to make it safe
  26. *
  27. * @var string
  28. */
  29. protected $_startQuote = '"';
  30. /**
  31. * String used to end a database identifier quoting to make it safe
  32. *
  33. * @var string
  34. */
  35. protected $_endQuote = '"';
  36. /**
  37. * Returns an dictionary of expressions to be transformed when compiling a Query
  38. * to SQL. Array keys are method names to be called in this class
  39. *
  40. * @return array
  41. */
  42. protected function _expressionTranslators() {
  43. $namespace = 'Cake\Database\Expression';
  44. return [
  45. $namespace . '\FunctionExpression' => '_transformFunctionExpression'
  46. ];
  47. }
  48. /**
  49. * Receives a FunctionExpression and changes it so that it conforms to this
  50. * SQL dialect.
  51. *
  52. * @param Cake\Database\Expression\FunctionExpression
  53. * @return void
  54. */
  55. protected function _transformFunctionExpression(FunctionExpression $expression) {
  56. switch ($expression->name()) {
  57. case 'CONCAT':
  58. // CONCAT function is expressed as exp1 || exp2
  59. $expression->name('')->type(' ||');
  60. break;
  61. case 'DATEDIFF':
  62. $expression
  63. ->name('ROUND')
  64. ->type('-')
  65. ->iterateParts(function($p) {
  66. return new FunctionExpression('JULIANDAY', [$p['value']], [$p['type']]);
  67. });
  68. break;
  69. case 'NOW':
  70. $expression->name('DATETIME')->add(["'now'" => 'literal']);
  71. break;
  72. case 'CURRENT_DATE':
  73. $expression->name('DATE')->add(["'now'" => 'literal']);
  74. break;
  75. case 'CURRENT_TIME':
  76. $expression->name('TIME')->add(["'now'" => 'literal']);
  77. break;
  78. }
  79. }
  80. /**
  81. * Transforms an insert query that is meant to insert multiple rows at a time,
  82. * otherwise it leaves the query untouched.
  83. *
  84. * The way SQLite works with multi insert is by having multiple select statements
  85. * joined with UNION.
  86. *
  87. * @return Query
  88. */
  89. protected function _insertQueryTranslator($query) {
  90. $v = $query->clause('values');
  91. if (count($v->values()) === 1 || $v->query()) {
  92. return $query;
  93. }
  94. $newQuery = $query->connection()->newQuery();
  95. $cols = $v->columns();
  96. foreach ($v->values() as $k => $val) {
  97. $fillLength = count($cols) - count($val);
  98. if ($fillLength > 0) {
  99. $val = array_merge($val, array_fill(0, $fillLength, null));
  100. }
  101. $val = array_map(function($val) {
  102. return $val instanceof ExpressionInterface ? $val : '?';
  103. }, $val);
  104. $select = array_combine($cols, $val);
  105. if ($k === 0) {
  106. $newQuery->select($select);
  107. continue;
  108. }
  109. $q = $newQuery->connection()->newQuery();
  110. $newQuery->union($q->select($select), true);
  111. }
  112. $v->query($newQuery);
  113. return $query;
  114. }
  115. /**
  116. * Get the schema dialect.
  117. *
  118. * Used by Cake\Schema package to reflect schema and
  119. * generate schema.
  120. *
  121. * @return Cake\Database\Schema\SqliteSchema
  122. */
  123. public function schemaDialect() {
  124. return new \Cake\Database\Schema\SqliteSchema($this);
  125. }
  126. }