Sqlite   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 130
Duplicated Lines 6.15 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 5
dl 8
loc 130
rs 10
c 0
b 0
f 0
ccs 54
cts 54
cp 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A insertAndSyncWithAutoInc() 5 27 3
A describe() 0 24 4
A hasCompositeKey() 0 9 1
B normalizeColumnDefinition() 3 26 8

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace ORM\Dbal;
4
5
use ORM\Entity;
6
use ORM\Exception;
7
use PDO;
8
9
/**
10
 * Database abstraction for SQLite databases
11
 *
12
 * @package ORM\Dbal
13
 * @author  Thomas Flori <[email protected]>
14
 */
15
class Sqlite extends Dbal
16
{
17
    protected static $typeMapping = [
18
        'integer' => Type\Number::class,
19
        'int'     => Type\Number::class,
20
        'double'  => Type\Number::class,
21
        'real'    => Type\Number::class,
22
        'float'   => Type\Number::class,
23
        'numeric' => Type\Number::class,
24
        'decimal' => Type\Number::class,
25
26
        'varchar'   => Type\VarChar::class,
27
        'character' => Type\VarChar::class,
28
29
        'text' => Type\Text::class,
30
31
        'boolean' => Type\Boolean::class,
32
        'json'    => Type\Json::class,
33
34
        'datetime' => Type\DateTime::class,
35
        'date'     => Type\DateTime::class,
36
        'time'     => Type\Time::class,
37
    ];
38 2
39
    public function insertAndSyncWithAutoInc(Entity ...$entities)
40 2
    {
41 2
        if (count($entities) === 0) {
42
            return false;
43 2
        }
44 1
        static::assertSameType($entities);
45 1
46
        $entity = reset($entities);
47 1
        $pdo = $this->entityManager->getConnection();
48
        $table = $this->escapeIdentifier($entity::getTableName());
49
        $pKey = $this->escapeIdentifier($entity::getColumnName($entity::getPrimaryKeyVars()[0]));
50 2
        $pdo->beginTransaction();
51
        $pdo->query($this->buildInsertStatement(...$entities));
52
        $rows = $pdo->query('SELECT * FROM ' . $table . ' WHERE ' . $pKey . ' <= ' . $pdo->lastInsertId() .
53 32
                            ' ORDER BY ' . $pKey . ' DESC LIMIT ' . count($entities))
54
            ->fetchAll(PDO::FETCH_ASSOC);
55 32
        $pdo->commit();
56 32
57 32
        /** @var Entity $entity */
58 View Code Duplication
        foreach (array_reverse($entities) as $key => $entity) {
59 32
            $entity->setOriginalData($rows[$key]);
60 32
            $entity->reset();
61
            $this->entityManager->map($entity, true);
62 32
        }
63
64 32
        return true;
65 2
    }
66
67
    public function describe($schemaTable)
68 30
    {
69
        $table = explode($this->identifierDivider, $schemaTable);
70 30
        list($schema, $table) = count($table) === 2 ? $table : [ null, $table[ 0 ] ];
71 30
        $schema = $schema !== null ? $this->escapeIdentifier($schema) . '.' : '';
72 30
73 30
        $result     = $this->entityManager->getConnection()->query(
74
            'PRAGMA ' . $schema . 'table_info(' . $this->escapeIdentifier($table) . ')'
75 30
        );
76
        $rawColumns = $result->fetchAll(PDO::FETCH_ASSOC);
77
78
        if (count($rawColumns) === 0) {
79
            throw new Exception('Unknown table ' . $table);
80
        }
81
82
        $compositeKey = $this->hasCompositeKey($rawColumns);
83
84 30
        $cols = array_map(function ($rawColumn) use ($compositeKey) {
85
            $columnDefinition = $this->normalizeColumnDefinition($rawColumn, $compositeKey);
86 30
            return new Column($this, $columnDefinition);
87 30
        }, $rawColumns);
88 30
89 30
        return new Table($cols);
90
    }
91 30
92
    /**
93
     * Checks $rawColumns for a multiple primary key
94
     *
95
     * @param array $rawColumns
96
     * @return bool
97
     */
98
    protected function hasCompositeKey($rawColumns)
99
    {
100
        return count(array_filter(array_map(
101
            function ($rawColumn) {
102
                return $rawColumn[ 'pk' ];
103
            },
104 30
            $rawColumns
105
        ))) > 1;
106 30
    }
107
108 30
    /**
109 30
     * Normalize a column definition
110 29
     *
111
     * The column definition from "PRAGMA table_info(<table>)" is to special as useful. Here we normalize it to a more
112
     * ANSI-SQL style.
113 30
     *
114 30
     * @param array $rawColumn
115 30
     * @param bool  $compositeKey
116 30
     * @return array
117 30
     */
118
    protected function normalizeColumnDefinition($rawColumn, $compositeKey = false)
119 30
    {
120 30
        $definition = [];
121 28
122 2
        $definition['data_type'] = $this->normalizeType($rawColumn['type']);
123 2
        $definition['type'] = isset(static::$typeMapping[$definition['data_type']]) ?
124 28
            static::$typeMapping[$definition['data_type']] : null;
125 27
126 27
        $definition['column_name']              = $rawColumn['name'];
127 2
        $definition['is_nullable']              = $rawColumn['notnull'] === '0';
128 2
        $definition['column_default']           = $rawColumn['dflt_value'];
129 26
        $definition['character_maximum_length'] = null;
130 9
        $definition['datetime_precision']       = null;
131 1
132
        if (in_array($definition['data_type'], ['varchar', 'char'])) {
133 9
            $definition['character_maximum_length'] = $this->extractParenthesis($rawColumn['type']);
134 View Code Duplication
        } elseif (in_array($definition['data_type'], ['datetime', 'timestamp', 'time'])) {
135
            $definition['datetime_precision'] = $this->extractParenthesis($rawColumn['type']);
136 30
        } elseif ($definition['data_type'] === 'integer' && !$definition['column_default'] &&
137
                  $rawColumn['pk'] === '1' && !$compositeKey
138
        ) {
139
            $definition['column_default'] = 'sequence(rowid)';
140
        }
141
142
        return $definition;
143
    }
144
}
145