Completed
Branch feature/pre-split (b025f2)
by Anton
03:30
created

Driver::queryCompiler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Entities;
10
11
use Spiral\Cache\StoreInterface;
12
use Spiral\Core\FactoryInterface;
13
use Spiral\Database\Builders\DeleteQuery;
14
use Spiral\Database\Builders\InsertQuery;
15
use Spiral\Database\Builders\SelectQuery;
16
use Spiral\Database\Builders\UpdateQuery;
17
use Spiral\Database\Exceptions\DriverException;
18
use Spiral\Database\Exceptions\QueryException;
19
use Spiral\Database\Entities\Query\CachedResult;
20
//use Spiral\Database\Schemas\AbstractTable;
21
22
/**
23
 * Driver abstraction is responsible for DBMS specific set of functions and used by Databases to
24
 * hide implementation specific functionality. Extends PDODriver and adds ability to create driver
25
 * specific query builders and schemas (basically operates like a factory).
26
 */
27
abstract class Driver extends PDODriver
28
{
29
    /**
30
     * Schema table class.
31
     */
32
    const SCHEMA_TABLE = '';
33
34
    /**
35
     * Commander used to execute commands. :).
36
     */
37
    const COMMANDER = '';
38
39
    /**
40
     * Query compiler class.
41
     */
42
    const QUERY_COMPILER = '';
43
44
    /**
45
     * Default datetime value.
46
     */
47
    const DEFAULT_DATETIME = '1970-01-01 00:00:00';
48
49
    /**
50
     * Default timestamp expression.
51
     */
52
    const TIMESTAMP_NOW = 'DRIVER_SPECIFIC_NOW_EXPRESSION';
53
54
    /**
55
     * Associated cache store, if any.
56
     *
57
     * @var StoreInterface
58
     */
59
    protected $cacheStore = null;
60
61
    /**
62
     * @var FactoryInterface
63
     */
64
    protected $factory = null;
65
66
    /**
67
     * @param string           $name
68
     * @param array            $connection
69
     * @param FactoryInterface $factory Required to build instances of query builders and compilers.
70
     * @param StoreInterface   $store   Cache store associated with driver (optional).
71
     */
72
    public function __construct(
73
        string $name,
74
        array $connection,
75
        FactoryInterface $factory,
76
        StoreInterface $store = null
77
    ) {
78
        parent::__construct($name, $connection);
79
80
        $this->factory = $factory;
81
        $this->cacheStore = $store;
82
    }
83
84
    /**
85
     * Set cache store to be used by driver.
86
     *
87
     * @param StoreInterface $store
88
     *
89
     * @return self|$this
90
     */
91
    public function setStore(StoreInterface $store): Driver
92
    {
93
        $this->cacheStore = $store;
94
95
        return $this;
96
    }
97
98
    /**
99
     * Execute statement or fetch result from cache and return cached query iterator.
100
     *
101
     * @param string         $query
102
     * @param array          $parameters Parameters to be binded into query.
103
     * @param int            $lifetime   Cache lifetime in seconds.
104
     * @param string         $key        Cache key to be used to store query result.
105
     * @param StoreInterface $store      Cache store to store result in, if null default store will
106
     *                                   be used.
107
     *
108
     * @return CachedResult
109
     *
110
     * @throws DriverException
111
     * @throws QueryException
112
     */
113
    public function cachedQuery(
114
        string $query,
115
        array $parameters = [],
116
        int $lifetime,
117
        string $key = '',
118
        StoreInterface $store = null
119
    ) {
120
        if (empty($store)) {
121
            if (empty($this->cacheStore)) {
122
                throw new DriverException("StoreInterface is missing");
0 ignored issues
show
Unused Code introduced by
The call to DriverException::__construct() has too many arguments starting with 'StoreInterface is missing'.

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...
123
            }
124
125
            $store = $this->cacheStore;
126
        }
127
128
        if (empty($key)) {
129
            //Trying to build unique query id based on provided options and environment.
130
            $key = md5(serialize([$query, $parameters, $this->getName()]));
131
        }
132
133
        $data = $store->remember($key, $lifetime, function () use ($query, $parameters) {
134
            return $this->query($query, $parameters)->fetchAll();
135
        });
136
137
        return new CachedResult($data, $parameters, $query, $key, $store);
138
    }
139
140
    /**
141
     * Current timestamp expression value.
142
     *
143
     * @return string
144
     */
145
    public function nowExpression(): string
146
    {
147
        return static::TIMESTAMP_NOW;
148
    }
149
150
    /**
151
     * Check if table exists.
152
     *
153
     * @param string $name
154
     *
155
     * @return bool
156
     */
157
    abstract public function hasTable(string $name): bool;
158
159
    /**
160
     * Clean (truncate) specified driver table.
161
     *
162
     * @param string $table Table name with prefix included.
163
     */
164
    abstract public function truncateData(string $table);
165
166
    /**
167
     * Get every available table name as array.
168
     *
169
     * @return array
170
     */
171
    abstract public function tableNames(): array;
172
173
//    /**
174
//     * Get Driver specific AbstractTable implementation.
175
//     *
176
//     * @param string $table  Table name without prefix included.
177
//     * @param string $prefix Database specific table prefix, this parameter is not required,
178
//     *                       but if provided all
179
//     *                       foreign keys will be created using it.
180
//     *
181
//     * @return AbstractTable
182
//     */
183
//    public function tableSchema(string $table, string $prefix = ''): AbstractTable
184
//    {
185
//        return $this->factory->make(
186
//            static::SCHEMA_TABLE,
187
//            [
188
//                'driver'    => $this,
189
//                'name'      => $table,
190
//                'prefix'    => $prefix,
191
//                'commander' => $this->factory->make(static::COMMANDER, ['driver' => $this]),
192
//            ]
193
//        );
194
//    }
195
196
    /**
197
     * Get instance of Driver specific QueryCompiler.
198
     *
199
     * @param string $prefix Database specific table prefix, used to quote table names and build
200
     *                       aliases.
201
     *
202
     * @return QueryCompiler
203
     */
204
    public function queryCompiler(string $prefix = ''): QueryCompiler
205
    {
206
        return $this->factory->make(
207
            static::QUERY_COMPILER,
208
            ['driver' => $this, 'quoter' => new Quoter($this, $prefix)]
209
        );
210
    }
211
212
    /**
213
     * Get InsertQuery builder with driver specific query compiler.
214
     *
215
     * @param string $prefix     Database specific table prefix, used to quote table names and build
216
     *                           aliases.
217
     * @param array  $parameters Initial builder parameters.
218
     *
219
     * @return InsertQuery
220
     */
221 View Code Duplication
    public function insertBuilder(string $prefix, array $parameters = []): InsertQuery
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...
222
    {
223
        return $this->factory->make(
224
            InsertQuery::class,
225
            ['driver' => $this, 'compiler' => $this->queryCompiler($prefix)] + $parameters
226
        );
227
    }
228
229
    /**
230
     * Get SelectQuery builder with driver specific query compiler.
231
     *
232
     * @param string $prefix     Database specific table prefix, used to quote table names and build
233
     *                           aliases.
234
     * @param array  $parameters Initial builder parameters.
235
     *
236
     * @return SelectQuery
237
     */
238 View Code Duplication
    public function selectBuilder(string $prefix, array $parameters = []): SelectQuery
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...
239
    {
240
        return $this->factory->make(
241
            SelectQuery::class,
242
            ['driver' => $this, 'compiler' => $this->queryCompiler($prefix)] + $parameters
243
        );
244
    }
245
246
    /**
247
     * Get DeleteQuery builder with driver specific query compiler.
248
     *
249
     * @param string $prefix     Database specific table prefix, used to quote table names and build
250
     *                           aliases.
251
     * @param array  $parameters Initial builder parameters.
252
     *
253
     * @return DeleteQuery
254
     */
255 View Code Duplication
    public function deleteBuilder(string $prefix, array $parameters = []): DeleteQuery
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...
256
    {
257
258
        return $this->factory->make(
259
            DeleteQuery::class,
260
            ['driver' => $this, 'compiler' => $this->queryCompiler($prefix)] + $parameters
261
        );
262
    }
263
264
    /**
265
     * Get UpdateQuery builder with driver specific query compiler.
266
     *
267
     * @param string $prefix     Database specific table prefix, used to quote table names and build
268
     *                           aliases.
269
     * @param array  $parameters Initial builder parameters.
270
     *
271
     * @return UpdateQuery
272
     */
273 View Code Duplication
    public function updateBuilder(string $prefix, array $parameters = []): UpdateQuery
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...
274
    {
275
        return $this->factory->make(
276
            UpdateQuery::class,
277
            ['driver' => $this, 'compiler' => $this->queryCompiler($prefix)] + $parameters
278
        );
279
    }
280
}
281