Completed
Branch feature/pre-split (9269d3)
by Anton
05:27
created

QueryBuilder::sqlStatement()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
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\Builders;
10
11
use Interop\Container\ContainerInterface;
12
use Spiral\Core\Component;
13
use Spiral\Database\Entities\Driver;
14
use Spiral\Database\Entities\QueryCompiler;
15
use Spiral\Database\Exceptions\BuilderException;
16
use Spiral\Database\Helpers\QueryInterpolator;
17
use Spiral\Database\Injections\ExpressionInterface;
18
use Spiral\Database\Injections\ParameterInterface;
19
20
/**
21
 * QueryBuilder classes generate set of control tokens for query compilers, this is query level
22
 * abstraction.
23
 */
24
abstract class QueryBuilder extends Component implements ExpressionInterface
25
{
26
    /**
27
     * @var Driver
28
     */
29
    protected $driver = null;
30
31
    /**
32
     * @var QueryCompiler
33
     */
34
    protected $compiler = null;
35
36
    /**
37
     * @param Driver        $driver   Associated driver.
38
     * @param QueryCompiler $compiler Driver specific QueryCompiler instance (one per builder).
39
     */
40
    public function __construct(Driver $driver, QueryCompiler $compiler)
41
    {
42
        $this->driver = $driver;
43
        $this->compiler = $compiler;
44
    }
45
46
    /**
47
     * Get associated driver instance.
48
     *
49
     * @return Driver
50
     */
51
    public function getDriver(): Driver
52
    {
53
        return $this->driver;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @param QueryCompiler $compiler Associated compiled to be used by default.
60
     */
61
    abstract public function sqlStatement(QueryCompiler $compiler = null): string;
62
63
    /**
64
     * Get ordered list of builder parameters in a form of ParameterInterface array.
65
     *
66
     * @return ParameterInterface[]
67
     *
68
     * @throws BuilderException
69
     */
70
    abstract public function getParameters(): array;
71
72
    /**
73
     * Get interpolated (populated with parameters) SQL which will be run against database, please
74
     * use this method for debugging purposes only.
75
     *
76
     * @return string
77
     */
78
    public function queryString(): string
79
    {
80
        return QueryInterpolator::interpolate($this->sqlStatement(), $this->getParameters());
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    public function __toString(): string
87
    {
88
        return $this->sqlStatement();
89
    }
90
91
    /**
92
     * @return array
93
     */
94
    public function __debugInfo()
95
    {
96
        try {
97
            $queryString = $this->queryString();
98
        } catch (\Exception $e) {
99
            $queryString = "[ERROR: {$e->getMessage()}]";
100
        }
101
102
        $debugInfo = [
103
            'statement'  => $queryString,
104
            'parameters' => $this->getParameters(),
105
            'driver'     => $this->driver
106
        ];
107
108
        return $debugInfo;
109
    }
110
111
    /**
112
     * Helper methods used to correctly fetch and split identifiers provided by function
113
     * parameters.
114
     * It support array list, string or comma separated list. Attention, this method will not work
115
     * with complex parameters (such as functions) provided as one comma separated string, please
116
     * use arrays in this case.
117
     *
118
     * @param array $identifiers
119
     *
120
     * @return array
121
     */
122
    protected function fetchIdentifiers(array $identifiers): array
123
    {
124
        if (count($identifiers) == 1 && is_string($identifiers[0])) {
125
            return array_map('trim', explode(',', $identifiers[0]));
126
        }
127
128
        if (count($identifiers) == 1 && is_array($identifiers[0])) {
129
            return $identifiers[0];
130
        }
131
132
        return $identifiers;
133
    }
134
135
    /**
136
     * Expand all QueryBuilder parameters to create flatten list.
137
     *
138
     * @param array $parameters
139
     *
140
     * @return array
141
     */
142
    protected function flattenParameters(array $parameters): array
143
    {
144
        $result = [];
145
        foreach ($parameters as $parameter) {
146
            if ($parameter instanceof self) {
147
                $result = array_merge($result, $parameter->getParameters());
148
                continue;
149
            }
150
151
            $result[] = $parameter;
152
        }
153
154
        return $result;
155
    }
156
157
    /**
158
     * Generate PDO statement based on generated sql and parameters.
159
     *
160
     * @return \PDOStatement
161
     */
162
    protected function pdoStatement(): \PDOStatement
163
    {
164
        return $this->driver->statement($this->sqlStatement(), $this->getParameters());
165
    }
166
167
    /**
168
     * @return ContainerInterface
169
     */
170
    protected function iocContainer()
171
    {
172
        //Falling back to driver specific container
173
        return $this->driver->iocContainer();
174
    }
175
}
176