1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Data\Persistence\Sql\Oracle;
6:
7: use Atk4\Data\Exception;
8: use Atk4\Data\Field;
9: use Atk4\Data\Persistence\Sql\Query as BaseQuery;
10:
11: class Query extends BaseQuery
12: {
13: use ExpressionTrait;
14:
15: protected string $paramBase = 'xxaaaa';
16:
17: protected string $identifierEscapeChar = '"';
18: protected string $expressionClass = Expression::class;
19:
20: #[\Override]
21: public function render(): array
22: {
23: if ($this->mode === 'select' && count($this->args['table'] ?? []) === 0) {
24: try {
25: $this->table('DUAL');
26:
27: return parent::render();
28: } finally {
29: unset($this->args['table']);
30: }
31: }
32:
33: return parent::render();
34: }
35:
36: #[\Override]
37: protected function _subrenderCondition(array $row): string
38: {
39: if (count($row) === 2) {
40: [$field, $value] = $row;
41: $cond = '=';
42: } elseif (count($row) >= 3) {
43: [$field, $cond, $value] = $row;
44: }
45:
46: if (count($row) >= 2 && $field instanceof Field
47: && in_array($field->type, ['text', 'blob'], true)) {
48: if ($field->type === 'text') {
49: $field = $this->expr('LOWER([])', [$field]);
50: $value = $this->expr('LOWER([])', [$value]);
51: }
52:
53: if (in_array($cond, ['=', '!='], true)) {
54: $row = [$this->expr('dbms_lob.compare([], [])', [$field, $value]), $cond, 0];
55: } else {
56: throw (new Exception('Unsupported CLOB/BLOB field operator'))
57: ->addMoreInfo('operator', $cond)
58: ->addMoreInfo('type', $field->type);
59: }
60: }
61:
62: return parent::_subrenderCondition($row);
63: }
64:
65: #[\Override]
66: protected function _renderLimit(): ?string
67: {
68: if (!isset($this->args['limit'])) {
69: return null;
70: }
71:
72: $cnt = (int) $this->args['limit']['cnt'];
73: $shift = (int) $this->args['limit']['shift'];
74:
75: return ($shift ? ' offset ' . $shift . ' rows' : '')
76: . ' fetch next ' . $cnt . ' rows only';
77: }
78:
79: #[\Override]
80: public function groupConcat($field, string $separator = ',')
81: {
82: return $this->expr('listagg({field}, []) within group (order by {field})', ['field' => $field, $separator]);
83: }
84:
85: #[\Override]
86: public function exists()
87: {
88: return $this->dsql()->mode('select')->field(
89: $this->dsql()->expr('case when exists[] then 1 else 0 end', [$this])
90: );
91: }
92: }
93: