Completed
Push — master ( 7b7ebd...db1323 )
by Sébastien
02:06
created

MysqlInformationSchema::getUniqueKeys()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 9.2
cc 4
eloc 10
nc 6
nop 2
crap 4
1
<?php
2
namespace Soluble\Schema\Source;
3
4
use Soluble\Schema\Exception;
5
use Soluble\Schema\Source;
6
use Soluble\Schema\Db\Wrapper\MysqlConnectionAdapter;
7
use ArrayObject;
8
9
class MysqlInformationSchema extends Source\AbstractSchemaSource
10
{
11
    /**
12
     * Schema name
13
     *
14
     * @var string
15
     */
16
    protected $schema;
17
18
    /**
19
     * @var MysqlConnectionAdapter
20
     */
21
    protected $adapter;
22
23
24
25
    /**
26
     * Used to restore innodb stats mysql global variable
27
     * @var string
28
     */
29
    protected $mysql_innodbstats_value;
30
31
    /**
32
     * Whether to include full schema options like comment, collations...
33
     * @var boolean
34
     */
35
    protected $include_options = true;
36
37
    /**
38
     *
39
     * @var array
40
     */
41
    protected static $localCache = array();
42
43
44
    /**
45
     *
46
     * @var boolean
47
     */
48
    protected $useLocalCaching = true;
49
50
    /**
51
     *
52
     * @var array
53
     */
54
    protected static $fullyCachedSchemas = array();
55
56
57
    /**
58
     *
59
     * @var Mysql\MysqlDriverInterface
60
     */
61
    protected $driver;
62
63
    /**
64
     * Constructor
65
     *
66
     * @param \PDO|\mysqli $connection
67
     * @param string $schema default schema, taken from adapter if not given
68
     * @throws Exception\InvalidArgumentException for invalid connection
69
     * @throws Exception\InvalidUsageException thrown if no schema can be found.
70
     */
71 23
    public function __construct($connection, $schema = null)
72
    {
73
        try {
74 23
            $this->adapter = new MysqlConnectionAdapter($connection);
75 23
        } catch (Exception\InvalidArgumentException $e) {
76
            $msg = "MysqlInformationSchema requires a valid 'mysqli' or 'pdo:mysql' connection object ({$e->getMessage()}).";
77
            throw new Exception\InvalidArgumentException($msg);
78
        }
79
80 23
        if ($schema === null) {
81 23
            $schema = $this->adapter->getCurrentSchema();
82 23
            if ($schema === false || $schema == '') {
83
                $msg = "Database name (schema) parameter missing and no default schema set on connection";
84
                throw new Exception\InvalidUsageException($msg);
85
            }
86 23
        }
87
88 23
        $this->driver = new Mysql\MysqlDriver51($this->adapter, $schema);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Soluble\Schema\Sour...this->adapter, $schema) of type object<Soluble\Schema\Source\Mysql\MysqlDriver51> is incompatible with the declared type object<Soluble\Schema\So...l\MysqlDriverInterface> of property $driver.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
89
90 23
        $this->setDefaultSchema($schema);
91 23
    }
92
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 1
    public function getUniqueKeys($table, $include_primary = false)
98
    {
99 1
        $this->loadCacheInformation($table);
100 1
        $uniques = (array) self::$localCache[$this->schema]['tables'][$table]['unique_keys'];
101 1
        if ($include_primary) {
102
            try {
103 1
                $pks = $this->getPrimaryKeys($table);
104 1
                if (count($pks) > 0) {
105 1
                    $uniques = array_merge($uniques, array('PRIMARY' => $pks));
106 1
                }
107 1
            } catch (Exception\NoPrimaryKeyException $e) {
108
                // Ignore exception
109
            }
110 1
        }
111 1
        return $uniques;
112
    }
113
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function getIndexesInformation($table)
119
    {
120
        $this->loadCacheInformation($table);
121
        return self::$localCache[$this->schema]['tables'][$table]['indexes'];
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 5
    public function getPrimaryKey($table)
128
    {
129 5
        $pks = $this->getPrimaryKeys($table);
130 2
        if (count($pks) > 1) {
131 1
            $keys = join(',', $pks);
132 1
            throw new Exception\MultiplePrimaryKeyException(__METHOD__ . ". Multiple primary keys found on table '{$this->schema}'.'$table':  $keys");
133
        }
134 2
        return $pks[0];
135
    }
136
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 9
    public function getPrimaryKeys($table)
142
    {
143 9
        $this->loadCacheInformation($table);
144 6
        $pks = self::$localCache[$this->schema]['tables'][$table]['primary_keys'];
145 6
        if (count($pks) == 0) {
146 3
            throw new Exception\NoPrimaryKeyException(__METHOD__ . ". No primary keys found on table  '{$this->schema}'.'$table'.");
147
        }
148 4
        return $pks;
149
    }
150
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 2
    public function getColumnsInformation($table)
156
    {
157 2
        $this->loadCacheInformation($table);
158 2
        return self::$localCache[$this->schema]['tables'][$table]['columns'];
159
    }
160
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 1
    public function getForeignKeys($table)
166
    {
167 1
        $this->loadCacheInformation($table);
168 1
        return self::$localCache[$this->schema]['tables'][$table]['foreign_keys'];
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174 1
    public function getReferences($table)
175
    {
176 1
        $this->loadCacheInformation($table);
177 1
        return self::$localCache[$this->schema]['tables'][$table]['references'];
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183 3
    public function getTablesInformation()
184
    {
185 3
        $this->loadCacheInformation(null);
186 3
        return self::$localCache[$this->schema]['tables'];
187
    }
188
189
    /**
190
     * Get a table configuration
191
     *
192
     * @throws Exception\ErrorException
193
     * @throws Exception\TableNotFoundException
194
     *
195
     * @param string $table table name
196
     * @param boolean|null $include_options include extended information
197
     * @return array
198
     */
199 13
    protected function getTableConfig($table, $include_options = null)
200
    {
201 13
        if ($include_options === null) {
202 13
            $include_options = $this->include_options;
203 13
        }
204
205 13
        $schema = $this->schema;
206
207 13
        if ($this->useLocalCaching &&
208 13
                isset(self::$localCache[$schema]['tables'][$table])) {
209 9
            return self::$localCache[$schema]['tables'][$table];
210
        }
211
212 4
        $config = $this->driver->getSchemaConfig($table, $include_options);
0 ignored issues
show
Bug introduced by
The method getSchemaConfig() does not seem to exist on object<Soluble\Schema\So...l\MysqlDriverInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
213
214 4
        if (!array_key_exists($table, $config['tables'])) {
215 2
            throw new Exception\TableNotFoundException(__METHOD__ . ". Table '$table' in database schema '{$schema}' not found.");
216
        }
217
218 2
        if ($this->useLocalCaching) {
219 3
            if (!array_key_exists($schema, self::$localCache)) {
220 1
                self::$localCache[$schema] = array();
221 3
            }
222 3
            self::$localCache[$schema] = array_merge_recursive(self::$localCache[$schema], (array) $config);
223 2
        }
224
225 2
        return $config['tables'][$table];
226
    }
227
228
229
    /**
230
     * Get schema configuration
231
     *
232
     * @throws Exception\ErrorException
233
     * @throws Exception\SchemaNotFoundException
234
     *
235
     * @param boolean|null $include_options include extended information
236
     * @return ArrayObject
237
     */
238 2
    public function getSchemaConfig($include_options = null)
239
    {
240 2
        if ($include_options === null) {
241 2
            $include_options = $this->include_options;
242 2
        }
243 2
        $schema = $this->schema;
244 2
        if ($this->useLocalCaching && in_array($schema, self::$fullyCachedSchemas)) {
245
            return self::$localCache[$schema];
246
        }
247
248 2
        $config = $this->driver->getSchemaConfig($table = null, $include_options);
0 ignored issues
show
Bug introduced by
The method getSchemaConfig() does not seem to exist on object<Soluble\Schema\So...l\MysqlDriverInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
249 2
        if (count($config['tables']) == 0) {
250 1
            throw new Exception\SchemaNotFoundException(__METHOD__ . " Error: schema '{$schema}' not found or without any table or view");
251
        }
252 1
        if ($this->useLocalCaching) {
253 1
            self::$localCache[$schema] = $config;
254 1
            self::$fullyCachedSchemas[] = $schema;
255 1
        }
256 1
        return $config;
257
    }
258
259
260
261
262
    /**
263
     *
264
     * @param string $table
265
     * @throws Exception\InvalidArgumentException
266
     * @throws Exception\TableNotFoundException
267
     *
268
     */
269 16
    protected function loadCacheInformation($table = null)
270 1
    {
271 16
        $schema = $this->schema;
272 16
        $this->checkTableArgument($table);
273
274 14
        if (!in_array($schema, self::$fullyCachedSchemas)) {
275 3
            if ($table !== null) {
276 3
                $this->getTableConfig($table);
277 3
            } else {
278
                $this->getSchemaConfig();
279
            }
280 14
        } elseif ($table !== null) {
281
            // Just in case to check if table exists
282 8
            $this->getTableConfig($table);
283 7
        }
284 13
    }
285
286
    /**
287
     * Clear local cache information for the current schema
288
     *
289
     * @throws Exception\InvalidArgumentException
290
     */
291 1
    public function clearCacheInformation()
292
    {
293 1
        $schema = $this->schema;
294 1
        if (array_key_exists($schema, self::$localCache)) {
295 1
            unset(self::$localCache[$schema]);
296 1
            if (($key = array_search($schema, self::$fullyCachedSchemas)) !== false) {
297 1
                unset(self::$fullyCachedSchemas[$key]);
298 1
            }
299 1
        }
300 1
    }
301
}
302