• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

letsdrink / ouzo / 6037036166

31 Aug 2023 11:53AM UTC coverage: 84.202% (-1.8%) from 86.01%
6037036166

push

github

web-flow
Add string space const (#318)

4877 of 5792 relevant lines covered (84.2%)

33.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.32
/src/Ouzo/Core/Db/Dialect/Dialect.php
1
<?php
2
/*
3
 * Copyright (c) Ouzo contributors, https://github.com/letsdrink/ouzo
4
 * This file is made available under the MIT License (view the LICENSE file for more information).
5
 */
6

7
namespace Ouzo\Db\Dialect;
8

9
use Ouzo\Db\JoinClause;
10
use Ouzo\Db\OnConflict;
11
use Ouzo\Db\Query;
12
use Ouzo\Db\QueryType;
13
use Ouzo\Db\WhereClause\WhereClause;
14
use Ouzo\DbConnectionException;
15
use Ouzo\DbException;
16
use Ouzo\Utilities\Arrays;
17
use Ouzo\Utilities\Joiner;
18
use Ouzo\Utilities\Strings;
19
use PDO;
20

21
abstract class Dialect
22
{
23
    protected Query $query;
24

25
    public function select(int $queryType = null): string
26
    {
27
        $type = $queryType ?: $this->query->type;
564✔
28
        if ($type == QueryType::$SELECT) {
564✔
29
            $distinct = $this->query->distinct ? 'DISTINCT ' : (empty($this->query->distinctOnColumns) ? Strings::EMPTY : $this->getDistinctOnQuery());
543✔
30
            $columns = empty($this->query->selectColumns) ? '*' : Joiner::on(', ')->map(DialectUtil::addAliases())->join($this->query->selectColumns);
543✔
31
            return "SELECT {$distinct}{$columns}";
543✔
32
        }
33
        if ($type == QueryType::$COUNT) {
24✔
34
            if ($this->query->distinct) {
24✔
35
                throw new DbException('Illegal query, cannot use selectDistinct with count.');
3✔
36
            }
37
            return 'SELECT count(*)';
21✔
38
        }
39
        return Strings::EMPTY;
×
40
    }
41

42
    public function update(): string
43
    {
44
        $attributes = DialectUtil::buildAttributesPartForUpdate($this->query->updateAttributes);
44✔
45
        $table = $this->table();
44✔
46
        return "UPDATE {$table} SET {$attributes}";
44✔
47
    }
48

49
    public function insert(): string
50
    {
51
        $data = $this->query->updateAttributes;
467✔
52

53
        $columns = array_keys($data);
467✔
54
        $values = array_values($data);
467✔
55

56
        if ($values) {
467✔
57
            $joinedColumns = implode(', ', $columns);
464✔
58
            $joinedValues = implode(', ', array_fill(0, count($values), '?'));
464✔
59
            return "INSERT INTO {$this->query->table} ({$joinedColumns}) VALUES ({$joinedValues})";
464✔
60
        } else {
61
            return $this->insertEmptyRow();
6✔
62
        }
63
    }
64

65
    abstract public function onConflictUpdate(): string;
66

67
    abstract public function onConflictDoNothing(): string;
68

69
    public function delete(): string
70
    {
71
        return "DELETE";
20✔
72
    }
73

74
    public function join(): string
75
    {
76
        $join = DialectUtil::buildJoinQuery($this->query->joinClauses);
560✔
77
        if ($join) {
560✔
78
            return " {$join}";
104✔
79
        }
80
        return '';
459✔
81
    }
82

83
    public function where(): string
84
    {
85
        return $this->whereClause(Arrays::toArray($this->query->whereClauses));
566✔
86
    }
87

88
    private function whereWithUsing(): string
89
    {
90
        $usingClauses = $this->query->usingClauses;
20✔
91
        $whereClauses = Arrays::map($usingClauses, function (JoinClause $usingClause) {
20✔
92
            return WhereClause::create($usingClause->getJoinColumnWithTable() . ' = ' . $usingClause->getJoinedColumnWithTable());
8✔
93
        });
20✔
94
        return $this->whereClause(array_merge($whereClauses, $this->query->whereClauses));
20✔
95
    }
96

97
    public function using(): string
98
    {
99
        return $this->usingClause($this->query->usingClauses);
9✔
100
    }
101

102
    public function groupBy(): string
103
    {
104
        $groupBy = $this->query->groupBy;
542✔
105
        if ($groupBy) {
542✔
106
            $groupBy = is_array($groupBy) ? implode(', ', $groupBy) : $groupBy;
18✔
107
            return " GROUP BY {$groupBy}";
18✔
108
        }
109
        return '';
530✔
110
    }
111

112
    public function order(): string
113
    {
114
        $order = $this->query->order;
539✔
115
        if ($order) {
539✔
116
            $order = is_array($order) ? implode(', ', $order) : $order;
31✔
117
            return " ORDER BY {$order}";
31✔
118
        }
119
        return '';
511✔
120
    }
121

122
    public function limit(): string
123
    {
124
        if ($this->query->limit !== null) {
539✔
125
            return ' LIMIT ?';
9✔
126
        }
127
        return '';
530✔
128
    }
129

130
    public function offset(): string
131
    {
132
        if ($this->query->offset) {
539✔
133
            return ' OFFSET ?';
9✔
134
        }
135
        return '';
530✔
136
    }
137

138
    public function table(): string
139
    {
140
        $alias = $this->query->aliasTable ? " AS {$this->query->aliasTable}" : '';
375✔
141
        return $this->tableOrSubQuery() . $alias;
375✔
142
    }
143

144
    public function tableOrSubQuery(): string
145
    {
146
        if ($this->query->table instanceof Query) {
579✔
147
            $query = DialectFactory::create()->buildQuery($this->query->table);
6✔
148
            return "({$query})";
6✔
149
        }
150
        return $this->query->table;
579✔
151
    }
152

153
    public function from(): string
154
    {
155
        return " FROM {$this->table()}";
573✔
156
    }
157

158
    public function comment(): string
159
    {
160
        return $this->query->comment ? " /* {$this->query->comment} */ " : '';
640✔
161
    }
162

163
    public function lockForUpdate(): string
164
    {
165
        return $this->query->lockForUpdate ? ' FOR UPDATE' : '';
406✔
166
    }
167

168
    public function buildQuery(Query $query): string
169
    {
170
        $this->query = $query;
644✔
171
        $sql = '';
644✔
172

173
        if ($query->type == QueryType::$UPDATE) {
644✔
174
            $sql .= $this->update();
45✔
175
            $sql .= $this->where();
44✔
176
        } elseif ($query->type == QueryType::$INSERT) {
640✔
177
            $sql .= $this->insert();
457✔
178
        } elseif ($query->type == QueryType::$INSERT_OR_DO_NOTHING) {
587✔
179
            $sql .= $this->insert();
1✔
180
            $sql .= $this->onConflictDoNothing();
1✔
181
        } elseif ($query->type == QueryType::$UPSERT) {
586✔
182
            $sql .= $this->insert();
14✔
183
            $sql .= $this->onConflictUpdate();
14✔
184
        } elseif ($query->type == QueryType::$DELETE) {
576✔
185
            $sql .= $this->delete();
20✔
186
            $sql .= $this->from();
20✔
187
            $sql .= $this->using();
20✔
188
            $sql .= $this->whereWithUsing();
20✔
189
        } elseif ($query->type == QueryType::$COUNT && !empty($query->distinctOnColumns)) {
564✔
190
            $sql .= $this->select(QueryType::$SELECT);
3✔
191
            $sql .= $this->from();
3✔
192
            $sql .= $this->join();
3✔
193
            $sql .= $this->where();
3✔
194
            $sql .= $this->groupBy();
3✔
195
            $sql = $this->wrapQueryWithDistinctCount($sql);
3✔
196
        } elseif ($query->type == QueryType::$COUNT) {
561✔
197
            $sql .= $this->select();
24✔
198
            $sql .= $this->from();
21✔
199
            $sql .= $this->join();
21✔
200
            $sql .= $this->where();
21✔
201
        } else {
202
            $sql .= $this->select();
540✔
203
            $sql .= $this->from();
540✔
204
            $sql .= $this->join();
540✔
205
            $sql .= $this->where();
539✔
206
            $sql .= $this->groupBy();
539✔
207
            $sql .= $this->order();
539✔
208
            $sql .= $this->limit();
539✔
209
            $sql .= $this->offset();
539✔
210
            $sql .= $this->lockForUpdate();
539✔
211
        }
212
        $sql .= $this->comment();
640✔
213

214
        return rtrim($sql);
640✔
215
    }
216

217
    public function getExceptionForError(array $errorInfo): string
218
    {
219
        if ($this->isConnectionError($errorInfo)) {
19✔
220
            return DbConnectionException::class;
6✔
221
        }
222
        return DbException::class;
13✔
223
    }
224

225
    public function isConnectionError(array $errorInfo): bool
226
    {
227
        return in_array($this->getErrorCode($errorInfo), $this->getConnectionErrorCodes());
19✔
228
    }
229

230
    abstract public function getConnectionErrorCodes(): array;
231

232
    abstract public function getErrorCode(array $errorInfo): mixed;
233

234
    /** @param string[] $columns */
235
    abstract public function batchInsert(
236
        string $table, string $primaryKey, array $columns, int $batchSize,
237
        ?OnConflict $onConflict
238
    ): string;
239

240
    abstract public function regexpMatcher(): string;
241

242
    /** @param WhereClause[] $whereClauses */
243
    protected function whereClause(array $whereClauses): string
244
    {
245
        $where = DialectUtil::buildWhereQuery($whereClauses);
578✔
246
        if ($where) {
578✔
247
            return " WHERE {$where}";
385✔
248
        }
249
        return '';
257✔
250
    }
251

252
    /** @param JoinClause[] $usingClauses */
253
    protected function usingClause(array $usingClauses, string $glue = ', ', string $table = null, string $alias = null): string
254
    {
255
        $using = DialectUtil::buildUsingQuery($usingClauses, $glue, $table, $alias);
18✔
256
        if ($using) {
18✔
257
            return " USING {$using}";
8✔
258
        }
259
        return '';
10✔
260
    }
261

262
    abstract protected function insertEmptyRow(): string;
263

264
    /** @return int[] */
265
    public function getIteratorOptions(): array
266
    {
267
        return [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL];
4✔
268
    }
269

270
    abstract protected function quote(string $word): string;
271

272
    abstract protected function getDistinctOnQuery(): string;
273

274
    abstract protected function wrapQueryWithDistinctCount(string $sql) : string;
275
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc