Documentation is available at tgcSqlBuilder.php
1 <?php
2 /**
3 * $Id: tgcSqlBuilder.php,v 1.1.1.1 2004/02/14 01:43:19 luckec Exp $
4 *
5 * Class that helps you to generate sql-statements without handling string concatenation.
6 *
7 * @package tgcSqlBuilder
8 * @author Carsten Lucke <luckec@tool-garage.de>
9 * @copyright Carsten Lucke <http://www.tool-garage.de>
10 */
11
12
13
14 /**
15 * Uses PEAR error-management
16 */
17 require_once 'PEAR.php';
18
19 /**
20 * Uses PEAR::DB
21 */
22 require_once 'DB.php';
23
24
25
26 /**
27 * sorting direction: ascending
28 *
29 * @access public
30 */
31 define('SQLBUILDER_ORDER_ASC', 'ASC');
32
33 /**
34 * sorting direction: descending
35 *
36 * @access public
37 */
38 define('SQLBUILDER_ORDER_DESC', 'DESC');
39
40 /**
41 * equal
42 *
43 * @access public
44 */
45 define( 'SQLBUILDER_COMP_EQUAL', '=' );
46
47 /**
48 * equal
49 *
50 * @access public
51 */
52 define( 'SQLBUILDER_COMP_NOT_EQUAL', '<>' );
53
54 /**
55 * lesser than
56 *
57 * @access public
58 */
59 define( 'SQLBUILDER_COMP_LESSER_THAN', '<' );
60
61 /**
62 * lesser equal
63 *
64 * @access public
65 */
66 define( 'SQLBUILDER_COMP_LESSER_EQUAL', '<=' );
67
68 /**
69 * greater equal
70 *
71 * @access public
72 */
73 define( 'SQLBUILDER_COMP_GREATER_EQUAL', '>=' );
74
75 /**
76 * greater than
77 *
78 * @access public
79 */
80 define( 'SQLBUILDER_COMP_GREATER_THAN', '>' );
81
82 /**
83 * starts with
84 *
85 * @access public
86 */
87 define( 'SQLBUILDER_COMP_STARTSWITH', 'LIKE_' );
88
89 /**
90 * contains
91 *
92 * @access public
93 */
94 define( 'SQLBUILDER_COMP_CONTAINS', '_LIKE_' );
95
96 /**
97 * ends with
98 *
99 * @access public
100 */
101 define( 'SQLBUILDER_COMP_ENDSWITH', '_LIKE' );
102
103 /**
104 * BETWEEN
105 *
106 * @access public
107 */
108 define( 'SQLBUILDER_COMP_BETWEEN', 'BETWEEN' );
109
110 /**
111 * logical AND
112 *
113 * @access public
114 */
115 define('SQLBUILDER_LOGICAL_AND', 'AND');
116
117 /**
118 * logical OR
119 *
120 * @access public
121 */
122 define('SQLBUILDER_LOGICAL_OR', 'OR');
123
124 /**
125 * Invalid parameter cobination
126 *
127 * @access public
128 */
129 define( 'SQLBUILDER_ERROR_INVALID_PARAM_COMBO', 1 );
130
131 /**
132 * Wrong parameter for a method
133 *
134 * @access public
135 */
136 define('SQLBUILDER_ERROR_INVALID_PARAMETER', 2);
137
138 /**
139 * Wrong parametercount for a method
140 *
141 * @access public
142 */
143 define('SQLBUILDER_ERROR_INVALID_PARAMETERCOUNT', 3);
144
145 /**
146 * operation on a column that does not exist in object data (i.e. remove)
147 *
148 * @access public
149 */
150 define('SQLBUILDER_ERROR_COLUMN_DOES_NOT_EXIST', 4);
151
152 /**
153 * the user specified an invalid logical operator
154 *
155 * @access public
156 */
157 define('SQLBUILDER_ERROR_INVALID_LOGICAL_OPERATOR', 5);
158
159 /**
160 * No table has been specified
161 *
162 * @access public
163 */
164 define( 'SQLBUILDER_ERROR_NO_TABLE_FOUND', 6 );
165
166
167
168
169 /**
170 * Class that helps you to generate sql-statements without handling string concatenation.
171 *
172 * @package tgcSqlBuilder
173 * @access public
174 * @version 1.0.0
175 * @author Carsten Lucke <luckec@tool-garage.de>
176 * @abstract
177 */
178 class tgcSqlBuilder
179 {
180
181 /**
182 * PEAR::DB object
183 *
184 * @access private
185 * @var object PEAR::DB connection object
186 */
187 var $_dbc;
188
189 /**
190 * Tablename on which a sql-statement concerns.
191 *
192 * It's a associative array, that contains the tablenames as keys and aliases as values.
193 * If no alias is specified the value is NULL.
194 *
195 * @access private
196 * @var array tablename
197 */
198 var $_tables = array();
199
200
201
202 /**
203 * Constructor
204 *
205 * @access public
206 * @param object $dbc PEAR::DB connection object
207 * @return mixed PEAR_Error or an sqlBuilder object
208 */
209 function tgcSqlBuilder(&$dbc)
210 {
211 $this->_dbc = $dbc;
212 }
213
214
215 /**
216 * Add the statements table.
217 *
218 * <code>
219 * $sql = new tgcSqlBuilder_Select($dbc);
220 * $sql->addTable('users');
221 * // now the generated sql-statement would look like: SELECT ... FROM users ...
222 * </code>
223 *
224 * @access public
225 * @param string $tableName tablename
226 * @param string $alias aliasname
227 */
228 function addTable($tableName, $alias = null)
229 {
230 $this->_tables[$tableName] = $alias;
231 }
232
233 /**
234 * Remove one or all tablename(s).
235 *
236 * If you specify a tablename, then this one will be removed.
237 * If you don't specify a param, then all tablenames will be removed.
238 *
239 * <code>
240 * // remove a specific tablename
241 * $sql = new tgcSqlBuilder_Select($dbc);
242 * $sql->removeTable('users');
243 *
244 * // remove all tablenames
245 * $sql = new tgcSqlBuilder_Select($dbc);
246 * $sql->removeTable();
247 * </code>
248 *
249 * @access public
250 * @param string $tableName tablename
251 */
252 function removeTable($tableName = null)
253 {
254 // remove a specific table
255 if(! is_null($tableName)) {
256 if (isset($this->_tables[$tableName])) {
257 unset($this->_tables[$tableName]);
258 }
259 return;
260 }
261
262 // remove all tables
263 $this->_tables = array();
264 }
265
266 /**
267 * Generate the sql-statement.
268 *
269 * This method generates a query based on the object-information and returns it as a string.
270 *
271 * <code>
272 * $sql = new tgcSqlBuilder_Select($dbc);
273 * $query = $sql->generateQuery();
274 * </code>
275 *
276 * @access public
277 * @return string sql-statement
278 * @abstract
279 */
280 function generateQuery()
281 {
282 }
283
284 /**
285 * Escapes a variable appropriate for the used database-system.
286 *
287 * @access public
288 * @param mixed $var variable you want to be escaped
289 * @return mixed escaped variable
290 */
291 function escape($var)
292 {
293 return $this->_dbc->quote($var);
294 }
295
296 /**
297 * Reset the object's whole information.
298 *
299 * @access public
300 * @abstract
301 */
302 function reset()
303 {
304 }
305
306 /**
307 * Generates a string based on the objects WHERE information.
308 *
309 * Must only be called from objects that contain a WHERE attribute.
310 *
311 * @access private
312 * @param array $where WHERE attribute
313 * @param array $rawWhere raw WHERE attribute
314 */
315 function _generateWhereInformation(&$where, &$rawWhere)
316 {
317 $statement = '';
318
319 // WHERE['AND']
320 if (count($where[SQLBUILDER_LOGICAL_AND])) {
321 foreach ($where[SQLBUILDER_LOGICAL_AND] as $statementData) {
322 if ($statement != '') {
323 $statement .= ' ' . SQLBUILDER_LOGICAL_AND . ' ';
324 }
325 $statement .= sprintf ("%s.%s %s %s", $statementData['table'],
326 $statementData['column'],
327 str_replace('_', '', $statementData['compOp']),
328 $this->_createFilteredValue($statementData['value'], $statementData['compOp'])
329 );
330 }
331 }
332
333 // raw WHERE['AND']
334 if (count($rawWhere[SQLBUILDER_LOGICAL_AND])) {
335 foreach ($rawWhere[SQLBUILDER_LOGICAL_AND] as $stmnt) {
336 if ($statement != '') {
337 $statement .= ' ' . SQLBUILDER_LOGICAL_AND . ' ';
338 }
339 $statement .= $stmnt;
340 }
341 }
342
343 // WHERE['OR']
344 if (count($where[SQLBUILDER_LOGICAL_OR])) {
345 foreach ($where[SQLBUILDER_LOGICAL_OR] as $statementData) {
346 if ($statement != '') {
347 $statement .= ' ' . SQLBUILDER_LOGICAL_OR . ' ';
348 }
349 $statement .= sprintf ("%s.%s %s %s", $statementData['table'],
350 $statementData['column'],
351 str_replace('_', '', $statementData['compOp']),
352 $this->_createFilteredValue($statementData['value'], $statementData['compOp'])
353 );
354 }
355 }
356
357 // raw WHERE['OR']
358 if (count($rawWhere[SQLBUILDER_LOGICAL_OR])) {
359 foreach ($rawWhere[SQLBUILDER_LOGICAL_OR] as $stmnt) {
360 if ($statement != '') {
361 $statement .= ' ' . SQLBUILDER_LOGICAL_OR . ' ';
362 }
363 $statement .= $stmnt;
364 }
365 }
366
367 return $statement;
368 }
369
370 /**
371 * Gets a value and a filtername and returns the value with applied filter-characters, if necessary.
372 * The value that will be returned is also being qouted appropriate to your database system.
373 *
374 * Example: If the value would be (string) "foobar" and the filter SQLBUILDER_COMP_CONTAINS, then
375 * the returned value would be (string) "%foobar%".
376 *
377 * @access private
378 * @param mixed $value value on which the filter has to be applied
379 * @param string $filter constant representing a filter
380 * @return mixed filtered value
381 */
382 function _createFilteredValue($value, $filter)
383 {
384 $return = null;
385
386 switch ($filter) {
387 case SQLBUILDER_COMP_STARTSWITH:
388 $return = $this->escape($value . '%');
389 break;
390
391 case SQLBUILDER_COMP_CONTAINS:
392 $return = $this->escape('%' . $value . '%');
393 break;
394
395 case SQLBUILDER_COMP_ENDSWITH:
396 $return = $this->escape('%' . $value);
397 break;
398
399 case SQLBUILDER_COMP_BETWEEN:
400 $return = $this->escape($value[0]) . ' AND ' . $this->escape($value[1]);
401 break;
402
403 default:
404 $return = $this->escape($value);
405 break;
406 }
407
408 return $return;
409 }
410
411 /**
412 * Generates a string based on the objects ORDER BY information.
413 *
414 * Must only be called from objects that contain a ORDER BY attribute.
415 *
416 * @access private
417 * @param mixed $att ORDER BY attribute
418 */
419 function _generateOrderByInformation(&$att)
420 {
421 $statements = array();
422
423 foreach ($att as $orderByData) {
424 if (! is_null($orderByData['column'])) {
425 array_push ($statements, sprintf("%s.%s %s", $orderByData['table'],
426 $orderByData['column'],
427 $orderByData['direction'])
428 );
429 } else {
430 array_push ($statements, sprintf("%s %s", $orderByData['table'],
431 $orderByData['direction'])
432 );
433 }
434 }
435
436 return implode(', ', $statements);
437 }
438
439 /**
440 * Generates a string based on the objects LIMIT information.
441 *
442 * Must only be called from objects that contain a LIMIT attribute.
443 *
444 * @access private
445 * @param mixed $att LIMIT attribute
446 */
447 function _generateLimitInformation(&$att)
448 {
449 if (! isset($att['rows'])) {
450 return $att['offset'];
451 }
452
453 return sprintf("%d, %d", $att['offset'], $att['rows']);
454 }
455
456 /**
457 * Adds the data for a WHERE or HAVING statement
458 *
459 * @access private
460 * @param array $att the object's WHERE or HAVING attribute
461 * @param string $table tablename
462 * @param string $column columnname
463 * @param mixed $value value(s)
464 * @param string $compOp comparison operator
465 * @param string $logic logical linkup
466 */
467 function _addWhereHaving(&$att, $table, $column, $value, $compOp = null, $logic = null)
468 {
469 $where['table'] = $table;
470 $where['column'] = $column;
471 $where['value'] = $value;
472 $where['compOp'] = is_null($compOp) ? SQLBUILDER_COMP_EQUAL : $compOp;
473 $logic = is_null($logic) ? SQLBUILDER_LOGICAL_AND : $logic;
474
475 array_push($att[$logic], $where);
476 }
477
478 /**
479 * Remove a WHERE or HAVING statement
480 *
481 * @access private
482 * @param array $att the object's WHERE or HAVING attribute
483 * @param string $table tablename
484 * @param string $column columnname
485 * @param string $logic logical operation (possible values: SQLBUILDER_LOGICAL_AND, SQLBUILDER_LOGICAL_OR)
486 * @return mixed true on success or PEAR_Error (possible error(s): SQLBUILDER_ERROR_INVALID_PARAM_COMBO)
487 */
488 function _removeWhereHaving(&$att, $table = null, $column = null, $logic = null)
489 {
490 if (is_null($table) && is_null($column)) {
491 $att = array
492 (
493 SQLBUILDER_LOGICAL_AND => array(),
494 SQLBUILDER_LOGICAL_OR => array()
495 );
496 return true;
497 }
498
499 if (! is_null($table) && ! is_null($column)) {
500 if (is_null($logic)) {
501 foreach ($att[SQLBUILDER_LOGICAL_AND] as $index => $whereData) {
502 if ($whereData['table'] == $table && $whereData['column'] == $column) {
503 unset($att[SQLBUILDER_LOGICAL_AND][$index]);
504 }
505 }
506 foreach ($att[SQLBUILDER_LOGICAL_OR] as $index => $whereData) {
507 if ($whereData['table'] == $table && $whereData['column'] == $column) {
508 unset($att[SQLBUILDER_LOGICAL_OR][$index]);
509 }
510 }
511 return true;
512 }
513 foreach ($att[$logic] as $index => $whereData) {
514 if ($whereData['table'] == $table && $whereData['column'] == $column) {
515 unset($att[$logic][$index]);
516 }
517 }
518 return true;
519 }
520
521 return PEAR::raiseError (
522 'The combination of parameters is invalid',
523 SQLBUILDER_ERROR_INVALID_PARAM_COMBO,
524 null,
525 null,
526 'You have to call the method with none or two parameters'
527 );
528 }
529
530 /**
531 * Add a raw WHERE or HAVING statement.
532 *
533 * @access private
534 * @param array $att the object's WHERE or HAVING attribute
535 * @param string $statement raw HAVING statement
536 * @param string $logic SQLBUILDER_LOGICAL_AND or SQLBUILDER_LOGICAL_OR
537 */
538 function _addRawWhereHaving(&$att, $statement, $logic = SQLBUILDER_LOGICAL_AND)
539 {
540 array_push($att[$logic], $statement);
541 }
542
543 /**
544 * Remove a raw WHERE or HAVING statement.
545 *
546 * @access private
547 * @param array $att the object's WHERE or HAVING attribute
548 * @param string $logic SQLBUILDER_LOGICAL_AND or SQLBUILDER_LOGICAL_OR
549 * @return mixed true on success, else PEAR_Error
550 */
551 function _removeRawWhereHaving(&$att, $logic = null)
552 {
553 // check $logic, if specified
554 if (! is_null($logic) && ($logic != SQLBUILDER_LOGICAL_AND && $logic != SQLBUILDER_LOGICAL_OR)) {
555 return PEAR::raiseError (
556 'Invalid logical operator',
557 SQLBUILDER_ERROR_INVALID_LOGICAL_OPERATOR
558 );
559 }
560
561 // remove all raw WHERE statements
562 if (is_null($logic)) {
563 $att = array
564 (
565 SQLBUILDER_LOGICAL_AND => array(),
566 SQLBUILDER_LOGICAL_OR => array()
567 );
568 return true;
569 }
570
571 // delete depending on $logic
572 $att[$logic] = array();
573 return true;
574 }
575
576 }
577 ?>
Documentation generated on Fri, 19 Nov 2004 23:54:05 +0100 by phpDocumentor 1.2.3