/[cvs]/nfo/php/libs/net.php.pear/DB/common.php
ViewVC logotype

Contents of /nfo/php/libs/net.php.pear/DB/common.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Oct 29 19:11:41 2002 UTC (21 years, 8 months ago) by cvsjoko
Branch: MAIN
CVS Tags: HEAD
+ new pear-libraries

1 <?php
2 //
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4 |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Author: Stig Bakken <ssb@fast.no> |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: common.php,v 1.81.2.2 2002/04/09 19:04:11 ssb Exp $
20 //
21 // Base class for DB implementations.
22 //
23
24 /**
25 * DB_common is a base class for DB implementations, and must be
26 * inherited by all such.
27 */
28
29 class DB_common extends PEAR
30 {
31 // {{{ properties
32 /**
33 * assoc of capabilities for this DB implementation
34 * $features['limit'] => 'emulate' => emulate with fetch row by number
35 * 'alter' => alter the query
36 * false => skip rows
37 * @var array
38 */
39 var $features;
40
41 /**
42 * assoc mapping native error codes to DB ones
43 * @var array
44 */
45 var $errorcode_map;
46
47 /**
48 * DB type (mysql, oci8, odbc etc.)
49 * @var string
50 */
51 var $type;
52
53 /**
54 * @var string
55 */
56 var $prepare_tokens;
57
58 /**
59 * @var string
60 */
61 var $prepare_types;
62
63 /**
64 * @var string
65 */
66 var $prepared_queries;
67
68 /**
69 * @var integer
70 */
71 var $prepare_maxstmt = 0;
72
73 /**
74 * @var string
75 */
76 var $last_query = '';
77
78 /**
79 * @var integer
80 */
81 var $fetchmode = DB_FETCHMODE_ORDERED;
82
83 /**
84 * @var string
85 */
86 var $fetchmode_object_class = 'stdClass';
87
88 /**
89 * $options["persistent"] -> boolean persistent connection true|false?
90 * $options["optimize"] -> string 'performance' or 'portability'
91 * $options["debug"] -> integer numeric debug level
92 * @var array
93 */
94 var $options = array(
95 'persistent' => false,
96 'optimize' => 'performance',
97 'debug' => 0,
98 'seqname_format' => '%s_seq',
99 );
100
101 /**
102 * DB handle
103 * @var resource
104 */
105 var $dbh;
106
107 // }}}
108 // {{{ toString()
109 /**
110 * String conversation
111 *
112 * @return string
113 * @access private
114 */
115 function toString()
116 {
117 $info = get_class($this);
118 $info .= ": (phptype=" . $this->phptype .
119 ", dbsyntax=" . $this->dbsyntax .
120 ")";
121
122 if ($this->connection) {
123 $info .= " [connected]";
124 }
125
126 return $info;
127 }
128
129 // }}}
130 // {{{ constructor
131 /**
132 * Constructor
133 */
134 function DB_common()
135 {
136 $this->PEAR('DB_Error');
137 $this->features = array();
138 $this->errorcode_map = array();
139 $this->fetchmode = DB_FETCHMODE_ORDERED;
140 }
141
142 // }}}
143 // {{{ quoteString()
144
145 /**
146 * Quotes a string so it can be safely used within string delimiters
147 * in a query (preserved for compatibility issues, quote() is preffered).
148 *
149 * @return string quoted string
150 * @access public
151 * @see quote()
152 */
153 function quoteString($string)
154 {
155 $string = $this->quote($string);
156 if ($string{0} == "'") {
157 return substr($string, 1, -1);
158 }
159 return $string;
160 }
161
162 /**
163 * Quotes a string so it can be safely used in a query. It will return
164 * the string with single quotes around. Other backend quote styles
165 * should override this method.
166 *
167 * @param string $string the input string to quote
168 *
169 * @return string The NULL string or the string quotes
170 * in magic_quote_sybase style
171 */
172 function quote($string)
173 {
174 return ($string === null) ? 'NULL' : "'".str_replace("'", "''", $string)."'";
175 }
176
177 // }}}
178 // {{{ provides()
179
180 /**
181 * Tell whether a DB implementation or its backend extension
182 * supports a given feature.
183 *
184 * @param array $feature name of the feature (see the DB class doc)
185 * @return bool whether this DB implementation supports $feature
186 * @access public
187 */
188
189 function provides($feature)
190 {
191 return $this->features[$feature];
192 }
193
194 // }}}
195 // {{{ errorCode()
196
197 /**
198 * Map native error codes to DB's portable ones. Requires that
199 * the DB implementation's constructor fills in the $errorcode_map
200 * property.
201 *
202 * @param mixed $nativecode the native error code, as returned by the backend
203 * database extension (string or integer)
204 *
205 * @return int a portable DB error code, or FALSE if this DB
206 * implementation has no mapping for the given error code.
207 *
208 * @access public
209 */
210
211 function errorCode($nativecode)
212 {
213 if (isset($this->errorcode_map[$nativecode])) {
214 return $this->errorcode_map[$nativecode];
215 }
216
217 //php_error(E_WARNING, get_class($this)."::errorCode: no mapping for $nativecode");
218 // Fall back to DB_ERROR if there was no mapping.
219
220 return DB_ERROR;
221 }
222
223 // }}}
224 // {{{ errorMessage()
225
226 /**
227 * Map a DB error code to a textual message. This is actually
228 * just a wrapper for DB::errorMessage().
229 *
230 * @param integer $dbcode the DB error code
231 *
232 * @return string the corresponding error message, of FALSE
233 * if the error code was unknown
234 *
235 * @access public
236 */
237
238 function errorMessage($dbcode)
239 {
240 return DB::errorMessage($this->errorcode_map[$dbcode]);
241 }
242
243 // }}}
244 // {{{ raiseError()
245
246 /**
247 * This method is used to communicate an error and invoke error
248 * callbacks etc. Basically a wrapper for PEAR::raiseError
249 * without the message string.
250 *
251 * @param mixed integer error code, or a PEAR error object (all
252 * other parameters are ignored if this parameter is
253 * an object
254 *
255 * @param int error mode, see PEAR_Error docs
256 *
257 * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the
258 * error level (E_USER_NOTICE etc). If error mode is
259 * PEAR_ERROR_CALLBACK, this is the callback function,
260 * either as a function name, or as an array of an
261 * object and method name. For other error modes this
262 * parameter is ignored.
263 *
264 * @param string Extra debug information. Defaults to the last
265 * query and native error code.
266 *
267 * @param mixed Native error code, integer or string depending the
268 * backend.
269 *
270 * @return object a PEAR error object
271 *
272 * @access public
273 * @see PEAR_Error
274 */
275 function &raiseError($code = DB_ERROR, $mode = null, $options = null,
276 $userinfo = null, $nativecode = null)
277 {
278 // The error is yet a DB error object
279 if (is_object($code)) {
280 // because we the static PEAR::raiseError, our global
281 // handler should be used if it is set
282 if ($mode === null && !empty($this->_default_error_mode)) {
283 $mode = $this->_default_error_mode;
284 $options = $this->_default_error_options;
285 }
286 return PEAR::raiseError($code, null, $mode, $options, null, null, true);
287 }
288
289 if ($userinfo === null) {
290 $userinfo = $this->last_query;
291 }
292
293 if ($nativecode) {
294 $userinfo .= " [nativecode=$nativecode]";
295 }
296
297 return PEAR::raiseError(null, $code, $mode, $options, $userinfo,
298 'DB_Error', true);
299 }
300
301 // }}}
302 // {{{ setFetchMode()
303
304 /**
305 * Sets which fetch mode should be used by default on queries
306 * on this connection.
307 *
308 * @param integer $fetchmode DB_FETCHMODE_ORDERED or
309 * DB_FETCHMODE_ASSOC, possibly bit-wise OR'ed with
310 * DB_FETCHMODE_FLIPPED.
311 *
312 * @param string $object_class The class of the object
313 * to be returned by the fetch methods when
314 * the DB_FETCHMODE_OBJECT mode is selected.
315 * If no class is specified by default a cast
316 * to object from the assoc array row will be done.
317 * There is also the posibility to use and extend the
318 * 'DB_Row' class.
319 *
320 * @see DB_FETCHMODE_ORDERED
321 * @see DB_FETCHMODE_ASSOC
322 * @see DB_FETCHMODE_FLIPPED
323 * @see DB_FETCHMODE_OBJECT
324 * @see DB_Row::DB_Row()
325 * @access public
326 */
327
328 function setFetchMode($fetchmode, $object_class = null)
329 {
330 switch ($fetchmode) {
331 case DB_FETCHMODE_OBJECT:
332 if ($object_class) {
333 $this->fetchmode_object_class = $object_class;
334 }
335 case DB_FETCHMODE_ORDERED:
336 case DB_FETCHMODE_ASSOC:
337 $this->fetchmode = $fetchmode;
338 break;
339 default:
340 return $this->raiseError('invalid fetchmode mode');
341 }
342 }
343
344 // }}}
345 // {{{ setOption()
346 /**
347 * set the option for the db class
348 *
349 * @param string $option option name
350 * @param mixed $value value for the option
351 *
352 * @return mixed DB_OK or DB_Error
353 */
354 function setOption($option, $value)
355 {
356 if (isset($this->options[$option])) {
357 $this->options[$option] = $value;
358 return DB_OK;
359 }
360 return $this->raiseError("unknown option $option");
361 }
362
363 // }}}
364 // {{{ getOption()
365 /**
366 * returns the value of an option
367 *
368 * @param string $option option name
369 *
370 * @return mixed the option value
371 */
372 function getOption($option)
373 {
374 if (isset($this->options[$option])) {
375 return $this->options[$option];
376 }
377 return $this->raiseError("unknown option $option");
378 }
379
380 // }}}
381 // {{{ prepare()
382
383 /**
384 * Prepares a query for multiple execution with execute().
385 * With some database backends, this is emulated.
386 * prepare() requires a generic query as string like
387 * "INSERT INTO numbers VALUES(?,?,?)". The ? are wildcards.
388 * Types of wildcards:
389 * ? - a quoted scalar value, i.e. strings, integers
390 * & - requires a file name, the content of the file
391 * insert into the query (i.e. saving binary data
392 * in a db)
393 * ! - value is inserted 'as is'
394 *
395 * @param string the query to prepare
396 *
397 * @return resource handle for the query
398 *
399 * @access public
400 * @see execute
401 */
402
403 function prepare($query)
404 {
405 $tokens = split("[\&\?\!]", $query);
406 $token = 0;
407 $types = array();
408
409 for ($i = 0; $i < strlen($query); $i++) {
410 switch ($query[$i]) {
411 case '?':
412 $types[$token++] = DB_PARAM_SCALAR;
413 break;
414 case '&':
415 $types[$token++] = DB_PARAM_OPAQUE;
416 break;
417 case '!':
418 $types[$token++] = DB_PARAM_MISC;
419 break;
420 }
421 }
422
423 $this->prepare_tokens[] = &$tokens;
424 end($this->prepare_tokens);
425
426 $k = key($this->prepare_tokens);
427 $this->prepare_types[$k] = $types;
428 $this->prepared_queries[$k] = &$query;
429
430 return $k;
431 }
432
433 // }}}
434 // {{{ execute()
435 /**
436 * Executes a prepared SQL query
437 * With execute() the generic query of prepare is
438 * assigned with the given data array. The values
439 * of the array inserted into the query in the same
440 * order like the array order
441 *
442 * @param resource $stmt query handle from prepare()
443 * @param array $data numeric array containing the
444 * data to insert into the query
445 *
446 * @return mixed a new DB_Result or a DB_Error when fail
447 *
448 * @access public
449 * @see prepare()
450 */
451 function execute($stmt, $data = false)
452 {
453 $realquery = $this->executeEmulateQuery($stmt, $data);
454 if (DB::isError($realquery)) {
455 return $realquery;
456 }
457 $result = $this->simpleQuery($realquery);
458 if (DB::isError($result) || $result === DB_OK) {
459 return $result;
460 } else {
461 return new DB_result($this, $result);
462 }
463 }
464
465 // }}}
466 // {{{ executeEmulateQuery()
467
468 /**
469 * Emulates the execute statement, when not supported
470 *
471 * @param resource $stmt query handle from prepare()
472 * @param array $data numeric array containing the
473 * data to insert into the query
474 *
475 * @return mixed a string containing the real query run when emulating
476 * prepare/execute. A DB error code is returned on failure.
477 *
478 * @access private
479 * @see execute()
480 */
481
482 function executeEmulateQuery($stmt, $data = false)
483 {
484 $p = &$this->prepare_tokens;
485
486 if (!isset($this->prepare_tokens[$stmt]) ||
487 !is_array($this->prepare_tokens[$stmt]) ||
488 !sizeof($this->prepare_tokens[$stmt]))
489 {
490 return $this->raiseError(DB_ERROR_INVALID);
491 }
492
493 $qq = &$this->prepare_tokens[$stmt];
494 $qp = sizeof($qq) - 1;
495
496 if ((!$data && $qp > 0) ||
497 (!is_array($data) && $qp > 1) ||
498 (is_array($data) && $qp > sizeof($data)))
499 {
500 $this->last_query = $this->prepared_queries[$stmt];
501 return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
502 }
503
504 $realquery = $qq[0];
505 for ($i = 0; $i < $qp; $i++) {
506 $type = $this->prepare_types[$stmt][$i];
507 if ($type == DB_PARAM_OPAQUE) {
508 if (is_array($data)) {
509 $fp = fopen($data[$i], 'r');
510 } else {
511 $fp = fopen($data, 'r');
512 }
513
514 $pdata = '';
515
516 if ($fp) {
517 while (($buf = fread($fp, 4096)) != false) {
518 $pdata .= $buf;
519 }
520 }
521 } else {
522 if (is_array($data)) {
523 $pdata = &$data[$i];
524 } else {
525 $pdata = &$data;
526 }
527 }
528
529 $realquery .= ($type != DB_PARAM_MISC) ? $this->quote($pdata) : $pdata;
530 $realquery .= $qq[$i + 1];
531 }
532
533 return $realquery;
534 }
535
536 // }}}
537 // {{{ executeMultiple()
538
539 /**
540 * This function does several execute() calls on the same
541 * statement handle. $data must be an array indexed numerically
542 * from 0, one execute call is done for every "row" in the array.
543 *
544 * If an error occurs during execute(), executeMultiple() does not
545 * execute the unfinished rows, but rather returns that error.
546 *
547 * @param resource $stmt query handle from prepare()
548 * @param array $data numeric array containing the
549 * data to insert into the query
550 *
551 * @return mixed DB_OK or DB_Error
552 *
553 * @access public
554 * @see prepare(), execute()
555 */
556
557 function executeMultiple( $stmt, &$data )
558 {
559 for($i = 0; $i < sizeof( $data ); $i++) {
560 $res = $this->execute($stmt, $data[$i]);
561 if (DB::isError($res)) {
562 return $res;
563 }
564 }
565 return DB_OK;
566 }
567
568 // }}}
569 // {{{ modifyQuery()
570
571 /**
572 * This method is used by backends to alter queries for various
573 * reasons. It is defined here to assure that all implementations
574 * have this method defined.
575 *
576 * @param string $query query to modify
577 *
578 * @return the new (modified) query
579 *
580 * @access private
581 */
582 function modifyQuery($query) {
583 return $query;
584 }
585
586 // }}}
587 // {{{ modifyLimitQuery()
588 /**
589 * This method is used by backends to alter limited queries
590 *
591 * @param string $query query to modify
592 * @param integer $from the row to start to fetching
593 * @param integer $count the numbers of rows to fetch
594 *
595 * @return the new (modified) query
596 *
597 * @access private
598 */
599
600 function modifyLimitQuery($query, $from, $count)
601 {
602 return $query;
603 }
604
605 // }}}
606 // {{{ query()
607
608 /**
609 * Send a query to the database and return any results with a
610 * DB_result object.
611 *
612 * @access public
613 *
614 * @param string $query the SQL query or the statement to prepare
615 * @param string $params the data to be added to the query
616 * @return mixed a DB_result object or DB_OK on success, a DB
617 * error on failure
618 *
619 * @see DB::isError
620 * @see DB_common::prepare
621 * @see DB_common::execute
622 */
623 function &query($query, $params = array()) {
624 if (sizeof($params) > 0) {
625 $sth = $this->prepare($query);
626 if (DB::isError($sth)) {
627 return $sth;
628 }
629 return $this->execute($sth, $params);
630 } else {
631 $result = $this->simpleQuery($query);
632 if (DB::isError($result) || $result === DB_OK) {
633 return $result;
634 } else {
635 return new DB_result($this, $result);
636 }
637 }
638 }
639
640 // }}}
641 // {{{ limitQuery()
642 /**
643 * Generates a limited query
644 * *EXPERIMENTAL*
645 *
646 * @param string $query query
647 * @param integer $from the row to start to fetching
648 * @param integer $count the numbers of rows to fetch
649 *
650 * @return mixed a DB_Result object or a DB_Error
651 *
652 * @access public
653 */
654 function limitQuery($query, $from, $count)
655 {
656 $query = $this->modifyLimitQuery($query, $from, $count);
657 $result = $this->simpleQuery($query);
658 if (DB::isError($result) || $result === DB_OK) {
659 return $result;
660 } else {
661 $res_obj =& new DB_result($this, $result);
662 $res_obj->limit_from = $from;
663 $res_obj->limit_count = $count;
664 return $res_obj;
665 }
666 }
667
668 // }}}
669 // {{{ getOne()
670
671 /**
672 * Fetch the first column of the first row of data returned from
673 * a query. Takes care of doing the query and freeing the results
674 * when finished.
675 *
676 * @param string $query the SQL query
677 * @param array $params if supplied, prepare/execute will be used
678 * with this array as execute parameters
679 *
680 * @return mixed DB_Error or the returned value of the query
681 *
682 * @access public
683 */
684
685 function &getOne($query, $params = array())
686 {
687 settype($params, "array");
688 if (sizeof($params) > 0) {
689 $sth = $this->prepare($query);
690 if (DB::isError($sth)) {
691 return $sth;
692 }
693 $res = $this->execute($sth, $params);
694 } else {
695 $res = $this->query($query);
696 }
697
698 if (DB::isError($res)) {
699 return $res;
700 }
701
702 $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED);
703 if ($err !== DB_OK) {
704 return $err;
705 }
706
707 $res->free();
708
709 if (isset($sth)) {
710 $this->freeResult($sth);
711 }
712
713 return $row[0];
714 }
715
716 // }}}
717 // {{{ getRow()
718
719 /**
720 * Fetch the first row of data returned from a query. Takes care
721 * of doing the query and freeing the results when finished.
722 *
723 * @param string $query the SQL query
724 * @param integer $fetchmode the fetch mode to use
725 * @param array $params array if supplied, prepare/execute will be used
726 * with this array as execute parameters
727 * @access public
728 * @return array the first row of results as an array indexed from
729 * 0, or a DB error code.
730 */
731
732 function &getRow($query,
733 $params = null,
734 $fetchmode = DB_FETCHMODE_DEFAULT)
735 {
736 // compat check, the params and fetchmode parameters used to
737 // have the opposite order
738 if (!is_array($params)) {
739 if (is_array($fetchmode)) {
740 $tmp = $params;
741 $params = $fetchmode;
742 $fetchmode = $tmp;
743 } elseif ($params !== null) {
744 $fetchmode = $params;
745 $params = null;
746 }
747 }
748 $params = (empty($params)) ? array() : $params;
749 $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode;
750 settype($params, 'array');
751 if (sizeof($params) > 0) {
752 $sth = $this->prepare($query);
753 if (DB::isError($sth)) {
754 return $sth;
755 }
756 $res = $this->execute($sth, $params);
757 } else {
758 $res = $this->query($query);
759 }
760
761 if (DB::isError($res)) {
762 return $res;
763 }
764
765 $err = $res->fetchInto($row, $fetchmode);
766
767 if ($err !== DB_OK) {
768 return $err;
769 }
770 $res->free();
771
772 if (isset($sth)) {
773 $this->freeResult($sth);
774 }
775
776 return $row;
777 }
778
779 // }}}
780 // {{{ getCol()
781
782 /**
783 * Fetch a single column from a result set and return it as an
784 * indexed array.
785 *
786 * @param string $query the SQL query
787 *
788 * @param mixed $col which column to return (integer [column number,
789 * starting at 0] or string [column name])
790 *
791 * @param array $params array if supplied, prepare/execute will be used
792 * with this array as execute parameters
793 * @access public
794 *
795 * @return array an indexed array with the data from the first
796 * row at index 0, or a DB error code.
797 */
798
799 function &getCol($query, $col = 0, $params = array())
800 {
801 settype($params, "array");
802 if (sizeof($params) > 0) {
803 $sth = $this->prepare($query);
804
805 if (DB::isError($sth)) {
806 return $sth;
807 }
808
809 $res = $this->execute($sth, $params);
810 } else {
811 $res = $this->query($query);
812 }
813
814 if (DB::isError($res)) {
815 return $res;
816 }
817
818 $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
819 $ret = array();
820
821 while (is_array($row = $res->fetchRow($fetchmode))) {
822 $ret[] = $row[$col];
823 }
824 if (DB::isError($row)) {
825 $ret = $row;
826 }
827 $res->free();
828
829 if (isset($sth)) {
830 $this->freeResult($sth);
831 }
832
833 return $ret;
834 }
835
836 // }}}
837 // {{{ getAssoc()
838
839 /**
840 * Fetch the entire result set of a query and return it as an
841 * associative array using the first column as the key.
842 *
843 * If the result set contains more than two columns, the value
844 * will be an array of the values from column 2-n. If the result
845 * set contains only two columns, the returned value will be a
846 * scalar with the value of the second column (unless forced to an
847 * array with the $force_array parameter). A DB error code is
848 * returned on errors. If the result set contains fewer than two
849 * columns, a DB_ERROR_TRUNCATED error is returned.
850 *
851 * For example, if the table "mytable" contains:
852 *
853 * ID TEXT DATE
854 * --------------------------------
855 * 1 'one' 944679408
856 * 2 'two' 944679408
857 * 3 'three' 944679408
858 *
859 * Then the call getAssoc('SELECT id,text FROM mytable') returns:
860 * array(
861 * '1' => 'one',
862 * '2' => 'two',
863 * '3' => 'three',
864 * )
865 *
866 * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
867 * array(
868 * '1' => array('one', '944679408'),
869 * '2' => array('two', '944679408'),
870 * '3' => array('three', '944679408')
871 * )
872 *
873 * If the more than one row occurs with the same value in the
874 * first column, the last row overwrites all previous ones by
875 * default. Use the $group parameter if you don't want to
876 * overwrite like this. Example:
877 *
878 * getAssoc('SELECT category,id,name FROM mytable', false, null,
879 * DB_FETCHMODE_ASSOC, true) returns:
880 * array(
881 * '1' => array(array('id' => '4', 'name' => 'number four'),
882 * array('id' => '6', 'name' => 'number six')
883 * ),
884 * '9' => array(array('id' => '4', 'name' => 'number four'),
885 * array('id' => '6', 'name' => 'number six')
886 * )
887 * )
888 *
889 * Keep in mind that database functions in PHP usually return string
890 * values for results regardless of the database's internal type.
891 *
892 * @param string $query the SQL query
893 *
894 * @param boolean $force_array used only when the query returns
895 * exactly two columns. If true, the values of the returned array
896 * will be one-element arrays instead of scalars.
897 *
898 * @param array $params array if supplied, prepare/execute will be used
899 * with this array as execute parameters
900 *
901 * @param boolean $group if true, the values of the returned array
902 * is wrapped in another array. If the same
903 * key value (in the first column) repeats
904 * itself, the values will be appended to
905 * this array instead of overwriting the
906 * existing values.
907 *
908 * @access public
909 *
910 * @return array associative array with results from the query.
911 */
912
913 function &getAssoc($query, $force_array = false, $params = array(),
914 $fetchmode = DB_FETCHMODE_ORDERED, $group = false)
915 {
916 settype($params, "array");
917 if (sizeof($params) > 0) {
918 $sth = $this->prepare($query);
919
920 if (DB::isError($sth)) {
921 return $sth;
922 }
923
924 $res = $this->execute($sth, $params);
925 } else {
926 $res = $this->query($query);
927 }
928
929 if (DB::isError($res)) {
930 return $res;
931 }
932
933 $cols = $res->numCols();
934
935 if ($cols < 2) {
936 return $this->raiseError(DB_ERROR_TRUNCATED);
937 }
938
939 $results = array();
940
941 if ($cols > 2 || $force_array) {
942 // return array values
943 // XXX this part can be optimized
944 if ($fetchmode == DB_FETCHMODE_ASSOC) {
945 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) {
946 reset($row);
947 $key = current($row);
948 unset($row[key($row)]);
949 if ($group) {
950 $results[$key][] = $row;
951 } else {
952 $results[$key] = $row;
953 }
954 }
955 } else {
956 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
957 // we shift away the first element to get
958 // indices running from 0 again
959 $key = array_shift($row);
960 if ($group) {
961 $results[$key][] = $row;
962 } else {
963 $results[$key] = $row;
964 }
965 }
966 }
967 if (DB::isError($row)) {
968 $results = $row;
969 }
970 } else {
971 // return scalar values
972 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
973 if ($group) {
974 $results[$row[0]][] = $row[1];
975 } else {
976 $results[$row[0]] = $row[1];
977 }
978 }
979 if (DB::isError($row)) {
980 $results = $row;
981 }
982 }
983
984 $res->free();
985
986 if (isset($sth)) {
987 $this->freeResult($sth);
988 }
989
990 return $results;
991 }
992
993 // }}}
994 // {{{ getAll()
995
996 /**
997 * Fetch all the rows returned from a query.
998 *
999 * @param string $query the SQL query
1000 *
1001 * @param array $params array if supplied, prepare/execute will be used
1002 * with this array as execute parameters
1003 * @param integer $fetchmode the fetch mode to use
1004 *
1005 * @access public
1006 * @return array an nested array, or a DB error
1007 */
1008
1009 function &getAll($query,
1010 $params = null,
1011 $fetchmode = DB_FETCHMODE_DEFAULT)
1012 {
1013 // compat check, the params and fetchmode parameters used to
1014 // have the opposite order
1015 if (!is_array($params)) {
1016 if (is_array($fetchmode)) {
1017 $tmp = $params;
1018 $params = $fetchmode;
1019 $fetchmode = $tmp;
1020 } elseif ($params !== null) {
1021 $fetchmode = $params;
1022 $params = null;
1023 }
1024 }
1025 $params = (empty($params)) ? array() : $params;
1026 $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode;
1027 settype($params, "array");
1028 if (sizeof($params) > 0) {
1029 $sth = $this->prepare($query);
1030
1031 if (DB::isError($sth)) {
1032 return $sth;
1033 }
1034
1035 $res = $this->execute($sth, $params);
1036 } else {
1037 $res = $this->query($query);
1038 }
1039
1040 if (DB::isError($res)) {
1041 return $res;
1042 }
1043
1044 $results = array();
1045 $this->pushErrorHandling(PEAR_ERROR_RETURN);
1046 while (DB_OK === $res->fetchInto($row, $fetchmode)) {
1047 if ($fetchmode & DB_FETCHMODE_FLIPPED) {
1048 foreach ($row as $key => $val) {
1049 $results[$key][] = $val;
1050 }
1051 } else {
1052 $results[] = $row;
1053 }
1054 }
1055 $this->popErrorHandling();
1056
1057 $res->free();
1058
1059 if (isset($sth)) {
1060 $this->freeResult($sth);
1061 }
1062 if (DB::isError($row)) {
1063 return $this->raiseError($row);
1064 }
1065 return $results;
1066 }
1067
1068 // }}}
1069 // {{{ autoCommit()
1070 /**
1071 * enable automatic Commit
1072 *
1073 * @param boolean $onoff
1074 * @return mixed DB_Error
1075 *
1076 * @access public
1077 */
1078 function autoCommit($onoff=false)
1079 {
1080 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1081 }
1082
1083 // }}}
1084 // {{{ commit()
1085 /**
1086 * starts a Commit
1087 *
1088 * @return mixed DB_Error
1089 *
1090 * @access public
1091 */
1092 function commit()
1093 {
1094 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1095 }
1096
1097 // }}}
1098 // {{{ rollback()
1099 /**
1100 * starts a rollback
1101 *
1102 * @return mixed DB_Error
1103 *
1104 * @access public
1105 */
1106 function rollback()
1107 {
1108 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1109 }
1110
1111 // }}}
1112 // {{{ numRows()
1113 /**
1114 * returns the number of rows in a result object
1115 *
1116 * @param object DB_Result the result object to check
1117 *
1118 * @return mixed DB_Error or the number of rows
1119 *
1120 * @access public
1121 */
1122 function numRows($result)
1123 {
1124 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1125 }
1126
1127 // }}}
1128 // {{{ affectedRows()
1129 /**
1130 * returns the affected rows of a query
1131 *
1132 * @return mixed DB_Error or number of rows
1133 *
1134 * @access public
1135 */
1136 function affectedRows()
1137 {
1138 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1139 }
1140
1141 // }}}
1142 // {{{ errorNative()
1143 /**
1144 * returns an errormessage, provides by the database
1145 *
1146 * @return mixed DB_Error or message
1147 *
1148 * @access public
1149 */
1150 function errorNative()
1151 {
1152 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1153 }
1154
1155 // }}}
1156 // {{{ nextId()
1157 /**
1158 * returns the next free id of a sequence
1159 *
1160 * @param string $seq_name name of the sequence
1161 * @param boolean $ondemand when true the seqence is
1162 * automatic created, if it
1163 * not exists
1164 *
1165 * @return mixed DB_Error or id
1166 */
1167 function nextId($seq_name, $ondemand = true)
1168 {
1169 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1170 }
1171
1172 // }}}
1173 // {{{ createSequence()
1174 /**
1175 * creates a new sequence
1176 *
1177 * @param string $seq_name name of the new sequence
1178 *
1179 * @return mixed DB_Error
1180 *
1181 * @access public
1182 */
1183 function createSequence($seq_name)
1184 {
1185 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1186 }
1187
1188 // }}}
1189 // {{{ dropSequence()
1190 /**
1191 * deletes a sequence
1192 *
1193 * @param string $seq_name name of the sequence
1194 *
1195 * @return mixed DB_Error
1196 *
1197 * @access public
1198 */
1199 function dropSequence($seq_name)
1200 {
1201 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1202 }
1203
1204 // }}}
1205 // {{{ tableInfo()
1206 /**
1207 * returns meta data about the result set
1208 *
1209 * @param object DB_Result $result the result object to analyse
1210 * @param mixed $mode depends on implementation
1211 *
1212 * @return mixed DB_Error
1213 *
1214 * @access public
1215 */
1216 function tableInfo($result, $mode = null)
1217 {
1218 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1219 }
1220
1221 // }}}
1222 // {{{ getTables()
1223 /**
1224 * @deprecated
1225 */
1226 function getTables()
1227 {
1228 return $this->getListOf('tables');
1229 }
1230
1231 // }}}
1232 // {{{ getListOf()
1233 /**
1234 * list internal DB info
1235 * valid values for $type are db dependent,
1236 * often: databases, users, view, functions
1237 *
1238 * @param string $type type of requested info
1239 *
1240 * @return mixed DB_Error or the requested data
1241 *
1242 * @access public
1243 */
1244 function getListOf($type)
1245 {
1246 $sql = $this->getSpecialQuery($type);
1247 if ($sql === null) { // No support
1248 return $this->raiseError(DB_ERROR_UNSUPPORTED);
1249 } elseif (is_int($sql) || DB::isError($sql)) { // Previous error
1250 return $this->raiseError($sql);
1251 } elseif (is_array($sql)) { // Already the result
1252 return $sql;
1253 }
1254 return $this->getCol($sql); // Launch this query
1255 }
1256 // }}}
1257 // {{{ getSequenceName()
1258
1259 function getSequenceName($sqn)
1260 {
1261 return sprintf($this->getOption("seqname_format"),
1262 preg_replace('/[^a-z0-9_]/i', '_', $sqn));
1263 }
1264
1265 // }}}
1266 }
1267
1268 // Used by many drivers
1269 if (!function_exists('array_change_key_case')) {
1270 define('CASE_UPPER', 1);
1271 define('CASE_LOWER', 0);
1272 function &array_change_key_case(&$array, $case) {
1273 $casefunc = ($case == CASE_LOWER) ? 'strtolower' : 'strtoupper';
1274 $ret = array();
1275 foreach ($array as $key => $value) {
1276 $ret[$casefunc($key)] = $value;
1277 }
1278 return $ret;
1279 }
1280 }
1281
1282 ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed