GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( ecf3ef...78a151 )
by Robert
11:40
created

QueryBuilder   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 267
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 38
lcom 1
cbo 11
dl 0
loc 267
ccs 0
cts 151
cp 0
rs 8.3999
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A defaultExpressionBuilders() 0 6 1
C upsert() 0 51 11
B resetSequence() 0 19 5
A buildLimit() 0 17 4
A selectExists() 0 4 1
A dropIndex() 0 12 3
A addCheck() 0 4 1
A dropCheck() 0 4 1
A addCommentOnColumn() 0 11 2
A addCommentOnTable() 0 4 1
A dropCommentFromColumn() 0 4 1
A dropCommentFromTable() 0 4 1
B getColumnDefinition() 0 24 6
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db\cubrid;
9
10
use yii\base\InvalidArgumentException;
11
use yii\base\NotSupportedException;
12
use yii\db\Constraint;
13
use yii\db\Exception;
14
use yii\db\Expression;
15
16
/**
17
 * QueryBuilder is the query builder for CUBRID databases (version 9.3.x and higher).
18
 *
19
 * @author Carsten Brandt <[email protected]>
20
 * @since 2.0
21
 */
22
class QueryBuilder extends \yii\db\QueryBuilder
23
{
24
    /**
25
     * @var array mapping from abstract column types (keys) to physical column types (values).
26
     */
27
    public $typeMap = [
28
        Schema::TYPE_PK => 'int NOT NULL AUTO_INCREMENT PRIMARY KEY',
29
        Schema::TYPE_UPK => 'int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
30
        Schema::TYPE_BIGPK => 'bigint NOT NULL AUTO_INCREMENT PRIMARY KEY',
31
        Schema::TYPE_UBIGPK => 'bigint UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
32
        Schema::TYPE_CHAR => 'char(1)',
33
        Schema::TYPE_STRING => 'varchar(255)',
34
        Schema::TYPE_TEXT => 'varchar',
35
        Schema::TYPE_SMALLINT => 'smallint',
36
        Schema::TYPE_INTEGER => 'int',
37
        Schema::TYPE_BIGINT => 'bigint',
38
        Schema::TYPE_FLOAT => 'float(7)',
39
        Schema::TYPE_DOUBLE => 'double(15)',
40
        Schema::TYPE_DECIMAL => 'decimal(10,0)',
41
        Schema::TYPE_DATETIME => 'datetime',
42
        Schema::TYPE_TIMESTAMP => 'timestamp',
43
        Schema::TYPE_TIME => 'time',
44
        Schema::TYPE_DATE => 'date',
45
        Schema::TYPE_BINARY => 'blob',
46
        Schema::TYPE_BOOLEAN => 'smallint',
47
        Schema::TYPE_MONEY => 'decimal(19,4)',
48
    ];
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    protected function defaultExpressionBuilders()
54
    {
55
        return array_merge(parent::defaultExpressionBuilders(), [
56
            'yii\db\conditions\LikeCondition' => 'yii\db\cubrid\conditions\LikeConditionBuilder',
57
        ]);
58
    }
59
60
    /**
61
     * @inheritdoc
62
     * @see https://www.cubrid.org/manual/en/9.3.0/sql/query/merge.html
63
     */
64
    public function upsert($table, $insertColumns, $updateColumns, &$params)
65
    {
66
        /** @var Constraint[] $constraints */
67
        list($uniqueNames, $insertNames, $updateNames) = $this->prepareUpsertColumns($table, $insertColumns, $updateColumns, $constraints);
68
        if (empty($uniqueNames)) {
69
            return $this->insert($table, $insertColumns, $params);
70
        }
71
72
        $onCondition = ['or'];
73
        $quotedTableName = $this->db->quoteTableName($table);
74
        foreach ($constraints as $constraint) {
75
            $constraintCondition = ['and'];
76
            foreach ($constraint->columnNames as $name) {
0 ignored issues
show
Bug introduced by
The expression $constraint->columnNames of type array<integer,string>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
77
                $quotedName = $this->db->quoteColumnName($name);
78
                $constraintCondition[] = "$quotedTableName.$quotedName=\"EXCLUDED\".$quotedName";
79
            }
80
            $onCondition[] = $constraintCondition;
81
        }
82
        $on = $this->buildCondition($onCondition, $params);
83
        list(, $placeholders, $values, $params) = $this->prepareInsertValues($table, $insertColumns, $params);
84
        $mergeSql = 'MERGE INTO ' . $this->db->quoteTableName($table) . ' '
85
            . 'USING (' . (!empty($placeholders) ? 'VALUES (' . implode(', ', $placeholders) . ')' : ltrim($values, ' ')) . ') AS "EXCLUDED" (' . implode(', ', $insertNames) . ') '
86
            . 'ON ' . $on;
87
        $insertValues = [];
88
        foreach ($insertNames as $name) {
89
            $quotedName = $this->db->quoteColumnName($name);
90
            if (strrpos($quotedName, '.') === false) {
91
                $quotedName = '"EXCLUDED".' . $quotedName;
92
            }
93
            $insertValues[] = $quotedName;
94
        }
95
        $insertSql = 'INSERT (' . implode(', ', $insertNames) . ')'
96
            . ' VALUES (' . implode(', ', $insertValues) . ')';
97
        if ($updateColumns === false) {
98
            return "$mergeSql WHEN NOT MATCHED THEN $insertSql";
99
        }
100
101
        if ($updateColumns === true) {
102
            $updateColumns = [];
103
            foreach ($updateNames as $name) {
104
                $quotedName = $this->db->quoteColumnName($name);
105
                if (strrpos($quotedName, '.') === false) {
106
                    $quotedName = '"EXCLUDED".' . $quotedName;
107
                }
108
                $updateColumns[$name] = new Expression($quotedName);
109
            }
110
        }
111
        list($updates, $params) = $this->prepareUpdateSets($table, $updateColumns, $params);
112
        $updateSql = 'UPDATE SET ' . implode(', ', $updates);
113
        return "$mergeSql WHEN MATCHED THEN $updateSql WHEN NOT MATCHED THEN $insertSql";
114
    }
115
116
    /**
117
     * Creates a SQL statement for resetting the sequence value of a table's primary key.
118
     * The sequence will be reset such that the primary key of the next new row inserted
119
     * will have the specified value or 1.
120
     * @param string $tableName the name of the table whose primary key sequence will be reset
121
     * @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
122
     * the next new row's primary key will have a value 1.
123
     * @return string the SQL statement for resetting sequence
124
     * @throws InvalidArgumentException if the table does not exist or there is no sequence associated with the table.
125
     */
126
    public function resetSequence($tableName, $value = null)
127
    {
128
        $table = $this->db->getTableSchema($tableName);
129
        if ($table !== null && $table->sequenceName !== null) {
130
            $tableName = $this->db->quoteTableName($tableName);
131
            if ($value === null) {
132
                $key = reset($table->primaryKey);
133
                $value = (int) $this->db->createCommand("SELECT MAX(`$key`) FROM " . $this->db->schema->quoteTableName($tableName))->queryScalar() + 1;
134
            } else {
135
                $value = (int) $value;
136
            }
137
138
            return 'ALTER TABLE ' . $this->db->schema->quoteTableName($tableName) . " AUTO_INCREMENT=$value;";
139
        } elseif ($table === null) {
140
            throw new InvalidArgumentException("Table not found: $tableName");
141
        }
142
143
        throw new InvalidArgumentException("There is not sequence associated with table '$tableName'.");
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function buildLimit($limit, $offset)
150
    {
151
        $sql = '';
152
        // limit is not optional in CUBRID
153
        // http://www.cubrid.org/manual/90/en/LIMIT%20Clause
154
        // "You can specify a very big integer for row_count to display to the last row, starting from a specific row."
155
        if ($this->hasLimit($limit)) {
156
            $sql = 'LIMIT ' . $limit;
157
            if ($this->hasOffset($offset)) {
158
                $sql .= ' OFFSET ' . $offset;
159
            }
160
        } elseif ($this->hasOffset($offset)) {
161
            $sql = "LIMIT 9223372036854775807 OFFSET $offset"; // 2^63-1
162
        }
163
164
        return $sql;
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     * @since 2.0.8
170
     */
171
    public function selectExists($rawSql)
172
    {
173
        return 'SELECT CASE WHEN EXISTS(' . $rawSql . ') THEN 1 ELSE 0 END';
174
    }
175
176
    /**
177
     * @inheritDoc
178
     * @see http://www.cubrid.org/manual/93/en/sql/schema/table.html#drop-index-clause
179
     */
180
    public function dropIndex($name, $table)
181
    {
182
        /** @var Schema $schema */
183
        $schema = $this->db->getSchema();
184
        foreach ($schema->getTableUniques($table) as $unique) {
185
            if ($unique->name === $name) {
186
                return $this->dropUnique($name, $table);
187
            }
188
        }
189
190
        return 'DROP INDEX ' . $this->db->quoteTableName($name) . ' ON ' . $this->db->quoteTableName($table);
191
    }
192
193
    /**
194
     * @inheritDoc
195
     * @throws NotSupportedException this is not supported by CUBRID.
196
     */
197
    public function addCheck($name, $table, $expression)
198
    {
199
        throw new NotSupportedException(__METHOD__ . ' is not supported by CUBRID.');
200
    }
201
202
    /**
203
     * @inheritDoc
204
     * @throws NotSupportedException this is not supported by CUBRID.
205
     */
206
    public function dropCheck($name, $table)
207
    {
208
        throw new NotSupportedException(__METHOD__ . ' is not supported by CUBRID.');
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     * @since 2.0.8
214
     */
215
    public function addCommentOnColumn($table, $column, $comment)
216
    {
217
        $definition = $this->getColumnDefinition($table, $column);
218
        $definition = trim(preg_replace("/COMMENT '(.*?)'/i", '', $definition));
219
220
        return 'ALTER TABLE ' . $this->db->quoteTableName($table)
221
        . ' CHANGE ' . $this->db->quoteColumnName($column)
222
        . ' ' . $this->db->quoteColumnName($column)
223
        . (empty($definition) ? '' : ' ' . $definition)
224
        . ' COMMENT ' . $this->db->quoteValue($comment);
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     * @since 2.0.8
230
     */
231
    public function addCommentOnTable($table, $comment)
232
    {
233
        return 'ALTER TABLE ' . $this->db->quoteTableName($table) . ' COMMENT ' . $this->db->quoteValue($comment);
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     * @since 2.0.8
239
     */
240
    public function dropCommentFromColumn($table, $column)
241
    {
242
        return $this->addCommentOnColumn($table, $column, '');
243
    }
244
245
    /**
246
     * {@inheritdoc}
247
     * @since 2.0.8
248
     */
249
    public function dropCommentFromTable($table)
250
    {
251
        return $this->addCommentOnTable($table, '');
252
    }
253
254
255
    /**
256
     * Gets column definition.
257
     *
258
     * @param string $table table name
259
     * @param string $column column name
260
     * @return null|string the column definition
261
     * @throws Exception in case when table does not contain column
262
     * @since 2.0.8
263
     */
264
    private function getColumnDefinition($table, $column)
265
    {
266
        $row = $this->db->createCommand('SHOW CREATE TABLE ' . $this->db->quoteTableName($table))->queryOne();
267
        if ($row === false) {
268
            throw new Exception("Unable to find column '$column' in table '$table'.");
269
        }
270
        if (isset($row['Create Table'])) {
271
            $sql = $row['Create Table'];
272
        } else {
273
            $row = array_values($row);
274
            $sql = $row[1];
275
        }
276
        $sql = preg_replace('/^[^(]+\((.*)\).*$/', '\1', $sql);
277
        $sql = str_replace(', [', ",\n[", $sql);
278
        if (preg_match_all('/^\s*\[(.*?)\]\s+(.*?),?$/m', $sql, $matches)) {
279
            foreach ($matches[1] as $i => $c) {
280
                if ($c === $column) {
281
                    return $matches[2][$i];
282
                }
283
            }
284
        }
285
286
        return null;
287
    }
288
}
289