1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package fwolflib |
4
|
|
|
* @subpackage class |
5
|
|
|
* @copyright Copyright 2003-2008, Fwolf |
6
|
|
|
* @author Fwolf <[email protected]> |
7
|
|
|
* @since 2003-08-25 |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
|
11
|
|
|
require_once(dirname(__FILE__) . '/fwolflib.php'); |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* SQL语句生成类 |
16
|
|
|
* 虽然用ADOdb能够完成大部分工作,但这个类是作为生成SQL的辅助工具用的 |
17
|
|
|
* |
18
|
|
|
* Test and demo code: |
19
|
|
|
* <code> |
20
|
|
|
* <?php |
21
|
|
|
* require_once('fwolflib/func/ecl.php'); |
22
|
|
|
* require_once('fwolflib/class/adodb.php'); |
23
|
|
|
* require_once('adodb/tohtml.inc.php'); |
24
|
|
|
* header('Content-Type: text/html; charset=utf-8'); |
25
|
|
|
* |
26
|
|
|
* $db = new Adodb(array( |
27
|
|
|
* 'type' => 'mysqli', |
28
|
|
|
* 'host' => '192.168.0.5', |
29
|
|
|
* 'name' => '2008-zbb', |
30
|
|
|
* 'user' => '2008-zbb', |
31
|
|
|
* 'pass' => '2008-moo', |
32
|
|
|
* 'lang' => 'utf8', |
33
|
|
|
* )); |
34
|
|
|
* |
35
|
|
|
* $db->Connect(); |
36
|
|
|
* |
37
|
|
|
* |
38
|
|
|
* // Test INSERT, normal mode |
39
|
|
|
* $ar = array( |
40
|
|
|
* 'INSERT' => 'bagy_cc_anc', |
41
|
|
|
* 'VALUES' => ' (authcode, region) VALUES ("a\"t\a\'c", "130100")' |
42
|
|
|
* ); |
43
|
|
|
* $sql = $db->GenSql($ar); |
44
|
|
|
* TestSql($sql); |
45
|
|
|
* |
46
|
|
|
* |
47
|
|
|
* // Test INSERT, special mode |
48
|
|
|
* $ar['VALUES'] = array( |
49
|
|
|
* 'authcode' => 'v_authcode', |
50
|
|
|
* 'region' => '130100', |
51
|
|
|
* 'proj_title' => '项目名称', |
52
|
|
|
* 'anc_st' => date('Y-m-d H:i:s'), |
53
|
|
|
* 'aprv_by' => 10, |
54
|
|
|
* 'flag' => 2 |
55
|
|
|
* ); |
56
|
|
|
* $sql = $db->GenSql($ar); |
57
|
|
|
* TestSql($sql); |
58
|
|
|
* |
59
|
|
|
* |
60
|
|
|
* // Test Update, normal mode |
61
|
|
|
* $ar = array('UPDATE', 'SET', 'WHERE', 'ORDERBY', 'LIMIT'); |
62
|
|
|
* $ar = array( |
63
|
|
|
* 'UPDATE' => 'bagy_cc_anc', |
64
|
|
|
* 'SET' => 'email = "[email protected]"', |
65
|
|
|
* 'WHERE' => 'id > 70', |
66
|
|
|
* 'ORDERBY' => 'id desc', |
67
|
|
|
* 'LIMIT' => 1, |
68
|
|
|
* ); |
69
|
|
|
* $sql = $db->GenSql($ar); |
70
|
|
|
* TestSql($sql); |
71
|
|
|
* |
72
|
|
|
* |
73
|
|
|
* // Test Update, special mode |
74
|
|
|
* $ar['SET'] = array( |
75
|
|
|
* 'email' => '[email protected]', |
76
|
|
|
* 'authcode' => '12345678', |
77
|
|
|
* ); |
78
|
|
|
* $ar['WHERE'] = array( |
79
|
|
|
* 'id > 70', |
80
|
|
|
* '1 = (id % 2)', // 单数 |
81
|
|
|
* ); |
82
|
|
|
* $ar['ORDERBY'] = array( |
83
|
|
|
* 'id desc', 'aprv_by asc' |
84
|
|
|
* ); |
85
|
|
|
* //$ar['LIMIT'] = array(2, 1); // Update can only limit [roucount] |
86
|
|
|
* $sql = $db->GenSql($ar); |
87
|
|
|
* TestSql($sql); |
88
|
|
|
* |
89
|
|
|
* |
90
|
|
|
* // Test DELETE, normal mode |
91
|
|
|
* $ar = array('DELETE', 'WHERE', 'ORDERBY', 'LIMIT'); |
92
|
|
|
* $ar = array( |
93
|
|
|
* 'DELETE' => 'bagy_cc_anc', |
94
|
|
|
* 'WHERE' => 'flag = 0', |
95
|
|
|
* 'ORDERBY' => 'id desc', |
96
|
|
|
* 'LIMIT' => 1 // Delete can only limit [roucount] |
97
|
|
|
* ); |
98
|
|
|
* $sql = $db->GenSql($ar); |
99
|
|
|
* TestSql($sql); |
100
|
|
|
* |
101
|
|
|
* |
102
|
|
|
* // Delete special mode is obmitted |
103
|
|
|
* |
104
|
|
|
* |
105
|
|
|
* // Test SELECT, normal mode |
106
|
|
|
* $ar = array('SELECT', 'FROM', 'WHERE', 'GROUPBY', 'HAVING', |
107
|
|
|
* 'ORDERBY', 'LIMIT'); |
108
|
|
|
* $ar = array( |
109
|
|
|
* 'SELECT' => 'id, email, a.authcode, proj_title, anc_st, aprv_by, a.flag, b.title', |
110
|
|
|
* 'FROM' => 'bagy_cc_anc a, region b', |
111
|
|
|
* 'WHERE' => 'a.region = b.code', |
112
|
|
|
* //'GROUPBY' => 'b.code', // Tested ok |
113
|
|
|
* 'HAVING' => 'a.id > 1', |
114
|
|
|
* 'ORDERBY' => 'a.id desc', |
115
|
|
|
* 'LIMIT' => 3, |
116
|
|
|
* ); |
117
|
|
|
* $sql = $db->GenSql($ar); |
118
|
|
|
* TestSql($sql); |
119
|
|
|
* |
120
|
|
|
* |
121
|
|
|
* // Test SELECT, special mode |
122
|
|
|
* $ar['SELECT'] = array( |
123
|
|
|
* 'a.id', 'c.email', 'a.authcode', 'bagy_cc_anc.proj_title', 'b.title' |
124
|
|
|
* ); |
125
|
|
|
* $ar['FROM'] = array( |
126
|
|
|
* 'a' => 'bagy_cc_anc', |
127
|
|
|
* 'b' => 'region', |
128
|
|
|
* 'bagy_cc_anc', // :NOTICE: mixed with-alias and without-alias |
129
|
|
|
* 'c' => 'bagy_cc_anc', |
130
|
|
|
* ); |
131
|
|
|
* $ar['WHERE'] = array( |
132
|
|
|
* 'a.region = b.code', |
133
|
|
|
* 'a.id = bagy_cc_anc.id', |
134
|
|
|
* 'a.id = c.id', |
135
|
|
|
* ); |
136
|
|
|
* $ar['LIMIT'] = array(1, 3); |
137
|
|
|
* $sql = $db->GenSql($ar); |
138
|
|
|
* TestSql($sql); |
139
|
|
|
* |
140
|
|
|
* |
141
|
|
|
* function TestSql($sql) |
142
|
|
|
* { |
143
|
|
|
* global $db; |
144
|
|
|
* ecl($sql); |
145
|
|
|
* $rs = $db->Execute($sql); |
146
|
|
|
* if (!empty($rs)) |
147
|
|
|
* ecl(rs2html($rs)); |
148
|
|
|
* else |
149
|
|
|
* ecl($db->ErrorNo() . ' : ' . $db->ErrorMsg()); |
150
|
|
|
* ecl('<hr />'); |
151
|
|
|
* } // end of func TestSql |
152
|
|
|
* ?> |
153
|
|
|
* </code> |
154
|
|
|
* |
155
|
|
|
* @deprecated Use Fwlib\Db\SqlGenerator |
156
|
|
|
* @package fwolflib |
157
|
|
|
* @subpackage class |
158
|
|
|
* @copyright Copyright 2003-2008, Fwolf |
159
|
|
|
* @author Fwolf <[email protected]> |
160
|
|
|
* @since 2003-08-25 09:48:31 |
161
|
|
|
* @version $Id$ |
162
|
|
|
*/ |
163
|
|
|
class SqlGenerator extends Fwolflib { |
|
|
|
|
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* From part user set, used in SELECT only |
167
|
|
|
* @var mixed |
168
|
|
|
*/ |
169
|
|
|
protected $mFrom = ''; |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Group by part user set. |
173
|
|
|
* @var mixed |
174
|
|
|
*/ |
175
|
|
|
protected $mGroupby = ''; |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Having part user set. |
179
|
|
|
* @var mixed |
180
|
|
|
*/ |
181
|
|
|
protected $mHaving = ''; |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Limit part user set. |
185
|
|
|
* @var mixed |
186
|
|
|
*/ |
187
|
|
|
protected $mLimit = ''; |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Order by part user set. |
191
|
|
|
* @var mixed |
192
|
|
|
*/ |
193
|
|
|
protected $mOrderby = ''; |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Select (column list) part user set. |
197
|
|
|
* @var mixed |
198
|
|
|
*/ |
199
|
|
|
protected $mSelect = ''; |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Set part user set, in UPDATE only. |
203
|
|
|
* @var mixed |
204
|
|
|
*/ |
205
|
|
|
protected $mSet = ''; |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Values part user set. |
209
|
|
|
* @var mixed |
210
|
|
|
*/ |
211
|
|
|
protected $mValues = ''; |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Where part user set. |
215
|
|
|
* @var mixed |
216
|
|
|
*/ |
217
|
|
|
protected $mWhere = ''; |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Db object who call $this |
221
|
|
|
* @var object |
222
|
|
|
*/ |
223
|
|
|
protected $oDb; |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Delete part(table name, 1 table only) user set. |
227
|
|
|
* @var string |
228
|
|
|
*/ |
229
|
|
|
protected $sDelete = ''; |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Insert part(table name, 1 table only) user set. |
233
|
|
|
* @var string |
234
|
|
|
*/ |
235
|
|
|
protected $sInsert = ''; |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Delete sql part generated |
239
|
|
|
* @var string |
240
|
|
|
*/ |
241
|
|
|
protected $sSqlDelect = ''; |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* From sql part generated |
245
|
|
|
* @var string |
246
|
|
|
*/ |
247
|
|
|
protected $sSqlFrom = ''; |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Group by sql part generated |
251
|
|
|
* @var string |
252
|
|
|
*/ |
253
|
|
|
protected $sSqlGroupby = ''; |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Having sql part generated |
257
|
|
|
* @var string |
258
|
|
|
*/ |
259
|
|
|
protected $sSqlHaving = ''; |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Insert sql part generated |
263
|
|
|
* @var string |
264
|
|
|
*/ |
265
|
|
|
protected $sSqlInsert = ''; |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Limit sql part generated |
269
|
|
|
* @var string |
270
|
|
|
*/ |
271
|
|
|
protected $sSqlLimit = ''; |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Order by sql part generated |
275
|
|
|
* @var string |
276
|
|
|
*/ |
277
|
|
|
protected $sSqlOrderby = ''; |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* Select sql part generated |
281
|
|
|
* @var string |
282
|
|
|
*/ |
283
|
|
|
protected $sSqlSelect = ''; |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Set sql part generated, for UPDATE only. |
287
|
|
|
* @var string |
288
|
|
|
*/ |
289
|
|
|
protected $sSqlSet = ''; |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Update sql part generated |
293
|
|
|
* @var string |
294
|
|
|
*/ |
295
|
|
|
protected $sSqlUpdate = ''; |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Values sql part generated, for INSERT only. |
299
|
|
|
* @var string |
300
|
|
|
*/ |
301
|
|
|
protected $sSqlValues = ''; |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Where sql part generated |
305
|
|
|
* @var string |
306
|
|
|
*/ |
307
|
|
|
protected $sSqlWhere = ''; |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Update part(table name, 1 table only) user set. |
311
|
|
|
* @var string |
312
|
|
|
*/ |
313
|
|
|
protected $sUpdate = ''; |
314
|
|
|
|
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* Construct |
318
|
|
|
* @param object &$db Db object |
319
|
|
|
*/ |
320
|
|
|
public function __construct(&$db) |
321
|
|
|
{ |
322
|
|
|
if (!empty($db)) |
323
|
|
|
$this->oDb = $db; |
324
|
|
|
} // end of func __construct |
325
|
|
|
|
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* 重置已经设定的参数, or part of them |
329
|
|
|
* |
330
|
|
|
* @param string $part 重设哪一部分 |
331
|
|
|
* @see gsql() |
332
|
|
|
*/ |
333
|
|
|
public function Clear($part = '') |
334
|
|
|
{ |
335
|
|
|
// order by => ORDERBY |
336
|
|
|
$part = str_replace(' ', '', (strtolower($part))); |
337
|
|
|
|
338
|
|
|
// Reset-able part |
339
|
|
|
$ar_part = array( |
340
|
|
|
'SELECT', |
341
|
|
|
'UPDATE', |
342
|
|
|
'INSERT', |
343
|
|
|
'DELETE', |
344
|
|
|
'VALUES', |
345
|
|
|
'SET', |
346
|
|
|
'FROM', |
347
|
|
|
'WHERE', |
348
|
|
|
'GROUPBY', |
349
|
|
|
'HAVING', |
350
|
|
|
'ORDERBY', |
351
|
|
|
'LIMIT', |
352
|
|
|
); |
353
|
|
|
|
354
|
|
|
if (empty($part) || 'all' == $part) |
355
|
|
|
{ |
356
|
|
|
// Reset all |
357
|
|
|
foreach ($ar_part as $s) |
358
|
|
|
{ |
359
|
|
|
$s = ucfirst(strtolower($s)); |
360
|
|
|
$this->${"m$s"} = ''; |
361
|
|
|
$this->${"sSql$s"} = ''; |
362
|
|
|
} |
363
|
|
|
} |
364
|
|
|
else |
365
|
|
|
{ |
366
|
|
|
// Reset 1 part |
367
|
|
|
$s = ucfirst($part); |
368
|
|
|
$this->${"m$s"} = ''; |
369
|
|
|
$this->${"sSql$s"} = ''; |
370
|
|
|
} |
371
|
|
|
} // end of function Clear |
372
|
|
|
|
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Generate an DELETE sql |
376
|
|
|
* @param array $ar_config |
377
|
|
|
* @return string |
378
|
|
|
*/ |
379
|
|
|
protected function GenDelete($ar_config = array()) |
380
|
|
|
{ |
381
|
|
|
if (is_array($ar_config) && !empty($ar_config)) |
382
|
|
|
{ |
383
|
|
|
// Using parts in $ar_config, not all parts |
384
|
|
|
// config value has been set already, here only use it's 'name' |
385
|
|
|
$ar = &$ar_config; |
386
|
|
|
} |
387
|
|
|
else |
388
|
|
|
{ |
389
|
|
|
// Using all parts, by this sequence |
390
|
|
|
// http://dev.mysql.com/doc/refman/5.0/en/delete.html |
391
|
|
|
$ar = array('DELETE', 'WHERE', 'ORDERBY', 'LIMIT'); |
392
|
|
|
} |
393
|
|
|
$sql = ''; |
394
|
|
|
foreach ($ar as $part => $param) |
395
|
|
|
{ |
396
|
|
|
$part = ucfirst(strtolower($part)); |
397
|
|
|
$sql .= $this->{"sSql$part"}; |
398
|
|
|
} |
399
|
|
|
return $sql; |
400
|
|
|
} // end of func GenDelete |
401
|
|
|
|
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* Generate an INSERT sql |
405
|
|
|
* @param array $ar_config |
406
|
|
|
* @return string |
407
|
|
|
*/ |
408
|
|
|
protected function GenInsert($ar_config = array()) |
409
|
|
|
{ |
410
|
|
|
if (is_array($ar_config) && !empty($ar_config)) |
411
|
|
|
{ |
412
|
|
|
// Using parts in $ar_config, not all parts |
413
|
|
|
// config value has been set already, here only use it's 'name' |
414
|
|
|
$ar = &$ar_config; |
415
|
|
|
} |
416
|
|
|
else |
417
|
|
|
{ |
418
|
|
|
// Using all parts, by this sequence |
419
|
|
|
// http://dev.mysql.com/doc/refman/5.0/en/insert.html |
420
|
|
|
$ar = array('INSERT', 'VALUES'); |
421
|
|
|
} |
422
|
|
|
$sql = ''; |
423
|
|
|
foreach ($ar as $part => $param) |
424
|
|
|
{ |
425
|
|
|
$part = ucfirst(strtolower($part)); |
426
|
|
|
$sql .= $this->{"sSql$part"}; |
427
|
|
|
} |
428
|
|
|
return $sql; |
429
|
|
|
} // end of func GenInsert |
430
|
|
|
|
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Generate an SELECT sql |
434
|
|
|
* @param array $ar_config |
435
|
|
|
* @return string |
436
|
|
|
*/ |
437
|
|
View Code Duplication |
protected function GenSelect($ar_config = array()) |
|
|
|
|
438
|
|
|
{ |
439
|
|
|
if (is_array($ar_config) && !empty($ar_config)) |
440
|
|
|
{ |
441
|
|
|
// Using parts in $ar_config, not all parts |
442
|
|
|
// config value has been set already, here only use it's 'name' |
443
|
|
|
$ar = &$ar_config; |
444
|
|
|
} |
445
|
|
|
else |
446
|
|
|
{ |
447
|
|
|
// Using all parts, by this sequence |
448
|
|
|
// http://dev.mysql.com/doc/refman/5.0/en/select.html |
449
|
|
|
$ar = array('SELECT', 'FROM', 'WHERE', 'GROUPBY', 'HAVING', |
450
|
|
|
'ORDERBY', 'LIMIT'); |
451
|
|
|
} |
452
|
|
|
$sql = ''; |
453
|
|
|
foreach ($ar as $part => $param) |
454
|
|
|
{ |
455
|
|
|
$part = ucfirst(strtolower($part)); |
456
|
|
|
$sql .= $this->{"sSql$part"}; |
457
|
|
|
} |
458
|
|
|
return $sql; |
459
|
|
|
} // end of func GenSelect |
460
|
|
|
|
461
|
|
|
|
462
|
|
|
/** |
463
|
|
|
* Generate SQL part, which param is array and need to list out in plain format. |
464
|
|
|
* |
465
|
|
|
* @param mixed $param |
466
|
|
|
* @param string $s_split String used between parts. |
467
|
|
|
* @return string |
468
|
|
|
*/ |
469
|
|
View Code Duplication |
protected function GenSqlArray($param, $s_split = ', ') |
|
|
|
|
470
|
|
|
{ |
471
|
|
|
$sql = ''; |
472
|
|
|
if (is_array($param) && !empty($param)) |
473
|
|
|
// Because of plain format, so $k is useless |
474
|
|
|
foreach ($param as $k=>$v) |
475
|
|
|
{ |
476
|
|
|
/* |
477
|
|
|
if (is_int($k)) |
478
|
|
|
$sql .= ", $v"; |
479
|
|
|
else |
480
|
|
|
$sql .= ", $k $v"; |
481
|
|
|
*/ |
482
|
|
|
$sql .= "$s_split $v"; |
483
|
|
|
} |
484
|
|
|
else |
485
|
|
|
$sql .= "$s_split $param"; |
486
|
|
|
$sql = substr($sql, strlen($s_split)); |
487
|
|
|
|
488
|
|
|
return $sql; |
489
|
|
|
} // end of func GenSqlArray |
490
|
|
|
|
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* Generate SQL part, which param is array and need use AS in it. |
494
|
|
|
* @link http://dev.mysql.com/doc/refman/5.0/en/select.html |
495
|
|
|
* @param mixed $param Items in SQL SELECT part, Array or string. |
496
|
|
|
* Array($k=>$v) means '$k AS $v' in sql, |
497
|
|
|
* but when $k is int, means '$v AS $v' in sql. |
498
|
|
|
* @param boolean $use_as Sybase table alias can't use AS |
499
|
|
|
* @param boolean $quote AS column alias, need to be quoted(true), |
500
|
|
|
* AS table alias, need not to be quoted(false). |
501
|
|
|
* @param boolean $tas True = reverse order, in table alias and select list, |
502
|
|
|
* array($k=>$v) means 'FROM $v AS $k', |
503
|
|
|
* set by $v => $k is because 1 table can have multi alias, |
504
|
|
|
* and alias are unique, and this way is more goodlook when |
505
|
|
|
* combile indexed and non-indexed item in list |
506
|
|
|
* (non-indexed will use it's original name). |
507
|
|
|
* @return string |
508
|
|
|
*/ |
509
|
|
View Code Duplication |
protected function GenSqlArrayAs($param, $use_as = true, $quote = false, $tas = true) |
|
|
|
|
510
|
|
|
{ |
511
|
|
|
$sql = ''; |
512
|
|
|
if (is_array($param) && !empty($param)) |
513
|
|
|
foreach ($param as $k=>$v) |
514
|
|
|
{ |
515
|
|
|
// If there are space in $v, it need to be quoted |
516
|
|
|
// so always quote it. |
517
|
|
|
if (is_int($k)) |
518
|
|
|
{ |
519
|
|
|
$sql .= ", $v"; |
520
|
|
|
} |
521
|
|
|
else |
522
|
|
|
{ |
523
|
|
|
// table AS a |
524
|
|
|
// tabel AS 'a' |
525
|
|
|
$s_split = ($quote) ? "'" : ''; |
526
|
|
|
$s_as = ($use_as) ? 'AS' : ''; |
527
|
|
|
if ($tas) |
528
|
|
|
$sql .= ", $v $s_as $s_split{$k}$s_split"; |
529
|
|
|
else |
530
|
|
|
$sql .= ", $k $s_as $s_split{$v}$s_split"; |
531
|
|
|
} |
532
|
|
|
} |
533
|
|
|
else |
534
|
|
|
$sql .= ", $param"; |
535
|
|
|
$sql = substr($sql, 2); |
536
|
|
|
|
537
|
|
|
return $sql; |
538
|
|
|
} // end of func GenSqlArrayAs |
539
|
|
|
|
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Generate SQL part, SET subparse of UPDATE |
543
|
|
|
* @link http://dev.mysql.com/doc/refman/5.0/en/update.html |
544
|
|
|
* @param array $param Items in SQL UPDATE part, |
545
|
|
|
* Array only, string will return original value. |
546
|
|
|
* Array($k=>$v) means 'SET $k = $v, ' in sql, |
547
|
|
|
* @return string |
548
|
|
|
*/ |
549
|
|
View Code Duplication |
protected function GenSqlArraySet($param) |
|
|
|
|
550
|
|
|
{ |
551
|
|
|
$sql = ''; |
552
|
|
|
if (is_array($param) && !empty($param)) |
553
|
|
|
{ |
554
|
|
|
foreach ($param as $k=>$v) |
555
|
|
|
{ |
556
|
|
|
$sql .= ", $k = " . $this->GenSqlQuote($this->sUpdate, $k, $v); |
557
|
|
|
} |
558
|
|
|
$sql = ' SET ' . substr($sql, 2); |
559
|
|
|
} |
560
|
|
|
else |
561
|
|
|
{ |
562
|
|
|
// If you fogot 'SET ', I add for you |
563
|
|
|
if ('SET ' != substr(strtoupper(trim($param)), 0, 4)) |
564
|
|
|
$sql .= ' SET '; |
565
|
|
|
$sql .= $param; |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
return $sql; |
569
|
|
|
} // end of func GenSqlArraySet |
570
|
|
|
|
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Generate SQL part, VALUES subparse of INSERT |
574
|
|
|
* @link http://dev.mysql.com/doc/refman/5.0/en/insert.html |
575
|
|
|
* @param array $param Items in SQL INSERT part, |
576
|
|
|
* Array only, string will return original value. |
577
|
|
|
* Array($k=>$v) means '($k) VALUES ($v)' in sql, |
578
|
|
|
* @return string |
579
|
|
|
*/ |
580
|
|
View Code Duplication |
protected function GenSqlArrayValues($param) |
|
|
|
|
581
|
|
|
{ |
582
|
|
|
$sql = ' ( '; |
583
|
|
|
if (is_array($param) && !empty($param)) |
584
|
|
|
{ |
585
|
|
|
$sql1 = ''; |
586
|
|
|
$sql2 = ''; |
587
|
|
|
foreach ($param as $k=>$v) |
588
|
|
|
{ |
589
|
|
|
$sql1 .= ', ' . $k; |
590
|
|
|
$sql2 .= ', ' . $this->GenSqlQuote($this->sInsert, $k, $v); |
591
|
|
|
} |
592
|
|
|
$sql1 = substr($sql1, 2); |
593
|
|
|
$sql2 = substr($sql2, 2); |
594
|
|
|
$sql .= $sql1 . ' ) VALUES ( ' . $sql2 . ' ) '; |
595
|
|
|
} |
596
|
|
|
else |
597
|
|
|
{ |
598
|
|
|
$sql = $param; |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
return $sql; |
602
|
|
|
} // end of func GenSqlArrayValues |
603
|
|
|
|
604
|
|
|
|
605
|
|
|
/** |
606
|
|
|
* Smarty quote string in sql, by check columns type |
607
|
|
|
* @param string $table |
608
|
|
|
* @param string $column |
609
|
|
|
* @param mixed $val |
610
|
|
|
* @return string |
611
|
|
|
*/ |
612
|
|
|
protected function GenSqlQuote($table, $column, $val) |
613
|
|
|
{ |
614
|
|
|
return $this->oDb->QuoteValue($table, $column, $val); |
615
|
|
|
/* |
616
|
|
|
$this->oDb->GetMetaColumn($table); |
617
|
|
|
$type = $this->oDb->aMetaColumn[$table][$column]->type; |
618
|
|
|
//var_dump($type); |
619
|
|
|
if (in_array($type, array( |
620
|
|
|
'bigint', |
621
|
|
|
'bit', |
622
|
|
|
'decimal', |
623
|
|
|
'double', |
624
|
|
|
'float', |
625
|
|
|
'int', |
626
|
|
|
'mediumint', |
627
|
|
|
'numeric', |
628
|
|
|
'real', |
629
|
|
|
'smallint', |
630
|
|
|
'tinyint', |
631
|
|
|
))) |
632
|
|
|
// Need not quote, output directly |
633
|
|
|
return $val; |
634
|
|
|
else |
635
|
|
|
{ |
636
|
|
|
// Need quote, use db's quote method |
637
|
|
|
$val = stripslashes($val); |
638
|
|
|
return $this->oDb->qstr($val, false); |
639
|
|
|
} |
640
|
|
|
*/ |
641
|
|
|
} // end of func GenSqlQuote |
642
|
|
|
|
643
|
|
|
|
644
|
|
|
/** |
645
|
|
|
* Generate an UPDATE sql |
646
|
|
|
* @param array $ar_config |
647
|
|
|
* @return string |
648
|
|
|
*/ |
649
|
|
View Code Duplication |
protected function GenUpdate($ar_config = array()) |
|
|
|
|
650
|
|
|
{ |
651
|
|
|
if (is_array($ar_config) && !empty($ar_config)) |
652
|
|
|
{ |
653
|
|
|
// Using parts in $ar_config, not all parts |
654
|
|
|
// config value has been set already, here only use it's 'name' |
655
|
|
|
$ar = &$ar_config; |
656
|
|
|
} |
657
|
|
|
else |
658
|
|
|
{ |
659
|
|
|
// Using all parts, by this sequence |
660
|
|
|
// http://dev.mysql.com/doc/refman/5.0/en/update.html |
661
|
|
|
$ar = array('UPDATE', 'SET', 'WHERE', 'ORDERBY', 'LIMIT'); |
662
|
|
|
} |
663
|
|
|
$sql = ''; |
664
|
|
|
foreach ($ar as $part => $param) |
665
|
|
|
{ |
666
|
|
|
$part = ucfirst(strtolower($part)); |
667
|
|
|
$sql .= $this->{"sSql$part"}; |
668
|
|
|
} |
669
|
|
|
return $sql; |
670
|
|
|
} // end of func GenUpdate |
671
|
|
|
|
672
|
|
|
|
673
|
|
|
/** |
674
|
|
|
* Get DELETE sql only |
675
|
|
|
* @param array $ar_config |
676
|
|
|
* @return string |
677
|
|
|
*/ |
678
|
|
|
public function GetDelete($ar_config = array()) |
679
|
|
|
{ |
680
|
|
|
return $this->GetSql($ar_config, 'DELETE'); |
681
|
|
|
} // end of func GetDelete |
682
|
|
|
|
683
|
|
|
|
684
|
|
|
/** |
685
|
|
|
* Get INSERT sql only |
686
|
|
|
* @param array $ar_config |
687
|
|
|
* @return string |
688
|
|
|
*/ |
689
|
|
|
public function GetInsert($ar_config = array()) |
690
|
|
|
{ |
691
|
|
|
return $this->GetSql($ar_config, 'INSERT'); |
692
|
|
|
} // end of func GetInsert |
693
|
|
|
|
694
|
|
|
|
695
|
|
|
/** |
696
|
|
|
* Get SELECT sql only |
697
|
|
|
* @param array $ar_config |
698
|
|
|
* @return string |
699
|
|
|
*/ |
700
|
|
|
public function GetSelect($ar_config = array()) |
701
|
|
|
{ |
702
|
|
|
return $this->GetSql($ar_config, 'SELECT'); |
703
|
|
|
} // end of func GetSelect |
704
|
|
|
|
705
|
|
|
|
706
|
|
|
/** |
707
|
|
|
* Get SQL statement |
708
|
|
|
* |
709
|
|
|
* If use SELECT, UPDATE, INSERT, DELETE simultaneously, |
710
|
|
|
* System will select the first on occurs by this order. |
711
|
|
|
* @param array $ar_config Array(SELECT=>..., FROM=>...) |
712
|
|
|
* If obmit, use rememberd value. |
713
|
|
|
* @param string $action SELECT/UPDATE ... etc |
714
|
|
|
* @return string |
715
|
|
|
*/ |
716
|
|
|
public function GetSql($ar_config = array(), $action = '') |
717
|
|
|
{ |
718
|
|
|
$action = strtoupper($action); |
719
|
|
|
$this->Set($ar_config); |
720
|
|
|
|
721
|
|
|
// Got real action |
722
|
|
|
if (is_array($ar_config) && !empty($ar_config)) |
723
|
|
|
foreach ($ar_config as $part => $param) |
724
|
|
|
{ |
725
|
|
|
// SELECT/UPDATE/INSERT/DELETE ? Use the 1st occur guy. |
726
|
|
|
$part = strtoupper($part); |
727
|
|
View Code Duplication |
if (empty($action) && |
|
|
|
|
728
|
|
|
in_array($part, |
729
|
|
|
array('SELECT', 'UPDATE', 'INSERT', 'DELETE')) |
730
|
|
|
) |
731
|
|
|
$action = $part; |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
// Call seperate func to generate sql |
735
|
|
|
$action = ucfirst(strtolower($action)); |
736
|
|
|
$sql = $this->{"Gen$action"}($ar_config); |
737
|
|
|
|
738
|
|
|
return $sql; |
739
|
|
|
} // end of func GetSql |
740
|
|
|
|
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Get SQL statement for Prepare usage |
744
|
|
|
* |
745
|
|
|
* value -> ? or :name, and quote chars removed |
746
|
|
|
* |
747
|
|
|
* Only simple treatment now. |
748
|
|
|
* @param array $ar_config Same as GenSql() |
749
|
|
|
* @return string |
750
|
|
|
* @see GetSql() |
751
|
|
|
*/ |
752
|
|
View Code Duplication |
public function GetSqlPrepare($ar_config = array()) { |
|
|
|
|
753
|
|
|
$sql = $this->GetSql($ar_config); |
754
|
|
|
/* Old treatment |
755
|
|
|
// Notice: The simple treatment here may cause wrong when ? and : are original sql needed |
756
|
|
|
$sql = str_replace("'?'", '?', $sql); |
757
|
|
|
// Notice: For oracle, not tested yet. |
758
|
|
|
$sql = preg_replace('/\'(:[^\']+)\'/', '$1', $sql); |
759
|
|
|
*/ |
760
|
|
|
|
761
|
|
|
// Better treatment |
762
|
|
|
// Remove duplicate ' in sql add by SqlGenerator, |
763
|
|
|
// Execute after Prepare will auto recoginize variant type and quote, |
764
|
|
|
// but notice, it's VAR TYPE and NOT DB COLUMN TYPE. |
765
|
|
|
// replaceQuote: The string used to escape quotes. Eg. double single-quotes for |
766
|
|
|
// Microsoft SQL, and backslash-quote for MySQL. Used by qstr. |
767
|
|
|
if ("''" == $this->oDb->replaceQuote) |
768
|
|
|
$s_quote = "'"; |
769
|
|
|
else |
770
|
|
|
$s_quote = $this->oDb->replaceQuote; |
771
|
|
|
$sql = preg_replace( |
772
|
|
|
"/ {$s_quote}([\?\:\w\-_]+){$s_quote}([, ])/i", |
773
|
|
|
" $1$2", $sql); |
774
|
|
|
|
775
|
|
|
return $sql; |
776
|
|
|
} // end of function GetSqlPrepare |
777
|
|
|
|
778
|
|
|
|
779
|
|
|
/** |
780
|
|
|
* Get UPDATE sql only |
781
|
|
|
* @param array $ar_config |
782
|
|
|
* @return string |
783
|
|
|
*/ |
784
|
|
|
public function GetUpdate($ar_config = array()) |
785
|
|
|
{ |
786
|
|
|
return $this->GetSql($ar_config, 'UPDATE'); |
787
|
|
|
} // end of func GetUpdate |
788
|
|
|
|
789
|
|
|
|
790
|
|
|
/** |
791
|
|
|
* Set value in array to property |
792
|
|
|
* @param array &$ar_config |
793
|
|
|
* @return string |
794
|
|
|
*/ |
795
|
|
|
public function Set(&$ar_config) |
796
|
|
|
{ |
797
|
|
|
if (is_array($ar_config) && !empty($ar_config)) { |
798
|
|
|
// Re-order sql part |
799
|
|
|
$ar = array(); |
800
|
|
|
// Global clause order, will sort by this. |
801
|
|
|
$ar_clause = array('SELECT', 'DELETE', 'INSERT', 'UPDATE', |
802
|
|
|
'VALUES', 'FROM', 'SET', |
803
|
|
|
'WHERE', 'GROUPBY', 'HAVING', 'ORDERBY', 'LIMIT'); |
804
|
|
|
foreach ($ar_clause as $clause) { |
805
|
|
|
$clause = strtoupper($clause); |
806
|
|
|
if (isset($ar_config[$clause])) |
807
|
|
|
$ar[$clause] = $ar_config[$clause]; |
808
|
|
|
$clause = strtolower($clause); |
809
|
|
|
if (isset($ar_config[$clause])) |
810
|
|
|
$ar[$clause] = $ar_config[$clause]; |
811
|
|
|
} |
812
|
|
|
// Write data back to config |
813
|
|
|
$ar_config = $ar; |
814
|
|
|
|
815
|
|
|
foreach ($ar_config as $part => $param) |
816
|
|
|
{ |
817
|
|
|
// Write config to property |
818
|
|
|
$part = ucfirst(strtolower($part)); |
819
|
|
|
$this->{"Set$part"}($param); |
820
|
|
|
} |
821
|
|
|
} |
822
|
|
|
} // end of function |
823
|
|
|
|
824
|
|
|
|
825
|
|
|
/** |
826
|
|
|
* Set Delete |
827
|
|
|
* @param mixed $param |
828
|
|
|
* @return string |
829
|
|
|
*/ |
830
|
|
|
public function SetDelete($param) |
831
|
|
|
{ |
832
|
|
|
$this->sDelete = $param; |
833
|
|
|
$this->sSqlDelete = ' DELETE FROM ' . $param; |
|
|
|
|
834
|
|
|
|
835
|
|
|
// Retrieve table schema, so VALUES/SET can detimine how to quote |
836
|
|
|
$this->oDb->GetMetaColumn($param); |
837
|
|
|
|
838
|
|
|
return $this->sSqlDelete; |
|
|
|
|
839
|
|
|
} // end of func SetDelete |
840
|
|
|
|
841
|
|
|
|
842
|
|
|
/** |
843
|
|
|
* Set From |
844
|
|
|
* @param mixed $param |
845
|
|
|
* @return string |
846
|
|
|
*/ |
847
|
|
|
public function SetFrom($param) |
848
|
|
|
{ |
849
|
|
|
$this->mFrom = $param; |
850
|
|
|
// :NOTICE: 'FROM tbl as a', No space allowed in 'a', need not quote. |
851
|
|
|
$this->sSqlFrom = ' FROM ' . $this->GenSqlArrayAs($param, false, false, true); |
852
|
|
|
return $this->sSqlFrom; |
853
|
|
|
} // end of func SetFrom |
854
|
|
|
|
855
|
|
|
|
856
|
|
|
/** |
857
|
|
|
* Set Group by |
858
|
|
|
* @param mixed $param |
859
|
|
|
* @return string |
860
|
|
|
*/ |
861
|
|
|
public function SetGroupby($param) |
862
|
|
|
{ |
863
|
|
|
$this->mGroupby = $param; |
864
|
|
|
$this->sSqlGroupby = ' GROUP BY' . $this->GenSqlArray($param); |
865
|
|
|
return $this->sSqlGroupby; |
866
|
|
|
} // end of func SetGroupby |
867
|
|
|
|
868
|
|
|
|
869
|
|
|
/** |
870
|
|
|
* Set Having |
871
|
|
|
* @param mixed $param |
872
|
|
|
* @return string |
873
|
|
|
*/ |
874
|
|
|
public function SetHaving($param) |
875
|
|
|
{ |
876
|
|
|
$this->mHaving = $param; |
877
|
|
|
$this->sSqlHaving = ' HAVING ' . $this->GenSqlArray($param, ' AND '); |
878
|
|
|
return $this->sSqlHaving; |
879
|
|
|
} // end of func SetHaving |
880
|
|
|
|
881
|
|
|
|
882
|
|
|
/** |
883
|
|
|
* Set Insert |
884
|
|
|
* @param mixed $param |
885
|
|
|
* @return string |
886
|
|
|
*/ |
887
|
|
|
public function SetInsert($param) |
888
|
|
|
{ |
889
|
|
|
$this->sInsert = $param; |
890
|
|
|
$this->sSqlInsert = ' INSERT INTO ' . $param; |
891
|
|
|
|
892
|
|
|
// Retrieve table schema, so VALUES/SET can detimine how to quote |
893
|
|
|
$this->oDb->GetMetaColumn($param); |
894
|
|
|
|
895
|
|
|
return $this->sSqlInsert; |
896
|
|
|
} // end of func SetInsert |
897
|
|
|
|
898
|
|
|
|
899
|
|
|
/** |
900
|
|
|
* Set Limit |
901
|
|
|
* @param mixed $param |
902
|
|
|
* @return string |
903
|
|
|
*/ |
904
|
|
|
public function SetLimit($param) |
905
|
|
|
{ |
906
|
|
|
if (!$this->oDb->IsDbSybase()) |
907
|
|
|
{ |
908
|
|
|
$this->mLimit = $param; |
909
|
|
|
$this->sSqlLimit = ' LIMIT ' . $this->GenSqlArray($param); |
910
|
|
|
} |
911
|
|
|
else |
912
|
|
|
{ |
913
|
|
|
$this->mLimit = ''; |
914
|
|
|
$this->sSqlLimit = ''; |
915
|
|
|
} |
916
|
|
|
return $this->sSqlLimit; |
917
|
|
|
} // end of func SetLimit |
918
|
|
|
|
919
|
|
|
|
920
|
|
|
/** |
921
|
|
|
* Set Order by |
922
|
|
|
* @param mixed $param |
923
|
|
|
* @return string |
924
|
|
|
*/ |
925
|
|
|
public function SetOrderby($param) |
926
|
|
|
{ |
927
|
|
|
$this->mOrderby = $param; |
928
|
|
|
$this->sSqlOrderby = ' ORDER BY ' . $this->GenSqlArray($param); |
929
|
|
|
return $this->sSqlOrderby; |
930
|
|
|
} // end of func SetOrderby |
931
|
|
|
|
932
|
|
|
|
933
|
|
|
/** |
934
|
|
|
* Set Select |
935
|
|
|
* @param mixed $param |
936
|
|
|
* @return string |
937
|
|
|
*/ |
938
|
|
|
public function SetSelect($param) |
939
|
|
|
{ |
940
|
|
|
$this->mSelect = $param; |
941
|
|
|
$this->sSqlSelect = ' SELECT ' . $this->GenSqlArrayAs($param, true, true, true); |
942
|
|
|
return $this->sSqlSelect; |
943
|
|
|
} // end of func SetSelect |
944
|
|
|
|
945
|
|
|
|
946
|
|
|
/** |
947
|
|
|
* Set Set |
948
|
|
|
* @param mixed $param |
949
|
|
|
* @return string |
950
|
|
|
*/ |
951
|
|
|
public function SetSet($param) |
952
|
|
|
{ |
953
|
|
|
$this->mSetSet = $param; |
|
|
|
|
954
|
|
|
// For UPDATE only, INSERT uses VALUES |
955
|
|
|
// User give param array(col => value) |
956
|
|
|
$this->sSqlSet = $this->GenSqlArraySet($param); |
957
|
|
|
return $this->sSqlSet; |
958
|
|
|
} // end of func SetSet |
959
|
|
|
|
960
|
|
|
|
961
|
|
|
/** |
962
|
|
|
* Set Update |
963
|
|
|
* @param mixed $param |
964
|
|
|
* @return string |
965
|
|
|
*/ |
966
|
|
|
public function SetUpdate($param) |
967
|
|
|
{ |
968
|
|
|
$this->sUpdate = $param; |
969
|
|
|
$this->sSqlUpdate = ' UPDATE ' . $param; |
970
|
|
|
|
971
|
|
|
// Retrieve table schema, so VALUES/SET can detimine how to quote |
972
|
|
|
$this->oDb->GetMetaColumn($param); |
973
|
|
|
|
974
|
|
|
return $this->sSqlUpdate; |
975
|
|
|
} // end of func SetUpdate |
976
|
|
|
|
977
|
|
|
|
978
|
|
|
/** |
979
|
|
|
* Set Values |
980
|
|
|
* @param mixed $param |
981
|
|
|
* @return string |
982
|
|
|
*/ |
983
|
|
|
public function SetValues($param) |
984
|
|
|
{ |
985
|
|
|
$this->mSetValues = $param; |
|
|
|
|
986
|
|
|
// For INSERT only, UPDATE uses SET |
987
|
|
|
// User give param array(col => value) |
988
|
|
|
$this->sSqlValues = $this->GenSqlArrayValues($param); |
|
|
|
|
989
|
|
|
return $this->sSqlValues; |
990
|
|
|
} // end of func SetValues |
991
|
|
|
|
992
|
|
|
|
993
|
|
|
/** |
994
|
|
|
* Set Where |
995
|
|
|
* @param mixed $param |
996
|
|
|
* @return string |
997
|
|
|
*/ |
998
|
|
|
public function SetWhere($param) |
999
|
|
|
{ |
1000
|
|
|
$this->mSetWhere = $param; |
|
|
|
|
1001
|
|
|
// Add '(' to defend sql injection |
1002
|
|
|
$this->sSqlWhere = ' WHERE ( ' . $this->GenSqlArray($param, ') AND (') . ' )'; |
1003
|
|
|
return $this->sSqlWhere; |
1004
|
|
|
} // end of func SetWhere |
1005
|
|
|
|
1006
|
|
|
|
1007
|
|
|
} // end of class SqlGenerator |
1008
|
|
|
?> |
|
|
|
|
1009
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.