SQLiteGrammar.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace Illuminate\Database\Query\Grammars;
  3. use Illuminate\Database\Query\Builder;
  4. class SQLiteGrammar extends Grammar
  5. {
  6. /**
  7. * The components that make up a select clause.
  8. *
  9. * @var array
  10. */
  11. protected $selectComponents = [
  12. 'aggregate',
  13. 'columns',
  14. 'from',
  15. 'joins',
  16. 'wheres',
  17. 'groups',
  18. 'havings',
  19. 'orders',
  20. 'limit',
  21. 'offset',
  22. 'lock',
  23. ];
  24. /**
  25. * All of the available clause operators.
  26. *
  27. * @var array
  28. */
  29. protected $operators = [
  30. '=', '<', '>', '<=', '>=', '<>', '!=',
  31. 'like', 'not like', 'ilike',
  32. '&', '|', '<<', '>>',
  33. ];
  34. /**
  35. * Compile a select query into SQL.
  36. *
  37. * @param \Illuminate\Database\Query\Builder $query
  38. * @return string
  39. */
  40. public function compileSelect(Builder $query)
  41. {
  42. $sql = parent::compileSelect($query);
  43. if ($query->unions) {
  44. $sql = 'select * from ('.$sql.') '.$this->compileUnions($query);
  45. }
  46. return $sql;
  47. }
  48. /**
  49. * Compile a single union statement.
  50. *
  51. * @param array $union
  52. * @return string
  53. */
  54. protected function compileUnion(array $union)
  55. {
  56. $conjuction = $union['all'] ? ' union all ' : ' union ';
  57. return $conjuction.'select * from ('.$union['query']->toSql().')';
  58. }
  59. /**
  60. * Compile a "where date" clause.
  61. *
  62. * @param \Illuminate\Database\Query\Builder $query
  63. * @param array $where
  64. * @return string
  65. */
  66. protected function whereDate(Builder $query, $where)
  67. {
  68. return $this->dateBasedWhere('%Y-%m-%d', $query, $where);
  69. }
  70. /**
  71. * Compile a "where day" clause.
  72. *
  73. * @param \Illuminate\Database\Query\Builder $query
  74. * @param array $where
  75. * @return string
  76. */
  77. protected function whereDay(Builder $query, $where)
  78. {
  79. return $this->dateBasedWhere('%d', $query, $where);
  80. }
  81. /**
  82. * Compile a "where month" clause.
  83. *
  84. * @param \Illuminate\Database\Query\Builder $query
  85. * @param array $where
  86. * @return string
  87. */
  88. protected function whereMonth(Builder $query, $where)
  89. {
  90. return $this->dateBasedWhere('%m', $query, $where);
  91. }
  92. /**
  93. * Compile a "where year" clause.
  94. *
  95. * @param \Illuminate\Database\Query\Builder $query
  96. * @param array $where
  97. * @return string
  98. */
  99. protected function whereYear(Builder $query, $where)
  100. {
  101. return $this->dateBasedWhere('%Y', $query, $where);
  102. }
  103. /**
  104. * Compile a "where time" clause.
  105. *
  106. * @param \Illuminate\Database\Query\Builder $query
  107. * @param array $where
  108. * @return string
  109. */
  110. protected function whereTime(Builder $query, $where)
  111. {
  112. return $this->dateBasedWhere('%H:%M:%S', $query, $where);
  113. }
  114. /**
  115. * Compile a date based where clause.
  116. *
  117. * @param string $type
  118. * @param \Illuminate\Database\Query\Builder $query
  119. * @param array $where
  120. * @return string
  121. */
  122. protected function dateBasedWhere($type, Builder $query, $where)
  123. {
  124. $value = str_pad($where['value'], 2, '0', STR_PAD_LEFT);
  125. $value = $this->parameter($value);
  126. return "strftime('{$type}', {$this->wrap($where['column'])}) {$where['operator']} {$value}";
  127. }
  128. /**
  129. * Compile an insert statement into SQL.
  130. *
  131. * @param \Illuminate\Database\Query\Builder $query
  132. * @param array $values
  133. * @return string
  134. */
  135. public function compileInsert(Builder $query, array $values)
  136. {
  137. // Essentially we will force every insert to be treated as a batch insert which
  138. // simply makes creating the SQL easier for us since we can utilize the same
  139. // basic routine regardless of an amount of records given to us to insert.
  140. $table = $this->wrapTable($query->from);
  141. if (! is_array(reset($values))) {
  142. $values = [$values];
  143. }
  144. // If there is only one record being inserted, we will just use the usual query
  145. // grammar insert builder because no special syntax is needed for the single
  146. // row inserts in SQLite. However, if there are multiples, we'll continue.
  147. if (count($values) == 1) {
  148. return empty(reset($values))
  149. ? "insert into $table default values"
  150. : parent::compileInsert($query, reset($values));
  151. }
  152. $names = $this->columnize(array_keys(reset($values)));
  153. $columns = [];
  154. // SQLite requires us to build the multi-row insert as a listing of select with
  155. // unions joining them together. So we'll build out this list of columns and
  156. // then join them all together with select unions to complete the queries.
  157. foreach (array_keys(reset($values)) as $column) {
  158. $columns[] = '? as '.$this->wrap($column);
  159. }
  160. $columns = array_fill(0, count($values), implode(', ', $columns));
  161. return "insert into $table ($names) select ".implode(' union all select ', $columns);
  162. }
  163. /**
  164. * Compile a truncate table statement into SQL.
  165. *
  166. * @param \Illuminate\Database\Query\Builder $query
  167. * @return array
  168. */
  169. public function compileTruncate(Builder $query)
  170. {
  171. return [
  172. 'delete from sqlite_sequence where name = ?' => [$query->from],
  173. 'delete from '.$this->wrapTable($query->from) => [],
  174. ];
  175. }
  176. }