|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace BfwSql; |
|
4
|
|
|
|
|
5
|
|
|
use \Exception; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* Class to access to query writer |
|
9
|
|
|
* |
|
10
|
|
|
* @package bfw-sql |
|
11
|
|
|
* @author Vermeulen Maxime <[email protected]> |
|
12
|
|
|
* @version 2.0 |
|
13
|
|
|
*/ |
|
14
|
|
|
class Sql |
|
15
|
|
|
{ |
|
16
|
|
|
/** |
|
17
|
|
|
* @const ERR_QUERY_BAD_REQUEST Exception code if the request executed |
|
18
|
|
|
* on query method have an error. |
|
19
|
|
|
*/ |
|
20
|
|
|
const ERR_QUERY_BAD_REQUEST = 2103001; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* @var \BfwSql\SqlConnect $sqlConnect SqlConnect object |
|
24
|
|
|
*/ |
|
25
|
|
|
protected $sqlConnect; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @var string $prefix Tables prefix |
|
29
|
|
|
*/ |
|
30
|
|
|
protected $prefix = ''; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* Constructor |
|
34
|
|
|
* |
|
35
|
|
|
* @param \BfwSql\SqlConnect $sqlConnect SqlConnect instance |
|
36
|
|
|
* |
|
37
|
|
|
* @throws \Exception |
|
38
|
|
|
*/ |
|
39
|
|
|
public function __construct(\BfwSql\SqlConnect $sqlConnect) |
|
40
|
|
|
{ |
|
41
|
|
|
$this->sqlConnect = $sqlConnect; |
|
42
|
|
|
$this->prefix = $sqlConnect->getConnectionInfos()->tablePrefix; |
|
43
|
|
|
} |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* Getter to the property sqlConnect |
|
47
|
|
|
* |
|
48
|
|
|
* @return \BfwSql\SqlConnect |
|
49
|
|
|
*/ |
|
50
|
|
|
public function getSqlConnect() |
|
51
|
|
|
{ |
|
52
|
|
|
return $this->sqlConnect; |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* Getter to the property prefix |
|
57
|
|
|
* |
|
58
|
|
|
* @return string |
|
59
|
|
|
*/ |
|
60
|
|
|
public function getPrefix() |
|
61
|
|
|
{ |
|
62
|
|
|
return $this->prefix; |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Get the id for the last item has been insert in database |
|
67
|
|
|
* |
|
68
|
|
|
* @param string|null $name (default: null) Name of the sequence for the id |
|
69
|
|
|
* Used for SGDB like PostgreSQL. Not use it for mysql. |
|
70
|
|
|
* |
|
71
|
|
|
* @return integer |
|
72
|
|
|
*/ |
|
73
|
|
|
public function obtainLastInsertedId($name = null) |
|
74
|
|
|
{ |
|
75
|
|
|
return (int) $this->sqlConnect->getPDO()->lastInsertId($name); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Get the id for the last item has been insert in database for a table |
|
80
|
|
|
* without auto-increment |
|
81
|
|
|
* |
|
82
|
|
|
* @param string $table The table name |
|
83
|
|
|
* @param string $colId The column name for the ID |
|
84
|
|
|
* @param string|array $order Columns to sort table content |
|
85
|
|
|
* @param string|array $where All where instruction used for filter content |
|
86
|
|
|
* |
|
87
|
|
|
* @return integer |
|
88
|
|
|
*/ |
|
89
|
|
|
public function obtainLastInsertedIdWithoutAI( |
|
90
|
|
|
$table, |
|
91
|
|
|
$colId, |
|
92
|
|
|
$order, |
|
93
|
|
|
$where = '' |
|
94
|
|
|
) { |
|
95
|
|
|
$req = $this->select() |
|
96
|
|
|
->from($table, $colId) |
|
97
|
|
|
->limit(1); |
|
98
|
|
|
|
|
99
|
|
|
if (is_array($where)) { |
|
100
|
|
|
foreach ($where as $val) { |
|
101
|
|
|
$req->where($val); |
|
102
|
|
|
} |
|
103
|
|
|
} elseif ($where != '') { |
|
104
|
|
|
$req->where($where); |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
if (is_array($order)) { |
|
108
|
|
|
foreach ($order as $val) { |
|
109
|
|
|
$req->order($val); |
|
110
|
|
|
} |
|
111
|
|
|
} else { |
|
112
|
|
|
$req->order($order); |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
$res = $req->fetchRow(); |
|
116
|
|
|
$req->closeCursor(); |
|
117
|
|
|
|
|
118
|
|
|
if ($res) { |
|
119
|
|
|
return (int) $res[$colId]; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
return 0; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Return a new instance of SqlSelect |
|
127
|
|
|
* |
|
128
|
|
|
* @param string $type (default: "array") Return PHP type |
|
129
|
|
|
* Possible value : "array" or "object" |
|
130
|
|
|
* |
|
131
|
|
|
* @return \BfwSql\SqlSelect |
|
132
|
|
|
*/ |
|
133
|
|
|
public function select($type = 'array') |
|
134
|
|
|
{ |
|
135
|
|
|
$usedClass = \BfwSql\UsedClass::getInstance(); |
|
136
|
|
|
$selectClassName = $usedClass->obtainClassNameToUse('ActionsSelect'); |
|
137
|
|
|
|
|
138
|
|
|
return new $selectClassName($this->sqlConnect, $type); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
/** |
|
142
|
|
|
* Return a new instance of SqlInsert |
|
143
|
|
|
* |
|
144
|
|
|
* @param string $table The table concerned by the request |
|
145
|
|
|
* @param array $columns (default: null) All datas to add |
|
146
|
|
|
* Format is array('columnName' => 'value', ...); |
|
147
|
|
|
* @param string $quoteStatus (default: QUOTE_ALL) Status to automatic |
|
148
|
|
|
* quoted string value system. |
|
149
|
|
|
* |
|
150
|
|
|
* @return \BfwSql\SqlInsert |
|
151
|
|
|
*/ |
|
152
|
|
View Code Duplication |
public function insert( |
|
|
|
|
|
|
153
|
|
|
$table, |
|
154
|
|
|
$columns = null, |
|
155
|
|
|
$quoteStatus = \BfwSql\Actions\AbstractActions::QUOTE_ALL |
|
156
|
|
|
) { |
|
157
|
|
|
$usedClass = \BfwSql\UsedClass::getInstance(); |
|
158
|
|
|
$insertClassName = $usedClass->obtainClassNameToUse('ActionsInsert'); |
|
159
|
|
|
|
|
160
|
|
|
return new $insertClassName( |
|
161
|
|
|
$this->sqlConnect, |
|
162
|
|
|
$table, |
|
163
|
|
|
$columns, |
|
164
|
|
|
$quoteStatus |
|
165
|
|
|
); |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
/** |
|
169
|
|
|
* Return a new instance of SqlUpdate |
|
170
|
|
|
* |
|
171
|
|
|
* @param string $table The table concerned by the request |
|
172
|
|
|
* @param array $columns (default: null) All datas to update |
|
173
|
|
|
* Format is array('columnName' => 'newValue', ...); |
|
174
|
|
|
* @param string $quoteStatus (default: QUOTE_ALL) Status to automatic |
|
175
|
|
|
* quoted string value system. |
|
176
|
|
|
* |
|
177
|
|
|
* @return \BfwSql\SqlUpdate |
|
178
|
|
|
*/ |
|
179
|
|
View Code Duplication |
public function update( |
|
|
|
|
|
|
180
|
|
|
$table, |
|
181
|
|
|
$columns = null, |
|
182
|
|
|
$quoteStatus = \BfwSql\Actions\AbstractActions::QUOTE_ALL |
|
183
|
|
|
) { |
|
184
|
|
|
$usedClass = \BfwSql\UsedClass::getInstance(); |
|
185
|
|
|
$updateClassName = $usedClass->obtainClassNameToUse('ActionsUpdate'); |
|
186
|
|
|
|
|
187
|
|
|
return new $updateClassName( |
|
188
|
|
|
$this->sqlConnect, |
|
189
|
|
|
$table, |
|
190
|
|
|
$columns, |
|
191
|
|
|
$quoteStatus |
|
192
|
|
|
); |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
/** |
|
196
|
|
|
* Return a new instance of SqlDelete |
|
197
|
|
|
* |
|
198
|
|
|
* @param string $table The table concerned by the request |
|
199
|
|
|
* |
|
200
|
|
|
* @return \BfwSql\SqlDelete |
|
201
|
|
|
*/ |
|
202
|
|
|
public function delete($table) |
|
203
|
|
|
{ |
|
204
|
|
|
$usedClass = \BfwSql\UsedClass::getInstance(); |
|
205
|
|
|
$deleteClassName = $usedClass->obtainClassNameToUse('ActionsDelete'); |
|
206
|
|
|
|
|
207
|
|
|
return new $deleteClassName($this->sqlConnect, $table); |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
/** |
|
211
|
|
|
* Find the first vacant id on a table and for a column |
|
212
|
|
|
* |
|
213
|
|
|
* @param string $table The table concerned by the request |
|
214
|
|
|
* @param string $column The id column. Must be an integer.. |
|
215
|
|
|
* |
|
216
|
|
|
* @throws \Exception If a error has been throw during the search |
|
217
|
|
|
* |
|
218
|
|
|
* @return integer |
|
219
|
|
|
*/ |
|
220
|
|
|
public function createId($table, $column) |
|
221
|
|
|
{ |
|
222
|
|
|
//Search the first line in the table |
|
223
|
|
|
$reqFirstLine = $this->select() |
|
224
|
|
|
->from($table, $column) |
|
225
|
|
|
->order($column.' ASC') |
|
226
|
|
|
->limit(1); |
|
227
|
|
|
|
|
228
|
|
|
$resFirstLine = $reqFirstLine->fetchRow(); |
|
229
|
|
|
$reqFirstLine->closeCursor(); |
|
230
|
|
|
|
|
231
|
|
|
// If nothing in the table. First AI is 1 |
|
232
|
|
|
if (!$resFirstLine) { |
|
233
|
|
|
return 1; |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
// If the id for the first line is > 1 |
|
237
|
|
|
if ($resFirstLine[$column] > 1) { |
|
238
|
|
|
return $resFirstLine[$column] - 1; |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
//First line have ID=1, we search from the end |
|
242
|
|
|
$reqLastLine = $this->select() |
|
243
|
|
|
->from($table, $column) |
|
244
|
|
|
->order($column.' DESC') |
|
245
|
|
|
->limit(1); |
|
246
|
|
|
|
|
247
|
|
|
$resLastLine = $reqLastLine->fetchRow(); |
|
248
|
|
|
$reqLastLine->closeCursor(); |
|
249
|
|
|
|
|
250
|
|
|
//Get the last ID and add 1 |
|
251
|
|
|
return $resLastLine[$column] + 1; |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* Run the query in parameter |
|
256
|
|
|
* |
|
257
|
|
|
* @param string $request The request to run |
|
258
|
|
|
* |
|
259
|
|
|
* @throws \Exception If the request has failed |
|
260
|
|
|
* |
|
261
|
|
|
* @return \PDOStatement |
|
262
|
|
|
*/ |
|
263
|
|
|
public function query($request) |
|
264
|
|
|
{ |
|
265
|
|
|
$this->sqlConnect->upNbQuery(); |
|
266
|
|
|
|
|
267
|
|
|
$req = $this->sqlConnect->getPDO()->query($request); |
|
268
|
|
|
$error = $this->sqlConnect->getPDO()->errorInfo(); |
|
269
|
|
|
|
|
270
|
|
|
$app = \BFW\Application::getInstance(); |
|
271
|
|
|
$subject = $app->getSubjectList()->getSubjectForName('bfw-sql'); |
|
272
|
|
|
$subject->addNotification( |
|
273
|
|
|
'user query', |
|
274
|
|
|
(object) [ |
|
275
|
|
|
'request' => $request, |
|
276
|
|
|
'error' => $error |
|
277
|
|
|
] |
|
278
|
|
|
); |
|
279
|
|
|
|
|
280
|
|
|
if ( |
|
281
|
|
|
!$req |
|
282
|
|
|
&& $error[0] !== null |
|
283
|
|
|
&& $error[0] !== '00000' |
|
284
|
|
|
&& isset($error[2]) |
|
285
|
|
|
) { |
|
286
|
|
|
throw new Exception( |
|
287
|
|
|
$error[2], |
|
288
|
|
|
self::ERR_QUERY_BAD_REQUEST |
|
289
|
|
|
); |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
|
|
return $req; |
|
293
|
|
|
} |
|
294
|
|
|
} |
|
295
|
|
|
|
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.