1 | <?php |
---|
2 | // +----------------------------------------------------------------------+ |
---|
3 | // | PHP versions 4 and 5 | |
---|
4 | // +----------------------------------------------------------------------+ |
---|
5 | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
---|
6 | // | Stig. S. Bakken, Lukas Smith | |
---|
7 | // | All rights reserved. | |
---|
8 | // +----------------------------------------------------------------------+ |
---|
9 | // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
---|
10 | // | API as well as database abstraction for PHP applications. | |
---|
11 | // | This LICENSE is in the BSD license style. | |
---|
12 | // | | |
---|
13 | // | Redistribution and use in source and binary forms, with or without | |
---|
14 | // | modification, are permitted provided that the following conditions | |
---|
15 | // | are met: | |
---|
16 | // | | |
---|
17 | // | Redistributions of source code must retain the above copyright | |
---|
18 | // | notice, this list of conditions and the following disclaimer. | |
---|
19 | // | | |
---|
20 | // | Redistributions in binary form must reproduce the above copyright | |
---|
21 | // | notice, this list of conditions and the following disclaimer in the | |
---|
22 | // | documentation and/or other materials provided with the distribution. | |
---|
23 | // | | |
---|
24 | // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
---|
25 | // | Lukas Smith nor the names of his contributors may be used to endorse | |
---|
26 | // | or promote products derived from this software without specific prior| |
---|
27 | // | written permission. | |
---|
28 | // | | |
---|
29 | // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
---|
30 | // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
---|
31 | // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
---|
32 | // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
---|
33 | // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
---|
34 | // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
---|
35 | // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
---|
36 | // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
---|
37 | // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
---|
38 | // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
---|
39 | // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
---|
40 | // | POSSIBILITY OF SUCH DAMAGE. | |
---|
41 | // +----------------------------------------------------------------------+ |
---|
42 | // | Author: Lukas Smith <smith@pooteeweet.org> | |
---|
43 | // +----------------------------------------------------------------------+ |
---|
44 | // |
---|
45 | // $Id: Common.php,v 1.139 2008/12/04 11:50:42 afz Exp $ |
---|
46 | |
---|
47 | require_once 'MDB2/LOB.php'; |
---|
48 | |
---|
49 | /** |
---|
50 | * @package MDB2 |
---|
51 | * @category Database |
---|
52 | * @author Lukas Smith <smith@pooteeweet.org> |
---|
53 | */ |
---|
54 | |
---|
55 | /** |
---|
56 | * MDB2_Driver_Common: Base class that is extended by each MDB2 driver |
---|
57 | * |
---|
58 | * To load this module in the MDB2 object: |
---|
59 | * $mdb->loadModule('Datatype'); |
---|
60 | * |
---|
61 | * @package MDB2 |
---|
62 | * @category Database |
---|
63 | * @author Lukas Smith <smith@pooteeweet.org> |
---|
64 | */ |
---|
65 | class MDB2_Driver_Datatype_Common extends MDB2_Module_Common |
---|
66 | { |
---|
67 | var $valid_default_values = array( |
---|
68 | 'text' => '', |
---|
69 | 'boolean' => true, |
---|
70 | 'integer' => 0, |
---|
71 | 'decimal' => 0.0, |
---|
72 | 'float' => 0.0, |
---|
73 | 'timestamp' => '1970-01-01 00:00:00', |
---|
74 | 'time' => '00:00:00', |
---|
75 | 'date' => '1970-01-01', |
---|
76 | 'clob' => '', |
---|
77 | 'blob' => '', |
---|
78 | ); |
---|
79 | |
---|
80 | /** |
---|
81 | * contains all LOB objects created with this MDB2 instance |
---|
82 | * @var array |
---|
83 | * @access protected |
---|
84 | */ |
---|
85 | var $lobs = array(); |
---|
86 | |
---|
87 | // }}} |
---|
88 | // {{{ getValidTypes() |
---|
89 | |
---|
90 | /** |
---|
91 | * Get the list of valid types |
---|
92 | * |
---|
93 | * This function returns an array of valid types as keys with the values |
---|
94 | * being possible default values for all native datatypes and mapped types |
---|
95 | * for custom datatypes. |
---|
96 | * |
---|
97 | * @return mixed array on success, a MDB2 error on failure |
---|
98 | * @access public |
---|
99 | */ |
---|
100 | function getValidTypes() |
---|
101 | { |
---|
102 | $types = $this->valid_default_values; |
---|
103 | $db =& $this->getDBInstance(); |
---|
104 | if (PEAR::isError($db)) { |
---|
105 | return $db; |
---|
106 | } |
---|
107 | if (!empty($db->options['datatype_map'])) { |
---|
108 | foreach ($db->options['datatype_map'] as $type => $mapped_type) { |
---|
109 | if (array_key_exists($mapped_type, $types)) { |
---|
110 | $types[$type] = $types[$mapped_type]; |
---|
111 | } elseif (!empty($db->options['datatype_map_callback'][$type])) { |
---|
112 | $parameter = array('type' => $type, 'mapped_type' => $mapped_type); |
---|
113 | $default = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
114 | $types[$type] = $default; |
---|
115 | } |
---|
116 | } |
---|
117 | } |
---|
118 | return $types; |
---|
119 | } |
---|
120 | |
---|
121 | // }}} |
---|
122 | // {{{ checkResultTypes() |
---|
123 | |
---|
124 | /** |
---|
125 | * Define the list of types to be associated with the columns of a given |
---|
126 | * result set. |
---|
127 | * |
---|
128 | * This function may be called before invoking fetchRow(), fetchOne() |
---|
129 | * fetchCole() and fetchAll() so that the necessary data type |
---|
130 | * conversions are performed on the data to be retrieved by them. If this |
---|
131 | * function is not called, the type of all result set columns is assumed |
---|
132 | * to be text, thus leading to not perform any conversions. |
---|
133 | * |
---|
134 | * @param array $types array variable that lists the |
---|
135 | * data types to be expected in the result set columns. If this array |
---|
136 | * contains less types than the number of columns that are returned |
---|
137 | * in the result set, the remaining columns are assumed to be of the |
---|
138 | * type text. Currently, the types clob and blob are not fully |
---|
139 | * supported. |
---|
140 | * @return mixed MDB2_OK on success, a MDB2 error on failure |
---|
141 | * @access public |
---|
142 | */ |
---|
143 | function checkResultTypes($types) |
---|
144 | { |
---|
145 | $types = is_array($types) ? $types : array($types); |
---|
146 | foreach ($types as $key => $type) { |
---|
147 | if (!isset($this->valid_default_values[$type])) { |
---|
148 | $db =& $this->getDBInstance(); |
---|
149 | if (PEAR::isError($db)) { |
---|
150 | return $db; |
---|
151 | } |
---|
152 | if (empty($db->options['datatype_map'][$type])) { |
---|
153 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
154 | $type.' for '.$key.' is not a supported column type', __FUNCTION__); |
---|
155 | } |
---|
156 | } |
---|
157 | } |
---|
158 | return $types; |
---|
159 | } |
---|
160 | |
---|
161 | // }}} |
---|
162 | // {{{ _baseConvertResult() |
---|
163 | |
---|
164 | /** |
---|
165 | * General type conversion method |
---|
166 | * |
---|
167 | * @param mixed $value reference to a value to be converted |
---|
168 | * @param string $type specifies which type to convert to |
---|
169 | * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text |
---|
170 | * @return object an MDB2 error on failure |
---|
171 | * @access protected |
---|
172 | */ |
---|
173 | function _baseConvertResult($value, $type, $rtrim = true) |
---|
174 | { |
---|
175 | switch ($type) { |
---|
176 | case 'text': |
---|
177 | if ($rtrim) { |
---|
178 | $value = rtrim($value); |
---|
179 | } |
---|
180 | return $value; |
---|
181 | case 'integer': |
---|
182 | return intval($value); |
---|
183 | case 'boolean': |
---|
184 | return !empty($value); |
---|
185 | case 'decimal': |
---|
186 | return $value; |
---|
187 | case 'float': |
---|
188 | return doubleval($value); |
---|
189 | case 'date': |
---|
190 | return $value; |
---|
191 | case 'time': |
---|
192 | return $value; |
---|
193 | case 'timestamp': |
---|
194 | return $value; |
---|
195 | case 'clob': |
---|
196 | case 'blob': |
---|
197 | $this->lobs[] = array( |
---|
198 | 'buffer' => null, |
---|
199 | 'position' => 0, |
---|
200 | 'lob_index' => null, |
---|
201 | 'endOfLOB' => false, |
---|
202 | 'resource' => $value, |
---|
203 | 'value' => null, |
---|
204 | 'loaded' => false, |
---|
205 | ); |
---|
206 | end($this->lobs); |
---|
207 | $lob_index = key($this->lobs); |
---|
208 | $this->lobs[$lob_index]['lob_index'] = $lob_index; |
---|
209 | return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+'); |
---|
210 | } |
---|
211 | |
---|
212 | $db =& $this->getDBInstance(); |
---|
213 | if (PEAR::isError($db)) { |
---|
214 | return $db; |
---|
215 | } |
---|
216 | |
---|
217 | return $db->raiseError(MDB2_ERROR_INVALID, null, null, |
---|
218 | 'attempt to convert result value to an unknown type :' . $type, __FUNCTION__); |
---|
219 | } |
---|
220 | |
---|
221 | // }}} |
---|
222 | // {{{ convertResult() |
---|
223 | |
---|
224 | /** |
---|
225 | * Convert a value to a RDBMS indipendent MDB2 type |
---|
226 | * |
---|
227 | * @param mixed $value value to be converted |
---|
228 | * @param string $type specifies which type to convert to |
---|
229 | * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text |
---|
230 | * @return mixed converted value |
---|
231 | * @access public |
---|
232 | */ |
---|
233 | function convertResult($value, $type, $rtrim = true) |
---|
234 | { |
---|
235 | if (is_null($value)) { |
---|
236 | return null; |
---|
237 | } |
---|
238 | $db =& $this->getDBInstance(); |
---|
239 | if (PEAR::isError($db)) { |
---|
240 | return $db; |
---|
241 | } |
---|
242 | if (!empty($db->options['datatype_map'][$type])) { |
---|
243 | $type = $db->options['datatype_map'][$type]; |
---|
244 | if (!empty($db->options['datatype_map_callback'][$type])) { |
---|
245 | $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim); |
---|
246 | return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
247 | } |
---|
248 | } |
---|
249 | return $this->_baseConvertResult($value, $type, $rtrim); |
---|
250 | } |
---|
251 | |
---|
252 | // }}} |
---|
253 | // {{{ convertResultRow() |
---|
254 | |
---|
255 | /** |
---|
256 | * Convert a result row |
---|
257 | * |
---|
258 | * @param array $types |
---|
259 | * @param array $row specifies the types to convert to |
---|
260 | * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text |
---|
261 | * @return mixed MDB2_OK on success, an MDB2 error on failure |
---|
262 | * @access public |
---|
263 | */ |
---|
264 | function convertResultRow($types, $row, $rtrim = true) |
---|
265 | { |
---|
266 | $types = $this->_sortResultFieldTypes(array_keys($row), $types); |
---|
267 | foreach ($row as $key => $value) { |
---|
268 | if (empty($types[$key])) { |
---|
269 | continue; |
---|
270 | } |
---|
271 | $value = $this->convertResult($row[$key], $types[$key], $rtrim); |
---|
272 | if (PEAR::isError($value)) { |
---|
273 | return $value; |
---|
274 | } |
---|
275 | $row[$key] = $value; |
---|
276 | } |
---|
277 | return $row; |
---|
278 | } |
---|
279 | |
---|
280 | // }}} |
---|
281 | // {{{ _sortResultFieldTypes() |
---|
282 | |
---|
283 | /** |
---|
284 | * convert a result row |
---|
285 | * |
---|
286 | * @param array $types |
---|
287 | * @param array $row specifies the types to convert to |
---|
288 | * @param bool $rtrim if to rtrim text values or not |
---|
289 | * @return mixed MDB2_OK on success, a MDB2 error on failure |
---|
290 | * @access public |
---|
291 | */ |
---|
292 | function _sortResultFieldTypes($columns, $types) |
---|
293 | { |
---|
294 | $n_cols = count($columns); |
---|
295 | $n_types = count($types); |
---|
296 | if ($n_cols > $n_types) { |
---|
297 | for ($i= $n_cols - $n_types; $i >= 0; $i--) { |
---|
298 | $types[] = null; |
---|
299 | } |
---|
300 | } |
---|
301 | $sorted_types = array(); |
---|
302 | foreach ($columns as $col) { |
---|
303 | $sorted_types[$col] = null; |
---|
304 | } |
---|
305 | foreach ($types as $name => $type) { |
---|
306 | if (array_key_exists($name, $sorted_types)) { |
---|
307 | $sorted_types[$name] = $type; |
---|
308 | unset($types[$name]); |
---|
309 | } |
---|
310 | } |
---|
311 | // if there are left types in the array, fill the null values of the |
---|
312 | // sorted array with them, in order. |
---|
313 | if (count($types)) { |
---|
314 | reset($types); |
---|
315 | foreach (array_keys($sorted_types) as $k) { |
---|
316 | if (is_null($sorted_types[$k])) { |
---|
317 | $sorted_types[$k] = current($types); |
---|
318 | next($types); |
---|
319 | } |
---|
320 | } |
---|
321 | } |
---|
322 | return $sorted_types; |
---|
323 | } |
---|
324 | |
---|
325 | // }}} |
---|
326 | // {{{ getDeclaration() |
---|
327 | |
---|
328 | /** |
---|
329 | * Obtain DBMS specific SQL code portion needed to declare |
---|
330 | * of the given type |
---|
331 | * |
---|
332 | * @param string $type type to which the value should be converted to |
---|
333 | * @param string $name name the field to be declared. |
---|
334 | * @param string $field definition of the field |
---|
335 | * @return string DBMS specific SQL code portion that should be used to |
---|
336 | * declare the specified field. |
---|
337 | * @access public |
---|
338 | */ |
---|
339 | function getDeclaration($type, $name, $field) |
---|
340 | { |
---|
341 | $db =& $this->getDBInstance(); |
---|
342 | if (PEAR::isError($db)) { |
---|
343 | return $db; |
---|
344 | } |
---|
345 | |
---|
346 | if (!empty($db->options['datatype_map'][$type])) { |
---|
347 | $type = $db->options['datatype_map'][$type]; |
---|
348 | if (!empty($db->options['datatype_map_callback'][$type])) { |
---|
349 | $parameter = array('type' => $type, 'name' => $name, 'field' => $field); |
---|
350 | return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
351 | } |
---|
352 | $field['type'] = $type; |
---|
353 | } |
---|
354 | |
---|
355 | if (!method_exists($this, "_get{$type}Declaration")) { |
---|
356 | return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
---|
357 | 'type not defined: '.$type, __FUNCTION__); |
---|
358 | } |
---|
359 | return $this->{"_get{$type}Declaration"}($name, $field); |
---|
360 | } |
---|
361 | |
---|
362 | // }}} |
---|
363 | // {{{ getTypeDeclaration() |
---|
364 | |
---|
365 | /** |
---|
366 | * Obtain DBMS specific SQL code portion needed to declare an text type |
---|
367 | * field to be used in statements like CREATE TABLE. |
---|
368 | * |
---|
369 | * @param array $field associative array with the name of the properties |
---|
370 | * of the field being declared as array indexes. Currently, the types |
---|
371 | * of supported field properties are as follows: |
---|
372 | * |
---|
373 | * length |
---|
374 | * Integer value that determines the maximum length of the text |
---|
375 | * field. If this argument is missing the field should be |
---|
376 | * declared to have the longest length allowed by the DBMS. |
---|
377 | * |
---|
378 | * default |
---|
379 | * Text value to be used as default for this field. |
---|
380 | * |
---|
381 | * notnull |
---|
382 | * Boolean flag that indicates whether this field is constrained |
---|
383 | * to not be set to null. |
---|
384 | * @return string DBMS specific SQL code portion that should be used to |
---|
385 | * declare the specified field. |
---|
386 | * @access public |
---|
387 | */ |
---|
388 | function getTypeDeclaration($field) |
---|
389 | { |
---|
390 | $db =& $this->getDBInstance(); |
---|
391 | if (PEAR::isError($db)) { |
---|
392 | return $db; |
---|
393 | } |
---|
394 | |
---|
395 | switch ($field['type']) { |
---|
396 | case 'text': |
---|
397 | $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length']; |
---|
398 | $fixed = !empty($field['fixed']) ? $field['fixed'] : false; |
---|
399 | return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') |
---|
400 | : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); |
---|
401 | case 'clob': |
---|
402 | return 'TEXT'; |
---|
403 | case 'blob': |
---|
404 | return 'TEXT'; |
---|
405 | case 'integer': |
---|
406 | return 'INT'; |
---|
407 | case 'boolean': |
---|
408 | return 'INT'; |
---|
409 | case 'date': |
---|
410 | return 'CHAR ('.strlen('YYYY-MM-DD').')'; |
---|
411 | case 'time': |
---|
412 | return 'CHAR ('.strlen('HH:MM:SS').')'; |
---|
413 | case 'timestamp': |
---|
414 | return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')'; |
---|
415 | case 'float': |
---|
416 | return 'TEXT'; |
---|
417 | case 'decimal': |
---|
418 | return 'TEXT'; |
---|
419 | } |
---|
420 | return ''; |
---|
421 | } |
---|
422 | |
---|
423 | // }}} |
---|
424 | // {{{ _getDeclaration() |
---|
425 | |
---|
426 | /** |
---|
427 | * Obtain DBMS specific SQL code portion needed to declare a generic type |
---|
428 | * field to be used in statements like CREATE TABLE. |
---|
429 | * |
---|
430 | * @param string $name name the field to be declared. |
---|
431 | * @param array $field associative array with the name of the properties |
---|
432 | * of the field being declared as array indexes. Currently, the types |
---|
433 | * of supported field properties are as follows: |
---|
434 | * |
---|
435 | * length |
---|
436 | * Integer value that determines the maximum length of the text |
---|
437 | * field. If this argument is missing the field should be |
---|
438 | * declared to have the longest length allowed by the DBMS. |
---|
439 | * |
---|
440 | * default |
---|
441 | * Text value to be used as default for this field. |
---|
442 | * |
---|
443 | * notnull |
---|
444 | * Boolean flag that indicates whether this field is constrained |
---|
445 | * to not be set to null. |
---|
446 | * charset |
---|
447 | * Text value with the default CHARACTER SET for this field. |
---|
448 | * collation |
---|
449 | * Text value with the default COLLATION for this field. |
---|
450 | * @return string DBMS specific SQL code portion that should be used to |
---|
451 | * declare the specified field, or a MDB2_Error on failure |
---|
452 | * @access protected |
---|
453 | */ |
---|
454 | function _getDeclaration($name, $field) |
---|
455 | { |
---|
456 | $db =& $this->getDBInstance(); |
---|
457 | if (PEAR::isError($db)) { |
---|
458 | return $db; |
---|
459 | } |
---|
460 | |
---|
461 | $name = $db->quoteIdentifier($name, true); |
---|
462 | $declaration_options = $db->datatype->_getDeclarationOptions($field); |
---|
463 | if (PEAR::isError($declaration_options)) { |
---|
464 | return $declaration_options; |
---|
465 | } |
---|
466 | return $name.' '.$this->getTypeDeclaration($field).$declaration_options; |
---|
467 | } |
---|
468 | |
---|
469 | // }}} |
---|
470 | // {{{ _getDeclarationOptions() |
---|
471 | |
---|
472 | /** |
---|
473 | * Obtain DBMS specific SQL code portion needed to declare a generic type |
---|
474 | * field to be used in statement like CREATE TABLE, without the field name |
---|
475 | * and type values (ie. just the character set, default value, if the |
---|
476 | * field is permitted to be NULL or not, and the collation options). |
---|
477 | * |
---|
478 | * @param array $field associative array with the name of the properties |
---|
479 | * of the field being declared as array indexes. Currently, the types |
---|
480 | * of supported field properties are as follows: |
---|
481 | * |
---|
482 | * default |
---|
483 | * Text value to be used as default for this field. |
---|
484 | * notnull |
---|
485 | * Boolean flag that indicates whether this field is constrained |
---|
486 | * to not be set to null. |
---|
487 | * charset |
---|
488 | * Text value with the default CHARACTER SET for this field. |
---|
489 | * collation |
---|
490 | * Text value with the default COLLATION for this field. |
---|
491 | * @return string DBMS specific SQL code portion that should be used to |
---|
492 | * declare the specified field's options. |
---|
493 | * @access protected |
---|
494 | */ |
---|
495 | function _getDeclarationOptions($field) |
---|
496 | { |
---|
497 | $charset = empty($field['charset']) ? '' : |
---|
498 | ' '.$this->_getCharsetFieldDeclaration($field['charset']); |
---|
499 | |
---|
500 | $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
---|
501 | $default = ''; |
---|
502 | if (array_key_exists('default', $field)) { |
---|
503 | if ($field['default'] === '') { |
---|
504 | $db =& $this->getDBInstance(); |
---|
505 | if (PEAR::isError($db)) { |
---|
506 | return $db; |
---|
507 | } |
---|
508 | $valid_default_values = $this->getValidTypes(); |
---|
509 | $field['default'] = $valid_default_values[$field['type']]; |
---|
510 | if ($field['default'] === ''&& ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) { |
---|
511 | $field['default'] = ' '; |
---|
512 | } |
---|
513 | } |
---|
514 | if (!is_null($field['default'])) { |
---|
515 | $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']); |
---|
516 | } |
---|
517 | } |
---|
518 | |
---|
519 | $collation = empty($field['collation']) ? '' : |
---|
520 | ' '.$this->_getCollationFieldDeclaration($field['collation']); |
---|
521 | |
---|
522 | return $charset.$default.$notnull.$collation; |
---|
523 | } |
---|
524 | |
---|
525 | // }}} |
---|
526 | // {{{ _getCharsetFieldDeclaration() |
---|
527 | |
---|
528 | /** |
---|
529 | * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET |
---|
530 | * of a field declaration to be used in statements like CREATE TABLE. |
---|
531 | * |
---|
532 | * @param string $charset name of the charset |
---|
533 | * @return string DBMS specific SQL code portion needed to set the CHARACTER SET |
---|
534 | * of a field declaration. |
---|
535 | */ |
---|
536 | function _getCharsetFieldDeclaration($charset) |
---|
537 | { |
---|
538 | return ''; |
---|
539 | } |
---|
540 | |
---|
541 | // }}} |
---|
542 | // {{{ _getCollationFieldDeclaration() |
---|
543 | |
---|
544 | /** |
---|
545 | * Obtain DBMS specific SQL code portion needed to set the COLLATION |
---|
546 | * of a field declaration to be used in statements like CREATE TABLE. |
---|
547 | * |
---|
548 | * @param string $collation name of the collation |
---|
549 | * @return string DBMS specific SQL code portion needed to set the COLLATION |
---|
550 | * of a field declaration. |
---|
551 | */ |
---|
552 | function _getCollationFieldDeclaration($collation) |
---|
553 | { |
---|
554 | return ''; |
---|
555 | } |
---|
556 | |
---|
557 | // }}} |
---|
558 | // {{{ _getIntegerDeclaration() |
---|
559 | |
---|
560 | /** |
---|
561 | * Obtain DBMS specific SQL code portion needed to declare an integer type |
---|
562 | * field to be used in statements like CREATE TABLE. |
---|
563 | * |
---|
564 | * @param string $name name the field to be declared. |
---|
565 | * @param array $field associative array with the name of the properties |
---|
566 | * of the field being declared as array indexes. Currently, the types |
---|
567 | * of supported field properties are as follows: |
---|
568 | * |
---|
569 | * unsigned |
---|
570 | * Boolean flag that indicates whether the field should be |
---|
571 | * declared as unsigned integer if possible. |
---|
572 | * |
---|
573 | * default |
---|
574 | * Integer value to be used as default for this field. |
---|
575 | * |
---|
576 | * notnull |
---|
577 | * Boolean flag that indicates whether this field is constrained |
---|
578 | * to not be set to null. |
---|
579 | * @return string DBMS specific SQL code portion that should be used to |
---|
580 | * declare the specified field. |
---|
581 | * @access protected |
---|
582 | */ |
---|
583 | function _getIntegerDeclaration($name, $field) |
---|
584 | { |
---|
585 | if (!empty($field['unsigned'])) { |
---|
586 | $db =& $this->getDBInstance(); |
---|
587 | if (PEAR::isError($db)) { |
---|
588 | return $db; |
---|
589 | } |
---|
590 | |
---|
591 | $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; |
---|
592 | } |
---|
593 | return $this->_getDeclaration($name, $field); |
---|
594 | } |
---|
595 | |
---|
596 | // }}} |
---|
597 | // {{{ _getTextDeclaration() |
---|
598 | |
---|
599 | /** |
---|
600 | * Obtain DBMS specific SQL code portion needed to declare an text type |
---|
601 | * field to be used in statements like CREATE TABLE. |
---|
602 | * |
---|
603 | * @param string $name name the field to be declared. |
---|
604 | * @param array $field associative array with the name of the properties |
---|
605 | * of the field being declared as array indexes. Currently, the types |
---|
606 | * of supported field properties are as follows: |
---|
607 | * |
---|
608 | * length |
---|
609 | * Integer value that determines the maximum length of the text |
---|
610 | * field. If this argument is missing the field should be |
---|
611 | * declared to have the longest length allowed by the DBMS. |
---|
612 | * |
---|
613 | * default |
---|
614 | * Text value to be used as default for this field. |
---|
615 | * |
---|
616 | * notnull |
---|
617 | * Boolean flag that indicates whether this field is constrained |
---|
618 | * to not be set to null. |
---|
619 | * @return string DBMS specific SQL code portion that should be used to |
---|
620 | * declare the specified field. |
---|
621 | * @access protected |
---|
622 | */ |
---|
623 | function _getTextDeclaration($name, $field) |
---|
624 | { |
---|
625 | return $this->_getDeclaration($name, $field); |
---|
626 | } |
---|
627 | |
---|
628 | // }}} |
---|
629 | // {{{ _getCLOBDeclaration() |
---|
630 | |
---|
631 | /** |
---|
632 | * Obtain DBMS specific SQL code portion needed to declare an character |
---|
633 | * large object type field to be used in statements like CREATE TABLE. |
---|
634 | * |
---|
635 | * @param string $name name the field to be declared. |
---|
636 | * @param array $field associative array with the name of the properties |
---|
637 | * of the field being declared as array indexes. Currently, the types |
---|
638 | * of supported field properties are as follows: |
---|
639 | * |
---|
640 | * length |
---|
641 | * Integer value that determines the maximum length of the large |
---|
642 | * object field. If this argument is missing the field should be |
---|
643 | * declared to have the longest length allowed by the DBMS. |
---|
644 | * |
---|
645 | * notnull |
---|
646 | * Boolean flag that indicates whether this field is constrained |
---|
647 | * to not be set to null. |
---|
648 | * @return string DBMS specific SQL code portion that should be used to |
---|
649 | * declare the specified field. |
---|
650 | * @access public |
---|
651 | */ |
---|
652 | function _getCLOBDeclaration($name, $field) |
---|
653 | { |
---|
654 | $db =& $this->getDBInstance(); |
---|
655 | if (PEAR::isError($db)) { |
---|
656 | return $db; |
---|
657 | } |
---|
658 | |
---|
659 | $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
---|
660 | $name = $db->quoteIdentifier($name, true); |
---|
661 | return $name.' '.$this->getTypeDeclaration($field).$notnull; |
---|
662 | } |
---|
663 | |
---|
664 | // }}} |
---|
665 | // {{{ _getBLOBDeclaration() |
---|
666 | |
---|
667 | /** |
---|
668 | * Obtain DBMS specific SQL code portion needed to declare an binary large |
---|
669 | * object type field to be used in statements like CREATE TABLE. |
---|
670 | * |
---|
671 | * @param string $name name the field to be declared. |
---|
672 | * @param array $field associative array with the name of the properties |
---|
673 | * of the field being declared as array indexes. Currently, the types |
---|
674 | * of supported field properties are as follows: |
---|
675 | * |
---|
676 | * length |
---|
677 | * Integer value that determines the maximum length of the large |
---|
678 | * object field. If this argument is missing the field should be |
---|
679 | * declared to have the longest length allowed by the DBMS. |
---|
680 | * |
---|
681 | * notnull |
---|
682 | * Boolean flag that indicates whether this field is constrained |
---|
683 | * to not be set to null. |
---|
684 | * @return string DBMS specific SQL code portion that should be used to |
---|
685 | * declare the specified field. |
---|
686 | * @access protected |
---|
687 | */ |
---|
688 | function _getBLOBDeclaration($name, $field) |
---|
689 | { |
---|
690 | $db =& $this->getDBInstance(); |
---|
691 | if (PEAR::isError($db)) { |
---|
692 | return $db; |
---|
693 | } |
---|
694 | |
---|
695 | $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
---|
696 | $name = $db->quoteIdentifier($name, true); |
---|
697 | return $name.' '.$this->getTypeDeclaration($field).$notnull; |
---|
698 | } |
---|
699 | |
---|
700 | // }}} |
---|
701 | // {{{ _getBooleanDeclaration() |
---|
702 | |
---|
703 | /** |
---|
704 | * Obtain DBMS specific SQL code portion needed to declare a boolean type |
---|
705 | * field to be used in statements like CREATE TABLE. |
---|
706 | * |
---|
707 | * @param string $name name the field to be declared. |
---|
708 | * @param array $field associative array with the name of the properties |
---|
709 | * of the field being declared as array indexes. Currently, the types |
---|
710 | * of supported field properties are as follows: |
---|
711 | * |
---|
712 | * default |
---|
713 | * Boolean value to be used as default for this field. |
---|
714 | * |
---|
715 | * notnullL |
---|
716 | * Boolean flag that indicates whether this field is constrained |
---|
717 | * to not be set to null. |
---|
718 | * @return string DBMS specific SQL code portion that should be used to |
---|
719 | * declare the specified field. |
---|
720 | * @access protected |
---|
721 | */ |
---|
722 | function _getBooleanDeclaration($name, $field) |
---|
723 | { |
---|
724 | return $this->_getDeclaration($name, $field); |
---|
725 | } |
---|
726 | |
---|
727 | // }}} |
---|
728 | // {{{ _getDateDeclaration() |
---|
729 | |
---|
730 | /** |
---|
731 | * Obtain DBMS specific SQL code portion needed to declare a date type |
---|
732 | * field to be used in statements like CREATE TABLE. |
---|
733 | * |
---|
734 | * @param string $name name the field to be declared. |
---|
735 | * @param array $field associative array with the name of the properties |
---|
736 | * of the field being declared as array indexes. Currently, the types |
---|
737 | * of supported field properties are as follows: |
---|
738 | * |
---|
739 | * default |
---|
740 | * Date value to be used as default for this field. |
---|
741 | * |
---|
742 | * notnull |
---|
743 | * Boolean flag that indicates whether this field is constrained |
---|
744 | * to not be set to null. |
---|
745 | * @return string DBMS specific SQL code portion that should be used to |
---|
746 | * declare the specified field. |
---|
747 | * @access protected |
---|
748 | */ |
---|
749 | function _getDateDeclaration($name, $field) |
---|
750 | { |
---|
751 | return $this->_getDeclaration($name, $field); |
---|
752 | } |
---|
753 | |
---|
754 | // }}} |
---|
755 | // {{{ _getTimestampDeclaration() |
---|
756 | |
---|
757 | /** |
---|
758 | * Obtain DBMS specific SQL code portion needed to declare a timestamp |
---|
759 | * field to be used in statements like CREATE TABLE. |
---|
760 | * |
---|
761 | * @param string $name name the field to be declared. |
---|
762 | * @param array $field associative array with the name of the properties |
---|
763 | * of the field being declared as array indexes. Currently, the types |
---|
764 | * of supported field properties are as follows: |
---|
765 | * |
---|
766 | * default |
---|
767 | * Timestamp value to be used as default for this field. |
---|
768 | * |
---|
769 | * notnull |
---|
770 | * Boolean flag that indicates whether this field is constrained |
---|
771 | * to not be set to null. |
---|
772 | * @return string DBMS specific SQL code portion that should be used to |
---|
773 | * declare the specified field. |
---|
774 | * @access protected |
---|
775 | */ |
---|
776 | function _getTimestampDeclaration($name, $field) |
---|
777 | { |
---|
778 | return $this->_getDeclaration($name, $field); |
---|
779 | } |
---|
780 | |
---|
781 | // }}} |
---|
782 | // {{{ _getTimeDeclaration() |
---|
783 | |
---|
784 | /** |
---|
785 | * Obtain DBMS specific SQL code portion needed to declare a time |
---|
786 | * field to be used in statements like CREATE TABLE. |
---|
787 | * |
---|
788 | * @param string $name name the field to be declared. |
---|
789 | * @param array $field associative array with the name of the properties |
---|
790 | * of the field being declared as array indexes. Currently, the types |
---|
791 | * of supported field properties are as follows: |
---|
792 | * |
---|
793 | * default |
---|
794 | * Time value to be used as default for this field. |
---|
795 | * |
---|
796 | * notnull |
---|
797 | * Boolean flag that indicates whether this field is constrained |
---|
798 | * to not be set to null. |
---|
799 | * @return string DBMS specific SQL code portion that should be used to |
---|
800 | * declare the specified field. |
---|
801 | * @access protected |
---|
802 | */ |
---|
803 | function _getTimeDeclaration($name, $field) |
---|
804 | { |
---|
805 | return $this->_getDeclaration($name, $field); |
---|
806 | } |
---|
807 | |
---|
808 | // }}} |
---|
809 | // {{{ _getFloatDeclaration() |
---|
810 | |
---|
811 | /** |
---|
812 | * Obtain DBMS specific SQL code portion needed to declare a float type |
---|
813 | * field to be used in statements like CREATE TABLE. |
---|
814 | * |
---|
815 | * @param string $name name the field to be declared. |
---|
816 | * @param array $field associative array with the name of the properties |
---|
817 | * of the field being declared as array indexes. Currently, the types |
---|
818 | * of supported field properties are as follows: |
---|
819 | * |
---|
820 | * default |
---|
821 | * Float value to be used as default for this field. |
---|
822 | * |
---|
823 | * notnull |
---|
824 | * Boolean flag that indicates whether this field is constrained |
---|
825 | * to not be set to null. |
---|
826 | * @return string DBMS specific SQL code portion that should be used to |
---|
827 | * declare the specified field. |
---|
828 | * @access protected |
---|
829 | */ |
---|
830 | function _getFloatDeclaration($name, $field) |
---|
831 | { |
---|
832 | return $this->_getDeclaration($name, $field); |
---|
833 | } |
---|
834 | |
---|
835 | // }}} |
---|
836 | // {{{ _getDecimalDeclaration() |
---|
837 | |
---|
838 | /** |
---|
839 | * Obtain DBMS specific SQL code portion needed to declare a decimal type |
---|
840 | * field to be used in statements like CREATE TABLE. |
---|
841 | * |
---|
842 | * @param string $name name the field to be declared. |
---|
843 | * @param array $field associative array with the name of the properties |
---|
844 | * of the field being declared as array indexes. Currently, the types |
---|
845 | * of supported field properties are as follows: |
---|
846 | * |
---|
847 | * default |
---|
848 | * Decimal value to be used as default for this field. |
---|
849 | * |
---|
850 | * notnull |
---|
851 | * Boolean flag that indicates whether this field is constrained |
---|
852 | * to not be set to null. |
---|
853 | * @return string DBMS specific SQL code portion that should be used to |
---|
854 | * declare the specified field. |
---|
855 | * @access protected |
---|
856 | */ |
---|
857 | function _getDecimalDeclaration($name, $field) |
---|
858 | { |
---|
859 | return $this->_getDeclaration($name, $field); |
---|
860 | } |
---|
861 | |
---|
862 | // }}} |
---|
863 | // {{{ compareDefinition() |
---|
864 | |
---|
865 | /** |
---|
866 | * Obtain an array of changes that may need to applied |
---|
867 | * |
---|
868 | * @param array $current new definition |
---|
869 | * @param array $previous old definition |
---|
870 | * @return array containing all changes that will need to be applied |
---|
871 | * @access public |
---|
872 | */ |
---|
873 | function compareDefinition($current, $previous) |
---|
874 | { |
---|
875 | $type = !empty($current['type']) ? $current['type'] : null; |
---|
876 | |
---|
877 | if (!method_exists($this, "_compare{$type}Definition")) { |
---|
878 | $db =& $this->getDBInstance(); |
---|
879 | if (PEAR::isError($db)) { |
---|
880 | return $db; |
---|
881 | } |
---|
882 | if (!empty($db->options['datatype_map_callback'][$type])) { |
---|
883 | $parameter = array('current' => $current, 'previous' => $previous); |
---|
884 | $change = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
885 | return $change; |
---|
886 | } |
---|
887 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
888 | 'type "'.$current['type'].'" is not yet supported', __FUNCTION__); |
---|
889 | } |
---|
890 | |
---|
891 | if (empty($previous['type']) || $previous['type'] != $type) { |
---|
892 | return $current; |
---|
893 | } |
---|
894 | |
---|
895 | $change = $this->{"_compare{$type}Definition"}($current, $previous); |
---|
896 | |
---|
897 | if ($previous['type'] != $type) { |
---|
898 | $change['type'] = true; |
---|
899 | } |
---|
900 | |
---|
901 | $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false; |
---|
902 | $notnull = !empty($current['notnull']) ? $current['notnull'] : false; |
---|
903 | if ($previous_notnull != $notnull) { |
---|
904 | $change['notnull'] = true; |
---|
905 | } |
---|
906 | |
---|
907 | $previous_default = array_key_exists('default', $previous) ? $previous['default'] : |
---|
908 | ($previous_notnull ? '' : null); |
---|
909 | $default = array_key_exists('default', $current) ? $current['default'] : |
---|
910 | ($notnull ? '' : null); |
---|
911 | if ($previous_default !== $default) { |
---|
912 | $change['default'] = true; |
---|
913 | } |
---|
914 | |
---|
915 | return $change; |
---|
916 | } |
---|
917 | |
---|
918 | // }}} |
---|
919 | // {{{ _compareIntegerDefinition() |
---|
920 | |
---|
921 | /** |
---|
922 | * Obtain an array of changes that may need to applied to an integer field |
---|
923 | * |
---|
924 | * @param array $current new definition |
---|
925 | * @param array $previous old definition |
---|
926 | * @return array containing all changes that will need to be applied |
---|
927 | * @access protected |
---|
928 | */ |
---|
929 | function _compareIntegerDefinition($current, $previous) |
---|
930 | { |
---|
931 | $change = array(); |
---|
932 | $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false; |
---|
933 | $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false; |
---|
934 | if ($previous_unsigned != $unsigned) { |
---|
935 | $change['unsigned'] = true; |
---|
936 | } |
---|
937 | $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false; |
---|
938 | $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false; |
---|
939 | if ($previous_autoincrement != $autoincrement) { |
---|
940 | $change['autoincrement'] = true; |
---|
941 | } |
---|
942 | return $change; |
---|
943 | } |
---|
944 | |
---|
945 | // }}} |
---|
946 | // {{{ _compareTextDefinition() |
---|
947 | |
---|
948 | /** |
---|
949 | * Obtain an array of changes that may need to applied to an text field |
---|
950 | * |
---|
951 | * @param array $current new definition |
---|
952 | * @param array $previous old definition |
---|
953 | * @return array containing all changes that will need to be applied |
---|
954 | * @access protected |
---|
955 | */ |
---|
956 | function _compareTextDefinition($current, $previous) |
---|
957 | { |
---|
958 | $change = array(); |
---|
959 | $previous_length = !empty($previous['length']) ? $previous['length'] : 0; |
---|
960 | $length = !empty($current['length']) ? $current['length'] : 0; |
---|
961 | if ($previous_length != $length) { |
---|
962 | $change['length'] = true; |
---|
963 | } |
---|
964 | $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0; |
---|
965 | $fixed = !empty($current['fixed']) ? $current['fixed'] : 0; |
---|
966 | if ($previous_fixed != $fixed) { |
---|
967 | $change['fixed'] = true; |
---|
968 | } |
---|
969 | return $change; |
---|
970 | } |
---|
971 | |
---|
972 | // }}} |
---|
973 | // {{{ _compareCLOBDefinition() |
---|
974 | |
---|
975 | /** |
---|
976 | * Obtain an array of changes that may need to applied to an CLOB field |
---|
977 | * |
---|
978 | * @param array $current new definition |
---|
979 | * @param array $previous old definition |
---|
980 | * @return array containing all changes that will need to be applied |
---|
981 | * @access protected |
---|
982 | */ |
---|
983 | function _compareCLOBDefinition($current, $previous) |
---|
984 | { |
---|
985 | return $this->_compareTextDefinition($current, $previous); |
---|
986 | } |
---|
987 | |
---|
988 | // }}} |
---|
989 | // {{{ _compareBLOBDefinition() |
---|
990 | |
---|
991 | /** |
---|
992 | * Obtain an array of changes that may need to applied to an BLOB field |
---|
993 | * |
---|
994 | * @param array $current new definition |
---|
995 | * @param array $previous old definition |
---|
996 | * @return array containing all changes that will need to be applied |
---|
997 | * @access protected |
---|
998 | */ |
---|
999 | function _compareBLOBDefinition($current, $previous) |
---|
1000 | { |
---|
1001 | return $this->_compareTextDefinition($current, $previous); |
---|
1002 | } |
---|
1003 | |
---|
1004 | // }}} |
---|
1005 | // {{{ _compareDateDefinition() |
---|
1006 | |
---|
1007 | /** |
---|
1008 | * Obtain an array of changes that may need to applied to an date field |
---|
1009 | * |
---|
1010 | * @param array $current new definition |
---|
1011 | * @param array $previous old definition |
---|
1012 | * @return array containing all changes that will need to be applied |
---|
1013 | * @access protected |
---|
1014 | */ |
---|
1015 | function _compareDateDefinition($current, $previous) |
---|
1016 | { |
---|
1017 | return array(); |
---|
1018 | } |
---|
1019 | |
---|
1020 | // }}} |
---|
1021 | // {{{ _compareTimeDefinition() |
---|
1022 | |
---|
1023 | /** |
---|
1024 | * Obtain an array of changes that may need to applied to an time field |
---|
1025 | * |
---|
1026 | * @param array $current new definition |
---|
1027 | * @param array $previous old definition |
---|
1028 | * @return array containing all changes that will need to be applied |
---|
1029 | * @access protected |
---|
1030 | */ |
---|
1031 | function _compareTimeDefinition($current, $previous) |
---|
1032 | { |
---|
1033 | return array(); |
---|
1034 | } |
---|
1035 | |
---|
1036 | // }}} |
---|
1037 | // {{{ _compareTimestampDefinition() |
---|
1038 | |
---|
1039 | /** |
---|
1040 | * Obtain an array of changes that may need to applied to an timestamp field |
---|
1041 | * |
---|
1042 | * @param array $current new definition |
---|
1043 | * @param array $previous old definition |
---|
1044 | * @return array containing all changes that will need to be applied |
---|
1045 | * @access protected |
---|
1046 | */ |
---|
1047 | function _compareTimestampDefinition($current, $previous) |
---|
1048 | { |
---|
1049 | return array(); |
---|
1050 | } |
---|
1051 | |
---|
1052 | // }}} |
---|
1053 | // {{{ _compareBooleanDefinition() |
---|
1054 | |
---|
1055 | /** |
---|
1056 | * Obtain an array of changes that may need to applied to an boolean field |
---|
1057 | * |
---|
1058 | * @param array $current new definition |
---|
1059 | * @param array $previous old definition |
---|
1060 | * @return array containing all changes that will need to be applied |
---|
1061 | * @access protected |
---|
1062 | */ |
---|
1063 | function _compareBooleanDefinition($current, $previous) |
---|
1064 | { |
---|
1065 | return array(); |
---|
1066 | } |
---|
1067 | |
---|
1068 | // }}} |
---|
1069 | // {{{ _compareFloatDefinition() |
---|
1070 | |
---|
1071 | /** |
---|
1072 | * Obtain an array of changes that may need to applied to an float field |
---|
1073 | * |
---|
1074 | * @param array $current new definition |
---|
1075 | * @param array $previous old definition |
---|
1076 | * @return array containing all changes that will need to be applied |
---|
1077 | * @access protected |
---|
1078 | */ |
---|
1079 | function _compareFloatDefinition($current, $previous) |
---|
1080 | { |
---|
1081 | return array(); |
---|
1082 | } |
---|
1083 | |
---|
1084 | // }}} |
---|
1085 | // {{{ _compareDecimalDefinition() |
---|
1086 | |
---|
1087 | /** |
---|
1088 | * Obtain an array of changes that may need to applied to an decimal field |
---|
1089 | * |
---|
1090 | * @param array $current new definition |
---|
1091 | * @param array $previous old definition |
---|
1092 | * @return array containing all changes that will need to be applied |
---|
1093 | * @access protected |
---|
1094 | */ |
---|
1095 | function _compareDecimalDefinition($current, $previous) |
---|
1096 | { |
---|
1097 | return array(); |
---|
1098 | } |
---|
1099 | |
---|
1100 | // }}} |
---|
1101 | // {{{ quote() |
---|
1102 | |
---|
1103 | /** |
---|
1104 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1105 | * compose query statements. |
---|
1106 | * |
---|
1107 | * @param string $value text string value that is intended to be converted. |
---|
1108 | * @param string $type type to which the value should be converted to |
---|
1109 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1110 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1111 | * @return string text string that represents the given argument value in |
---|
1112 | * a DBMS specific format. |
---|
1113 | * @access public |
---|
1114 | */ |
---|
1115 | function quote($value, $type = null, $quote = true, $escape_wildcards = false) |
---|
1116 | { |
---|
1117 | $db =& $this->getDBInstance(); |
---|
1118 | if (PEAR::isError($db)) { |
---|
1119 | return $db; |
---|
1120 | } |
---|
1121 | |
---|
1122 | if (is_null($value) |
---|
1123 | || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL) |
---|
1124 | ) { |
---|
1125 | if (!$quote) { |
---|
1126 | return null; |
---|
1127 | } |
---|
1128 | return 'NULL'; |
---|
1129 | } |
---|
1130 | |
---|
1131 | if (is_null($type)) { |
---|
1132 | switch (gettype($value)) { |
---|
1133 | case 'integer': |
---|
1134 | $type = 'integer'; |
---|
1135 | break; |
---|
1136 | case 'double': |
---|
1137 | // todo: default to decimal as float is quite unusual |
---|
1138 | // $type = 'float'; |
---|
1139 | $type = 'decimal'; |
---|
1140 | break; |
---|
1141 | case 'boolean': |
---|
1142 | $type = 'boolean'; |
---|
1143 | break; |
---|
1144 | case 'array': |
---|
1145 | $value = serialize($value); |
---|
1146 | case 'object': |
---|
1147 | $type = 'text'; |
---|
1148 | break; |
---|
1149 | default: |
---|
1150 | if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) { |
---|
1151 | $type = 'timestamp'; |
---|
1152 | } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) { |
---|
1153 | $type = 'time'; |
---|
1154 | } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { |
---|
1155 | $type = 'date'; |
---|
1156 | } else { |
---|
1157 | $type = 'text'; |
---|
1158 | } |
---|
1159 | break; |
---|
1160 | } |
---|
1161 | } elseif (!empty($db->options['datatype_map'][$type])) { |
---|
1162 | $type = $db->options['datatype_map'][$type]; |
---|
1163 | if (!empty($db->options['datatype_map_callback'][$type])) { |
---|
1164 | $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards); |
---|
1165 | return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
1166 | } |
---|
1167 | } |
---|
1168 | |
---|
1169 | if (!method_exists($this, "_quote{$type}")) { |
---|
1170 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
1171 | 'type not defined: '.$type, __FUNCTION__); |
---|
1172 | } |
---|
1173 | $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards); |
---|
1174 | if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern'] |
---|
1175 | && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern'] |
---|
1176 | ) { |
---|
1177 | $value.= $this->patternEscapeString(); |
---|
1178 | } |
---|
1179 | return $value; |
---|
1180 | } |
---|
1181 | |
---|
1182 | // }}} |
---|
1183 | // {{{ _quoteInteger() |
---|
1184 | |
---|
1185 | /** |
---|
1186 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1187 | * compose query statements. |
---|
1188 | * |
---|
1189 | * @param string $value text string value that is intended to be converted. |
---|
1190 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1191 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1192 | * @return string text string that represents the given argument value in |
---|
1193 | * a DBMS specific format. |
---|
1194 | * @access protected |
---|
1195 | */ |
---|
1196 | function _quoteInteger($value, $quote, $escape_wildcards) |
---|
1197 | { |
---|
1198 | return (int)$value; |
---|
1199 | } |
---|
1200 | |
---|
1201 | // }}} |
---|
1202 | // {{{ _quoteText() |
---|
1203 | |
---|
1204 | /** |
---|
1205 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1206 | * compose query statements. |
---|
1207 | * |
---|
1208 | * @param string $value text string value that is intended to be converted. |
---|
1209 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1210 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1211 | * @return string text string that already contains any DBMS specific |
---|
1212 | * escaped character sequences. |
---|
1213 | * @access protected |
---|
1214 | */ |
---|
1215 | function _quoteText($value, $quote, $escape_wildcards) |
---|
1216 | { |
---|
1217 | if (!$quote) { |
---|
1218 | return $value; |
---|
1219 | } |
---|
1220 | |
---|
1221 | $db =& $this->getDBInstance(); |
---|
1222 | if (PEAR::isError($db)) { |
---|
1223 | return $db; |
---|
1224 | } |
---|
1225 | |
---|
1226 | $value = $db->escape($value, $escape_wildcards); |
---|
1227 | if (PEAR::isError($value)) { |
---|
1228 | return $value; |
---|
1229 | } |
---|
1230 | return "'".$value."'"; |
---|
1231 | } |
---|
1232 | |
---|
1233 | // }}} |
---|
1234 | // {{{ _readFile() |
---|
1235 | |
---|
1236 | /** |
---|
1237 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1238 | * compose query statements. |
---|
1239 | * |
---|
1240 | * @param string $value text string value that is intended to be converted. |
---|
1241 | * @return string text string that represents the given argument value in |
---|
1242 | * a DBMS specific format. |
---|
1243 | * @access protected |
---|
1244 | */ |
---|
1245 | function _readFile($value) |
---|
1246 | { |
---|
1247 | $close = false; |
---|
1248 | if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { |
---|
1249 | $close = true; |
---|
1250 | if ($match[1] == 'file://') { |
---|
1251 | $value = $match[2]; |
---|
1252 | } |
---|
1253 | $value = @fopen($value, 'r'); |
---|
1254 | } |
---|
1255 | |
---|
1256 | if (is_resource($value)) { |
---|
1257 | $db =& $this->getDBInstance(); |
---|
1258 | if (PEAR::isError($db)) { |
---|
1259 | return $db; |
---|
1260 | } |
---|
1261 | |
---|
1262 | $fp = $value; |
---|
1263 | $value = ''; |
---|
1264 | while (!@feof($fp)) { |
---|
1265 | $value.= @fread($fp, $db->options['lob_buffer_length']); |
---|
1266 | } |
---|
1267 | if ($close) { |
---|
1268 | @fclose($fp); |
---|
1269 | } |
---|
1270 | } |
---|
1271 | |
---|
1272 | return $value; |
---|
1273 | } |
---|
1274 | |
---|
1275 | // }}} |
---|
1276 | // {{{ _quoteLOB() |
---|
1277 | |
---|
1278 | /** |
---|
1279 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1280 | * compose query statements. |
---|
1281 | * |
---|
1282 | * @param string $value text string value that is intended to be converted. |
---|
1283 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1284 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1285 | * @return string text string that represents the given argument value in |
---|
1286 | * a DBMS specific format. |
---|
1287 | * @access protected |
---|
1288 | */ |
---|
1289 | function _quoteLOB($value, $quote, $escape_wildcards) |
---|
1290 | { |
---|
1291 | $value = $this->_readFile($value); |
---|
1292 | if (PEAR::isError($value)) { |
---|
1293 | return $value; |
---|
1294 | } |
---|
1295 | return $this->_quoteText($value, $quote, $escape_wildcards); |
---|
1296 | } |
---|
1297 | |
---|
1298 | // }}} |
---|
1299 | // {{{ _quoteCLOB() |
---|
1300 | |
---|
1301 | /** |
---|
1302 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1303 | * compose query statements. |
---|
1304 | * |
---|
1305 | * @param string $value text string value that is intended to be converted. |
---|
1306 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1307 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1308 | * @return string text string that represents the given argument value in |
---|
1309 | * a DBMS specific format. |
---|
1310 | * @access protected |
---|
1311 | */ |
---|
1312 | function _quoteCLOB($value, $quote, $escape_wildcards) |
---|
1313 | { |
---|
1314 | return $this->_quoteLOB($value, $quote, $escape_wildcards); |
---|
1315 | } |
---|
1316 | |
---|
1317 | // }}} |
---|
1318 | // {{{ _quoteBLOB() |
---|
1319 | |
---|
1320 | /** |
---|
1321 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1322 | * compose query statements. |
---|
1323 | * |
---|
1324 | * @param string $value text string value that is intended to be converted. |
---|
1325 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1326 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1327 | * @return string text string that represents the given argument value in |
---|
1328 | * a DBMS specific format. |
---|
1329 | * @access protected |
---|
1330 | */ |
---|
1331 | function _quoteBLOB($value, $quote, $escape_wildcards) |
---|
1332 | { |
---|
1333 | return $this->_quoteLOB($value, $quote, $escape_wildcards); |
---|
1334 | } |
---|
1335 | |
---|
1336 | // }}} |
---|
1337 | // {{{ _quoteBoolean() |
---|
1338 | |
---|
1339 | /** |
---|
1340 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1341 | * compose query statements. |
---|
1342 | * |
---|
1343 | * @param string $value text string value that is intended to be converted. |
---|
1344 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1345 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1346 | * @return string text string that represents the given argument value in |
---|
1347 | * a DBMS specific format. |
---|
1348 | * @access protected |
---|
1349 | */ |
---|
1350 | function _quoteBoolean($value, $quote, $escape_wildcards) |
---|
1351 | { |
---|
1352 | return ($value ? 1 : 0); |
---|
1353 | } |
---|
1354 | |
---|
1355 | // }}} |
---|
1356 | // {{{ _quoteDate() |
---|
1357 | |
---|
1358 | /** |
---|
1359 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1360 | * compose query statements. |
---|
1361 | * |
---|
1362 | * @param string $value text string value that is intended to be converted. |
---|
1363 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1364 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1365 | * @return string text string that represents the given argument value in |
---|
1366 | * a DBMS specific format. |
---|
1367 | * @access protected |
---|
1368 | */ |
---|
1369 | function _quoteDate($value, $quote, $escape_wildcards) |
---|
1370 | { |
---|
1371 | if ($value === 'CURRENT_DATE') { |
---|
1372 | $db =& $this->getDBInstance(); |
---|
1373 | if (PEAR::isError($db)) { |
---|
1374 | return $db; |
---|
1375 | } |
---|
1376 | if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { |
---|
1377 | return $db->function->now('date'); |
---|
1378 | } |
---|
1379 | return 'CURRENT_DATE'; |
---|
1380 | } |
---|
1381 | return $this->_quoteText($value, $quote, $escape_wildcards); |
---|
1382 | } |
---|
1383 | |
---|
1384 | // }}} |
---|
1385 | // {{{ _quoteTimestamp() |
---|
1386 | |
---|
1387 | /** |
---|
1388 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1389 | * compose query statements. |
---|
1390 | * |
---|
1391 | * @param string $value text string value that is intended to be converted. |
---|
1392 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1393 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1394 | * @return string text string that represents the given argument value in |
---|
1395 | * a DBMS specific format. |
---|
1396 | * @access protected |
---|
1397 | */ |
---|
1398 | function _quoteTimestamp($value, $quote, $escape_wildcards) |
---|
1399 | { |
---|
1400 | if ($value === 'CURRENT_TIMESTAMP') { |
---|
1401 | $db =& $this->getDBInstance(); |
---|
1402 | if (PEAR::isError($db)) { |
---|
1403 | return $db; |
---|
1404 | } |
---|
1405 | if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { |
---|
1406 | return $db->function->now('timestamp'); |
---|
1407 | } |
---|
1408 | return 'CURRENT_TIMESTAMP'; |
---|
1409 | } |
---|
1410 | return $this->_quoteText($value, $quote, $escape_wildcards); |
---|
1411 | } |
---|
1412 | |
---|
1413 | // }}} |
---|
1414 | // {{{ _quoteTime() |
---|
1415 | |
---|
1416 | /** |
---|
1417 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1418 | * compose query statements. |
---|
1419 | * |
---|
1420 | * @param string $value text string value that is intended to be converted. |
---|
1421 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1422 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1423 | * @return string text string that represents the given argument value in |
---|
1424 | * a DBMS specific format. |
---|
1425 | * @access protected |
---|
1426 | */ |
---|
1427 | function _quoteTime($value, $quote, $escape_wildcards) |
---|
1428 | { |
---|
1429 | if ($value === 'CURRENT_TIME') { |
---|
1430 | $db =& $this->getDBInstance(); |
---|
1431 | if (PEAR::isError($db)) { |
---|
1432 | return $db; |
---|
1433 | } |
---|
1434 | if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { |
---|
1435 | return $db->function->now('time'); |
---|
1436 | } |
---|
1437 | return 'CURRENT_TIME'; |
---|
1438 | } |
---|
1439 | return $this->_quoteText($value, $quote, $escape_wildcards); |
---|
1440 | } |
---|
1441 | |
---|
1442 | // }}} |
---|
1443 | // {{{ _quoteFloat() |
---|
1444 | |
---|
1445 | /** |
---|
1446 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1447 | * compose query statements. |
---|
1448 | * |
---|
1449 | * @param string $value text string value that is intended to be converted. |
---|
1450 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1451 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1452 | * @return string text string that represents the given argument value in |
---|
1453 | * a DBMS specific format. |
---|
1454 | * @access protected |
---|
1455 | */ |
---|
1456 | function _quoteFloat($value, $quote, $escape_wildcards) |
---|
1457 | { |
---|
1458 | if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) { |
---|
1459 | $decimal = $this->_quoteDecimal($matches[1], $quote, $escape_wildcards); |
---|
1460 | $sign = $matches[2]; |
---|
1461 | $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT); |
---|
1462 | $value = $decimal.'E'.$sign.$exponent; |
---|
1463 | } else { |
---|
1464 | $value = $this->_quoteDecimal($value, $quote, $escape_wildcards); |
---|
1465 | } |
---|
1466 | return $value; |
---|
1467 | } |
---|
1468 | |
---|
1469 | // }}} |
---|
1470 | // {{{ _quoteDecimal() |
---|
1471 | |
---|
1472 | /** |
---|
1473 | * Convert a text value into a DBMS specific format that is suitable to |
---|
1474 | * compose query statements. |
---|
1475 | * |
---|
1476 | * @param string $value text string value that is intended to be converted. |
---|
1477 | * @param bool $quote determines if the value should be quoted and escaped |
---|
1478 | * @param bool $escape_wildcards if to escape escape wildcards |
---|
1479 | * @return string text string that represents the given argument value in |
---|
1480 | * a DBMS specific format. |
---|
1481 | * @access protected |
---|
1482 | */ |
---|
1483 | function _quoteDecimal($value, $quote, $escape_wildcards) |
---|
1484 | { |
---|
1485 | $value = (string)$value; |
---|
1486 | $value = preg_replace('/[^\d\.,\-+eE]/', '', $value); |
---|
1487 | if (preg_match('/[^\.\d]/', $value)) { |
---|
1488 | if (strpos($value, ',')) { |
---|
1489 | // 1000,00 |
---|
1490 | if (!strpos($value, '.')) { |
---|
1491 | // convert the last "," to a "." |
---|
1492 | $value = strrev(str_replace(',', '.', strrev($value))); |
---|
1493 | // 1.000,00 |
---|
1494 | } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) { |
---|
1495 | $value = str_replace('.', '', $value); |
---|
1496 | // convert the last "," to a "." |
---|
1497 | $value = strrev(str_replace(',', '.', strrev($value))); |
---|
1498 | // 1,000.00 |
---|
1499 | } else { |
---|
1500 | $value = str_replace(',', '', $value); |
---|
1501 | } |
---|
1502 | } |
---|
1503 | } |
---|
1504 | return $value; |
---|
1505 | } |
---|
1506 | |
---|
1507 | // }}} |
---|
1508 | // {{{ writeLOBToFile() |
---|
1509 | |
---|
1510 | /** |
---|
1511 | * retrieve LOB from the database |
---|
1512 | * |
---|
1513 | * @param resource $lob stream handle |
---|
1514 | * @param string $file name of the file into which the LOb should be fetched |
---|
1515 | * @return mixed MDB2_OK on success, a MDB2 error on failure |
---|
1516 | * @access protected |
---|
1517 | */ |
---|
1518 | function writeLOBToFile($lob, $file) |
---|
1519 | { |
---|
1520 | $db =& $this->getDBInstance(); |
---|
1521 | if (PEAR::isError($db)) { |
---|
1522 | return $db; |
---|
1523 | } |
---|
1524 | |
---|
1525 | if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) { |
---|
1526 | if ($match[1] == 'file://') { |
---|
1527 | $file = $match[2]; |
---|
1528 | } |
---|
1529 | } |
---|
1530 | |
---|
1531 | $fp = @fopen($file, 'wb'); |
---|
1532 | while (!@feof($lob)) { |
---|
1533 | $result = @fread($lob, $db->options['lob_buffer_length']); |
---|
1534 | $read = strlen($result); |
---|
1535 | if (@fwrite($fp, $result, $read) != $read) { |
---|
1536 | @fclose($fp); |
---|
1537 | return $db->raiseError(MDB2_ERROR, null, null, |
---|
1538 | 'could not write to the output file', __FUNCTION__); |
---|
1539 | } |
---|
1540 | } |
---|
1541 | @fclose($fp); |
---|
1542 | return MDB2_OK; |
---|
1543 | } |
---|
1544 | |
---|
1545 | // }}} |
---|
1546 | // {{{ _retrieveLOB() |
---|
1547 | |
---|
1548 | /** |
---|
1549 | * retrieve LOB from the database |
---|
1550 | * |
---|
1551 | * @param array $lob array |
---|
1552 | * @return mixed MDB2_OK on success, a MDB2 error on failure |
---|
1553 | * @access protected |
---|
1554 | */ |
---|
1555 | function _retrieveLOB(&$lob) |
---|
1556 | { |
---|
1557 | if (is_null($lob['value'])) { |
---|
1558 | $lob['value'] = $lob['resource']; |
---|
1559 | } |
---|
1560 | $lob['loaded'] = true; |
---|
1561 | return MDB2_OK; |
---|
1562 | } |
---|
1563 | |
---|
1564 | // }}} |
---|
1565 | // {{{ readLOB() |
---|
1566 | |
---|
1567 | /** |
---|
1568 | * Read data from large object input stream. |
---|
1569 | * |
---|
1570 | * @param resource $lob stream handle |
---|
1571 | * @param string $data reference to a variable that will hold data |
---|
1572 | * to be read from the large object input stream |
---|
1573 | * @param integer $length value that indicates the largest ammount ofdata |
---|
1574 | * to be read from the large object input stream. |
---|
1575 | * @return mixed the effective number of bytes read from the large object |
---|
1576 | * input stream on sucess or an MDB2 error object. |
---|
1577 | * @access public |
---|
1578 | * @see endOfLOB() |
---|
1579 | */ |
---|
1580 | function _readLOB($lob, $length) |
---|
1581 | { |
---|
1582 | return substr($lob['value'], $lob['position'], $length); |
---|
1583 | } |
---|
1584 | |
---|
1585 | // }}} |
---|
1586 | // {{{ _endOfLOB() |
---|
1587 | |
---|
1588 | /** |
---|
1589 | * Determine whether it was reached the end of the large object and |
---|
1590 | * therefore there is no more data to be read for the its input stream. |
---|
1591 | * |
---|
1592 | * @param array $lob array |
---|
1593 | * @return mixed true or false on success, a MDB2 error on failure |
---|
1594 | * @access protected |
---|
1595 | */ |
---|
1596 | function _endOfLOB($lob) |
---|
1597 | { |
---|
1598 | return $lob['endOfLOB']; |
---|
1599 | } |
---|
1600 | |
---|
1601 | // }}} |
---|
1602 | // {{{ destroyLOB() |
---|
1603 | |
---|
1604 | /** |
---|
1605 | * Free any resources allocated during the lifetime of the large object |
---|
1606 | * handler object. |
---|
1607 | * |
---|
1608 | * @param resource $lob stream handle |
---|
1609 | * @access public |
---|
1610 | */ |
---|
1611 | function destroyLOB($lob) |
---|
1612 | { |
---|
1613 | $lob_data = stream_get_meta_data($lob); |
---|
1614 | $lob_index = $lob_data['wrapper_data']->lob_index; |
---|
1615 | fclose($lob); |
---|
1616 | if (isset($this->lobs[$lob_index])) { |
---|
1617 | $this->_destroyLOB($this->lobs[$lob_index]); |
---|
1618 | unset($this->lobs[$lob_index]); |
---|
1619 | } |
---|
1620 | return MDB2_OK; |
---|
1621 | } |
---|
1622 | |
---|
1623 | // }}} |
---|
1624 | // {{{ _destroyLOB() |
---|
1625 | |
---|
1626 | /** |
---|
1627 | * Free any resources allocated during the lifetime of the large object |
---|
1628 | * handler object. |
---|
1629 | * |
---|
1630 | * @param array $lob array |
---|
1631 | * @access private |
---|
1632 | */ |
---|
1633 | function _destroyLOB(&$lob) |
---|
1634 | { |
---|
1635 | return MDB2_OK; |
---|
1636 | } |
---|
1637 | |
---|
1638 | // }}} |
---|
1639 | // {{{ implodeArray() |
---|
1640 | |
---|
1641 | /** |
---|
1642 | * apply a type to all values of an array and return as a comma seperated string |
---|
1643 | * useful for generating IN statements |
---|
1644 | * |
---|
1645 | * @access public |
---|
1646 | * |
---|
1647 | * @param array $array data array |
---|
1648 | * @param string $type determines type of the field |
---|
1649 | * |
---|
1650 | * @return string comma seperated values |
---|
1651 | */ |
---|
1652 | function implodeArray($array, $type = false) |
---|
1653 | { |
---|
1654 | if (!is_array($array) || empty($array)) { |
---|
1655 | return 'NULL'; |
---|
1656 | } |
---|
1657 | if ($type) { |
---|
1658 | foreach ($array as $value) { |
---|
1659 | $return[] = $this->quote($value, $type); |
---|
1660 | } |
---|
1661 | } else { |
---|
1662 | $return = $array; |
---|
1663 | } |
---|
1664 | return implode(', ', $return); |
---|
1665 | } |
---|
1666 | |
---|
1667 | // }}} |
---|
1668 | // {{{ matchPattern() |
---|
1669 | |
---|
1670 | /** |
---|
1671 | * build a pattern matching string |
---|
1672 | * |
---|
1673 | * @access public |
---|
1674 | * |
---|
1675 | * @param array $pattern even keys are strings, odd are patterns (% and _) |
---|
1676 | * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) |
---|
1677 | * @param string $field optional field name that is being matched against |
---|
1678 | * (might be required when emulating ILIKE) |
---|
1679 | * |
---|
1680 | * @return string SQL pattern |
---|
1681 | */ |
---|
1682 | function matchPattern($pattern, $operator = null, $field = null) |
---|
1683 | { |
---|
1684 | $db =& $this->getDBInstance(); |
---|
1685 | if (PEAR::isError($db)) { |
---|
1686 | return $db; |
---|
1687 | } |
---|
1688 | |
---|
1689 | $match = ''; |
---|
1690 | if (!is_null($operator)) { |
---|
1691 | $operator = strtoupper($operator); |
---|
1692 | switch ($operator) { |
---|
1693 | // case insensitive |
---|
1694 | case 'ILIKE': |
---|
1695 | if (is_null($field)) { |
---|
1696 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
1697 | 'case insensitive LIKE matching requires passing the field name', __FUNCTION__); |
---|
1698 | } |
---|
1699 | $db->loadModule('Function', null, true); |
---|
1700 | $match = $db->function->lower($field).' LIKE '; |
---|
1701 | break; |
---|
1702 | // case sensitive |
---|
1703 | case 'LIKE': |
---|
1704 | $match = is_null($field) ? 'LIKE ' : $field.' LIKE '; |
---|
1705 | break; |
---|
1706 | default: |
---|
1707 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
1708 | 'not a supported operator type:'. $operator, __FUNCTION__); |
---|
1709 | } |
---|
1710 | } |
---|
1711 | $match.= "'"; |
---|
1712 | foreach ($pattern as $key => $value) { |
---|
1713 | if ($key % 2) { |
---|
1714 | $match.= $value; |
---|
1715 | } else { |
---|
1716 | if ($operator === 'ILIKE') { |
---|
1717 | $value = strtolower($value); |
---|
1718 | } |
---|
1719 | $escaped = $db->escape($value); |
---|
1720 | if (PEAR::isError($escaped)) { |
---|
1721 | return $escaped; |
---|
1722 | } |
---|
1723 | $match.= $db->escapePattern($escaped); |
---|
1724 | } |
---|
1725 | } |
---|
1726 | $match.= "'"; |
---|
1727 | $match.= $this->patternEscapeString(); |
---|
1728 | return $match; |
---|
1729 | } |
---|
1730 | |
---|
1731 | // }}} |
---|
1732 | // {{{ patternEscapeString() |
---|
1733 | |
---|
1734 | /** |
---|
1735 | * build string to define pattern escape character |
---|
1736 | * |
---|
1737 | * @access public |
---|
1738 | * |
---|
1739 | * @return string define pattern escape character |
---|
1740 | */ |
---|
1741 | function patternEscapeString() |
---|
1742 | { |
---|
1743 | return ''; |
---|
1744 | } |
---|
1745 | |
---|
1746 | // }}} |
---|
1747 | // {{{ mapNativeDatatype() |
---|
1748 | |
---|
1749 | /** |
---|
1750 | * Maps a native array description of a field to a MDB2 datatype and length |
---|
1751 | * |
---|
1752 | * @param array $field native field description |
---|
1753 | * @return array containing the various possible types, length, sign, fixed |
---|
1754 | * @access public |
---|
1755 | */ |
---|
1756 | function mapNativeDatatype($field) |
---|
1757 | { |
---|
1758 | $db =& $this->getDBInstance(); |
---|
1759 | if (PEAR::isError($db)) { |
---|
1760 | return $db; |
---|
1761 | } |
---|
1762 | |
---|
1763 | // If the user has specified an option to map the native field |
---|
1764 | // type to a custom MDB2 datatype... |
---|
1765 | $db_type = strtok($field['type'], '(), '); |
---|
1766 | if (!empty($db->options['nativetype_map_callback'][$db_type])) { |
---|
1767 | return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array($db, $field)); |
---|
1768 | } |
---|
1769 | |
---|
1770 | // Otherwise perform the built-in (i.e. normal) MDB2 native type to |
---|
1771 | // MDB2 datatype conversion |
---|
1772 | return $this->_mapNativeDatatype($field); |
---|
1773 | } |
---|
1774 | |
---|
1775 | // }}} |
---|
1776 | // {{{ _mapNativeDatatype() |
---|
1777 | |
---|
1778 | /** |
---|
1779 | * Maps a native array description of a field to a MDB2 datatype and length |
---|
1780 | * |
---|
1781 | * @param array $field native field description |
---|
1782 | * @return array containing the various possible types, length, sign, fixed |
---|
1783 | * @access public |
---|
1784 | */ |
---|
1785 | function _mapNativeDatatype($field) |
---|
1786 | { |
---|
1787 | $db =& $this->getDBInstance(); |
---|
1788 | if (PEAR::isError($db)) { |
---|
1789 | return $db; |
---|
1790 | } |
---|
1791 | |
---|
1792 | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
---|
1793 | 'method not implemented', __FUNCTION__); |
---|
1794 | } |
---|
1795 | |
---|
1796 | // }}} |
---|
1797 | // {{{ mapPrepareDatatype() |
---|
1798 | |
---|
1799 | /** |
---|
1800 | * Maps an mdb2 datatype to mysqli prepare type |
---|
1801 | * |
---|
1802 | * @param string $type |
---|
1803 | * @return string |
---|
1804 | * @access public |
---|
1805 | */ |
---|
1806 | function mapPrepareDatatype($type) |
---|
1807 | { |
---|
1808 | $db =& $this->getDBInstance(); |
---|
1809 | if (PEAR::isError($db)) { |
---|
1810 | return $db; |
---|
1811 | } |
---|
1812 | |
---|
1813 | if (!empty($db->options['datatype_map'][$type])) { |
---|
1814 | $type = $db->options['datatype_map'][$type]; |
---|
1815 | if (!empty($db->options['datatype_map_callback'][$type])) { |
---|
1816 | $parameter = array('type' => $type); |
---|
1817 | return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
---|
1818 | } |
---|
1819 | } |
---|
1820 | |
---|
1821 | return $type; |
---|
1822 | } |
---|
1823 | } |
---|
1824 | ?> |
---|