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