Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Doctrine\DBAL\Schema;
4
 
5
use Doctrine\DBAL\Exception;
6
use Doctrine\DBAL\Platforms\DB2Platform;
7
use Doctrine\DBAL\Result;
8
use Doctrine\DBAL\Types\Type;
9
use Doctrine\DBAL\Types\Types;
10
use Doctrine\Deprecations\Deprecation;
11
 
12
use function array_change_key_case;
13
use function implode;
14
use function preg_match;
15
use function str_replace;
16
use function strpos;
17
use function strtolower;
18
use function strtoupper;
19
use function substr;
20
 
21
use const CASE_LOWER;
22
 
23
/**
24
 * IBM Db2 Schema Manager.
25
 *
26
 * @extends AbstractSchemaManager<DB2Platform>
27
 */
28
class DB2SchemaManager extends AbstractSchemaManager
29
{
30
    /**
31
     * {@inheritDoc}
32
     */
33
    public function listTableNames()
34
    {
35
        return $this->doListTableNames();
36
    }
37
 
38
    /**
39
     * {@inheritDoc}
40
     */
41
    public function listTables()
42
    {
43
        return $this->doListTables();
44
    }
45
 
46
    /**
47
     * {@inheritDoc}
48
     *
49
     * @deprecated Use {@see introspectTable()} instead.
50
     */
51
    public function listTableDetails($name)
52
    {
53
        Deprecation::trigger(
54
            'doctrine/dbal',
55
            'https://github.com/doctrine/dbal/pull/5595',
56
            '%s is deprecated. Use introspectTable() instead.',
57
            __METHOD__,
58
        );
59
 
60
        return $this->doListTableDetails($name);
61
    }
62
 
63
    /**
64
     * {@inheritDoc}
65
     */
66
    public function listTableColumns($table, $database = null)
67
    {
68
        return $this->doListTableColumns($table, $database);
69
    }
70
 
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function listTableIndexes($table)
75
    {
76
        return $this->doListTableIndexes($table);
77
    }
78
 
79
    /**
80
     * {@inheritDoc}
81
     */
82
    public function listTableForeignKeys($table, $database = null)
83
    {
84
        return $this->doListTableForeignKeys($table, $database);
85
    }
86
 
87
    /**
88
     * {@inheritdoc}
89
     *
90
     * @throws Exception
91
     */
92
    protected function _getPortableTableColumnDefinition($tableColumn)
93
    {
94
        $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
95
 
96
        $length    = null;
97
        $fixed     = null;
98
        $scale     = false;
99
        $precision = false;
100
 
101
        $default = null;
102
 
103
        if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') {
104
            $default = $tableColumn['default'];
105
 
106
            if (preg_match('/^\'(.*)\'$/s', $default, $matches) === 1) {
107
                $default = str_replace("''", "'", $matches[1]);
108
            }
109
        }
110
 
111
        $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);
112
 
113
        if (isset($tableColumn['comment'])) {
114
            $type                   = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
115
            $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
116
        }
117
 
118
        switch (strtolower($tableColumn['typename'])) {
119
            case 'varchar':
120
                if ($tableColumn['codepage'] === 0) {
121
                    $type = Types::BINARY;
122
                }
123
 
124
                $length = $tableColumn['length'];
125
                $fixed  = false;
126
                break;
127
 
128
            case 'character':
129
                if ($tableColumn['codepage'] === 0) {
130
                    $type = Types::BINARY;
131
                }
132
 
133
                $length = $tableColumn['length'];
134
                $fixed  = true;
135
                break;
136
 
137
            case 'clob':
138
                $length = $tableColumn['length'];
139
                break;
140
 
141
            case 'decimal':
142
            case 'double':
143
            case 'real':
144
                $scale     = $tableColumn['scale'];
145
                $precision = $tableColumn['length'];
146
                break;
147
        }
148
 
149
        $options = [
150
            'length'        => $length,
151
            'unsigned'      => false,
152
            'fixed'         => (bool) $fixed,
153
            'default'       => $default,
154
            'autoincrement' => (bool) $tableColumn['autoincrement'],
155
            'notnull'       => $tableColumn['nulls'] === 'N',
156
            'scale'         => null,
157
            'precision'     => null,
158
            'comment'       => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
159
                ? $tableColumn['comment']
160
                : null,
161
            'platformOptions' => [],
162
        ];
163
 
164
        if ($scale !== null && $precision !== null) {
165
            $options['scale']     = $scale;
166
            $options['precision'] = $precision;
167
        }
168
 
169
        return new Column($tableColumn['colname'], Type::getType($type), $options);
170
    }
171
 
172
    /**
173
     * {@inheritdoc}
174
     */
175
    protected function _getPortableTableDefinition($table)
176
    {
177
        $table = array_change_key_case($table, CASE_LOWER);
178
 
179
        return $table['name'];
180
    }
181
 
182
    /**
183
     * {@inheritdoc}
184
     */
185
    protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
186
    {
187
        foreach ($tableIndexes as &$tableIndexRow) {
188
            $tableIndexRow            = array_change_key_case($tableIndexRow, CASE_LOWER);
189
            $tableIndexRow['primary'] = (bool) $tableIndexRow['primary'];
190
        }
191
 
192
        return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
193
    }
194
 
195
    /**
196
     * {@inheritdoc}
197
     */
198
    protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
199
    {
200
        return new ForeignKeyConstraint(
201
            $tableForeignKey['local_columns'],
202
            $tableForeignKey['foreign_table'],
203
            $tableForeignKey['foreign_columns'],
204
            $tableForeignKey['name'],
205
            $tableForeignKey['options'],
206
        );
207
    }
208
 
209
    /**
210
     * {@inheritdoc}
211
     */
212
    protected function _getPortableTableForeignKeysList($tableForeignKeys)
213
    {
214
        $foreignKeys = [];
215
 
216
        foreach ($tableForeignKeys as $tableForeignKey) {
217
            $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
218
 
219
            if (! isset($foreignKeys[$tableForeignKey['index_name']])) {
220
                $foreignKeys[$tableForeignKey['index_name']] = [
221
                    'local_columns'   => [$tableForeignKey['local_column']],
222
                    'foreign_table'   => $tableForeignKey['foreign_table'],
223
                    'foreign_columns' => [$tableForeignKey['foreign_column']],
224
                    'name'            => $tableForeignKey['index_name'],
225
                    'options'         => [
226
                        'onUpdate' => $tableForeignKey['on_update'],
227
                        'onDelete' => $tableForeignKey['on_delete'],
228
                    ],
229
                ];
230
            } else {
231
                $foreignKeys[$tableForeignKey['index_name']]['local_columns'][]   = $tableForeignKey['local_column'];
232
                $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column'];
233
            }
234
        }
235
 
236
        return parent::_getPortableTableForeignKeysList($foreignKeys);
237
    }
238
 
239
    /**
240
     * @param string $def
241
     *
242
     * @return string|null
243
     */
244
    protected function _getPortableForeignKeyRuleDef($def)
245
    {
246
        if ($def === 'C') {
247
            return 'CASCADE';
248
        }
249
 
250
        if ($def === 'N') {
251
            return 'SET NULL';
252
        }
253
 
254
        return null;
255
    }
256
 
257
    /**
258
     * {@inheritdoc}
259
     */
260
    protected function _getPortableViewDefinition($view)
261
    {
262
        $view = array_change_key_case($view, CASE_LOWER);
263
 
264
        $sql = '';
265
        $pos = strpos($view['text'], ' AS ');
266
 
267
        if ($pos !== false) {
268
            $sql = substr($view['text'], $pos + 4);
269
        }
270
 
271
        return new View($view['name'], $sql);
272
    }
273
 
274
    protected function normalizeName(string $name): string
275
    {
276
        $identifier = new Identifier($name);
277
 
278
        return $identifier->isQuoted() ? $identifier->getName() : strtoupper($name);
279
    }
280
 
281
    protected function selectTableNames(string $databaseName): Result
282
    {
283
        $sql = <<<'SQL'
284
SELECT NAME
285
FROM SYSIBM.SYSTABLES
286
WHERE TYPE = 'T'
287
  AND CREATOR = ?
288
SQL;
289
 
290
        return $this->_conn->executeQuery($sql, [$databaseName]);
291
    }
292
 
293
    protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result
294
    {
295
        $sql = 'SELECT';
296
 
297
        if ($tableName === null) {
298
            $sql .= ' C.TABNAME AS NAME,';
299
        }
300
 
301
        $sql .= <<<'SQL'
302
       C.COLNAME,
303
       C.TYPENAME,
304
       C.CODEPAGE,
305
       C.NULLS,
306
       C.LENGTH,
307
       C.SCALE,
308
       C.REMARKS AS COMMENT,
309
       CASE
310
           WHEN C.GENERATED = 'D' THEN 1
311
           ELSE 0
312
           END   AS AUTOINCREMENT,
313
       C.DEFAULT
314
FROM SYSCAT.COLUMNS C
315
         JOIN SYSCAT.TABLES AS T
316
              ON T.TABSCHEMA = C.TABSCHEMA
317
                  AND T.TABNAME = C.TABNAME
318
SQL;
319
 
320
        $conditions = ['C.TABSCHEMA = ?', "T.TYPE = 'T'"];
321
        $params     = [$databaseName];
322
 
323
        if ($tableName !== null) {
324
            $conditions[] = 'C.TABNAME = ?';
325
            $params[]     = $tableName;
326
        }
327
 
328
        $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY C.TABNAME, C.COLNO';
329
 
330
        return $this->_conn->executeQuery($sql, $params);
331
    }
332
 
333
    protected function selectIndexColumns(string $databaseName, ?string $tableName = null): Result
334
    {
335
        $sql = 'SELECT';
336
 
337
        if ($tableName === null) {
338
            $sql .= ' IDX.TABNAME AS NAME,';
339
        }
340
 
341
        $sql .= <<<'SQL'
342
             IDX.INDNAME AS KEY_NAME,
343
             IDXCOL.COLNAME AS COLUMN_NAME,
344
             CASE
345
                 WHEN IDX.UNIQUERULE = 'P' THEN 1
346
                 ELSE 0
347
             END AS PRIMARY,
348
             CASE
349
                 WHEN IDX.UNIQUERULE = 'D' THEN 1
350
                 ELSE 0
351
             END AS NON_UNIQUE
352
        FROM SYSCAT.INDEXES AS IDX
353
        JOIN SYSCAT.TABLES AS T
354
          ON IDX.TABSCHEMA = T.TABSCHEMA AND IDX.TABNAME = T.TABNAME
355
        JOIN SYSCAT.INDEXCOLUSE AS IDXCOL
356
          ON IDX.INDSCHEMA = IDXCOL.INDSCHEMA AND IDX.INDNAME = IDXCOL.INDNAME
357
SQL;
358
 
359
        $conditions = ['IDX.TABSCHEMA = ?', "T.TYPE = 'T'"];
360
        $params     = [$databaseName];
361
 
362
        if ($tableName !== null) {
363
            $conditions[] = 'IDX.TABNAME = ?';
364
            $params[]     = $tableName;
365
        }
366
 
367
        $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY IDX.INDNAME, IDXCOL.COLSEQ';
368
 
369
        return $this->_conn->executeQuery($sql, $params);
370
    }
371
 
372
    protected function selectForeignKeyColumns(string $databaseName, ?string $tableName = null): Result
373
    {
374
        $sql = 'SELECT';
375
 
376
        if ($tableName === null) {
377
            $sql .= ' R.TABNAME AS NAME,';
378
        }
379
 
380
        $sql .= <<<'SQL'
381
             FKCOL.COLNAME AS LOCAL_COLUMN,
382
             R.REFTABNAME AS FOREIGN_TABLE,
383
             PKCOL.COLNAME AS FOREIGN_COLUMN,
384
             R.CONSTNAME AS INDEX_NAME,
385
             CASE
386
                 WHEN R.UPDATERULE = 'R' THEN 'RESTRICT'
387
             END AS ON_UPDATE,
388
             CASE
389
                 WHEN R.DELETERULE = 'C' THEN 'CASCADE'
390
                 WHEN R.DELETERULE = 'N' THEN 'SET NULL'
391
                 WHEN R.DELETERULE = 'R' THEN 'RESTRICT'
392
             END AS ON_DELETE
393
        FROM SYSCAT.REFERENCES AS R
394
         JOIN SYSCAT.TABLES AS T
395
              ON T.TABSCHEMA = R.TABSCHEMA
396
                  AND T.TABNAME = R.TABNAME
397
         JOIN SYSCAT.KEYCOLUSE AS FKCOL
398
              ON FKCOL.CONSTNAME = R.CONSTNAME
399
                  AND FKCOL.TABSCHEMA = R.TABSCHEMA
400
                  AND FKCOL.TABNAME = R.TABNAME
401
         JOIN SYSCAT.KEYCOLUSE AS PKCOL
402
              ON PKCOL.CONSTNAME = R.REFKEYNAME
403
                  AND PKCOL.TABSCHEMA = R.REFTABSCHEMA
404
                  AND PKCOL.TABNAME = R.REFTABNAME
405
                  AND PKCOL.COLSEQ = FKCOL.COLSEQ
406
SQL;
407
 
408
        $conditions = ['R.TABSCHEMA = ?', "T.TYPE = 'T'"];
409
        $params     = [$databaseName];
410
 
411
        if ($tableName !== null) {
412
            $conditions[] = 'R.TABNAME = ?';
413
            $params[]     = $tableName;
414
        }
415
 
416
        $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY R.CONSTNAME, FKCOL.COLSEQ';
417
 
418
        return $this->_conn->executeQuery($sql, $params);
419
    }
420
 
421
    /**
422
     * {@inheritDoc}
423
     */
424
    protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array
425
    {
426
        $sql = 'SELECT NAME, REMARKS';
427
 
428
        $conditions = [];
429
        $params     = [];
430
 
431
        if ($tableName !== null) {
432
            $conditions[] = 'NAME = ?';
433
            $params[]     = $tableName;
434
        }
435
 
436
        $sql .= ' FROM SYSIBM.SYSTABLES';
437
 
438
        if ($conditions !== []) {
439
            $sql .= ' WHERE ' . implode(' AND ', $conditions);
440
        }
441
 
442
        /** @var array<string,array<string,mixed>> $metadata */
443
        $metadata = $this->_conn->executeQuery($sql, $params)
444
            ->fetchAllAssociativeIndexed();
445
 
446
        $tableOptions = [];
447
        foreach ($metadata as $table => $data) {
448
            $data = array_change_key_case($data, CASE_LOWER);
449
 
450
            $tableOptions[$table] = ['comment' => $data['remarks']];
451
        }
452
 
453
        return $tableOptions;
454
    }
455
}