Passed
Pull Request — dev (#57)
by Def
14:10 queued 04:35
created

CommandPDOOracle::prepare()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7.7656

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 13
nop 1
dl 0
loc 30
ccs 12
cts 16
cp 0.75
crap 7.7656
rs 8.8333
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A CommandPDOOracle::getCacheKey() 0 8 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Oracle\PDO;
6
7
use PDO;
8
use PDOException;
9
use Yiisoft\Db\Command\CommandPDO;
10
use Yiisoft\Db\Command\ParamInterface;
11
use Yiisoft\Db\Exception\ConvertException;
12
use Yiisoft\Db\Query\QueryBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Yiisoft\Db\Query\QueryBuilderInterface;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
15
use function array_keys;
16
use function count;
17
use function implode;
18
use function strlen;
19
20
/**
21
 * Command represents an Oracle SQL statement to be executed against a database.
22
 */
23
final class CommandPDOOracle extends CommandPDO
24
{
25 174
    public function queryBuilder(): QueryBuilderInterface
26
    {
27 174
        return $this->db->getQueryBuilder();
28
    }
29
30 1
    public function insertEx(string $table, array $columns): bool|array
31
    {
32 1
        $params = [];
33 1
        $sql = $this->queryBuilder()->insertEx($table, $columns, $params);
34
35 1
        $tableSchema = $this->queryBuilder()->schema()->getTableSchema($table);
36
37 1
        $returnColumns = $tableSchema?->getPrimaryKey() ?? [];
38 1
        $columnSchemas = $tableSchema?->getColumns() ?? [];
39
40 1
        $returnParams = [];
41 1
        $returning = [];
42 1
        foreach ($returnColumns as $name) {
43 1
            $phName = QueryBuilder::PARAM_PREFIX . (count($params) + count($returnParams));
44
45 1
            $returnParams[$phName] = [
46
                'column' => $name,
47
                'value' => '',
48
            ];
49
50 1
            if (!isset($columnSchemas[$name]) || $columnSchemas[$name]->getPhpType() !== 'integer') {
51
                $returnParams[$phName]['dataType'] = PDO::PARAM_STR;
52
            } else {
53 1
                $returnParams[$phName]['dataType'] = PDO::PARAM_INT;
54
            }
55
56 1
            $returnParams[$phName]['size'] = $columnSchemas[$name]->getSize() ?? -1;
57
58 1
            $returning[] = $this->db->getQuoter()->quoteColumnName($name);
59
        }
60
61 1
        $sql .= ' RETURNING ' . implode(', ', $returning) . ' INTO ' . implode(', ', array_keys($returnParams));
62
63 1
        $this->setSql($sql)->bindValues($params);
64 1
        $this->prepare(false);
65
66
        /** @psalm-var array<string, array{column: string, value: mixed, dataType: int, size: int}> $returnParams */
67 1
        foreach ($returnParams as $name => &$value) {
68 1
            $this->bindParam($name, $value['value'], $value['dataType'], $value['size']);
69
        }
70
71 1
        if (!$this->execute()) {
72
            return false;
73
        }
74
75 1
        $result = [];
76
77 1
        foreach ($returnParams as $value) {
78
            /** @var mixed */
79 1
            $result[$value['column']] = $value['value'];
80
        }
81
82 1
        return $result;
83
    }
84
85 164
    protected function bindPendingParams(): void
86
    {
87 164
        $paramsPassedByReference = [];
88
89
        /** @psalm-var ParamInterface[] */
90 164
        $params = $this->params;
91
92 164
        foreach ($params as $name => $value) {
93 141
            if (PDO::PARAM_STR === $value->getType()) {
94
                /** @var mixed */
95 135
                $paramsPassedByReference[$name] = $value->getValue();
96 135
                $this->pdoStatement?->bindParam(
97
                    $name,
98 135
                    $paramsPassedByReference[$name],
99 135
                    $value->getType(),
100 135
                    strlen((string) $value->getValue())
101
                );
102
            } else {
103 23
                $this->pdoStatement?->bindValue($name, $value->getValue(), $value->getType());
104
            }
105
        }
106
    }
107
108 155
    protected function getCacheKey(int $queryMode, string $rawSql): array
109
    {
110
        return [
111 155
            __CLASS__,
112
            $queryMode,
113 155
            $this->db->getDriver()->getDsn(),
114 155
            $this->db->getDriver()->getUsername(),
115
            $rawSql,
116
        ];
117
    }
118
119 163
    protected function internalExecute(?string $rawSql): void
120
    {
121 163
        $attempt = 0;
122
123 163
        while (true) {
124
            try {
125
                if (
126 163
                    ++$attempt === 1
127 163
                    && $this->isolationLevel !== null
128 163
                    && $this->db->getTransaction() === null
129
                ) {
130
                    $this->db->transaction(fn (string $rawSql) => $this->internalExecute($rawSql), $this->isolationLevel);
131
                } else {
132 163
                    $this->pdoStatement?->execute();
133
                }
134 163
                break;
135 6
            } catch (PDOException $e) {
136 6
                $rawSql = $rawSql ?: $this->getRawSql();
137 6
                $e = (new ConvertException($e, $rawSql))->run();
138
139 6
                if ($this->retryHandler === null || !($this->retryHandler)($e, $attempt)) {
140 6
                    throw $e;
141
                }
142
            }
143
        }
144
    }
145
}
146