Passed
Push — master ( 566a3a...fbef46 )
by 世昌
02:19
created

QueryAccess::createResult()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace suda\database\statement;
3
4
use PDO;
5
use PDOStatement;
6
use suda\database\Binder;
7
use ReflectionException;
8
use suda\database\DataSource;
9
use suda\database\connection\Connection;
10
use suda\database\middleware\Middleware;
11
use suda\database\exception\SQLException;
12
use suda\database\middleware\NullMiddleware;
13
14
class QueryAccess
15
{
16
    /**
17
     * 数据源
18
     *
19
     * @var DataSource
20
     */
21
    protected $source;
22
23
    /**
24
     * 中间件
25
     *
26
     * @var Middleware
27
     */
28
    protected $middleware;
29
30
    /**
31
     * 创建运行器
32
     *
33
     * @param DataSource $source
34
     * @param Middleware $middleware
35
     */
36
    public function __construct(DataSource $source, Middleware $middleware = null)
37
    {
38
        $this->source = $source;
39
        $this->middleware = $middleware ?: new NullMiddleware;
40
    }
41
42
43
    /**
44
     * 获取最后一次插入的主键ID(用于自增值
45
     *
46
     * @param string $name
47
     * @return string 则获取失败,整数则获取成功
48
     */
49
    public function lastInsertId(string $name = null):string
50
    {
51
        return $this->source->write()->lastInsertId($name);
52
    }
53
54
    /**
55
     * 事务系列,开启事务
56
     *
57
     * @return void
58
     */
59
    public function beginTransaction()
60
    {
61
        $this->source->write()->beginTransaction();
62
    }
63
64
    /**
65
     * 事务系列,提交事务
66
     *
67
     * @return void
68
     */
69
    public function commit()
70
    {
71
        $this->source->write()->commit();
72
    }
73
74
    /**
75
     * 事务系列,撤销事务
76
     *
77
     * @return void
78
     */
79
    public function rollBack()
80
    {
81
        $this->source->write()->rollBack();
82
    }
83
84
    /**
85
     * 运行SQL语句
86
     *
87
     * @param Statement $statement
88
     * @return mixed
89
     * @throws ReflectionException
90
     * @throws SQLException
91
     */
92
    public function run(Statement $statement)
93
    {
94
        $connection = $statement->isRead() ? $this->source->read() : $this->source->write();
95
        $this->runStatement($connection, $statement);
96
        return $this->createResult($connection, $statement);
97
    }
98
99
100
    /**
101
     * 获取运行结果
102
     *
103
     * @param $connection
104
     * @param Statement $statement
105
     * @return mixed
106
     * @throws ReflectionException
107
     * @throws SQLException
108
     */
109
    protected function createResult(Connection $connection, Statement $statement)
110
    {
111
        return (new QueryResult($connection, $this->middleware))->createResult($statement);
112
    }
113
114
    /**
115
     * 设置中间件
116
     *
117
     * @param Middleware $middleware
118
     * @return $this
119
     */
120
    public function setMiddleware(Middleware $middleware)
121
    {
122
        $this->middleware = $middleware;
123
        return $this;
124
    }
125
126
    /**
127
     * 创建SQL语句
128
     *
129
     * @param Connection $connection
130
     * @param Statement $statement
131
     * @return PDOStatement
132
     * @throws SQLException
133
     */
134
    protected function createPDOStatement(Connection $connection, Statement $statement): PDOStatement
135
    {
136
        $statement->prepare();
137
        $queryObj = $statement->getQuery();
138
        $query = $connection->prefix($queryObj->getQuery());
139
        if ($statement->isScroll()) {
140
            $stmt = $connection->getPdo()->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
141
        } else {
142
            $stmt = $connection->getPdo()->prepare($query);
143
        }
144
        if ($stmt instanceof PDOStatement) {
145
            return $stmt;
146
        }
147
        throw new SQLException(sprintf('error prepare %s', $statement->getString()), SQLException::ERR_PREPARE);
148
    }
149
150
    /**
151
     * 绑定值
152
     *
153
     * @param PDOStatement $stmt
154
     * @param Statement $statement
155
     * @return void
156
     */
157
    protected function bindPDOStatementValues(PDOStatement $stmt, Statement $statement)
158
    {
159
        foreach ($statement->getQuery()->getBinder() as $binder) {
160
            if ($binder->getKey() !== null) {
161
                $value = $this->middleware->input($binder->getKey(), $binder->getValue());
162
                $stmt->bindValue($binder->getName(), $value, Binder::typeOf($value));
163
            } else {
164
                $stmt->bindValue($binder->getName(), $binder->getValue(), Binder::typeOf($binder->getValue()));
165
            }
166
        }
167
    }
168
169
    /**
170
     * 运行语句
171
     *
172
     * @param Connection $connection
173
     * @param Statement $statement
174
     * @return void
175
     * @throws SQLException
176
     */
177
    protected function runStatement(Connection $connection, Statement $statement)
178
    {
179
        if ($statement->isScroll() && $statement->getStatement() !== null) {
180
            // noop
181
        } else {
182
            $stmt = $this->createPDOStatement($connection, $statement);
183
            $this->bindPDOStatementValues($stmt, $statement);
184
            $statement->setStatement($stmt);
185
            $start = microtime(true);
186
            $status = $stmt->execute();
187
            $statement->setSuccess($status);
188
            $connection->getObserver()->observe($this, $connection, $statement, microtime(true) - $start, $status);
189
            if ($status === false) {
190
                throw new SQLException(implode(':', $stmt->errorInfo()), intval($stmt->errorCode()));
191
            }
192
        }
193
    }
194
195
    /**
196
     * Get 中间件
197
     *
198
     * @return  Middleware
199
     */
200
    public function getMiddleware():Middleware
201
    {
202
        return $this->middleware;
203
    }
204
}
205