1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Data\Persistence\Sql\Mssql;
6:
7: use Atk4\Data\Persistence\Sql\Query as BaseQuery;
8:
9: class Query extends BaseQuery
10: {
11: use ExpressionTrait;
12:
13: protected string $identifierEscapeChar = ']';
14: protected string $expressionClass = Expression::class;
15:
16: protected string $templateInsert = <<<'EOF'
17: begin try
18: insert[option] into [tableNoalias] ([setFields]) values ([setValues]);
19: end try begin catch
20: if ERROR_NUMBER() = 544 begin
21: set IDENTITY_INSERT [tableNoalias] on;
22: begin try
23: insert[option] into [tableNoalias] ([setFields]) values ([setValues]);
24: set IDENTITY_INSERT [tableNoalias] off;
25: end try begin catch
26: set IDENTITY_INSERT [tableNoalias] off;
27: throw;
28: end catch
29: end else begin
30: throw;
31: end
32: end catch
33: EOF;
34:
35: #[\Override]
36: protected function deduplicateRenderOrder(array $sqls): array
37: {
38: $res = [];
39: foreach ($sqls as $sql) {
40: $sqlWithoutDirection = preg_replace('~\s+(?:asc|desc)\s*$~i', '', $sql);
41: if (!isset($res[$sqlWithoutDirection])) {
42: $res[$sqlWithoutDirection] = $sql;
43: }
44: }
45:
46: return array_values($res);
47: }
48:
49: #[\Override]
50: protected function _renderLimit(): ?string
51: {
52: if (!isset($this->args['limit'])) {
53: return null;
54: }
55:
56: $cnt = (int) $this->args['limit']['cnt'];
57: $shift = (int) $this->args['limit']['shift'];
58:
59: if ($cnt === 0) {
60: $cnt = 1;
61: $shift = \PHP_INT_MAX;
62: }
63:
64: return (!isset($this->args['order']) ? ' order by (select null)' : '')
65: . ' offset ' . $shift . ' rows'
66: . ' fetch next ' . $cnt . ' rows only';
67: }
68:
69: #[\Override]
70: public function groupConcat($field, string $separator = ',')
71: {
72: return $this->expr('string_agg({}, ' . $this->escapeStringLiteral($separator) . ')', [$field]);
73: }
74:
75: #[\Override]
76: public function exists()
77: {
78: return $this->dsql()->mode('select')->field(
79: $this->dsql()->expr('case when exists[] then 1 else 0 end', [$this])
80: );
81: }
82: }
83: