PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php

https://gitlab.com/jjpa2018/dashboard
PHP | 329 lines | 144 code | 47 blank | 138 comment | 13 complexity | a114a194ec1590df15f68a2a6edcbedf MD5 | raw file
  1. <?php
  2. namespace Illuminate\Database\Query\Grammars;
  3. use Illuminate\Database\Query\Builder;
  4. use Illuminate\Support\Str;
  5. class MySqlGrammar extends Grammar
  6. {
  7. /**
  8. * The grammar specific operators.
  9. *
  10. * @var string[]
  11. */
  12. protected $operators = ['sounds like'];
  13. /**
  14. * Add a "where null" clause to the query.
  15. *
  16. * @param \Illuminate\Database\Query\Builder $query
  17. * @param array $where
  18. * @return string
  19. */
  20. protected function whereNull(Builder $query, $where)
  21. {
  22. if ($this->isJsonSelector($where['column'])) {
  23. [$field, $path] = $this->wrapJsonFieldAndPath($where['column']);
  24. return '(json_extract('.$field.$path.') is null OR json_type(json_extract('.$field.$path.')) = \'NULL\')';
  25. }
  26. return parent::whereNull($query, $where);
  27. }
  28. /**
  29. * Add a "where not null" clause to the query.
  30. *
  31. * @param \Illuminate\Database\Query\Builder $query
  32. * @param array $where
  33. * @return string
  34. */
  35. protected function whereNotNull(Builder $query, $where)
  36. {
  37. if ($this->isJsonSelector($where['column'])) {
  38. [$field, $path] = $this->wrapJsonFieldAndPath($where['column']);
  39. return '(json_extract('.$field.$path.') is not null AND json_type(json_extract('.$field.$path.')) != \'NULL\')';
  40. }
  41. return parent::whereNotNull($query, $where);
  42. }
  43. /**
  44. * Compile a "where fulltext" clause.
  45. *
  46. * @param \Illuminate\Database\Query\Builder $query
  47. * @param array $where
  48. * @return string
  49. */
  50. public function whereFullText(Builder $query, $where)
  51. {
  52. $columns = $this->columnize($where['columns']);
  53. $value = $this->parameter($where['value']);
  54. $mode = ($where['options']['mode'] ?? []) === 'boolean'
  55. ? ' in boolean mode'
  56. : ' in natural language mode';
  57. $expanded = ($where['options']['expanded'] ?? []) && ($where['options']['mode'] ?? []) !== 'boolean'
  58. ? ' with query expansion'
  59. : '';
  60. return "match ({$columns}) against (".$value."{$mode}{$expanded})";
  61. }
  62. /**
  63. * Compile an insert ignore statement into SQL.
  64. *
  65. * @param \Illuminate\Database\Query\Builder $query
  66. * @param array $values
  67. * @return string
  68. */
  69. public function compileInsertOrIgnore(Builder $query, array $values)
  70. {
  71. return Str::replaceFirst('insert', 'insert ignore', $this->compileInsert($query, $values));
  72. }
  73. /**
  74. * Compile a "JSON contains" statement into SQL.
  75. *
  76. * @param string $column
  77. * @param string $value
  78. * @return string
  79. */
  80. protected function compileJsonContains($column, $value)
  81. {
  82. [$field, $path] = $this->wrapJsonFieldAndPath($column);
  83. return 'json_contains('.$field.', '.$value.$path.')';
  84. }
  85. /**
  86. * Compile a "JSON length" statement into SQL.
  87. *
  88. * @param string $column
  89. * @param string $operator
  90. * @param string $value
  91. * @return string
  92. */
  93. protected function compileJsonLength($column, $operator, $value)
  94. {
  95. [$field, $path] = $this->wrapJsonFieldAndPath($column);
  96. return 'json_length('.$field.$path.') '.$operator.' '.$value;
  97. }
  98. /**
  99. * Compile the random statement into SQL.
  100. *
  101. * @param string $seed
  102. * @return string
  103. */
  104. public function compileRandom($seed)
  105. {
  106. return 'RAND('.$seed.')';
  107. }
  108. /**
  109. * Compile the lock into SQL.
  110. *
  111. * @param \Illuminate\Database\Query\Builder $query
  112. * @param bool|string $value
  113. * @return string
  114. */
  115. protected function compileLock(Builder $query, $value)
  116. {
  117. if (! is_string($value)) {
  118. return $value ? 'for update' : 'lock in share mode';
  119. }
  120. return $value;
  121. }
  122. /**
  123. * Compile an insert statement into SQL.
  124. *
  125. * @param \Illuminate\Database\Query\Builder $query
  126. * @param array $values
  127. * @return string
  128. */
  129. public function compileInsert(Builder $query, array $values)
  130. {
  131. if (empty($values)) {
  132. $values = [[]];
  133. }
  134. return parent::compileInsert($query, $values);
  135. }
  136. /**
  137. * Compile the columns for an update statement.
  138. *
  139. * @param \Illuminate\Database\Query\Builder $query
  140. * @param array $values
  141. * @return string
  142. */
  143. protected function compileUpdateColumns(Builder $query, array $values)
  144. {
  145. return collect($values)->map(function ($value, $key) {
  146. if ($this->isJsonSelector($key)) {
  147. return $this->compileJsonUpdateColumn($key, $value);
  148. }
  149. return $this->wrap($key).' = '.$this->parameter($value);
  150. })->implode(', ');
  151. }
  152. /**
  153. * Compile an "upsert" statement into SQL.
  154. *
  155. * @param \Illuminate\Database\Query\Builder $query
  156. * @param array $values
  157. * @param array $uniqueBy
  158. * @param array $update
  159. * @return string
  160. */
  161. public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
  162. {
  163. $sql = $this->compileInsert($query, $values).' on duplicate key update ';
  164. $columns = collect($update)->map(function ($value, $key) {
  165. return is_numeric($key)
  166. ? $this->wrap($value).' = values('.$this->wrap($value).')'
  167. : $this->wrap($key).' = '.$this->parameter($value);
  168. })->implode(', ');
  169. return $sql.$columns;
  170. }
  171. /**
  172. * Prepare a JSON column being updated using the JSON_SET function.
  173. *
  174. * @param string $key
  175. * @param mixed $value
  176. * @return string
  177. */
  178. protected function compileJsonUpdateColumn($key, $value)
  179. {
  180. if (is_bool($value)) {
  181. $value = $value ? 'true' : 'false';
  182. } elseif (is_array($value)) {
  183. $value = 'cast(? as json)';
  184. } else {
  185. $value = $this->parameter($value);
  186. }
  187. [$field, $path] = $this->wrapJsonFieldAndPath($key);
  188. return "{$field} = json_set({$field}{$path}, {$value})";
  189. }
  190. /**
  191. * Compile an update statement without joins into SQL.
  192. *
  193. * @param \Illuminate\Database\Query\Builder $query
  194. * @param string $table
  195. * @param string $columns
  196. * @param string $where
  197. * @return string
  198. */
  199. protected function compileUpdateWithoutJoins(Builder $query, $table, $columns, $where)
  200. {
  201. $sql = parent::compileUpdateWithoutJoins($query, $table, $columns, $where);
  202. if (! empty($query->orders)) {
  203. $sql .= ' '.$this->compileOrders($query, $query->orders);
  204. }
  205. if (isset($query->limit)) {
  206. $sql .= ' '.$this->compileLimit($query, $query->limit);
  207. }
  208. return $sql;
  209. }
  210. /**
  211. * Prepare the bindings for an update statement.
  212. *
  213. * Booleans, integers, and doubles are inserted into JSON updates as raw values.
  214. *
  215. * @param array $bindings
  216. * @param array $values
  217. * @return array
  218. */
  219. public function prepareBindingsForUpdate(array $bindings, array $values)
  220. {
  221. $values = collect($values)->reject(function ($value, $column) {
  222. return $this->isJsonSelector($column) && is_bool($value);
  223. })->map(function ($value) {
  224. return is_array($value) ? json_encode($value) : $value;
  225. })->all();
  226. return parent::prepareBindingsForUpdate($bindings, $values);
  227. }
  228. /**
  229. * Compile a delete query that does not use joins.
  230. *
  231. * @param \Illuminate\Database\Query\Builder $query
  232. * @param string $table
  233. * @param string $where
  234. * @return string
  235. */
  236. protected function compileDeleteWithoutJoins(Builder $query, $table, $where)
  237. {
  238. $sql = parent::compileDeleteWithoutJoins($query, $table, $where);
  239. // When using MySQL, delete statements may contain order by statements and limits
  240. // so we will compile both of those here. Once we have finished compiling this
  241. // we will return the completed SQL statement so it will be executed for us.
  242. if (! empty($query->orders)) {
  243. $sql .= ' '.$this->compileOrders($query, $query->orders);
  244. }
  245. if (isset($query->limit)) {
  246. $sql .= ' '.$this->compileLimit($query, $query->limit);
  247. }
  248. return $sql;
  249. }
  250. /**
  251. * Wrap a single string in keyword identifiers.
  252. *
  253. * @param string $value
  254. * @return string
  255. */
  256. protected function wrapValue($value)
  257. {
  258. return $value === '*' ? $value : '`'.str_replace('`', '``', $value).'`';
  259. }
  260. /**
  261. * Wrap the given JSON selector.
  262. *
  263. * @param string $value
  264. * @return string
  265. */
  266. protected function wrapJsonSelector($value)
  267. {
  268. [$field, $path] = $this->wrapJsonFieldAndPath($value);
  269. return 'json_unquote(json_extract('.$field.$path.'))';
  270. }
  271. /**
  272. * Wrap the given JSON selector for boolean values.
  273. *
  274. * @param string $value
  275. * @return string
  276. */
  277. protected function wrapJsonBooleanSelector($value)
  278. {
  279. [$field, $path] = $this->wrapJsonFieldAndPath($value);
  280. return 'json_extract('.$field.$path.')';
  281. }
  282. }