Completed
Branch feature/pre-split (1fb89d)
by Anton
03:12
created

TableSchema::fetchIndexes()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 6
nop 0
dl 0
loc 22
rs 8.9197
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');
0 ignored issues
show
Unused Code introduced by
The call to SchemaException::__construct() has too many arguments starting with 'Table engine can be set... at moment of creation'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
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 View Code Duplication
    protected function fetchColumns(): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
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($this->getName(), $schema + $column);
133
        }
134
135
        return $result;
136
    }
137
138
    /**
139
     * Fetching primary keys from table.
140
     *
141
     * @return array
142
     */
143
    protected function fetchPrimaryKeys(): array
144
    {
145
        $query = "SHOW INDEXES FROM {$this->driver->identifier($this->getName())}";
146
147
        $primaryKeys = [];
148
        foreach ($this->driver->query($query) as $index) {
149
            if ($index['Key_name'] == 'PRIMARY') {
150
                $primaryKeys[] = $index['Column_name'];
151
            }
152
        }
153
154
        return $primaryKeys;
155
    }
156
}