Test Failed
Pull Request — master (#266)
by Wilmer
18:30 queued 14:44
created

DMLQueryBuilder   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 44
c 3
b 0
f 0
dl 0
loc 124
ccs 46
cts 46
cp 1
rs 10
wmc 16

4 Methods

Rating   Name   Duplication   Size   Complexity  
A resetSequence() 0 24 4
A insertWithReturningPks() 0 3 1
A upsert() 0 40 5
A prepareInsertValues() 0 27 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
6
7
use Yiisoft\Db\Exception\Exception;
8
use Yiisoft\Db\Exception\InvalidArgumentException;
9
use Yiisoft\Db\Exception\InvalidConfigException;
10
use Yiisoft\Db\Exception\NotSupportedException;
11
use Yiisoft\Db\Expression\Expression;
12
use Yiisoft\Db\Expression\ExpressionInterface;
13
use Yiisoft\Db\Query\Query;
14
use Yiisoft\Db\Query\QueryInterface;
15
use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder;
16
17
use function implode;
18
use function reset;
19
20
/**
21
 * Implements a DML (Data Manipulation Language) SQL statements for MySQL, MariaDB.
22
 */
23
final class DMLQueryBuilder extends AbstractDMLQueryBuilder
24
{
25
    /**
26
     * @throws Exception
27
     * @throws NotSupportedException
28 522
     */
29
    public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
30
    {
31
        throw new NotSupportedException(__METHOD__ . ' is not supported by Mysql.');
32
    }
33 522
34
    public function resetSequence(string $tableName, int|string $value = null): string
35
    {
36
        $table = $this->schema->getTableSchema($tableName);
0 ignored issues
show
Bug introduced by
The property schema is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
37
38
        if ($table === null) {
39
            throw new InvalidArgumentException("Table not found: '$tableName'.");
40 1
        }
41
42 1
        $sequenceName = $table->getSequenceName();
43
        if ($sequenceName === null) {
44
            throw new InvalidArgumentException("There is not sequence associated with table '$tableName'.");
45 4
        }
46
47 4
        $tableName = $this->quoter->quoteTableName($tableName);
0 ignored issues
show
Bug introduced by
The property quoter is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
48
49 4
        if ($value !== null) {
50 1
            return 'ALTER TABLE ' . $tableName . ' AUTO_INCREMENT=' . $value . ';';
51
        }
52
53 3
        $pk = $table->getPrimaryKey();
54 3
        $key = (string) reset($pk);
55 1
56
        return "SET @new_autoincrement_value := (SELECT MAX(`$key`) + 1 FROM $tableName);
57
SET @sql = CONCAT('ALTER TABLE $tableName AUTO_INCREMENT =', @new_autoincrement_value);
58 2
PREPARE autoincrement_stmt FROM @sql;
59
EXECUTE autoincrement_stmt";
60 2
    }
61 1
62
    public function upsert(
63
        string $table,
64 2
        QueryInterface|array $insertColumns,
65 2
        bool|array $updateColumns,
66
        array &$params
67 2
    ): string {
68 2
        $insertSql = $this->insert($table, $insertColumns, $params);
69
70 2
        /** @psalm-var array $uniqueNames */
71
        [$uniqueNames, , $updateNames] = $this->prepareUpsertColumns(
72
            $table,
73 34
            $insertColumns,
74
            $updateColumns,
75
        );
76
77
        if (empty($uniqueNames)) {
78
            return $insertSql;
79 34
        }
80
81
        if ($updateColumns === true) {
0 ignored issues
show
introduced by
The condition $updateColumns === true is always false.
Loading history...
82 34
            $updateColumns = [];
83 34
            /** @psalm-var string $name */
84 34
            foreach ($updateNames as $name) {
85 34
                $updateColumns[$name] = new Expression(
86 34
                    'VALUES(' . $this->quoter->quoteColumnName($name) . ')'
87
                );
88 34
            }
89 2
        }
90
91
        if (empty($updateColumns)) {
92 32
            return str_replace('INSERT INTO', 'INSERT IGNORE INTO', $insertSql);
93 10
        }
94
95 10
        /**
96 8
         *  @psalm-var array<array-key, string> $updates
97 8
         *  @psalm-var array<string, ExpressionInterface|string> $updateColumns
98 8
         */
99
        [$updates, $params] = $this->prepareUpdateSets($table, $updateColumns, $params);
100
101
        return $insertSql . ' ON DUPLICATE KEY UPDATE ' . implode(', ', $updates);
102 32
    }
103 14
104
    /**
105
     * Prepares a `VALUES` part for an `INSERT` SQL statement.
106
     *
107
     * @param string $table The table to insert new rows into.
108
     * @param array|QueryInterface $columns The column data (name => value) to insert into the table or instance of
109
     * {@see Query} to perform `INSERT INTO ... SELECT` SQL statement.
110 18
     * @param array $params The binding parameters that will be generated by this method.
111
     * They should be bound to the DB command later.
112 18
     *
113
     * @throws Exception
114
     * @throws InvalidArgumentException
115
     * @throws InvalidConfigException
116
     * @throws NotSupportedException
117
     *
118
     * @return array Array of column names, placeholders, values, and params.
119
     */
120
    protected function prepareInsertValues(string $table, QueryInterface|array $columns, array $params = []): array
121
    {
122
        /**
123
         * @psalm-var array $names
124
         * @psalm-var array $placeholders
125
         */
126
        [$names, $placeholders, $values, $params] = parent::prepareInsertValues($table, $columns, $params);
127
128
        if (!$columns instanceof QueryInterface && empty($names)) {
0 ignored issues
show
introduced by
$columns is never a sub-type of Yiisoft\Db\Query\QueryInterface.
Loading history...
129
            $tableSchema = $this->schema->getTableSchema($table);
0 ignored issues
show
Bug introduced by
The property schema is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
130
131 80
            if ($tableSchema !== null) {
132
                if (!empty($tableSchema->getPrimaryKey())) {
133
                    $columns = $tableSchema->getPrimaryKey();
134
                    $defaultValue = 'NULL';
135
                } else {
136
                    $columns = [current($tableSchema->getColumns())->getName()];
137 80
                    $defaultValue = 'DEFAULT';
138
                }
139 77
                foreach ($columns as $name) {
140 2
                    $names[] = $this->quoter->quoteColumnName($name);
0 ignored issues
show
Bug introduced by
The property quoter is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
141
                    $placeholders[] = $defaultValue;
142 2
                }
143 2
            }
144 2
        }
145 2
146
        return [$names, $placeholders, $values, $params];
147 1
    }
148
}
149