Passed
Pull Request — master (#752)
by Sergei
02:29
created

AbstractSchema::createColumnSchema()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 12
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 19
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Schema;
6
7
use Psr\SimpleCache\InvalidArgumentException;
8
use Throwable;
9
use Yiisoft\Db\Cache\SchemaCache;
10
use Yiisoft\Db\Command\DataType;
11
use Yiisoft\Db\Connection\ConnectionInterface;
12
use Yiisoft\Db\Constraint\Constraint;
13
use Yiisoft\Db\Exception\NotSupportedException;
14
use Yiisoft\Db\Schema\Column\BinaryColumnSchema;
15
use Yiisoft\Db\Schema\Column\BooleanColumnSchema;
16
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Db\Schema\ColumnSchemaInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
17
use Yiisoft\Db\Schema\Column\DoubleColumnSchema;
18
use Yiisoft\Db\Schema\Column\IntegerColumnSchema;
19
use Yiisoft\Db\Schema\Column\JsonColumnSchema;
20
use Yiisoft\Db\Schema\Column\StringColumnSchema;
21
use Yiisoft\Db\Schema\Column\BigIntColumnSchema;
22
23
use function array_change_key_case;
24
use function array_map;
25
use function gettype;
26
use function is_array;
27
use function preg_match;
28
use function preg_replace;
29
use function str_contains;
30
use function str_replace;
31
32
/**
33
 * Provides a set of methods for working with database schemas such as creating, modifying, and inspecting tables,
34
 * columns, and other database objects.
35
 *
36
 * It's a powerful and flexible tool that allows you to perform a wide range of database operations in a
37
 * database-agnostic way.
38
 */
39
abstract class AbstractSchema implements SchemaInterface
40
{
41
    /**
42
     * Schema cache version, to detect incompatibilities in cached values when the data format of the cache changes.
43
     */
44
    protected const SCHEMA_CACHE_VERSION = 1;
45
    protected const CACHE_VERSION = 'cacheVersion';
46
    /**
47
     * @var string|null $defaultSchema The default schema name used for the current session.
48
     */
49
    protected string|null $defaultSchema = null;
50
    protected array $viewNames = [];
51
    private array $schemaNames = [];
52
    /** @psalm-var string[]|array */
53
    private array $tableNames = [];
54
    private array $tableMetadata = [];
55
56
    public function __construct(protected ConnectionInterface $db, private SchemaCache $schemaCache)
57
    {
58
    }
59
60
    /**
61
     * @param string $name The table name.
62
     *
63
     * @return array The cache key for the specified table name.
64
     */
65
    abstract protected function getCacheKey(string $name): array;
66
67
    /**
68
     * @return string The cache tag name.
69
     *
70
     * This allows {@see refresh()} to invalidate all cached table schemas.
71
     */
72
    abstract protected function getCacheTag(): string;
73
74
    /**
75
     * Loads all check constraints for the given table.
76
     *
77
     * @param string $tableName The table name.
78
     *
79
     * @return array The check constraints for the given table.
80
     */
81
    abstract protected function loadTableChecks(string $tableName): array;
82
83
    /**
84
     * Loads all default value constraints for the given table.
85
     *
86
     * @param string $tableName The table name.
87
     *
88
     * @return array The default value constraints for the given table.
89
     */
90
    abstract protected function loadTableDefaultValues(string $tableName): array;
91
92
    /**
93
     * Loads all foreign keys for the given table.
94
     *
95
     * @param string $tableName The table name.
96
     *
97
     * @return array The foreign keys for the given table.
98
     */
99
    abstract protected function loadTableForeignKeys(string $tableName): array;
100
101
    /**
102
     * Loads all indexes for the given table.
103
     *
104
     * @param string $tableName The table name.
105
     *
106
     * @return array The indexes for the given table.
107
     */
108
    abstract protected function loadTableIndexes(string $tableName): array;
109
110
    /**
111
     * Loads a primary key for the given table.
112
     *
113
     * @param string $tableName The table name.
114
     *
115
     * @return Constraint|null The primary key for the given table. `null` if the table has no primary key.
116
     */
117
    abstract protected function loadTablePrimaryKey(string $tableName): Constraint|null;
118
119
    /**
120
     * Loads all unique constraints for the given table.
121
     *
122
     * @param string $tableName The table name.
123
     *
124
     * @return array The unique constraints for the given table.
125
     */
126
    abstract protected function loadTableUniques(string $tableName): array;
127
128
    /**
129
     * Loads the metadata for the specified table.
130
     *
131
     * @param string $name The table name.
132
     *
133
     * @return TableSchemaInterface|null DBMS-dependent table metadata, `null` if the table doesn't exist.
134
     */
135
    abstract protected function loadTableSchema(string $name): TableSchemaInterface|null;
136
137
    public function getDefaultSchema(): string|null
138
    {
139
        return $this->defaultSchema;
140
    }
141
142
    public function getDataType(mixed $data): int
143
    {
144
        /** @psalm-var array<string, int> $typeMap */
145
        $typeMap = [
146
            // php type => SQL data type
147
            SchemaInterface::PHP_TYPE_BOOLEAN => DataType::BOOLEAN,
148
            SchemaInterface::PHP_TYPE_INTEGER => DataType::INTEGER,
149
            SchemaInterface::PHP_TYPE_STRING => DataType::STRING,
150
            SchemaInterface::PHP_TYPE_RESOURCE => DataType::LOB,
151
            SchemaInterface::PHP_TYPE_NULL => DataType::NULL,
152
        ];
153
154
        $type = gettype($data);
155
156
        return $typeMap[$type] ?? DataType::STRING;
157
    }
158
159
    public function getRawTableName(string $name): string
160
    {
161
        if (str_contains($name, '{{')) {
162
            $name = preg_replace('/{{(.*?)}}/', '\1', $name);
163
164
            return str_replace('%', $this->db->getTablePrefix(), $name);
165
        }
166
167
        return $name;
168
    }
169
170
    /**
171
     * @throws InvalidArgumentException
172
     * @throws NotSupportedException
173
     */
174
    public function getSchemaChecks(string $schema = '', bool $refresh = false): array
175
    {
176
        return $this->getSchemaMetadata($schema, SchemaInterface::CHECKS, $refresh);
177
    }
178
179
    /**
180
     * @throws InvalidArgumentException
181
     * @throws NotSupportedException
182
     */
183
    public function getSchemaDefaultValues(string $schema = '', bool $refresh = false): array
184
    {
185
        return $this->getSchemaMetadata($schema, SchemaInterface::DEFAULT_VALUES, $refresh);
186
    }
187
188
    /**
189
     * @throws InvalidArgumentException
190
     * @throws NotSupportedException
191
     */
192
    public function getSchemaForeignKeys(string $schema = '', bool $refresh = false): array
193
    {
194
        return $this->getSchemaMetadata($schema, SchemaInterface::FOREIGN_KEYS, $refresh);
195
    }
196
197
    /**
198
     * @throws InvalidArgumentException
199
     * @throws NotSupportedException
200
     */
201
    public function getSchemaIndexes(string $schema = '', bool $refresh = false): array
202
    {
203
        return $this->getSchemaMetadata($schema, SchemaInterface::INDEXES, $refresh);
204
    }
205
206
    /**
207
     * @throws NotSupportedException If this method isn't supported by the underlying DBMS.
208
     */
209
    public function getSchemaNames(bool $refresh = false): array
210
    {
211
        if (empty($this->schemaNames) || $refresh) {
212
            $this->schemaNames = $this->findSchemaNames();
213
        }
214
215
        return $this->schemaNames;
216
    }
217
218
    /**
219
     * @throws InvalidArgumentException
220
     * @throws NotSupportedException
221
     */
222
    public function getSchemaPrimaryKeys(string $schema = '', bool $refresh = false): array
223
    {
224
        /** @psalm-var list<Constraint> */
225
        return $this->getSchemaMetadata($schema, SchemaInterface::PRIMARY_KEY, $refresh);
226
    }
227
228
    /**
229
     * @throws NotSupportedException
230
     * @throws InvalidArgumentException
231
     */
232
    public function getSchemaUniques(string $schema = '', bool $refresh = false): array
233
    {
234
        return $this->getSchemaMetadata($schema, SchemaInterface::UNIQUES, $refresh);
235
    }
236
237
    /**
238
     * @throws InvalidArgumentException
239
     */
240
    public function getTableChecks(string $name, bool $refresh = false): array
241
    {
242
        /** @psalm-var mixed $tableChecks */
243
        $tableChecks = $this->getTableMetadata($name, SchemaInterface::CHECKS, $refresh);
244
        return is_array($tableChecks) ? $tableChecks : [];
245
    }
246
247
    /**
248
     * @throws InvalidArgumentException
249
     */
250
    public function getTableDefaultValues(string $name, bool $refresh = false): array
251
    {
252
        /** @psalm-var mixed $tableDefaultValues */
253
        $tableDefaultValues = $this->getTableMetadata($name, SchemaInterface::DEFAULT_VALUES, $refresh);
254
        return is_array($tableDefaultValues) ? $tableDefaultValues : [];
255
    }
256
257
    /**
258
     * @throws InvalidArgumentException
259
     */
260
    public function getTableForeignKeys(string $name, bool $refresh = false): array
261
    {
262
        /** @psalm-var mixed $tableForeignKeys */
263
        $tableForeignKeys = $this->getTableMetadata($name, SchemaInterface::FOREIGN_KEYS, $refresh);
264
        return is_array($tableForeignKeys) ? $tableForeignKeys : [];
265
    }
266
267
    /**
268
     * @throws InvalidArgumentException
269
     */
270
    public function getTableIndexes(string $name, bool $refresh = false): array
271
    {
272
        /** @psalm-var mixed $tableIndexes */
273
        $tableIndexes = $this->getTableMetadata($name, SchemaInterface::INDEXES, $refresh);
274
        return is_array($tableIndexes) ? $tableIndexes : [];
275
    }
276
277
    /**
278
     * @throws NotSupportedException If this method isn't supported by the underlying DBMS.
279
     */
280
    public function getTableNames(string $schema = '', bool $refresh = false): array
281
    {
282
        if (!isset($this->tableNames[$schema]) || $refresh) {
283
            $this->tableNames[$schema] = $this->findTableNames($schema);
284
        }
285
286
        return is_array($this->tableNames[$schema]) ? $this->tableNames[$schema] : [];
287
    }
288
289
    /**
290
     * @throws InvalidArgumentException
291
     */
292
    public function getTablePrimaryKey(string $name, bool $refresh = false): Constraint|null
293
    {
294
        /** @psalm-var mixed $tablePrimaryKey */
295
        $tablePrimaryKey = $this->getTableMetadata($name, SchemaInterface::PRIMARY_KEY, $refresh);
296
        return $tablePrimaryKey instanceof Constraint ? $tablePrimaryKey : null;
297
    }
298
299
    /**
300
     * @throws InvalidArgumentException
301
     */
302
    public function getTableSchema(string $name, bool $refresh = false): TableSchemaInterface|null
303
    {
304
        /** @psalm-var mixed $tableSchema */
305
        $tableSchema = $this->getTableMetadata($name, SchemaInterface::SCHEMA, $refresh);
306
        return $tableSchema instanceof TableSchemaInterface ? $tableSchema : null;
307
    }
308
309
    /**
310
     * @throws NotSupportedException
311
     * @throws InvalidArgumentException
312
     */
313
    public function getTableSchemas(string $schema = '', bool $refresh = false): array
314
    {
315
        /** @psalm-var list<TableSchemaInterface> */
316
        return $this->getSchemaMetadata($schema, SchemaInterface::SCHEMA, $refresh);
317
    }
318
319
    /**
320
     * @throws InvalidArgumentException
321
     *
322
     * @return array The metadata for table unique constraints.
323
     */
324
    public function getTableUniques(string $name, bool $refresh = false): array
325
    {
326
        /** @psalm-var mixed $tableUniques */
327
        $tableUniques = $this->getTableMetadata($name, SchemaInterface::UNIQUES, $refresh);
328
        return is_array($tableUniques) ? $tableUniques : [];
329
    }
330
331
    public function isReadQuery(string $sql): bool
332
    {
333
        $pattern = '/^\s*(SELECT|SHOW|DESCRIBE)\b/i';
334
335
        return preg_match($pattern, $sql) > 0;
336
    }
337
338
    /**
339
     * @throws InvalidArgumentException
340
     */
341
    public function refresh(): void
342
    {
343
        if ($this->schemaCache->isEnabled()) {
344
            $this->schemaCache->invalidate($this->getCacheTag());
345
        }
346
347
        $this->tableNames = [];
348
        $this->tableMetadata = [];
349
    }
350
351
    /**
352
     * @throws InvalidArgumentException
353
     */
354
    public function refreshTableSchema(string $name): void
355
    {
356
        $rawName = $this->getRawTableName($name);
357
358
        unset($this->tableMetadata[$rawName]);
359
360
        $this->tableNames = [];
361
362
        if ($this->schemaCache->isEnabled()) {
363
            $this->schemaCache->remove($this->getCacheKey($rawName));
364
        }
365
    }
366
367
    public function enableCache(bool $value): void
368
    {
369
        $this->schemaCache->setEnabled($value);
370
    }
371
372
    /**
373
     * Returns all schema names in the database, including the default one but not system schemas.
374
     *
375
     * This method should be overridden by child classes to support this feature because the default
376
     * implementation simply throws an exception.
377
     *
378
     * @throws NotSupportedException If the DBMS doesn't support this method.
379
     *
380
     * @return array All schemas name in the database, except system schemas.
381
     */
382
    protected function findSchemaNames(): array
383
    {
384
        throw new NotSupportedException(static::class . ' does not support fetching all schema names.');
385
    }
386
387
    /**
388
     * Returns all table names in the database.
389
     *
390
     * This method should be overridden by child classes to support this feature because the default
391
     * implementation simply throws an exception.
392
     *
393
     * @param string $schema The schema of the tables. Defaults to empty string, meaning the current or default schema.
394
     *
395
     * @throws NotSupportedException If the DBMS doesn't support this method.
396
     *
397
     * @return array All tables name in the database. The names have NO schema name prefix.
398
     */
399
    protected function findTableNames(string $schema): array
0 ignored issues
show
Unused Code introduced by
The parameter $schema is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

399
    protected function findTableNames(/** @scrutinizer ignore-unused */ string $schema): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
400
    {
401
        throw new NotSupportedException(static::class . ' does not support fetching all table names.');
402
    }
403
404
    /**
405
     * Creates a column schema for the database.
406
     *
407
     * This method may be overridden by child classes to create a DBMS-specific column schema.
408
     *
409
     * @param string $type The abstract data type.
410
     * @param string $name The column name.
411
     * @param mixed ...$info The column information.
412
     * @psalm-param array{unsigned?: bool} $info The set of parameters may be different for a specific DBMS.
413
     *
414
     * @return ColumnSchemaInterface
415
     */
416
    protected function createColumnSchema(string $type, string $name, mixed ...$info): ColumnSchemaInterface
417
    {
418
        $phpType = $this->getColumnPhpType($type);
419
        $isUnsigned = !empty($info['unsigned']);
420
421
        if (
422
            $isUnsigned && PHP_INT_SIZE === 4 && $type === SchemaInterface::TYPE_INTEGER
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($isUnsigned && Yiisoft\...aInterface::TYPE_BIGINT, Probably Intended Meaning: $isUnsigned && Yiisoft\D...Interface::TYPE_BIGINT)
Loading history...
423
            || ($isUnsigned || PHP_INT_SIZE !== 8) && $type === SchemaInterface::TYPE_BIGINT
424
        ) {
425
            $column = new BigIntColumnSchema($name);
426
        } else {
427
            $column = $this->createPhpTypeColumnSchema($phpType, $name);
428
        }
429
430
        $column->type($type);
431
        $column->phpType($phpType);
432
        $column->unsigned($isUnsigned);
433
434
        return $column;
435
    }
436
437
    /**
438
     * Get the PHP type from an abstract database type.
439
     *
440
     * @param string $type The abstract database type.
441
     *
442
     * @return string The PHP type name.
443
     */
444
    protected function getColumnPhpType(string $type): string
445
    {
446
        return match ($type) {
447
            // abstract type => php type
448
            SchemaInterface::TYPE_TINYINT => SchemaInterface::PHP_TYPE_INTEGER,
449
            SchemaInterface::TYPE_SMALLINT => SchemaInterface::PHP_TYPE_INTEGER,
450
            SchemaInterface::TYPE_INTEGER => SchemaInterface::PHP_TYPE_INTEGER,
451
            SchemaInterface::TYPE_BIGINT => SchemaInterface::PHP_TYPE_INTEGER,
452
            SchemaInterface::TYPE_BOOLEAN => SchemaInterface::PHP_TYPE_BOOLEAN,
453
            SchemaInterface::TYPE_DECIMAL => SchemaInterface::PHP_TYPE_DOUBLE,
454
            SchemaInterface::TYPE_FLOAT => SchemaInterface::PHP_TYPE_DOUBLE,
455
            SchemaInterface::TYPE_DOUBLE => SchemaInterface::PHP_TYPE_DOUBLE,
456
            SchemaInterface::TYPE_BINARY => SchemaInterface::PHP_TYPE_RESOURCE,
457
            SchemaInterface::TYPE_JSON => SchemaInterface::PHP_TYPE_ARRAY,
458
            default => SchemaInterface::PHP_TYPE_STRING,
459
        };
460
    }
461
462
    protected function createPhpTypeColumnSchema(string $phpType, string $name): ColumnSchemaInterface
463
    {
464
        return match ($phpType) {
465
            SchemaInterface::PHP_TYPE_INTEGER => new IntegerColumnSchema($name),
466
            SchemaInterface::PHP_TYPE_DOUBLE => new DoubleColumnSchema($name),
467
            SchemaInterface::PHP_TYPE_BOOLEAN => new BooleanColumnSchema($name),
468
            SchemaInterface::PHP_TYPE_RESOURCE => new BinaryColumnSchema($name),
469
            SchemaInterface::PHP_TYPE_ARRAY => new JsonColumnSchema($name),
470
            default => new StringColumnSchema($name),
471
        };
472
    }
473
474
    /**
475
     * Returns the metadata of the given type for all tables in the given schema.
476
     *
477
     * @param string $schema The schema of the metadata. Defaults to empty string, meaning the current or default schema
478
     * name.
479
     * @param string $type The metadata type.
480
     * @param bool $refresh Whether to fetch the latest available table metadata. If this is `false`, cached data may be
481
     * returned if available.
482
     *
483
     * @throws InvalidArgumentException
484
     * @throws NotSupportedException
485
     *
486
     * @return array The metadata of the given type for all tables in the given schema.
487
     *
488
     * @psalm-return list<Constraint|TableSchemaInterface|array>
489
     */
490
    protected function getSchemaMetadata(string $schema, string $type, bool $refresh): array
491
    {
492
        $metadata = [];
493
        /** @psalm-var string[] $tableNames */
494
        $tableNames = $this->getTableNames($schema, $refresh);
495
496
        foreach ($tableNames as $name) {
497
            $name = $this->db->getQuoter()->quoteSimpleTableName($name);
498
499
            if ($schema !== '') {
500
                $name = $schema . '.' . $name;
501
            }
502
503
            $tableMetadata = $this->getTableTypeMetadata($type, $name, $refresh);
504
505
            if ($tableMetadata !== null) {
506
                $metadata[] = $tableMetadata;
507
            }
508
        }
509
510
        return $metadata;
511
    }
512
513
    /**
514
     * Returns the metadata of the given type for the given table.
515
     *
516
     * @param string $name The table name. The table name may contain a schema name if any.
517
     * Don't quote the table name.
518
     * @param string $type The metadata type.
519
     * @param bool $refresh whether to reload the table metadata even if it's found in the cache.
520
     *
521
     * @throws InvalidArgumentException
522
     *
523
     * @return mixed The metadata of the given type for the given table.
524
     */
525
    protected function getTableMetadata(string $name, string $type, bool $refresh = false): mixed
526
    {
527
        $rawName = $this->getRawTableName($name);
528
529
        if (!isset($this->tableMetadata[$rawName])) {
530
            $this->loadTableMetadataFromCache($rawName);
531
        }
532
533
        if ($refresh || !isset($this->tableMetadata[$rawName][$type])) {
534
            /** @psalm-suppress MixedArrayAssignment */
535
            $this->tableMetadata[$rawName][$type] = $this->loadTableTypeMetadata($type, $rawName);
536
            $this->saveTableMetadataToCache($rawName);
537
        }
538
539
        /** @psalm-suppress MixedArrayAccess */
540
        return $this->tableMetadata[$rawName][$type];
541
    }
542
543
    /**
544
     * This method returns the desired metadata type for the table name.
545
     */
546
    protected function loadTableTypeMetadata(string $type, string $name): Constraint|array|TableSchemaInterface|null
547
    {
548
        return match ($type) {
549
            SchemaInterface::SCHEMA => $this->loadTableSchema($name),
550
            SchemaInterface::PRIMARY_KEY => $this->loadTablePrimaryKey($name),
551
            SchemaInterface::UNIQUES => $this->loadTableUniques($name),
552
            SchemaInterface::FOREIGN_KEYS => $this->loadTableForeignKeys($name),
553
            SchemaInterface::INDEXES => $this->loadTableIndexes($name),
554
            SchemaInterface::DEFAULT_VALUES => $this->loadTableDefaultValues($name),
555
            SchemaInterface::CHECKS => $this->loadTableChecks($name),
556
            default => null,
557
        };
558
    }
559
560
    /**
561
     * This method returns the desired metadata type for table name (with refresh if needed).
562
     *
563
     * @throws InvalidArgumentException
564
     */
565
    protected function getTableTypeMetadata(
566
        string $type,
567
        string $name,
568
        bool $refresh = false
569
    ): Constraint|array|null|TableSchemaInterface {
570
        return match ($type) {
571
            SchemaInterface::SCHEMA => $this->getTableSchema($name, $refresh),
572
            SchemaInterface::PRIMARY_KEY => $this->getTablePrimaryKey($name, $refresh),
573
            SchemaInterface::UNIQUES => $this->getTableUniques($name, $refresh),
574
            SchemaInterface::FOREIGN_KEYS => $this->getTableForeignKeys($name, $refresh),
575
            SchemaInterface::INDEXES => $this->getTableIndexes($name, $refresh),
576
            SchemaInterface::DEFAULT_VALUES => $this->getTableDefaultValues($name, $refresh),
577
            SchemaInterface::CHECKS => $this->getTableChecks($name, $refresh),
578
            default => null,
579
        };
580
    }
581
582
    /**
583
     * Change row's array key case to lower.
584
     *
585
     * @param array $row Thew row's array or an array of row arrays.
586
     * @param bool $multiple Whether many rows or a single row passed.
587
     *
588
     * @return array The normalized row or rows.
589
     */
590
    protected function normalizeRowKeyCase(array $row, bool $multiple): array
591
    {
592
        if ($multiple) {
593
            return array_map(static fn (array $row) => array_change_key_case($row), $row);
594
        }
595
596
        return array_change_key_case($row);
597
    }
598
599
    /**
600
     * Resolves the table name and schema name (if any).
601
     *
602
     * @param string $name The table name.
603
     *
604
     * @throws NotSupportedException If the DBMS doesn't support this method.
605
     *
606
     * @return TableSchemaInterface The with resolved table, schema, etc. names.
607
     *
608
     * @see TableSchemaInterface
609
     */
610
    protected function resolveTableName(string $name): TableSchemaInterface
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

610
    protected function resolveTableName(/** @scrutinizer ignore-unused */ string $name): TableSchemaInterface

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
611
    {
612
        throw new NotSupportedException(static::class . ' does not support resolving table names.');
613
    }
614
615
    /**
616
     * Sets the metadata of the given type for the given table.
617
     *
618
     * @param string $name The table name.
619
     * @param string $type The metadata type.
620
     * @param mixed $data The metadata to set.
621
     */
622
    protected function setTableMetadata(string $name, string $type, mixed $data): void
623
    {
624
        /** @psalm-suppress MixedArrayAssignment  */
625
        $this->tableMetadata[$this->getRawTableName($name)][$type] = $data;
626
    }
627
628
    /**
629
     * Tries to load and populate table metadata from cache.
630
     *
631
     * @throws InvalidArgumentException
632
     */
633
    private function loadTableMetadataFromCache(string $rawName): void
634
    {
635
        if (!$this->schemaCache->isEnabled() || $this->schemaCache->isExcluded($rawName)) {
636
            $this->tableMetadata[$rawName] = [];
637
            return;
638
        }
639
640
        $metadata = $this->schemaCache->get($this->getCacheKey($rawName));
641
642
        if (
643
            !is_array($metadata) ||
644
            !isset($metadata[self::CACHE_VERSION]) ||
645
            $metadata[self::CACHE_VERSION] !== static::SCHEMA_CACHE_VERSION
646
        ) {
647
            $this->tableMetadata[$rawName] = [];
648
            return;
649
        }
650
651
        unset($metadata[self::CACHE_VERSION]);
652
        $this->tableMetadata[$rawName] = $metadata;
653
    }
654
655
    /**
656
     * Saves table metadata to cache.
657
     *
658
     * @throws InvalidArgumentException
659
     */
660
    private function saveTableMetadataToCache(string $rawName): void
661
    {
662
        if ($this->schemaCache->isEnabled() === false || $this->schemaCache->isExcluded($rawName) === true) {
663
            return;
664
        }
665
666
        /** @psalm-var array<string, array<TableSchemaInterface|int>> $metadata */
667
        $metadata = $this->tableMetadata[$rawName];
668
        /** @psalm-var int */
669
        $metadata[self::CACHE_VERSION] = static::SCHEMA_CACHE_VERSION;
670
671
        $this->schemaCache->set($this->getCacheKey($rawName), $metadata, $this->getCacheTag());
672
    }
673
674
    /**
675
     * Find the view names for the database.
676
     *
677
     * @param string $schema The schema of the views.
678
     * Defaults to empty string, meaning the current or default schema.
679
     *
680
     * @return array The names of all views in the database.
681
     */
682
    protected function findViewNames(string $schema = ''): array
0 ignored issues
show
Unused Code introduced by
The parameter $schema is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

682
    protected function findViewNames(/** @scrutinizer ignore-unused */ string $schema = ''): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
683
    {
684
        return [];
685
    }
686
687
    /**
688
     * @throws Throwable
689
     *
690
     * @return array The view names for the database.
691
     */
692
    public function getViewNames(string $schema = '', bool $refresh = false): array
693
    {
694
        if (!isset($this->viewNames[$schema]) || $refresh) {
695
            $this->viewNames[$schema] = $this->findViewNames($schema);
696
        }
697
698
        return (array) $this->viewNames[$schema];
699
    }
700
}
701