Passed
Pull Request — master (#41)
by Thomas
03:05
created

Sqlite   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 3 Features 0
Metric Value
wmc 19
c 5
b 3
f 0
lcom 1
cbo 5
dl 0
loc 121
ccs 51
cts 51
cp 1
rs 10

4 Methods

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