Completed
Branch feature/pre-split (57df1d)
by Anton
10:42
created

TableSchema::fetchReferences()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 16
nc 2
nop 0
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Drivers\MySQL\Schemas;
8
9
use Spiral\Database\Exceptions\SchemaException;
10
use Spiral\Database\Schemas\Prototypes\AbstractTable;
11
use Spiral\Database\Schemas\TableState;
12
13
class TableSchema extends AbstractTable
14
{
15
    /**
16
     * List of most common MySQL table engines.
17
     */
18
    const ENGINE_INNODB = 'InnoDB';
19
    const ENGINE_MYISAM = 'MyISAM';
20
    const ENGINE_MEMORY = 'Memory';
21
22
    /**
23
     * MySQL table engine.
24
     *
25
     * @var string
26
     */
27
    private $engine = self::ENGINE_INNODB;
28
29
    /**
30
     * Populate table schema with values from database.
31
     *
32
     * @param TableState $state
33
     */
34
    protected function initSchema(TableState $state)
35
    {
36
        parent::initSchema($state);
37
38
        //Reading table schema
39
        $this->engine = $this->driver->query('SHOW TABLE STATUS WHERE `Name` = ?', [
40
            $state->getName()
41
        ])->fetch()['Engine'];
42
    }
43
44
    /**
45
     * Change table engine. Such operation will be applied only at moment of table creation.
46
     *
47
     * @param string $engine
48
     *
49
     * @return $this
50
     *
51
     * @throws SchemaException
52
     */
53
    public function setEngine($engine)
54
    {
55
        if ($this->exists()) {
56
            throw new SchemaException('Table engine can be set only at moment of creation');
57
        }
58
59
        $this->engine = $engine;
60
61
        return $this;
62
    }
63
64
    /**
65
     * @return string
66
     */
67
    public function getEngine()
68
    {
69
        return $this->engine;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    protected function fetchColumns(): array
76
    {
77
        $query = "SHOW FULL COLUMNS FROM {$this->driver->identifier($this->getName())}";
78
79
        $result = [];
80
        foreach ($this->driver->query($query) as $schema) {
81
            $result[] = ColumnSchema::createInstance($this->getName(), $schema);
82
        }
83
84
        return $result;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    protected function fetchIndexes(): array
91
    {
92
        $query = "SHOW INDEXES FROM {$this->driver->identifier($this->getName())}";
93
94
        //Gluing all index definitions together
95
        $schemas = [];
96
        foreach ($this->driver->query($query) as $index) {
97
            if ($index['Key_name'] == 'PRIMARY') {
98
                //Skipping PRIMARY index
99
                continue;
100
            }
101
102
            $schemas[$index['Key_name']][] = $index;
103
        }
104
105
        $result = [];
106
        foreach ($schemas as $name => $index) {
107
            $result[] = IndexSchema::createInstance($this->getName(), $name, $index);
108
        }
109
110
        return $result;
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    protected function fetchReferences(): array
117
    {
118
        $references = $this->driver->query(
119
            'SELECT * FROM `information_schema`.`referential_constraints` WHERE `constraint_schema` = ? AND `table_name` = ?',
120
            [$this->driver->getSource(), $this->getName()]
121
        );
122
123
        $result = [];
124
        foreach ($references as $schema) {
0 ignored issues
show
Bug introduced by
The expression $references of type object<Spiral\Database\E...Query\PDOResult>|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
125
            $references = 'SELECT * FROM `information_schema`.`key_column_usage` WHERE `constraint_name` = ? AND `table_schema` = ? AND `table_name` = ?';
126
127
            $column = $this->driver->query(
128
                $references,
129
                [$schema['CONSTRAINT_NAME'], $this->driver->getSource(), $this->getName()]
130
            )->fetch();
131
132
            $result[] = ReferenceSchema::createInstance(
133
                $this->getName(),
134
                $this->getPrefix(),
135
                $schema + $column
136
            );
137
        }
138
139
        return $result;
140
    }
141
142
    /**
143
     * Fetching primary keys from table.
144
     *
145
     * @return array
146
     */
147
    protected function fetchPrimaryKeys(): array
148
    {
149
        $query = "SHOW INDEXES FROM {$this->driver->identifier($this->getName())}";
150
151
        $primaryKeys = [];
152
        foreach ($this->driver->query($query) as $index) {
153
            if ($index['Key_name'] == 'PRIMARY') {
154
                $primaryKeys[] = $index['Column_name'];
155
            }
156
        }
157
158
        return $primaryKeys;
159
    }
160
}