Test Failed
Pull Request — dev (#70)
by Wilmer
04:09 queued 37s
created

CommandPDOOracle::insertEx()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 53
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 7.025

Importance

Changes 0
Metric Value
cc 7
eloc 29
c 0
b 0
f 0
nc 18
nop 2
dl 0
loc 53
ccs 23
cts 25
cp 0.92
crap 7.025
rs 8.5226

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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