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 ( c73de3...97c43c )
by Robert
13:22
created

QueryBuilder   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 44
lcom 2
cbo 8
dl 0
loc 282
rs 8.3396
c 0
b 0
f 0
ccs 0
cts 162
cp 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
B buildOrderByAndLimit() 0 27 5
A renameTable() 0 4 1
A alterColumn() 0 6 1
A dropIndex() 0 4 1
B resetSequence() 0 22 4
A addForeignKey() 0 16 3
C insert() 0 43 15
C batchInsert() 0 41 11
A selectExists() 0 4 1
A dropCommentFromColumn() 0 4 1
A dropCommentFromTable() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like QueryBuilder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use QueryBuilder, and based on these observations, apply Extract Interface, too.

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\oci;
9
10
use yii\base\InvalidParamException;
11
use yii\db\Connection;
12
use yii\db\Exception;
13
use yii\db\Expression;
14
15
/**
16
 * QueryBuilder is the query builder for Oracle databases.
17
 *
18
 * @author Qiang Xue <[email protected]>
19
 * @since 2.0
20
 */
21
class QueryBuilder extends \yii\db\QueryBuilder
22
{
23
    /**
24
     * @var array mapping from abstract column types (keys) to physical column types (values).
25
     */
26
    public $typeMap = [
27
        Schema::TYPE_PK => 'NUMBER(10) NOT NULL PRIMARY KEY',
28
        Schema::TYPE_UPK => 'NUMBER(10) UNSIGNED NOT NULL PRIMARY KEY',
29
        Schema::TYPE_BIGPK => 'NUMBER(20) NOT NULL PRIMARY KEY',
30
        Schema::TYPE_UBIGPK => 'NUMBER(20) UNSIGNED NOT NULL PRIMARY KEY',
31
        Schema::TYPE_CHAR => 'CHAR(1)',
32
        Schema::TYPE_STRING => 'VARCHAR2(255)',
33
        Schema::TYPE_TEXT => 'CLOB',
34
        Schema::TYPE_SMALLINT => 'NUMBER(5)',
35
        Schema::TYPE_INTEGER => 'NUMBER(10)',
36
        Schema::TYPE_BIGINT => 'NUMBER(20)',
37
        Schema::TYPE_FLOAT => 'NUMBER',
38
        Schema::TYPE_DOUBLE => 'NUMBER',
39
        Schema::TYPE_DECIMAL => 'NUMBER',
40
        Schema::TYPE_DATETIME => 'TIMESTAMP',
41
        Schema::TYPE_TIMESTAMP => 'TIMESTAMP',
42
        Schema::TYPE_TIME => 'TIMESTAMP',
43
        Schema::TYPE_DATE => 'DATE',
44
        Schema::TYPE_BINARY => 'BLOB',
45
        Schema::TYPE_BOOLEAN => 'NUMBER(1)',
46
        Schema::TYPE_MONEY => 'NUMBER(19,4)',
47
    ];
48
49
50
    /**
51
     * @inheritdoc
52
     */
53
    public function buildOrderByAndLimit($sql, $orderBy, $limit, $offset)
54
    {
55
        $orderBy = $this->buildOrderBy($orderBy);
56
        if ($orderBy !== '') {
57
            $sql .= $this->separator . $orderBy;
58
        }
59
60
        $filters = [];
61
        if ($this->hasOffset($offset)) {
62
            $filters[] = 'rowNumId > ' . $offset;
63
        }
64
        if ($this->hasLimit($limit)) {
65
            $filters[] = 'rownum <= ' . $limit;
66
        }
67
        if (empty($filters)) {
68
            return $sql;
69
        }
70
71
        $filter = implode(' AND ', $filters);
72
        return <<<EOD
73
WITH USER_SQL AS ($sql),
74
    PAGINATION AS (SELECT USER_SQL.*, rownum as rowNumId FROM USER_SQL)
75
SELECT *
76
FROM PAGINATION
77
WHERE $filter
78
EOD;
79
    }
80
81
    /**
82
     * Builds a SQL statement for renaming a DB table.
83
     *
84
     * @param string $table the table to be renamed. The name will be properly quoted by the method.
85
     * @param string $newName the new table name. The name will be properly quoted by the method.
86
     * @return string the SQL statement for renaming a DB table.
87
     */
88
    public function renameTable($table, $newName)
89
    {
90
        return 'ALTER TABLE ' . $this->db->quoteTableName($table) . ' RENAME TO ' . $this->db->quoteTableName($newName);
91
    }
92
93
    /**
94
     * Builds a SQL statement for changing the definition of a column.
95
     *
96
     * @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
97
     * @param string $column the name of the column to be changed. The name will be properly quoted by the method.
98
     * @param string $type the new column type. The [[getColumnType]] method will be invoked to convert abstract column type (if any)
99
     * into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
100
     * For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
101
     * @return string the SQL statement for changing the definition of a column.
102
     */
103
    public function alterColumn($table, $column, $type)
104
    {
105
        $type = $this->getColumnType($type);
106
107
        return 'ALTER TABLE ' . $this->db->quoteTableName($table) . ' MODIFY ' . $this->db->quoteColumnName($column) . ' ' . $this->getColumnType($type);
108
    }
109
110
    /**
111
     * Builds a SQL statement for dropping an index.
112
     *
113
     * @param string $name the name of the index to be dropped. The name will be properly quoted by the method.
114
     * @param string $table the table whose index is to be dropped. The name will be properly quoted by the method.
115
     * @return string the SQL statement for dropping an index.
116
     */
117
    public function dropIndex($name, $table)
118
    {
119
        return 'DROP INDEX ' . $this->db->quoteTableName($name);
120
    }
121
122
    /**
123
     * @inheritdoc
124
     */
125
    public function resetSequence($table, $value = null)
126
    {
127
        $tableSchema = $this->db->getTableSchema($table);
128
        if ($tableSchema === null) {
129
            throw new InvalidParamException("Unknown table: $table");
130
        }
131
        if ($tableSchema->sequenceName === null) {
132
            return '';
133
        }
134
135
        if ($value !== null) {
136
            $value = (int) $value;
137
        } else {
138
            // use master connection to get the biggest PK value
139
            $value = $this->db->useMaster(function (Connection $db) use ($tableSchema) {
140
                return $db->createCommand("SELECT MAX(\"{$tableSchema->primaryKey}\") FROM \"{$tableSchema->name}\"")->queryScalar();
141
            }) + 1;
142
        }
143
144
        return "DROP SEQUENCE \"{$tableSchema->name}_SEQ\";"
145
            . "CREATE SEQUENCE \"{$tableSchema->name}_SEQ\" START WITH {$value} INCREMENT BY 1 NOMAXVALUE NOCACHE";
146
    }
147
148
    /**
149
     * @inheritdoc
150
     */
151
    public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
152
    {
153
        $sql = 'ALTER TABLE ' . $this->db->quoteTableName($table)
154
            . ' ADD CONSTRAINT ' . $this->db->quoteColumnName($name)
155
            . ' FOREIGN KEY (' . $this->buildColumns($columns) . ')'
156
            . ' REFERENCES ' . $this->db->quoteTableName($refTable)
157
            . ' (' . $this->buildColumns($refColumns) . ')';
158
        if ($delete !== null) {
159
            $sql .= ' ON DELETE ' . $delete;
160
        }
161
        if ($update !== null) {
162
            throw new Exception('Oracle does not support ON UPDATE clause.');
163
        }
164
165
        return $sql;
166
    }
167
168
    /**
169
     * @inheritdoc
170
     */
171
    public function insert($table, $columns, &$params)
172
    {
173
        $schema = $this->db->getSchema();
174
        if (($tableSchema = $schema->getTableSchema($table)) !== null) {
175
            $columnSchemas = $tableSchema->columns;
176
        } else {
177
            $columnSchemas = [];
178
        }
179
        $names = [];
180
        $placeholders = [];
181
        $values = ' DEFAULT VALUES';
182
        if ($columns instanceof \yii\db\Query) {
183
            list($names, $values) = $this->prepareInsertSelectSubQuery($columns, $schema);
184
        } else {
185
            foreach ($columns as $name => $value) {
186
                $names[] = $schema->quoteColumnName($name);
187
                if ($value instanceof Expression) {
188
                    $placeholders[] = $value->expression;
189
                    foreach ($value->params as $n => $v) {
190
                        $params[$n] = $v;
191
                    }
192
                } elseif ($value instanceof \yii\db\Query) {
193
                    list($sql, $params) = $this->build($value, $params);
194
                    $placeholders[] = "($sql)";
195
                } else {
196
                    $phName = self::PARAM_PREFIX . count($params);
197
                    $placeholders[] = $phName;
198
                    $params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
199
                }
200
            }
201
            if (empty($names) && $tableSchema !== null) {
202
                $columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : [reset($tableSchema->columns)->name];
203
                foreach ($columns as $name) {
204
                    $names[] = $schema->quoteColumnName($name);
205
                    $placeholders[] = 'DEFAULT';
206
                }
207
            }
208
        }
209
210
        return 'INSERT INTO ' . $schema->quoteTableName($table)
211
            . (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
212
            . (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : $values);
213
    }
214
215
    /**
216
     * Generates a batch INSERT SQL statement.
217
     * For example,
218
     *
219
     * ```php
220
     * $sql = $queryBuilder->batchInsert('user', ['name', 'age'], [
221
     *     ['Tom', 30],
222
     *     ['Jane', 20],
223
     *     ['Linda', 25],
224
     * ]);
225
     * ```
226
     *
227
     * Note that the values in each row must match the corresponding column names.
228
     *
229
     * @param string $table the table that new rows will be inserted into.
230
     * @param array $columns the column names
231
     * @param array $rows the rows to be batch inserted into the table
232
     * @return string the batch INSERT SQL statement
233
     */
234
    public function batchInsert($table, $columns, $rows)
235
    {
236
        if (empty($rows)) {
237
            return '';
238
        }
239
240
        $schema = $this->db->getSchema();
241
        if (($tableSchema = $schema->getTableSchema($table)) !== null) {
242
            $columnSchemas = $tableSchema->columns;
243
        } else {
244
            $columnSchemas = [];
245
        }
246
247
        $values = [];
248
        foreach ($rows as $row) {
249
            $vs = [];
250
            foreach ($row as $i => $value) {
251
                if (isset($columns[$i], $columnSchemas[$columns[$i]]) && !is_array($value)) {
252
                    $value = $columnSchemas[$columns[$i]]->dbTypecast($value);
253
                }
254
                if (is_string($value)) {
255
                    $value = $schema->quoteValue($value);
256
                } elseif ($value === false) {
257
                    $value = 0;
258
                } elseif ($value === null) {
259
                    $value = 'NULL';
260
                }
261
                $vs[] = $value;
262
            }
263
            $values[] = '(' . implode(', ', $vs) . ')';
264
        }
265
266
        foreach ($columns as $i => $name) {
267
            $columns[$i] = $schema->quoteColumnName($name);
268
        }
269
270
        $tableAndColumns = ' INTO ' . $schema->quoteTableName($table)
271
        . ' (' . implode(', ', $columns) . ') VALUES ';
272
273
        return 'INSERT ALL ' . $tableAndColumns . implode($tableAndColumns, $values) . ' SELECT 1 FROM SYS.DUAL';
274
    }
275
276
    /**
277
     * @inheritdoc
278
     * @since 2.0.8
279
     */
280
    public function selectExists($rawSql)
281
    {
282
        return 'SELECT CASE WHEN EXISTS(' . $rawSql . ') THEN 1 ELSE 0 END FROM DUAL';
283
    }
284
285
    /**
286
     * @inheritdoc
287
     * @since 2.0.8
288
     */
289
    public function dropCommentFromColumn($table, $column)
290
    {
291
        return 'COMMENT ON COLUMN ' . $this->db->quoteTableName($table) . '.' . $this->db->quoteColumnName($column) . " IS ''";
292
    }
293
294
    /**
295
     * @inheritdoc
296
     * @since 2.0.8
297
     */
298
    public function dropCommentFromTable($table)
299
    {
300
        return 'COMMENT ON TABLE ' . $this->db->quoteTableName($table) . " IS ''";
301
    }
302
}
303