PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.5
Independent Analytics – WordPress Analytics Plugin v2.15.5
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / illuminate / database / Query / Grammars / SqlServerGrammar.php
independent-analytics / vendor / illuminate / database / Query / Grammars Last commit date
Grammar.php 1 month ago MySqlGrammar.php 1 month ago PostgresGrammar.php 1 month ago SQLiteGrammar.php 1 month ago SqlServerGrammar.php 1 month ago
SqlServerGrammar.php
531 lines
1 <?php
2
3 namespace IAWPSCOPED\Illuminate\Database\Query\Grammars;
4
5 use IAWPSCOPED\Illuminate\Database\Query\Builder;
6 use IAWPSCOPED\Illuminate\Support\Arr;
7 use IAWPSCOPED\Illuminate\Support\Str;
8 /** @internal */
9 class SqlServerGrammar extends Grammar
10 {
11 /**
12 * All of the available clause operators.
13 *
14 * @var string[]
15 */
16 protected $operators = ['=', '<', '>', '<=', '>=', '!<', '!>', '<>', '!=', 'like', 'not like', 'ilike', '&', '&=', '|', '|=', '^', '^='];
17 /**
18 * Compile a select query into SQL.
19 *
20 * @param \Illuminate\Database\Query\Builder $query
21 * @return string
22 */
23 public function compileSelect(Builder $query)
24 {
25 if (!$query->offset) {
26 return parent::compileSelect($query);
27 }
28 if (\is_null($query->columns)) {
29 $query->columns = ['*'];
30 }
31 $components = $this->compileComponents($query);
32 if (!empty($components['orders'])) {
33 return parent::compileSelect($query) . " offset {$query->offset} rows fetch next {$query->limit} rows only";
34 }
35 // If an offset is present on the query, we will need to wrap the query in
36 // a big "ANSI" offset syntax block. This is very nasty compared to the
37 // other database systems but is necessary for implementing features.
38 return $this->compileAnsiOffset($query, $components);
39 }
40 /**
41 * Compile the "select *" portion of the query.
42 *
43 * @param \Illuminate\Database\Query\Builder $query
44 * @param array $columns
45 * @return string|null
46 */
47 protected function compileColumns(Builder $query, $columns)
48 {
49 if (!\is_null($query->aggregate)) {
50 return;
51 }
52 $select = $query->distinct ? 'select distinct ' : 'select ';
53 // If there is a limit on the query, but not an offset, we will add the top
54 // clause to the query, which serves as a "limit" type clause within the
55 // SQL Server system similar to the limit keywords available in MySQL.
56 if (\is_numeric($query->limit) && $query->limit > 0 && $query->offset <= 0) {
57 $select .= 'top ' . (int) $query->limit . ' ';
58 }
59 return $select . $this->columnize($columns);
60 }
61 /**
62 * Compile the "from" portion of the query.
63 *
64 * @param \Illuminate\Database\Query\Builder $query
65 * @param string $table
66 * @return string
67 */
68 protected function compileFrom(Builder $query, $table)
69 {
70 $from = parent::compileFrom($query, $table);
71 if (\is_string($query->lock)) {
72 return $from . ' ' . $query->lock;
73 }
74 if (!\is_null($query->lock)) {
75 return $from . ' with(rowlock,' . ($query->lock ? 'updlock,' : '') . 'holdlock)';
76 }
77 return $from;
78 }
79 /**
80 * Compile the index hints for the query.
81 *
82 * @param \Illuminate\Database\Query\Builder $query
83 * @param \Illuminate\Database\Query\IndexHint $indexHint
84 * @return string
85 */
86 protected function compileIndexHint(Builder $query, $indexHint)
87 {
88 return $indexHint->type === 'force' ? "with (index({$indexHint->index}))" : '';
89 }
90 /**
91 * {@inheritdoc}
92 *
93 * @param \Illuminate\Database\Query\Builder $query
94 * @param array $where
95 * @return string
96 */
97 protected function whereBitwise(Builder $query, $where)
98 {
99 $value = $this->parameter($where['value']);
100 $operator = \str_replace('?', '??', $where['operator']);
101 return '(' . $this->wrap($where['column']) . ' ' . $operator . ' ' . $value . ') != 0';
102 }
103 /**
104 * Compile a "where date" clause.
105 *
106 * @param \Illuminate\Database\Query\Builder $query
107 * @param array $where
108 * @return string
109 */
110 protected function whereDate(Builder $query, $where)
111 {
112 $value = $this->parameter($where['value']);
113 return 'cast(' . $this->wrap($where['column']) . ' as date) ' . $where['operator'] . ' ' . $value;
114 }
115 /**
116 * Compile a "where time" clause.
117 *
118 * @param \Illuminate\Database\Query\Builder $query
119 * @param array $where
120 * @return string
121 */
122 protected function whereTime(Builder $query, $where)
123 {
124 $value = $this->parameter($where['value']);
125 return 'cast(' . $this->wrap($where['column']) . ' as time) ' . $where['operator'] . ' ' . $value;
126 }
127 /**
128 * Compile a "JSON contains" statement into SQL.
129 *
130 * @param string $column
131 * @param string $value
132 * @return string
133 */
134 protected function compileJsonContains($column, $value)
135 {
136 [$field, $path] = $this->wrapJsonFieldAndPath($column);
137 return $value . ' in (select [value] from openjson(' . $field . $path . '))';
138 }
139 /**
140 * Prepare the binding for a "JSON contains" statement.
141 *
142 * @param mixed $binding
143 * @return string
144 */
145 public function prepareBindingForJsonContains($binding)
146 {
147 return \is_bool($binding) ? \json_encode($binding) : $binding;
148 }
149 /**
150 * Compile a "JSON contains key" statement into SQL.
151 *
152 * @param string $column
153 * @return string
154 */
155 protected function compileJsonContainsKey($column)
156 {
157 $segments = \explode('->', $column);
158 $lastSegment = \array_pop($segments);
159 if (\preg_match('/\\[([0-9]+)\\]$/', $lastSegment, $matches)) {
160 $segments[] = Str::beforeLast($lastSegment, $matches[0]);
161 $key = $matches[1];
162 } else {
163 $key = "'" . \str_replace("'", "''", $lastSegment) . "'";
164 }
165 [$field, $path] = $this->wrapJsonFieldAndPath(\implode('->', $segments));
166 return $key . ' in (select [key] from openjson(' . $field . $path . '))';
167 }
168 /**
169 * Compile a "JSON length" statement into SQL.
170 *
171 * @param string $column
172 * @param string $operator
173 * @param string $value
174 * @return string
175 */
176 protected function compileJsonLength($column, $operator, $value)
177 {
178 [$field, $path] = $this->wrapJsonFieldAndPath($column);
179 return '(select count(*) from openjson(' . $field . $path . ')) ' . $operator . ' ' . $value;
180 }
181 /**
182 * Compile a "JSON value cast" statement into SQL.
183 *
184 * @param string $value
185 * @return string
186 */
187 public function compileJsonValueCast($value)
188 {
189 return 'json_query(' . $value . ')';
190 }
191 /**
192 * Compile a single having clause.
193 *
194 * @param array $having
195 * @return string
196 */
197 protected function compileHaving(array $having)
198 {
199 if ($having['type'] === 'Bitwise') {
200 return $this->compileHavingBitwise($having);
201 }
202 return parent::compileHaving($having);
203 }
204 /**
205 * Compile a having clause involving a bitwise operator.
206 *
207 * @param array $having
208 * @return string
209 */
210 protected function compileHavingBitwise($having)
211 {
212 $column = $this->wrap($having['column']);
213 $parameter = $this->parameter($having['value']);
214 return '(' . $column . ' ' . $having['operator'] . ' ' . $parameter . ') != 0';
215 }
216 /**
217 * Create a full ANSI offset clause for the query.
218 *
219 * @param \Illuminate\Database\Query\Builder $query
220 * @param array $components
221 * @return string
222 */
223 protected function compileAnsiOffset(Builder $query, $components)
224 {
225 // An ORDER BY clause is required to make this offset query work, so if one does
226 // not exist we'll just create a dummy clause to trick the database and so it
227 // does not complain about the queries for not having an "order by" clause.
228 if (empty($components['orders'])) {
229 $components['orders'] = 'order by (select 0)';
230 }
231 // We need to add the row number to the query so we can compare it to the offset
232 // and limit values given for the statements. So we will add an expression to
233 // the "select" that will give back the row numbers on each of the records.
234 $components['columns'] .= $this->compileOver($components['orders']);
235 unset($components['orders']);
236 if ($this->queryOrderContainsSubquery($query)) {
237 $query->bindings = $this->sortBindingsForSubqueryOrderBy($query);
238 }
239 // Next we need to calculate the constraints that should be placed on the query
240 // to get the right offset and limit from our query but if there is no limit
241 // set we will just handle the offset only since that is all that matters.
242 $sql = $this->concatenate($components);
243 return $this->compileTableExpression($sql, $query);
244 }
245 /**
246 * Compile the over statement for a table expression.
247 *
248 * @param string $orderings
249 * @return string
250 */
251 protected function compileOver($orderings)
252 {
253 return ", row_number() over ({$orderings}) as row_num";
254 }
255 /**
256 * Determine if the query's order by clauses contain a subquery.
257 *
258 * @param \Illuminate\Database\Query\Builder $query
259 * @return bool
260 */
261 protected function queryOrderContainsSubquery($query)
262 {
263 if (!\is_array($query->orders)) {
264 return \false;
265 }
266 return Arr::first($query->orders, function ($value) {
267 return $this->isExpression($value['column'] ?? null);
268 }, \false) !== \false;
269 }
270 /**
271 * Move the order bindings to be after the "select" statement to account for an order by subquery.
272 *
273 * @param \Illuminate\Database\Query\Builder $query
274 * @return array
275 */
276 protected function sortBindingsForSubqueryOrderBy($query)
277 {
278 return Arr::sort($query->bindings, function ($bindings, $key) {
279 return \array_search($key, ['select', 'order', 'from', 'join', 'where', 'groupBy', 'having', 'union', 'unionOrder']);
280 });
281 }
282 /**
283 * Compile a common table expression for a query.
284 *
285 * @param string $sql
286 * @param \Illuminate\Database\Query\Builder $query
287 * @return string
288 */
289 protected function compileTableExpression($sql, $query)
290 {
291 $constraint = $this->compileRowConstraint($query);
292 return "select * from ({$sql}) as temp_table where row_num {$constraint} order by row_num";
293 }
294 /**
295 * Compile the limit / offset row constraint for a query.
296 *
297 * @param \Illuminate\Database\Query\Builder $query
298 * @return string
299 */
300 protected function compileRowConstraint($query)
301 {
302 $start = (int) $query->offset + 1;
303 if ($query->limit > 0) {
304 $finish = (int) $query->offset + (int) $query->limit;
305 return "between {$start} and {$finish}";
306 }
307 return ">= {$start}";
308 }
309 /**
310 * Compile a delete statement without joins into SQL.
311 *
312 * @param \Illuminate\Database\Query\Builder $query
313 * @param string $table
314 * @param string $where
315 * @return string
316 */
317 protected function compileDeleteWithoutJoins(Builder $query, $table, $where)
318 {
319 $sql = parent::compileDeleteWithoutJoins($query, $table, $where);
320 return !\is_null($query->limit) && $query->limit > 0 && $query->offset <= 0 ? Str::replaceFirst('delete', 'delete top (' . $query->limit . ')', $sql) : $sql;
321 }
322 /**
323 * Compile the random statement into SQL.
324 *
325 * @param string|int $seed
326 * @return string
327 */
328 public function compileRandom($seed)
329 {
330 return 'NEWID()';
331 }
332 /**
333 * Compile the "limit" portions of the query.
334 *
335 * @param \Illuminate\Database\Query\Builder $query
336 * @param int $limit
337 * @return string
338 */
339 protected function compileLimit(Builder $query, $limit)
340 {
341 return '';
342 }
343 /**
344 * Compile the "offset" portions of the query.
345 *
346 * @param \Illuminate\Database\Query\Builder $query
347 * @param int $offset
348 * @return string
349 */
350 protected function compileOffset(Builder $query, $offset)
351 {
352 return '';
353 }
354 /**
355 * Compile the lock into SQL.
356 *
357 * @param \Illuminate\Database\Query\Builder $query
358 * @param bool|string $value
359 * @return string
360 */
361 protected function compileLock(Builder $query, $value)
362 {
363 return '';
364 }
365 /**
366 * Wrap a union subquery in parentheses.
367 *
368 * @param string $sql
369 * @return string
370 */
371 protected function wrapUnion($sql)
372 {
373 return 'select * from (' . $sql . ') as ' . $this->wrapTable('temp_table');
374 }
375 /**
376 * Compile an exists statement into SQL.
377 *
378 * @param \Illuminate\Database\Query\Builder $query
379 * @return string
380 */
381 public function compileExists(Builder $query)
382 {
383 $existsQuery = clone $query;
384 $existsQuery->columns = [];
385 return $this->compileSelect($existsQuery->selectRaw('1 [exists]')->limit(1));
386 }
387 /**
388 * Compile an update statement with joins into SQL.
389 *
390 * @param \Illuminate\Database\Query\Builder $query
391 * @param string $table
392 * @param string $columns
393 * @param string $where
394 * @return string
395 */
396 protected function compileUpdateWithJoins(Builder $query, $table, $columns, $where)
397 {
398 $alias = \IAWPSCOPED\last(\explode(' as ', $table));
399 $joins = $this->compileJoins($query, $query->joins);
400 return "update {$alias} set {$columns} from {$table} {$joins} {$where}";
401 }
402 /**
403 * Compile an "upsert" statement into SQL.
404 *
405 * @param \Illuminate\Database\Query\Builder $query
406 * @param array $values
407 * @param array $uniqueBy
408 * @param array $update
409 * @return string
410 */
411 public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
412 {
413 $columns = $this->columnize(\array_keys(\reset($values)));
414 $sql = 'merge ' . $this->wrapTable($query->from) . ' ';
415 $parameters = \IAWPSCOPED\collect($values)->map(function ($record) {
416 return '(' . $this->parameterize($record) . ')';
417 })->implode(', ');
418 $sql .= 'using (values ' . $parameters . ') ' . $this->wrapTable('laravel_source') . ' (' . $columns . ') ';
419 $on = \IAWPSCOPED\collect($uniqueBy)->map(function ($column) use($query) {
420 return $this->wrap('laravel_source.' . $column) . ' = ' . $this->wrap($query->from . '.' . $column);
421 })->implode(' and ');
422 $sql .= 'on ' . $on . ' ';
423 if ($update) {
424 $update = \IAWPSCOPED\collect($update)->map(function ($value, $key) {
425 return \is_numeric($key) ? $this->wrap($value) . ' = ' . $this->wrap('laravel_source.' . $value) : $this->wrap($key) . ' = ' . $this->parameter($value);
426 })->implode(', ');
427 $sql .= 'when matched then update set ' . $update . ' ';
428 }
429 $sql .= 'when not matched then insert (' . $columns . ') values (' . $columns . ');';
430 return $sql;
431 }
432 /**
433 * Prepare the bindings for an update statement.
434 *
435 * @param array $bindings
436 * @param array $values
437 * @return array
438 */
439 public function prepareBindingsForUpdate(array $bindings, array $values)
440 {
441 $cleanBindings = Arr::except($bindings, 'select');
442 return \array_values(\array_merge($values, Arr::flatten($cleanBindings)));
443 }
444 /**
445 * Compile the SQL statement to define a savepoint.
446 *
447 * @param string $name
448 * @return string
449 */
450 public function compileSavepoint($name)
451 {
452 return 'SAVE TRANSACTION ' . $name;
453 }
454 /**
455 * Compile the SQL statement to execute a savepoint rollback.
456 *
457 * @param string $name
458 * @return string
459 */
460 public function compileSavepointRollBack($name)
461 {
462 return 'ROLLBACK TRANSACTION ' . $name;
463 }
464 /**
465 * Get the format for database stored dates.
466 *
467 * @return string
468 */
469 public function getDateFormat()
470 {
471 return 'Y-m-d H:i:s.v';
472 }
473 /**
474 * Wrap a single string in keyword identifiers.
475 *
476 * @param string $value
477 * @return string
478 */
479 protected function wrapValue($value)
480 {
481 return $value === '*' ? $value : '[' . \str_replace(']', ']]', $value) . ']';
482 }
483 /**
484 * Wrap the given JSON selector.
485 *
486 * @param string $value
487 * @return string
488 */
489 protected function wrapJsonSelector($value)
490 {
491 [$field, $path] = $this->wrapJsonFieldAndPath($value);
492 return 'json_value(' . $field . $path . ')';
493 }
494 /**
495 * Wrap the given JSON boolean value.
496 *
497 * @param string $value
498 * @return string
499 */
500 protected function wrapJsonBooleanValue($value)
501 {
502 return "'" . $value . "'";
503 }
504 /**
505 * Wrap a table in keyword identifiers.
506 *
507 * @param \Illuminate\Database\Query\Expression|string $table
508 * @return string
509 */
510 public function wrapTable($table)
511 {
512 if (!$this->isExpression($table)) {
513 return $this->wrapTableValuedFunction(parent::wrapTable($table));
514 }
515 return $this->getValue($table);
516 }
517 /**
518 * Wrap a table in keyword identifiers.
519 *
520 * @param string $table
521 * @return string
522 */
523 protected function wrapTableValuedFunction($table)
524 {
525 if (\preg_match('/^(.+?)(\\(.*?\\))]$/', $table, $matches) === 1) {
526 $table = $matches[1] . ']' . $matches[2];
527 }
528 return $table;
529 }
530 }
531