Completed
Branch feature/pre-split (d89158)
by Anton
04:43
created

SQLiteColumn::prepareEnum()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Drivers\SQLite\Schemas;
8
9
use Spiral\Database\Entities\Driver;
10
use Spiral\Database\Schemas\Prototypes\AbstractColumn;
11
12
class SQLiteColumn extends AbstractColumn
13
{
14
    /**
15
     * {@inheritdoc}
16
     */
17
    protected $mapping = [
18
        //Primary sequences
19
        'primary'     => [
20
            'type'       => 'integer',
21
            'primaryKey' => true,
22
            'nullable'   => false,
23
        ],
24
        'bigPrimary'  => [
25
            'type'       => 'integer',
26
            'primaryKey' => true,
27
            'nullable'   => false,
28
        ],
29
30
        //Enum type (mapped via method)
31
        'enum'        => 'enum',
32
33
        //Logical types
34
        'boolean'     => 'boolean',
35
36
        //Integer types (size can always be changed with size method), longInteger has method alias
37
        //bigInteger
38
        'integer'     => 'integer',
39
        'tinyInteger' => 'tinyint',
40
        'bigInteger'  => 'bigint',
41
42
        //String with specified length (mapped via method)
43
        'string'      => 'text',
44
45
        //Generic types
46
        'text'        => 'text',
47
        'tinyText'    => 'text',
48
        'longText'    => 'text',
49
50
        //Real types
51
        'double'      => 'double',
52
        'float'       => 'real',
53
54
        //Decimal type (mapped via method)
55
        'decimal'     => 'numeric',
56
57
        //Date and Time types
58
        'datetime'    => 'datetime',
59
        'date'        => 'date',
60
        'time'        => 'time',
61
        'timestamp'   => 'timestamp',
62
63
        //Binary types
64
        'binary'      => 'blob',
65
        'tinyBinary'  => 'blob',
66
        'longBinary'  => 'blob',
67
68
        //Additional types
69
        'json'        => 'text',
70
    ];
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    protected $reverseMapping = [
76
        'primary'     => [['type' => 'integer', 'primaryKey' => true]],
77
        'enum'        => ['enum'],
78
        'boolean'     => ['boolean'],
79
        'integer'     => ['int', 'integer', 'smallint', 'mediumint'],
80
        'tinyInteger' => ['tinyint'],
81
        'bigInteger'  => ['bigint'],
82
        'text'        => ['text', 'string'],
83
        'double'      => ['double'],
84
        'float'       => ['real'],
85
        'decimal'     => ['numeric'],
86
        'datetime'    => ['datetime'],
87
        'date'        => ['date'],
88
        'time'        => ['time'],
89
        'timestamp'   => ['timestamp'],
90
        'binary'      => ['blob'],
91
    ];
92
93
    /**
94
     * Indication that column is primary key.
95
     *
96
     * @var bool
97
     */
98
    protected $primaryKey = false;
99
100
    /**
101
     * DBMS specific reverse mapping must map database specific type into limited set of abstract
102
     * types.
103
     *
104
     * @return string
105
     */
106
    public function abstractType(): string
107
    {
108
        if ($this->primaryKey) {
109
            return 'primary';
110
        }
111
112
        return parent::abstractType();
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function sqlStatement(Driver $driver): string
119
    {
120
        $statement = parent::sqlStatement($driver);
121
        if ($this->abstractType() != 'enum') {
122
            return $statement;
123
        }
124
125
        $enumValues = [];
126
        foreach ($this->enumValues as $value) {
127
            $enumValues[] = $driver->quote($value);
128
        }
129
130
        $quoted = $driver->quote($this->name);
131
132
        return "$statement CHECK ({$quoted} IN (" . implode(', ', $enumValues) . '))';
133
    }
134
135
    /**
136
     * @param string $table Table name.
137
     * @param array  $schema
138
     *
139
     * @return SQLiteColumn
140
     */
141
    public static function createInstance(string $table, array $schema): self
142
    {
143
        $column = new self($table, $schema['name']);
144
145
        $column->nullable = !$schema['notnull'];
146
        $column->type = $schema['type'];
147
        $column->primaryKey = (bool)$schema['pk'];
148
149
        /*
150
         * Normalizing default value.
151
         */
152
        $column->defaultValue = $schema['dflt_value'];
153
154
        if (preg_match('/^[\'""].*?[\'"]$/', $column->defaultValue)) {
155
            $column->defaultValue = substr($column->defaultValue, 1, -1);
156
        }
157
158
        if (!preg_match(
159
            '/^(?P<type>[a-z]+) *(?:\((?P<options>[^\)]+)\))?/',
160
            $schema['type'],
161
            $matches
162
        )
163
        ) {
164
            //No type definition included
165
            return $column;
166
        }
167
168
        //Reformatted type value
169
        $column->type = $matches['type'];
170
171
        //Fetching size options
172 View Code Duplication
        if (!empty($matches['options'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
173
            $options = explode(',', $matches['options']);
174
175
            if (count($options) > 1) {
176
                $column->precision = (int)$options[0];
177
                $column->scale = (int)$options[1];
178
            } else {
179
                $column->size = (int)$options[0];
180
            }
181
        }
182
183
        if ($column->type == 'enum') {
184
            //Quoted column name
185
            $quoted = $schema['identifier'];
186
187
            foreach ($schema['tableStatement'] as $column) {
188
                //Looking for enum values in column definition code
189
                if (preg_match(
190
                    "/{$quoted} +enum.*?CHECK *\\({$quoted} in \\((.*?)\\)\\)/i",
191
                    trim($column),
192
                    $matches
193
                )) {
194
                    $enumValues = explode(',', $matches[1]);
195
                    foreach ($enumValues as &$value) {
196
                        //Trimming values
197
                        if (preg_match("/^'?(.*?)'?$/", trim($value), $matches)) {
198
                            //In database: 'value'
199
                            $value = $matches[1];
200
                        }
201
202
                        unset($value);
203
                    }
204
205
                    $column->enumValues = $enumValues;
206
                }
207
            }
208
        }
209
210
        return $column;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    protected function prepareEnum(Driver $driver): string
217
    {
218
        return '';
219
    }
220
}