MysqlDriver51::getSchemaConfig()   F
last analyzed

Complexity

Conditions 27
Paths 4863

Size

Total Lines 149
Code Lines 104

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 95
CRAP Score 27

Importance

Changes 0
Metric Value
dl 0
loc 149
ccs 95
cts 95
cp 1
rs 2
c 0
b 0
f 0
cc 27
eloc 104
nc 4863
nop 2
crap 27

How to fix   Long Method    Complexity   

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
namespace Soluble\Schema\Source\Mysql;
4
5
use Soluble\DbWrapper\Adapter\AdapterInterface;
6
use ArrayObject;
7
use Zend\Config\Config;
8
use Soluble\Schema\Exception;
9
10
class MysqlDriver51 extends AbstractMysqlDriver
11
{
12
    /**
13
     * @var AdapterInterface
14
     */
15
    protected $adapter;
16
17
    /**
18
     * Schema name.
19
     *
20
     * @var string
21
     */
22
    protected $schema;
23
24
    /**
25
     * {@inheritdoc}
26
     */
27 23
    public function __construct(AdapterInterface $adapter, $schema)
28
    {
29 23
        parent::__construct($adapter, $schema);
30 23
    }
31
32
    /**
33
     * {@inheritdoc}
34
     *
35
     * @throws Exception\ErrorException
36
     */
37 4
    public function getSchemaConfig($table = null, $include_options = true)
38
    {
39 4
        $results = $this->executeQuery($table);
40
41 4
        $references = [];
42 4
        $config = new Config(['tables' => []], true);
43 4
        $tables = $config->offsetGet('tables');
44
45 4
        foreach ($results as $r) {
46
            // Setting table information
47 1
            $table_name = $r['table_name'];
48 1
            if (!$tables->offsetExists($table_name)) {
49
                $table_def = [
50 1
                    'name' => $table_name,
51
                    'columns' => [],
52
                    'primary_keys' => [],
53
                    'unique_keys' => [],
54
                    'foreign_keys' => [],
55
                    'references' => [],
56
                    'indexes' => [],
57
                ];
58 1
                if ($include_options) {
59 1
                    $table_def['options'] = [
60 1
                       'comment' => $r['table_comment'],
61 1
                       'collation' => $r['table_collation'],
62 1
                       'type' => $r['table_type'],
63 1
                       'engine' => $r['engine']
64
                    ];
65
                }
66 1
                $tables->offsetSet($table_name, $table_def);
67
            }
68 1
            $table = $tables->offsetGet($table_name);
69 1
            $columns = $table->columns;
70 1
            $column_name = $r['column_name'];
71
72 1
            $data_type = strtolower($r['data_type']);
73
74
            $col_def = [
75 1
                'type' => $data_type,
76 1
                'primary' => ($r['constraint_type'] == 'PRIMARY KEY'),
77 1
                'nullable' => ($r['is_nullable'] == 'YES'),
78 1
                'default' => $r['column_default']
79
            ];
80 1
            if (($r['constraint_type'] == 'PRIMARY KEY')) {
81 1
                $col_def['primary'] = true;
82 1
                $col_def['autoincrement'] = ($r['extra'] == 'auto_increment');
83
            }
84
85 1
            $has_charset = false;
86 1
            if (in_array($data_type, ['int', 'tinyint', 'mediumint', 'bigint', 'int', 'smallint', 'year'])) {
87 1
                $col_def['unsigned'] = (bool) preg_match('/unsigned/', strtolower($r['column_type']));
88 1
                $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
89 1
            } elseif (in_array($data_type, ['real', 'double precision', 'decimal', 'numeric', 'float', 'dec', 'fixed'])) {
90 1
                $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
91 1
                $col_def['scale'] = is_numeric($r['numeric_scale']) ? (int) $r['numeric_scale'] : null;
92 1
            } elseif (in_array($data_type, ['timestamp', 'date', 'time', 'datetime'])) {
93
                // nothing yet
94 1
            } elseif (in_array($data_type, ['char', 'varchar', 'binary', 'varbinary', 'text', 'tinytext', 'mediumtext', 'longtext'])) {
95 1
                $col_def['octet_length'] = is_numeric($r['character_octet_length']) ? (int) $r['character_octet_length'] : null;
96 1
                $col_def['length'] = is_numeric($r['character_maximum_length']) ? (int) $r['character_maximum_length'] : null;
97 1
                $has_charset = true;
98 1
            } elseif (in_array($data_type, ['blob', 'tinyblob', 'mediumblob', 'longblob'])) {
99 1
                $col_def['octet_length'] = (int) $r['character_octet_length'];
100 1
                $col_def['length'] = (int) $r['character_maximum_length'];
101 1
            } elseif (in_array($data_type, ['enum', 'set'])) {
102 1
                $col_def['octet_length'] = (int) $r['character_octet_length'];
103 1
                $col_def['length'] = (int) $r['character_maximum_length'];
104 1
                $def = $r['column_type'];
105
106 1
                preg_match_all("/'([^']+)'/", $def, $matches);
107 1
                if (is_array($matches[1]) && count($matches) > 0) {
108 1
                    $col_def['values'] = $matches[1];
109
                }
110
            }
111
112 1
            if ($include_options) {
113 1
                $col_def['options'] = [
114 1
                        'comment' => $r['column_comment'],
115 1
                        'definition' => $r['column_type'],
116 1
                        'column_key' => $r['column_key'],
117 1
                        'ordinal_position' => $r['ordinal_position'],
118 1
                        'constraint_type' => $r['constraint_type'], // 'PRIMARY KEY', 'FOREIGN_KEY', 'UNIQUE'
119
                    ];
120 1
                if ($has_charset) {
121 1
                    $col_def['options']['charset'] = $r['character_set_name'];
122 1
                    $col_def['options']['collation'] = $r['collation_name'];
123
                }
124
            }
125
126 1
            $columns[$column_name] = $col_def;
127
128 1
            $foreign_keys = $table->foreign_keys;
129 1
            $unique_keys = $table->unique_keys;
130
131 1
            $constraint_name = $r['constraint_name'];
132 1
            $referenced_table_name = $r['referenced_table_name'];
133 1
            $referenced_column_name = $r['referenced_column_name'];
134 1
            switch ($r['constraint_type']) {
135 1
                case 'PRIMARY KEY':
136 1
                    $table->primary_keys = array_merge($table->primary_keys->toArray(), (array) $column_name);
137 1
                    break;
138 1
                case 'UNIQUE':
139 1
                    if (!$unique_keys->offsetExists($constraint_name)) {
140 1
                        $unique_keys[$constraint_name] = [];
141
                    }
142 1
                    $unique_keys[$constraint_name] = array_merge($unique_keys[$constraint_name]->toArray(), (array) $column_name);
143 1
                    break;
144 1
                case 'FOREIGN KEY':
145
                    /*
146
                    if (!$foreign_keys->offsetExists($constraint_name)) {
147
                        $foreign_keys[$constraint_name] = array();
148
                    }
149
                     *
150
                     */
151
                    $fk = [
152 1
                       'referenced_table' => $referenced_table_name,
153 1
                       'referenced_column' => $referenced_column_name,
154 1
                       'constraint_name' => $constraint_name
155
                    ];
156 1
                    $foreign_keys[$column_name] = $fk;
157
                    //$table->references[$referenced_table_name] = array($column_name => $r['referenced_column_name']);
158
159 1
                    if (!array_key_exists($referenced_table_name, $references)) {
160 1
                        $references[$referenced_table_name] = [];
161
                    }
162
163 1
                    $k = "$table_name:$referenced_column_name->$column_name";
164 1
                    $references[$referenced_table_name][$k] = [
165 1
                        'column' => $column_name,
166 1
                        'referencing_table' => $table_name,
167 1
                        'referencing_column' => $referenced_column_name,
168 1
                        'constraint_name' => $constraint_name
169
                    ];
170 1
                    break;
171
            }
172
        }
173
174 4
        foreach ($references as $referenced_table_name => $refs) {
175 1
            if ($tables->offsetExists($referenced_table_name)) {
176 1
                $table = $tables[$referenced_table_name];
177 1
                $table->references = $refs;
178
            }
179
        }
180
181 4
        $array = new ArrayObject($config->toArray());
182 4
        unset($config);
183
184 4
        return $array;
185
    }
186
187
    /**
188
     * Return information schema query.
189
     *
190
     * @param string|null $table
191
     *
192
     * @return string
193
     */
194 4
    protected function getQuery($table = null)
195
    {
196 4
        $qSchema = $this->adapter->quoteValue($this->schema);
197
198 4
        if ($table !== null) {
199 2
            $qTable = $this->adapter->quoteValue($table);
200 2
            $table_clause = "and (t.TABLE_NAME = $qTable or (kcu.referenced_table_name = $qTable and kcu.constraint_name = 'FOREIGN KEY'))";
201 2
            $table_join_condition = '(t.table_name = kcu.table_name or  kcu.referenced_table_name = t.table_name)';
202
        } else {
203 2
            $table_join_condition = 't.table_name = kcu.table_name';
204 2
            $table_clause = '';
205
        }
206
207
        $query = "
208
209
            SELECT
210
                    t.table_name,
211
                    c.column_name,
212
                    c.data_type,
213
                    c.column_type,
214
215
                    c.extra,
216
217
                    tc.constraint_type,
218
                    kcu.constraint_name,
219
                    kcu.referenced_table_name,
220
                    kcu.referenced_column_name,
221
222
                    c.column_default,
223
                    c.is_nullable,
224
                    c.numeric_precision,
225
                    c.numeric_scale,
226
                    c.character_octet_length,
227
                    c.character_maximum_length,
228
                    c.ordinal_position,
229
230
                    c.column_key, -- UNI/MUL/PRI
231
                    c.character_set_name,
232
233
234
                    c.collation_name,
235
236
                    c.column_comment,
237
238
                    t.table_type,
239
                    t.engine,
240
                    t.table_comment,
241
                    t.table_collation
242
243
            FROM `INFORMATION_SCHEMA`.`COLUMNS` c
244
            INNER JOIN `INFORMATION_SCHEMA`.`TABLES` t on c.TABLE_NAME = t.TABLE_NAME
245
            LEFT JOIN `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` kcu
246
               on (
247 4
                    $table_join_condition
248
                     and kcu.table_schema = t.table_schema
249
                     and kcu.column_name = c.column_name
250
                 )
251
              LEFT JOIN
252
                `INFORMATION_SCHEMA`.`TABLE_CONSTRAINTS` tc
253
               on (
254
                     t.table_name = tc.table_name
255
                      and tc.table_schema = t.table_schema
256
                      and tc.constraint_name = kcu.constraint_name
257
                  )
258
259
260 4
            where c.TABLE_SCHEMA = $qSchema
261 4
            and t.TABLE_SCHEMA = $qSchema
262 4
            $table_clause
263 4
            and (kcu.table_schema = $qSchema  or kcu.table_schema is null)
264
265
            and (kcu.column_name = c.column_name or kcu.column_name is null)
266
            order by t.table_name, c.ordinal_position
267
        ";
268
269 4
        return $query;
270
    }
271
272
    /**
273
     * Execute information schema query.
274
     *
275
     * @param string|null $table table name or null
276
     *
277
     * @return ArrayObject
278
     *
279
     * @throws Exception\ErrorException
280
     */
281 4
    protected function executeQuery($table = null)
282
    {
283 4
        $query = $this->getQuery($table);
284 4
        $this->disableInnoDbStats();
285
        try {
286 4
            $results = $this->adapter->query($query)->getArrayObject();
287
        } catch (\Exception $e) {
288
            $this->restoreInnoDbStats();
289
            throw new Exception\ErrorException(__METHOD__ . ': ' . $e->getMessage());
290
        }
291 4
        $this->restoreInnoDbStats();
292
293 4
        return $results;
294
    }
295
}
296