Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP Version 4                                                        |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
6
// | Stig. S. Bakken, Lukas Smith                                         |
7
// | All rights reserved.                                                 |
8
// +----------------------------------------------------------------------+
9
// | MDB 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@backendmedia.com>                         |
43
// +----------------------------------------------------------------------+
44
//
45
// $Id: Common.php,v 1.114.4.22 2004/04/08 19:11:58 lsmith Exp $
46
 
47
/**
48
 * @package MDB
49
 * @author Lukas Smith <smith@backendmedia.com>
50
 */
51
 
52
// }}}
53
// {{{ MDB_defaultDebugOutput()
54
 
55
/**
56
 * default debug output handler
57
 *
58
 * @param object $db reference to an MDB database object
59
 * @param string $message message that should be appended to the debug
60
 *       variable
61
 * @return string the corresponding error message, of FALSE
62
 * if the error code was unknown
63
 * @access public
64
 */
65
function MDB_defaultDebugOutput(&$db, $message)
66
{
67
    $db->debug_output .= $db->database . " $message" . $db->getOption('log_line_break');
68
}
69
 
70
/**
71
 * MDB_Common: Base class that is extended by each MDB driver
72
 *
73
 * @package MDB
74
 * @category Database
75
 * @author Lukas Smith <smith@backendmedia.com>
76
 */
77
class MDB_Common extends PEAR
78
{
79
    // {{{ properties
80
    /**
81
    * index of the MDB object withing the global $_MDB_databases array
82
    * @var integer
83
    * @access private
84
    */
85
    var $database = 0;
86
 
87
    /**
88
    * @var string
89
    * @access private
90
    */
91
    var $host = '';
92
 
93
    /**
94
    * @var string
95
    * @access private
96
    */
97
    var $port = '';
98
 
99
    /**
100
    * @var string
101
    * @access private
102
    */
103
    var $user = '';
104
 
105
    /**
106
    * @var string
107
    * @access private
108
    */
109
    var $password = '';
110
 
111
    /**
112
    * @var string
113
    * @access private
114
    */
115
    var $database_name = '';
116
 
117
    /**
118
    * @var array
119
    * @access private
120
    */
121
    var $supported = array();
122
 
123
    /**
124
    * $options["persistent"] -> boolean persistent connection true|false?
125
    * $options["debug"] -> integer numeric debug level
126
    * $options["autofree"] -> boolean
127
    * $options["lob_buffer_length"] -> integer LOB buffer length
128
    * $options["log_line_break"] -> string line-break format
129
    * $options["seqname_format"] -> string pattern for sequence name
130
    * $options["includelob"] -> boolean
131
    * $options["includemanager"] -> boolean
132
    * $options["UseTransactions"] -> boolean
133
    * $options["optimize"] -> string 'performance' or 'portability'
134
    * @var array
135
    * @access private
136
    */
137
    var $options = array(
138
            'persistent' => FALSE,
139
            'debug' => FALSE,
140
            'autofree' => FALSE,
141
            'lob_buffer_length' => 8192,
142
            'log_line_break' => "\n",
143
            'seqname_format' => '%s_seq',
144
            'sequence_col_name' => 'sequence',
145
            'includelob' => FALSE,
146
            'includemanager' => FALSE,
147
            'UseTransactions' => FALSE,
148
            'optimize' => 'performance',
149
        );
150
 
151
    /**
152
    * @var string
153
    * @access private
154
    */
155
    var $escape_quotes = '';
156
 
157
    /**
158
    * @var integer
159
    * @access private
160
    */
161
    var $decimal_places = 2;
162
 
163
    /**
164
    * @var string
165
    * @access private
166
    */
167
    var $manager_included_constant = '';
168
 
169
    /**
170
    * @var string
171
    * @access private
172
    */
173
    var $manager_include = '';
174
 
175
    /**
176
    * @var string
177
    * @access private
178
    */
179
    var $manager_class_name = '';
180
 
181
    /**
182
    * @var object
183
    * @access private
184
    */
185
    var $manager;
186
 
187
    /**
188
    * @var array
189
    * @access private
190
    */
191
    var $warnings = array();
192
 
193
    /**
194
    * @var string
195
    * @access private
196
    */
197
    var $debug = '';
198
 
199
    /**
200
    * @var string
201
    * @access private
202
    */
203
    var $debug_output = '';
204
 
205
    /**
206
    * @var boolean
207
    * @access private
208
    */
209
    var $pass_debug_handle = FALSE;
210
 
211
    /**
212
    * @var boolean
213
    * @access private
214
    */
215
    var $auto_commit = TRUE;
216
 
217
    /**
218
    * @var boolean
219
    * @access private
220
    */
221
    var $in_transaction = FALSE;
222
 
223
    /**
224
    * @var integer
225
    * @access private
226
    */
227
    var $first_selected_row = 0;
228
 
229
    /**
230
    * @var integer
231
    * @access private
232
    */
233
    var $selected_row_limit = 0;
234
 
235
    /**
236
    * DB type (mysql, oci8, odbc etc.)
237
    * @var string
238
    * @access private
239
    */
240
    var $type;
241
 
242
    /**
243
    * @var array
244
    * @access private
245
    */
246
    var $prepared_queries = array();
247
 
248
    /**
249
    * @var array
250
    * @access private
251
    */
252
    var $result_types;
253
 
254
    /**
255
    * @var string
256
    * @access private
257
    */
258
    var $last_query = '';
259
 
260
    /**
261
    * @var integer
262
    * @access private
263
    */
264
    var $fetchmode = MDB_FETCHMODE_ORDERED;
265
 
266
    /**
267
    * @var integer
268
    * @access private
269
    */
270
    var $affected_rows = -1;
271
 
272
    /**
273
    * @var array
274
    * @access private
275
    */
276
    var $lobs = array();
277
 
278
    /**
279
    * @var array
280
    * @access private
281
    */
282
    var $clobs = array();
283
 
284
    /**
285
    * @var array
286
    * @access private
287
    */
288
    var $blobs = array();
289
 
290
    // }}}
291
    // {{{ constructor
292
 
293
    /**
294
     * Constructor
295
     */
296
    function MDB_Common()
297
    {
298
        $database = count($GLOBALS['_MDB_databases']) + 1;
299
        $GLOBALS['_MDB_databases'][$database] = &$this;
300
        $this->database = $database;
301
 
302
        $this->PEAR('MDB_Error');
303
        $this->supported = array();
304
        $this->errorcode_map = array();
305
        $this->fetchmode = MDB_FETCHMODE_ORDERED;
306
    }
307
 
308
    // }}}
309
    // {{{ __toString()
310
 
311
    /**
312
     * String conversation
313
     *
314
     * @return string
315
     * @access public
316
     */
317
    function __toString()
318
    {
319
        $info = get_class($this);
320
        $info .= ': (phptype = ' . $this->phptype . ', dbsyntax = ' . $this->dbsyntax . ')';
321
        if ($this->connection) {
322
            $info .= ' [connected]';
323
        }
324
        return($info);
325
    }
326
 
327
    // }}}
328
    // {{{ errorCode()
329
 
330
    /**
331
     * Map native error codes to MDB's portable ones.  Requires that
332
     * the DB implementation's constructor fills in the $errorcode_map
333
     * property.
334
     *
335
     * @param mixed $nativecode the native error code, as returned by the
336
     *      backend database extension (string or integer)
337
     * @return int a portable MDB error code, or FALSE if this MDB
338
     *      implementation has no mapping for the given error code.
339
     * @access public
340
     */
341
    function errorCode($nativecode)
342
    {
343
        if (isset($this->errorcode_map[$nativecode])) {
344
            return($this->errorcode_map[$nativecode]);
345
        }
346
        // Fall back to MDB_ERROR if there was no mapping.
347
        return(MDB_ERROR);
348
    }
349
 
350
    // }}}
351
    // {{{ errorMessage()
352
 
353
    /**
354
     * Map a MDB error code to a textual message.  This is actually
355
     * just a wrapper for MDB::errorMessage().
356
     *
357
     * @param integer $dbcode the MDB error code
358
     * @return string the corresponding error message, of FALSE
359
     *      if the error code was unknown
360
     * @access public
361
     */
362
    function errorMessage($dbcode)
363
    {
364
        return(MDB::errorMessage($this->errorcode_map[$dbcode]));
365
    }
366
 
367
    // }}}
368
    // {{{ raiseError()
369
 
370
    /**
371
     * This method is used to communicate an error and invoke error
372
     * callbacks etc.  Basically a wrapper for PEAR::raiseError
373
     * without the message string.
374
     *
375
     * @param mixed $code integer error code, or a PEAR error object (all
376
     *      other parameters are ignored if this parameter is an object
377
     * @param int $mode error mode, see PEAR_Error docs
378
     * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
379
     *      error level (E_USER_NOTICE etc).  If error mode is
380
     *      PEAR_ERROR_CALLBACK, this is the callback function, either as a
381
     *      function name, or as an array of an object and method name. For
382
     *      other error modes this parameter is ignored.
383
     * @param string $userinfo Extra debug information.  Defaults to the last
384
     *      query and native error code.
385
     * @param mixed $nativecode Native error code, integer or string depending
386
     *      the backend.
387
     * @return object a PEAR error object
388
     * @access public
389
     * @see PEAR_Error
390
     */
391
    function &raiseError($code = MDB_ERROR, $mode = NULL, $options = NULL,
392
        $userinfo = NULL, $nativecode = NULL)
393
    {
394
        // The error is yet a MDB error object
395
        if (is_object($code)) {
396
            // because we the static PEAR::raiseError, our global
397
            // handler should be used if it is set
398
            if ($mode === null && !empty($this->_default_error_mode)) {
399
                $mode    = $this->_default_error_mode;
400
                $options = $this->_default_error_options;
401
            }
402
            $err = PEAR::raiseError($code, NULL, $mode, $options, NULL, NULL, TRUE);
403
            return($err);
404
        }
405
 
406
        if ($userinfo === NULL) {
407
            $userinfo = $this->last_query;
408
        }
409
 
410
        if ($nativecode) {
411
            $userinfo .= ' [nativecode=' . trim($nativecode) . ']';
412
        }
413
 
414
        $err = PEAR::raiseError(NULL, $code, $mode, $options, $userinfo, 'MDB_Error', TRUE);
415
        return($err);
416
    }
417
 
418
    // }}}
419
    // {{{ errorNative()
420
 
421
    /**
422
     * returns an errormessage, provides by the database
423
     *
424
     * @return mixed MDB_Error or message
425
     * @access public
426
     */
427
    function errorNative()
428
    {
429
        return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
430
    }
431
 
432
    // }}}
433
    // {{{ resetWarnings()
434
 
435
    /**
436
     * reset the warning array
437
     *
438
     * @access public
439
     */
440
    function resetWarnings()
441
    {
442
        $this->warnings = array();
443
    }
444
 
445
    // }}}
446
    // {{{ getWarnings()
447
 
448
    /**
449
     * get all warnings in reverse order.
450
     * This means that the last warning is the first element in the array
451
     *
452
     * @return array with warnings
453
     * @access public
454
     * @see resetWarnings()
455
     */
456
    function getWarnings()
457
    {
458
        return array_reverse($this->warnings);
459
    }
460
 
461
    // }}}
462
    // {{{ setOption()
463
 
464
    /**
465
     * set the option for the db class
466
     *
467
     * @param string $option option name
468
     * @param mixed $value value for the option
469
     * @return mixed MDB_OK or MDB_Error
470
     * @access public
471
     */
472
    function setOption($option, $value)
473
    {
474
        if (isset($this->options[$option])) {
475
            $this->options[$option] = $value;
476
            return MDB_OK;
477
        }
478
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
479
    }
480
 
481
    // }}}
482
    // {{{ getOption()
483
 
484
    /**
485
     * returns the value of an option
486
     *
487
     * @param string $option option name
488
     * @return mixed the option value or error object
489
     * @access public
490
     */
491
    function getOption($option)
492
    {
493
        if (isset($this->options[$option])) {
494
            return($this->options[$option]);
495
        }
496
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
497
    }
498
 
499
    // }}}
500
    // {{{ captureDebugOutput()
501
 
502
    /**
503
     * set a debug handler
504
     *
505
     * @param string $capture name of the function that should be used in
506
     *      debug()
507
     * @access public
508
     * @see debug()
509
     */
510
    function captureDebugOutput($capture)
511
    {
512
        $this->pass_debug_handle = $capture;
513
        $this->debug = ($capture ? 'MDB_defaultDebugOutput' : '');
514
    }
515
 
516
    // }}}
517
    // {{{ debug()
518
 
519
    /**
520
     * set a debug message
521
     *
522
     * @param string $message Message with information for the user.
523
     * @access public
524
     */
525
    function debug($message)
526
    {
527
        if (strcmp($function = $this->debug, '')) {
528
            if ($this->pass_debug_handle) {
529
                $function($this, $message);
530
            } else {
531
                $function($message);
532
            }
533
        }
534
    }
535
 
536
    // }}}
537
    // {{{ debugOutput()
538
 
539
    /**
540
     * output debug info
541
     *
542
     * @return string content of the debug_output class variable
543
     * @access public
544
     */
545
    function debugOutput()
546
    {
547
        return($this->debug_output);
548
    }
549
 
550
    // }}}
551
    // {{{ setError() (deprecated)
552
 
553
    /**
554
     * set an error (deprecated)
555
     *
556
     * @param string $scope Scope of the error message
557
     *     (usually the method tht caused the error)
558
     * @param string $message Message with information for the user.
559
     * @return boolean FALSE
560
     * @access private
561
     */
562
    function setError($scope, $message)
563
    {
564
        $this->last_error = $message;
565
        $this->debug($scope . ': ' . $message);
566
        if (($function = $this->error_handler) != '') {
567
            $error = array(
568
                'Scope' => $scope,
569
                'Message' => $message
570
            );
571
            $function($this, $error);
572
        }
573
        return(0);
574
    }
575
 
576
    // }}}
577
    // {{{ setErrorHandler() (deprecated)
578
 
579
    /**
580
     * Specify a function that is called when an error occurs.
581
     *
582
     * @param string $function Name of the function that will be called on
583
     *      error. If an empty string is specified, no handler function is
584
     *      called on error. The error handler function receives two arguments.
585
     *      The first argument a reference to the driver class object that
586
     *      triggered the error.
587
     *
588
     *      The second argument is a reference to an associative array that
589
     *      provides details about the error that occured. These details provide
590
     *      more information than it is returned by the MetabaseError function.
591
     *
592
     *      These are the currently supported error detail entries:
593
     *
594
     *      Scope
595
     *       String that indicates the scope of the driver object class
596
     *       within which the error occured.
597
     *
598
     *      Message
599
     *       Error message as is returned by the MetabaseError function.
600
     * @return string name of last function
601
     * @access public
602
     */
603
    function setErrorHandler($function)
604
    {
605
        $last_function = $this->error_handler;
606
        $this->error_handler = $function;
607
        return($last_function);
608
    }
609
 
610
    // }}}
611
    // {{{ error() (deprecated)
612
 
613
    /**
614
     * Retrieve the error message text associated with the last operation that
615
     * failed. Some functions may fail but they do not return the reason that
616
     * makes them to fail. This function is meant to retrieve a textual
617
     * description of the failure cause.
618
     *
619
     * @return string the error message text associated with the last failure.
620
     * @access public
621
     */
622
    function error()
623
    {
624
        return($this->last_error);
625
    }
626
 
627
    // }}}
628
    // {{{ _quote()
629
 
630
    /**
631
     * Quotes a string so it can be safely used in a query. It will quote
632
     * the text so it can safely be used within a query.
633
     *
634
     * @param string $text the input string to quote
635
     * @return string quoted string
636
     * @access private
637
     */
638
    function _quote($text)
639
    {
640
        if (strcmp($this->escape_quotes, "'")) {
641
            $text = str_replace($this->escape_quotes, $this->escape_quotes . $this->escape_quotes, $text);
642
        }
643
        return str_replace("'", $this->escape_quotes . "'", $text);
644
    }
645
 
646
    // }}}
647
    // {{{ quoteIdentifier()
648
 
649
    /**
650
     * Quote a string so it can be safely used as a table or column name
651
     *
652
     * Delimiting style depends on which database driver is being used.
653
     *
654
     * NOTE: just because you CAN use delimited identifiers doesn't mean
655
     * you SHOULD use them.  In general, they end up causing way more
656
     * problems than they solve.
657
     *
658
     * Portability is broken by using the following characters inside
659
     * delimited identifiers:
660
     *   + backtick (<kbd>`</kbd>) -- due to MySQL
661
     *   + double quote (<kbd>"</kbd>) -- due to Oracle
662
     *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
663
     *
664
     * Delimited identifiers are known to generally work correctly under
665
     * the following drivers:
666
     *   + mssql
667
     *   + mysql
668
     *   + mysqli
669
     *   + oci8
670
     *   + odbc(access)
671
     *   + odbc(db2)
672
     *   + pgsql
673
     *   + sqlite
674
     *   + sybase
675
     *
676
     * InterBase doesn't seem to be able to use delimited identifiers
677
     * via PHP 4.  They work fine under PHP 5.
678
     *
679
     * @param string $str  identifier name to be quoted
680
     *
681
     * @return string  quoted identifier string
682
     *
683
     * @access public
684
     */
685
    function quoteIdentifier($str)
686
    {
687
        return '"' . str_replace('"', '""', $str) . '"';
688
    }
689
 
690
    // }}}
691
    // {{{ _loadModule()
692
 
693
    /**
694
     * loads an module
695
     *
696
     * @param string $scope information about what method is being loaded,
697
     *      that is used for error messages
698
     * @param string $module name of the module that should be loaded
699
     *      (only used for error messages)
700
     * @param string $included_constant name of the constant that should be
701
     *      defined when the module has been loaded
702
     * @param string $include name of the script that includes the module
703
     * @access private
704
     */
705
    function _loadModule($scope, $module, $included_constant, $include)
706
    {
707
        if (strlen($included_constant) == 0 || !defined($included_constant)) {
708
            if($include) {
709
                $include = 'MDB/Modules/'.$include;
710
                if(MDB::isError($debug = $this->getOption('debug')) || $debug > 2) {
711
                    include_once($include);
712
                } else {
713
                    @include_once($include);
714
                }
715
            } else {
716
                return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
717
                    $scope . ': it was not specified an existing ' . $module . ' file (' . $include . ')'));
718
            }
719
        }
720
        return(MDB_OK);
721
    }
722
 
723
    // }}}
724
    // {{{ loadLob()
725
 
726
    /**
727
     * loads the LOB module
728
     *
729
     * @param string $scope information about what method is being loaded,
730
     *                       that is used for error messages
731
     * @access public
732
     */
733
    function loadLob($scope = '')
734
    {
735
        if (defined('MDB_LOB_INCLUDED')) {
736
            return(MDB_OK);
737
        }
738
        $result = $this->_loadModule($scope, 'LOB',
739
            'MDB_LOB_INCLUDED', 'LOB.php');
740
        if (MDB::isError($result)) {
741
            return($result);
742
        }
743
        return(MDB_OK);
744
    }
745
 
746
    // }}}
747
    // {{{ loadManager()
748
 
749
    /**
750
     * loads the Manager module
751
     *
752
     * @param string $scope information about what method is being loaded,
753
     *                       that is used for error messages
754
     * @access public
755
     */
756
    function loadManager($scope = '')
757
    {
758
        if (isset($this->manager) && is_object($this->manager)) {
759
            return(MDB_OK);
760
        }
761
        $result = $this->_loadModule($scope, 'Manager',
762
            'MDB_MANAGER_'.strtoupper($this->phptype).'_INCLUDED',
763
            'Manager/'.$this->phptype.'.php');
764
        if (MDB::isError($result)) {
765
            return($result);
766
        }
767
        $class_name = 'MDB_Manager_'.$this->dbsyntax;
768
        if (!class_exists($class_name)) {
769
            return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
770
                'Unable to load extension'));
771
        }
772
        @$this->manager = new $class_name;
773
        return(MDB_OK);
774
    }
775
 
776
    // }}}
777
    // {{{ autoCommit()
778
 
779
    /**
780
     * Define whether database changes done on the database be automatically
781
     * committed. This function may also implicitly start or end a transaction.
782
     *
783
     * @param boolean $auto_commit flag that indicates whether the database
784
     *      changes should be committed right after executing every query
785
     *      statement. If this argument is 0 a transaction implicitly started.
786
     *      Otherwise, if a transaction is in progress it is ended by committing
787
     *      any database changes that were pending.
788
     * @return mixed MDB_OK on success, a MDB error on failure
789
     * @access public
790
     */
791
    function autoCommit($auto_commit)
792
    {
793
        $this->debug('AutoCommit: ' . ($auto_commit ? 'On' : 'Off'));
794
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
795
            'Auto-commit transactions: transactions are not supported'));
796
    }
797
 
798
    // }}}
799
    // {{{ commit()
800
 
801
    /**
802
     * Commit the database changes done during a transaction that is in
803
     * progress. This function may only be called when auto-committing is
804
     * disabled, otherwise it will fail. Therefore, a new transaction is
805
     * implicitly started after committing the pending changes.
806
     *
807
     * @return mixed MDB_OK on success, a MDB error on failure
808
     * @access public
809
     */
810
    function commit()
811
    {
812
        $this->debug('Commit Transaction');
813
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
814
            'Commit transaction: commiting transactions are not supported'));
815
    }
816
 
817
    // }}}
818
    // {{{ rollback()
819
 
820
    /**
821
     * Cancel any database changes done during a transaction that is in
822
     * progress. This function may only be called when auto-committing is
823
     * disabled, otherwise it will fail. Therefore, a new transaction is
824
     * implicitly started after canceling the pending changes.
825
     *
826
     * @return mixed MDB_OK on success, a MDB error on failure
827
     * @access public
828
     */
829
    function rollback()
830
    {
831
        $this->debug('Rollback Transaction');
832
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
833
            'Rollback transaction: rolling back transactions are not supported'));
834
    }
835
 
836
    // }}}
837
    // {{{ disconnect()
838
 
839
    /**
840
     * Log out and disconnect from the database.
841
     *
842
     * @return mixed TRUE on success, FALSE if not connected and error
843
     *                object on error
844
     * @access public
845
     */
846
    function disconnect()
847
    {
848
        if ($this->in_transaction && !MDB::isError($this->rollback()) && !MDB::isError($this->autoCommit(TRUE))) {
849
            $this->in_transaction = FALSE;
850
        }
851
        return($this->_close());
852
    }
853
 
854
    // }}}
855
    // {{{ _close()
856
 
857
    /**
858
     * all the RDBMS specific things needed to close a DB connection
859
     *
860
     * @access private
861
     */
862
    function _close()
863
    {
864
        unset($GLOBALS['_MDB_databases'][$this->database]);
865
    }
866
 
867
    // }}}
868
    // {{{ setDatabase()
869
 
870
    /**
871
     * Select a different database
872
     *
873
     * @param string $name name of the database that should be selected
874
     * @return string name of the database previously connected to
875
     * @access public
876
     */
877
    function setDatabase($name)
878
    {
879
        $previous_database_name = $this->database_name;
880
        $this->database_name = $name;
881
        return($previous_database_name);
882
    }
883
 
884
    // }}}
885
    // {{{ setDSN()
886
 
887
    /**
888
     * set the DSN
889
     *
890
     * @param mixed     $dsninfo    DSN string or array
891
     * @return MDB_OK
892
     * @access public
893
     */
894
    function setDSN($dsn)
895
    {
896
        $dsninfo = MDB::parseDSN($dsn);
897
        if(isset($dsninfo['hostspec'])) {
898
            $this->host = $dsninfo['hostspec'];
899
        }
900
        if(isset($dsninfo['port'])) {
901
            $this->port = $dsninfo['port'];
902
        }
903
        if(isset($dsninfo['username'])) {
904
            $this->user = $dsninfo['username'];
905
        }
906
        if(isset($dsninfo['password'])) {
907
            $this->password = $dsninfo['password'];
908
        }
909
        if(isset($dsninfo['database'])) {
910
            $this->database_name = $dsninfo['database'];
911
        }
912
        return(MDB_OK);
913
    }
914
 
915
    // }}}
916
    // {{{ getDSN()
917
 
918
    /**
919
     * return the DSN as a string
920
     *
921
     * @param string     $type    type to return
922
     * @return mixed DSN in the chosen type
923
     * @access public
924
     */
925
    function getDSN($type = 'string')
926
    {
927
        switch($type) {
928
            case 'array':
929
                $dsn = array(
930
                    'phptype' => $this->phptype,
931
                    'username' => $this->user,
932
                    'password' => $this->password,
933
                    'hostspec' => $this->host,
934
                    'database' => $this->database_name
935
                );
936
                break;
937
            default:
938
                $dsn = $this->phptype.'://'.$this->user.':'
939
                    .$this->password.'@'.$this->host
940
                    .($this->port ? (':'.$this->port) : '')
941
                    .'/'.$this->database_name;
942
                break;
943
        }
944
        return($dsn);
945
    }
946
 
947
    // }}}
948
    // {{{ createDatabase()
949
 
950
    /**
951
     * create a new database
952
     *
953
     * @param string $name name of the database that should be created
954
     * @return mixed MDB_OK on success, a MDB error on failure
955
     * @access public
956
     */
957
    function createDatabase($name)
958
    {
959
        $result = $this->loadManager('Create database');
960
        if (MDB::isError($result)) {
961
            return($result);
962
        }
963
        return($this->manager->createDatabase($this, $name));
964
    }
965
 
966
    // }}}
967
    // {{{ dropDatabase()
968
 
969
    /**
970
     * drop an existing database
971
     *
972
     * @param string $name name of the database that should be dropped
973
     * @return mixed MDB_OK on success, a MDB error on failure
974
     * @access public
975
     */
976
    function dropDatabase($name)
977
    {
978
        $result = $this->loadManager('Drop database');
979
        if (MDB::isError($result)) {
980
            return($result);
981
        }
982
        return($this->manager->dropDatabase($this, $name));
983
    }
984
 
985
    // }}}
986
    // {{{ createTable()
987
 
988
    /**
989
     * create a new table
990
     *
991
     * @param string $name Name of the database that should be created
992
     * @param array $fields Associative array that contains the definition of
993
     *      each field of the new table. The indexes of the array entries are
994
     *      the names of the fields of the table an the array entry values are
995
     *      associative arrays like those that are meant to be passed with the
996
     *      field definitions to get[Type]Declaration() functions.
997
     *
998
     *      Example
999
     *        array(
1000
     *            'id' => array(
1001
     *                'type' => 'integer',
1002
     *                'unsigned' => 1
1003
     *                'notnull' => 1
1004
     *                'default' => 0
1005
     *            ),
1006
     *            'name' => array(
1007
     *                'type' => 'text',
1008
     *                'length' => 12
1009
     *            ),
1010
     *            'password' => array(
1011
     *                'type' => 'text',
1012
     *                'length' => 12
1013
     *            )
1014
     *        );
1015
     * @return mixed MDB_OK on success, a MDB error on failure
1016
     * @access public
1017
     */
1018
    function createTable($name, $fields)
1019
    {
1020
        $result = $this->loadManager('Create table');
1021
        if (MDB::isError($result)) {
1022
            return($result);
1023
        }
1024
        return($this->manager->createTable($this, $name, $fields));
1025
    }
1026
 
1027
    // }}}
1028
    // {{{ dropTable()
1029
 
1030
    /**
1031
     * drop an existing table
1032
     *
1033
     * @param string $name name of the table that should be dropped
1034
     * @return mixed MDB_OK on success, a MDB error on failure
1035
     * @access public
1036
     */
1037
    function dropTable($name)
1038
    {
1039
        $result = $this->loadManager('Drop table');
1040
        if (MDB::isError($result)) {
1041
            return($result);
1042
        }
1043
        return($this->manager->dropTable($this, $name));
1044
    }
1045
 
1046
    // }}}
1047
    // {{{ alterTable()
1048
 
1049
    /**
1050
     * alter an existing table
1051
     *
1052
     * @param string $name name of the table that is intended to be changed.
1053
     * @param array  $changes associative array that contains the details of
1054
     *       each type of change that is intended to be performed. The types of
1055
     *       changes that are currently supported are defined as follows:
1056
     *
1057
     *  name
1058
     *      New name for the table.
1059
     *
1060
     *  AddedFields
1061
     *      Associative array with the names of fields to be added as indexes of
1062
     *      the array. The value of each entry of the array should be set to
1063
     *      another associative array with the properties of the fields to be
1064
     *      added. The properties of the fields should be the same as defined by
1065
     *      the Metabase parser.
1066
     *
1067
     *      Additionally, there should be an entry named Declaration that is
1068
     *      expected to contain the portion of the field declaration already in
1069
     *       DBMS specific SQL code as it is used in the CREATE TABLE statement.
1070
     *
1071
     *  RemovedFields
1072
     *      Associative array with the names of fields to be removed as indexes of
1073
     *      the array. Currently the values assigned to each entry are ignored. An
1074
     *      empty array should be used for future compatibility.
1075
     *
1076
     *  RenamedFields
1077
     *      Associative array with the names of fields to be renamed as indexes of
1078
     *      the array. The value of each entry of the array should be set to another
1079
     *      associative array with the entry named name with the new field name and
1080
     *      the entry named Declaration that is expected to contain the portion of
1081
     *      the field declaration already in DBMS specific SQL code as it is used
1082
     *      in the CREATE TABLE statement.
1083
     *
1084
     *  ChangedFields
1085
     *      Associative array with the names of the fields to be changed as indexes
1086
     *      of the array. Keep in mind that if it is intended to change either the
1087
     *      name of a field and any other properties, the ChangedFields array
1088
     *      entries should have the new names of the fields as array indexes.
1089
     *
1090
     *      The value of each entry of the array should be set to another
1091
     *      associative array with the properties of the fields to that are meant
1092
     *      to be changed as array entries. These entries should be assigned to the
1093
     *      new values of the respective properties. The properties of the fields
1094
     *      should be the* same as defined by the Metabase parser.
1095
     *
1096
     *      If the default property is meant to be added, removed or changed, there
1097
     *      should also be an entry with index ChangedDefault assigned to 1.
1098
     *      Similarly, if the notnull constraint is to be added or removed, there
1099
     *      should also be an entry with index ChangedNotNull assigned to 1.
1100
     *
1101
     *      Additionally, there should be an entry named Declaration that is
1102
     *      expected to contain the portion of the field changed declaration
1103
     *      already in DBMS specific SQL code as it is used in the CREATE TABLE
1104
     *      statement.
1105
     *
1106
     *  Example
1107
     *      array(
1108
     *          'name' => 'userlist',
1109
     *          'AddedFields' => array(
1110
     *              'quota' => array(
1111
     *                  'type' => 'integer',
1112
     *                  'unsigned' => 1,
1113
     *                  'Declaration' => 'quota INT'
1114
     *              )
1115
     *          ),
1116
     *          'RemovedFields' => array(
1117
     *              'file_limit' => array(),
1118
     *              'time_limit' => array()
1119
     *          ),
1120
     *          'ChangedFields' => array(
1121
     *              'gender' => array(
1122
     *                  'default' => 'M',
1123
     *                  'ChangeDefault' => 1,
1124
     *                  'Declaration' => "gender CHAR(1) DEFAULT 'M'"
1125
     *              )
1126
     *          ),
1127
     *          'RenamedFields' => array(
1128
     *              'sex' => array(
1129
     *                  'name' => 'gender',
1130
     *                  'Declaration' => "gender CHAR(1) DEFAULT 'M'"
1131
     *              )
1132
     *          )
1133
     *      )
1134
     *
1135
     * @param boolean $check indicates whether the function should just check
1136
     *       if the DBMS driver can perform the requested table alterations if
1137
     *       the value is TRUE or actually perform them otherwise.
1138
     * @return mixed MDB_OK on success, a MDB error on failure
1139
     * @access public
1140
     */
1141
    function alterTable($name, $changes, $check)
1142
    {
1143
        $result = $this->loadManager('Alter table');
1144
        if (MDB::isError($result)) {
1145
            return($result);
1146
        }
1147
        return($this->manager->alterTable($this, $name, $changes, $check));
1148
    }
1149
 
1150
    // }}}
1151
    // {{{ listDatabases()
1152
 
1153
    /**
1154
     * list all databases
1155
     *
1156
     * @return mixed data array on success, a MDB error on failure
1157
     * @access public
1158
     */
1159
    function listDatabases()
1160
    {
1161
        $result = $this->loadManager('List databases');
1162
        if (MDB::isError($result)) {
1163
            return($result);
1164
        }
1165
        return($this->manager->listDatabases($this));
1166
    }
1167
 
1168
    // }}}
1169
    // {{{ listUsers()
1170
 
1171
    /**
1172
     * list all users
1173
     *
1174
     * @return mixed data array on success, a MDB error on failure
1175
     * @access public
1176
     */
1177
    function listUsers()
1178
    {
1179
        $result = $this->loadManager('List users');
1180
        if (MDB::isError($result)) {
1181
            return($result);
1182
        }
1183
        return($this->manager->listUsers($this));
1184
    }
1185
 
1186
    // }}}
1187
    // {{{ listViews()
1188
 
1189
    /**
1190
     * list all viewes in the current database
1191
     *
1192
     * @return mixed data array on success, a MDB error on failure
1193
     * @access public
1194
     */
1195
    function listViews()
1196
    {
1197
        $result = $this->loadManager('List views');
1198
        if (MDB::isError($result)) {
1199
            return($result);
1200
        }
1201
        return($this->manager->listViews($this));
1202
    }
1203
 
1204
    // }}}
1205
    // {{{ listFunctions()
1206
 
1207
    /**
1208
     * list all functions in the current database
1209
     *
1210
     * @return mixed data array on success, a MDB error on failure
1211
     * @access public
1212
     */
1213
    function listFunctions()
1214
    {
1215
        $result = $this->loadManager('List functions');
1216
        if (MDB::isError($result)) {
1217
            return($result);
1218
        }
1219
        return($this->manager->listFunctions($this));
1220
    }
1221
 
1222
    // }}}
1223
    // {{{ listTables()
1224
 
1225
    /**
1226
     * list all tables in the current database
1227
     *
1228
     * @return mixed data array on success, a MDB error on failure
1229
     * @access public
1230
     */
1231
    function listTables()
1232
    {
1233
        $result = $this->loadManager('List tables');
1234
        if (MDB::isError($result)) {
1235
            return($result);
1236
        }
1237
        return($this->manager->listTables($this));
1238
    }
1239
 
1240
    // }}}
1241
    // {{{ listTableFields()
1242
 
1243
    /**
1244
     * list all fields in a tables in the current database
1245
     *
1246
     * @param string $table name of table that should be used in method
1247
     * @return mixed data array on success, a MDB error on failure
1248
     * @access public
1249
     */
1250
    function listTableFields($table)
1251
    {
1252
        $result = $this->loadManager('List table fields');
1253
        if (MDB::isError($result)) {
1254
            return($result);
1255
        }
1256
        return($this->manager->listTableFields($this, $table));
1257
    }
1258
 
1259
    // }}}
1260
    // {{{ getTableFieldDefinition()
1261
 
1262
    /**
1263
     * get the stucture of a field into an array
1264
     *
1265
     * @param string $table name of table that should be used in method
1266
     * @param string $fields name of field that should be used in method
1267
     * @return mixed data array on success, a MDB error on failure
1268
     * @access public
1269
     */
1270
    function getTableFieldDefinition($table, $field)
1271
    {
1272
        $result = $this->loadManager('Get table field definition');
1273
        if (MDB::isError($result)) {
1274
            return($result);
1275
        }
1276
        return($this->manager->getTableFieldDefinition($this, $table, $field));
1277
    }
1278
 
1279
    // }}}
1280
    // {{{ getFieldDeclaration()
1281
 
1282
    /**
1283
     * get declaration of a field
1284
     *
1285
     * @param string $field_name name of the field to be created
1286
     * @param string $field associative array with the name of the properties
1287
     *       of the field being declared as array indexes. Currently, the types
1288
     *       of supported field properties are as follows:
1289
     *
1290
     *       default
1291
     *           Boolean value to be used as default for this field.
1292
     *
1293
     *       notnull
1294
     *           Boolean flag that indicates whether this field is constrained
1295
     *           to not be set to NULL.
1296
     * @return mixed string on success, a MDB error on failure
1297
     * @access public
1298
     */
1299
    function getFieldDeclaration($field_name, $field)
1300
    {
1301
        $result = $this->loadManager('Get table field definition');
1302
        if (MDB::isError($result)) {
1303
            return($result);
1304
        }
1305
        return($this->manager->getFieldDeclaration($this, $field_name, $field));
1306
    }
1307
 
1308
    // }}}
1309
    // {{{ getFieldDeclarationList()
1310
 
1311
    /**
1312
     * get declaration of a number of field in bulk
1313
     *
1314
     * @param string $fields a multidimensional associative array.
1315
     * The first dimension determines the field name, while the second
1316
     * dimension is keyed with the name of the properties
1317
     *       of the field being declared as array indexes. Currently, the types
1318
     *       of supported field properties are as follows:
1319
     *
1320
     *       default
1321
     *           Boolean value to be used as default for this field.
1322
     *
1323
     *       notnull
1324
     *           Boolean flag that indicates whether this field is constrained
1325
     *           to not be set to NULL.
1326
     *
1327
     *       default
1328
     *           Boolean value to be used as default for this field.
1329
     *
1330
     *       notnull
1331
     *           Boolean flag that indicates whether this field is constrained
1332
     *           to not be set to NULL.
1333
     * @return mixed string on success, a MDB error on failure
1334
     * @access public
1335
     */
1336
    function getFieldDeclarationList($fields)
1337
    {
1338
        $result = $this->loadManager('Get table field list');
1339
        if (MDB::isError($result)) {
1340
            return($result);
1341
        }
1342
        return($this->manager->getFieldDeclarationList($this, $fields));
1343
    }
1344
 
1345
    // }}}
1346
    // {{{ _isSequenceName()
1347
 
1348
    /**
1349
     * list all tables in the current database
1350
     *
1351
     * @param string $sqn string that containts name of a potential sequence
1352
     * @return mixed name of the sequence if $sqn is a name of a sequence, else FALSE
1353
     * @access private
1354
     */
1355
    function _isSequenceName($sqn)
1356
    {
1357
        $result = $this->loadManager('is sequence name');
1358
        if (MDB::isError($result)) {
1359
            return($result);
1360
        }
1361
        return($this->manager->_isSequenceName($this, $sqn));
1362
    }
1363
 
1364
    // }}}
1365
    // {{{ createIndex()
1366
 
1367
    /**
1368
     * get the stucture of a field into an array
1369
     *
1370
     * @param string $table name of the table on which the index is to be
1371
     *       created
1372
     * @param string $name name of the index to be created
1373
     * @param array $definition associative array that defines properties of
1374
     *       the index to be created. Currently, only one property named FIELDS
1375
     *       is supported. This property is also an associative with the names
1376
     *       of the index fields as array indexes. Each entry of this array is
1377
     *       set to another type of associative array that specifies properties
1378
     *       of the index that are specific to each field.
1379
     *
1380
     *       Currently, only the sorting property is supported. It should be
1381
     *       used to define the sorting direction of the index. It may be set
1382
     *       to either ascending or descending. Not all DBMS support index
1383
     *       sorting direction configuration. The DBMS drivers of those that do
1384
     *       not support it ignore this property. Use the function support() to
1385
     *       determine whether the DBMS driver can manage indexes.
1386
     *
1387
     *       Example
1388
     *          array(
1389
     *              'FIELDS' => array(
1390
     *                  'user_name' => array(
1391
     *                      'sorting' => 'ascending'
1392
     *                  ),
1393
     *                  'last_login' => array()
1394
     *              )
1395
     *          )
1396
     * @return mixed MDB_OK on success, a MDB error on failure
1397
     * @access public
1398
     */
1399
    function createIndex($table, $name, $definition)
1400
    {
1401
        $result = $this->loadManager('Create index');
1402
        if (MDB::isError($result)) {
1403
            return($result);
1404
        }
1405
        return($this->manager->createIndex($this, $table, $name, $definition));
1406
    }
1407
 
1408
    // }}}
1409
    // {{{ dropIndex()
1410
 
1411
    /**
1412
     * drop existing index
1413
     *
1414
     * @param string $table name of table that should be used in method
1415
     * @param string $name name of the index to be dropped
1416
     * @return mixed MDB_OK on success, a MDB error on failure
1417
     * @access public
1418
     */
1419
    function dropIndex($table, $name)
1420
    {
1421
        $result = $this->loadManager('Drop index');
1422
        if (MDB::isError($result)) {
1423
            return($result);
1424
        }
1425
        return($this->manager->dropIndex($this, $table , $name));
1426
    }
1427
 
1428
    // }}}
1429
    // {{{ listTableIndexes()
1430
 
1431
    /**
1432
     * list all indexes in a table
1433
     *
1434
     * @param string $table name of table that should be used in method
1435
     * @return mixed data array on success, a MDB error on failure
1436
     * @access public
1437
     */
1438
    function listTableIndexes($table)
1439
    {
1440
        $result = $this->loadManager('List table index');
1441
        if (MDB::isError($result)) {
1442
            return($result);
1443
        }
1444
        return($this->manager->listTableIndexes($this, $table));
1445
    }
1446
 
1447
    // }}}
1448
    // {{{ getTableIndexDefinition()
1449
 
1450
    /**
1451
     * get the stucture of an index into an array
1452
     *
1453
     * @param string $table name of table that should be used in method
1454
     * @param string $index name of index that should be used in method
1455
     * @return mixed data array on success, a MDB error on failure
1456
     * @access public
1457
     */
1458
    function getTableIndexDefinition($table, $index)
1459
    {
1460
        $result = $this->loadManager('Get table index definition');
1461
        if (MDB::isError($result)) {
1462
            return($result);
1463
        }
1464
        return($this->manager->getTableIndexDefinition($this, $table, $index));
1465
    }
1466
 
1467
    // }}}
1468
    // {{{ createSequence()
1469
 
1470
    /**
1471
     * create sequence
1472
     *
1473
     * @param string $name name of the sequence to be created
1474
     * @param string $start start value of the sequence; default is 1
1475
     * @return mixed MDB_OK on success, a MDB error on failure
1476
     * @access public
1477
     */
1478
    function createSequence($name, $start = 1)
1479
    {
1480
        $result = $this->loadManager('Create sequence');
1481
        if (MDB::isError($result)) {
1482
            return($result);
1483
        }
1484
        return($this->manager->createSequence($this, $name, $start));
1485
    }
1486
 
1487
    // }}}
1488
    // {{{ dropSequence()
1489
 
1490
    /**
1491
     * drop existing sequence
1492
     *
1493
     * @param string $name name of the sequence to be dropped
1494
     * @return mixed MDB_OK on success, a MDB error on failure
1495
     * @access public
1496
     */
1497
    function dropSequence($name)
1498
    {
1499
        $result = $this->loadManager('Drop sequence');
1500
        if (MDB::isError($result)) {
1501
            return($result);
1502
        }
1503
        return($this->manager->dropSequence($this, $name));
1504
    }
1505
 
1506
    // }}}
1507
    // {{{ listSequences()
1508
 
1509
    /**
1510
     * list all tables in the current database
1511
     *
1512
     * @return mixed data array on success, a MDB error on failure
1513
     * @access public
1514
     */
1515
    function listSequences()
1516
    {
1517
        $result = $this->loadManager('List sequences');
1518
        if (MDB::isError($result)) {
1519
            return($result);
1520
        }
1521
        return($this->manager->listSequences($this));
1522
    }
1523
 
1524
    // }}}
1525
    // {{{ getSequenceDefinition()
1526
 
1527
    /**
1528
     * get the stucture of a sequence into an array
1529
     *
1530
     * @param string $sequence name of sequence that should be used in method
1531
     * @return mixed data array on success, a MDB error on failure
1532
     * @access public
1533
     */
1534
    function getSequenceDefinition($sequence)
1535
    {
1536
        $result = $this->loadManager('Get sequence definition');
1537
        if (MDB::isError($result)) {
1538
            return($result);
1539
        }
1540
        return($this->manager->getSequenceDefinition($this, $sequence));
1541
    }
1542
 
1543
    // }}}
1544
    // {{{ query()
1545
 
1546
    /**
1547
     * Send a query to the database and return any results
1548
     *
1549
     * @param string $query the SQL query
1550
     * @param mixed   $types  array that contains the types of the columns in
1551
     *                        the result set
1552
     * @return mixed a result handle or MDB_OK on success, a MDB error on failure
1553
     * @access public
1554
     */
1555
    function query($query, $types = NULL)
1556
    {
1557
        $this->debug("Query: $query");
1558
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Query: database queries are not implemented'));
1559
    }
1560
 
1561
    // }}}
1562
    // {{{ setSelectedRowRange()
1563
 
1564
    /**
1565
     * set the range of the next query
1566
     *
1567
     * @param string $first first row to select
1568
     * @param string $limit number of rows to select
1569
     * @return mixed MDB_OK on success, a MDB error on failure
1570
     * @access public
1571
     */
1572
    function setSelectedRowRange($first, $limit)
1573
    {
1574
        if (!isset($this->supported['SelectRowRanges'])) {
1575
            return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
1576
                'Set selected row range: selecting row ranges is not supported by this driver'));
1577
        }
1578
        $first = (int)$first;
1579
        if ($first < 0) {
1580
            return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
1581
                'Set selected row range: it was not specified a valid first selected range row'));
1582
        }
1583
        $limit = (int)$limit;
1584
        if ($limit < 1) {
1585
            return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
1586
                'Set selected row range: it was not specified a valid selected range row limit'));
1587
        }
1588
        $this->first_selected_row = $first;
1589
        $this->selected_row_limit = $limit;
1590
        return(MDB_OK);
1591
    }
1592
 
1593
    // }}}
1594
    // {{{ limitQuery()
1595
 
1596
    /**
1597
     * Generates a limited query
1598
     *
1599
     * @param string $query query
1600
     * @param mixed   $types  array that contains the types of the columns in
1601
     *                        the result set
1602
     * @param integer $from the row to start to fetching
1603
     * @param integer $count the numbers of rows to fetch
1604
     * @return mixed a valid ressource pointer or a MDB_Error
1605
     * @access public
1606
     */
1607
    function limitQuery($query, $types = NULL, $from, $count)
1608
    {
1609
        $result = $this->setSelectedRowRange($from, $count);
1610
        if (MDB::isError($result)) {
1611
            return($result);
1612
        }
1613
        return($this->query($query, $types));
1614
    }
1615
 
1616
    // }}}
1617
    // {{{ subSelect()
1618
 
1619
    /**
1620
     * simple subselect emulation: leaves the query untouched for all RDBMS
1621
     * that support subselects
1622
     *
1623
     * @access public
1624
     *
1625
     * @param string $query the SQL query for the subselect that may only
1626
     *                      return a column
1627
     * @param string $quote determines if the data needs to be quoted before
1628
     *                      being returned
1629
     *
1630
     * @return string the query
1631
     */
1632
    function subSelect($query, $quote = FALSE)
1633
    {
1634
        if ($this->supported['SubSelects'] == 1) {
1635
            return($query);
1636
        }
1637
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Subselect: subselect not implemented'));
1638
    }
1639
 
1640
    // }}}
1641
    // {{{ replace()
1642
 
1643
    /**
1644
     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
1645
     * query, except that if there is already a row in the table with the same
1646
     * key field values, the REPLACE query just updates its values instead of
1647
     * inserting a new row.
1648
     *
1649
     * The REPLACE type of query does not make part of the SQL standards. Since
1650
     * pratically only MySQL implements it natively, this type of query is
1651
     * emulated through this method for other DBMS using standard types of
1652
     * queries inside a transaction to assure the atomicity of the operation.
1653
     *
1654
     * @param string $table name of the table on which the REPLACE query will
1655
     *       be executed.
1656
     * @param array $fields associative array that describes the fields and the
1657
     *       values that will be inserted or updated in the specified table. The
1658
     *       indexes of the array are the names of all the fields of the table.
1659
     *       The values of the array are also associative arrays that describe
1660
     *       the values and other properties of the table fields.
1661
     *
1662
     *       Here follows a list of field properties that need to be specified:
1663
     *
1664
     *       Value
1665
     *           Value to be assigned to the specified field. This value may be
1666
     *           of specified in database independent type format as this
1667
     *           function can perform the necessary datatype conversions.
1668
     *
1669
     *           Default: this property is required unless the Null property is
1670
     *           set to 1.
1671
     *
1672
     *       Type
1673
     *           Name of the type of the field. Currently, all types Metabase
1674
     *           are supported except for clob and blob.
1675
     *
1676
     *           Default: no type conversion
1677
     *
1678
     *       Null
1679
     *           Boolean property that indicates that the value for this field
1680
     *           should be set to NULL.
1681
     *
1682
     *           The default value for fields missing in INSERT queries may be
1683
     *           specified the definition of a table. Often, the default value
1684
     *           is already NULL, but since the REPLACE may be emulated using
1685
     *           an UPDATE query, make sure that all fields of the table are
1686
     *           listed in this function argument array.
1687
     *
1688
     *           Default: 0
1689
     *
1690
     *       Key
1691
     *           Boolean property that indicates that this field should be
1692
     *           handled as a primary key or at least as part of the compound
1693
     *           unique index of the table that will determine the row that will
1694
     *           updated if it exists or inserted a new row otherwise.
1695
     *
1696
     *           This function will fail if no key field is specified or if the
1697
     *           value of a key field is set to NULL because fields that are
1698
     *           part of unique index they may not be NULL.
1699
     *
1700
     *           Default: 0
1701
     * @return mixed MDB_OK on success, a MDB error on failure
1702
     * @access public
1703
     */
1704
    function replace($table, $fields)
1705
    {
1706
        if (!$this->supported['Replace']) {
1707
            return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Replace: replace query is not supported'));
1708
        }
1709
        $count = count($fields);
1710
        for($keys = 0, $condition = $insert = $values = '', reset($fields), $field = 0;
1711
            $field < $count;
1712
            next($fields), $field++)
1713
        {
1714
            $name = key($fields);
1715
            if ($field > 0) {
1716
                $insert .= ', ';
1717
                $values .= ', ';
1718
            }
1719
            $insert .= $name;
1720
            if (isset($fields[$name]['Null']) && $fields[$name]['Null']) {
1721
                $value = 'NULL';
1722
            } else {
1723
                if(isset($fields[$name]['Type'])) {
1724
                    switch ($fields[$name]['Type']) {
1725
                        case 'text':
1726
                            $value = $this->getTextValue($fields[$name]['Value']);
1727
                            break;
1728
                        case 'boolean':
1729
                            $value = $this->getBooleanValue($fields[$name]['Value']);
1730
                            break;
1731
                        case 'integer':
1732
                            $value = $this->getIntegerValue($fields[$name]['Value']);
1733
                            break;
1734
                        case 'decimal':
1735
                            $value = $this->getDecimalValue($fields[$name]['Value']);
1736
                            break;
1737
                        case 'float':
1738
                            $value = $this->getFloatValue($fields[$name]['Value']);
1739
                            break;
1740
                        case 'date':
1741
                            $value = $this->getDateValue($fields[$name]['Value']);
1742
                            break;
1743
                        case 'time':
1744
                            $value = $this->getTimeValue($fields[$name]['Value']);
1745
                            break;
1746
                        case 'timestamp':
1747
                            $value = $this->getTimestampValue($fields[$name]['Value']);
1748
                            break;
1749
                        default:
1750
                            return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
1751
                                'no supported type for field "' . $name . '" specified'));
1752
                    }
1753
                } else {
1754
                    $value = $fields[$name]['Value'];
1755
                }
1756
            }
1757
            $values .= $value;
1758
            if (isset($fields[$name]['Key']) && $fields[$name]['Key']) {
1759
                if ($value === 'NULL') {
1760
                    return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
1761
                        'key values may not be NULL'));
1762
                }
1763
                $condition .= ($keys ? ' AND ' : ' WHERE ') . $name . '=' . $value;
1764
                $keys++;
1765
            }
1766
        }
1767
        if ($keys == 0) {
1768
            return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
1769
                'not specified which fields are keys'));
1770
        }
1771
        $in_transaction = $this->in_transaction;
1772
        if (!$in_transaction && MDB::isError($result = $this->autoCommit(FALSE))) {
1773
            return($result);
1774
        }
1775
        $success = $this->query("DELETE FROM $table$condition");
1776
        if (!MDB::isError($success)) {
1777
            $affected_rows = $this->affected_rows;
1778
            $success = $this->query("INSERT INTO $table ($insert) VALUES ($values)");
1779
            $affected_rows += $this->affected_rows;
1780
        }
1781
 
1782
        if (!$in_transaction) {
1783
            if (!MDB::isError($success)) {
1784
                if (!MDB::isError($success = $this->commit())
1785
                    && !MDB::isError($success = $this->autoCommit(TRUE))
1786
                    && isset($this->supported['AffectedRows'])
1787
                ) {
1788
                    $this->affected_rows = $affected_rows;
1789
                }
1790
            } else {
1791
                $this->rollback();
1792
                $this->autoCommit(TRUE);
1793
            }
1794
        }
1795
        return($success);
1796
    }
1797
 
1798
    // }}}
1799
    // {{{ prepareQuery()
1800
 
1801
    /**
1802
     * Prepares a query for multiple execution with execute().
1803
     * With some database backends, this is emulated.
1804
     * prepareQuery() requires a generic query as string like
1805
     * 'INSERT INTO numbers VALUES(?,?,?)'. The ? are wildcards.
1806
     * Types of wildcards:
1807
     *    ? - a quoted scalar value, i.e. strings, integers
1808
     *
1809
     * @param string $ the query to prepare
1810
     * @return mixed resource handle for the prepared query on success, a DB
1811
     *        error on failure
1812
     * @access public
1813
     * @see execute
1814
     */
1815
    function prepareQuery($query)
1816
    {
1817
        $this->debug("PrepareQuery: $query");
1818
        $positions = array();
1819
        for($position = 0;
1820
            $position < strlen($query) && is_integer($question = strpos($query, '?', $position));
1821
        ) {
1822
            if (is_integer($quote = strpos($query, "'", $position))
1823
                && $quote < $question
1824
            ) {
1825
                if (!is_integer($end_quote = strpos($query, "'", $quote + 1))) {
1826
                    return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
1827
                        'Prepare query: query with an unterminated text string specified'));
1828
                }
1829
                switch ($this->escape_quotes) {
1830
                    case '':
1831
                    case "'":
1832
                        $position = $end_quote + 1;
1833
                        break;
1834
                    default:
1835
                        if ($end_quote == $quote + 1) {
1836
                            $position = $end_quote + 1;
1837
                        } else {
1838
                            if ($query[$end_quote-1] == $this->escape_quotes) {
1839
                                $position = $end_quote;
1840
                            } else {
1841
                                $position = $end_quote + 1;
1842
                            }
1843
                        }
1844
                        break;
1845
                }
1846
            } else {
1847
                $positions[] = $question;
1848
                $position = $question + 1;
1849
            }
1850
        }
1851
        $this->prepared_queries[] = array(
1852
            'Query' => $query,
1853
            'Positions' => $positions,
1854
            'Values' => array(),
1855
            'Types' => array()
1856
            );
1857
        $prepared_query = count($this->prepared_queries);
1858
        if ($this->selected_row_limit > 0) {
1859
            $this->prepared_queries[$prepared_query-1]['First'] = $this->first_selected_row;
1860
            $this->prepared_queries[$prepared_query-1]['Limit'] = $this->selected_row_limit;
1861
        }
1862
        return($prepared_query);
1863
    }
1864
 
1865
    // }}}
1866
    // {{{ _validatePreparedQuery()
1867
 
1868
    /**
1869
     * validate that a handle is infact a prepared query
1870
     *
1871
     * @param int $prepared_query argument is a handle that was returned by
1872
     *       the function prepareQuery()
1873
     * @access private
1874
     */
1875
    function _validatePreparedQuery($prepared_query)
1876
    {
1877
        if ($prepared_query < 1 || $prepared_query > count($this->prepared_queries)) {
1878
            return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
1879
                'Validate prepared query: invalid prepared query'));
1880
        }
1881
        if (gettype($this->prepared_queries[$prepared_query-1]) != 'array') {
1882
            return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
1883
                'Validate prepared query: prepared query was already freed'));
1884
        }
1885
        return(MDB_OK);
1886
    }
1887
 
1888
    // }}}
1889
    // {{{ freePreparedQuery()
1890
 
1891
    /**
1892
     * Release resources allocated for the specified prepared query.
1893
     *
1894
     * @param int $prepared_query argument is a handle that was returned by
1895
     *       the function prepareQuery()
1896
     * @return mixed MDB_OK on success, a MDB error on failure
1897
     * @access public
1898
     */
1899
    function freePreparedQuery($prepared_query)
1900
    {
1901
        $result = $this->_validatePreparedQuery($prepared_query);
1902
        if (MDB::isError($result)) {
1903
            return($result);
1904
        }
1905
        $this->prepared_queries[$prepared_query-1] = '';
1906
        return(MDB_OK);
1907
    }
1908
 
1909
    // }}}
1910
    // {{{ _executePreparedQuery()
1911
 
1912
    /**
1913
     * Execute a prepared query statement.
1914
     *
1915
     * @param int $prepared_query argument is a handle that was returned by
1916
     *       the function prepareQuery()
1917
     * @param string $query query to be executed
1918
     * @param array $types array that contains the types of the columns in
1919
     *       the result set
1920
     * @return mixed a result handle or MDB_OK on success, a MDB error on failure
1921
     * @access private
1922
     */
1923
    function _executePreparedQuery($prepared_query, $query, $types = NULL)
1924
    {
1925
        return($this->query($query, $types));
1926
    }
1927
 
1928
    // }}}
1929
    // {{{ executeQuery()
1930
 
1931
    /**
1932
     * Execute a prepared query statement.
1933
     *
1934
     * @param int $prepared_query argument is a handle that was returned by
1935
     *       the function prepareQuery()
1936
     * @param array $types array that contains the types of the columns in the
1937
     *       result set
1938
     * @return mixed a result handle or MDB_OK on success, a MDB error on failure
1939
     * @access public
1940
     */
1941
    function executeQuery($prepared_query, $types = NULL)
1942
    {
1943
        $result = $this->_validatePreparedQuery($prepared_query);
1944
        if (MDB::isError($result)) {
1945
            return($result);
1946
        }
1947
        $index = $prepared_query-1;
1948
        $success = MDB_OK;
1949
        $this->clobs[$prepared_query] = $this->blobs[$prepared_query] = array();
1950
        $query = '';
1951
        for($last_position = $position = 0;
1952
            $position < count($this->prepared_queries[$index]['Positions']);
1953
            $position++) {
1954
            if (!isset($this->prepared_queries[$index]['Values'][$position])) {
1955
                return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
1956
                    'Execute query: it was not defined query argument '.($position + 1)));
1957
            }
1958
            $current_position = $this->prepared_queries[$index]['Positions'][$position];
1959
            $query .= substr($this->prepared_queries[$index]['Query'], $last_position, $current_position - $last_position);
1960
            $value = $this->prepared_queries[$index]['Values'][$position];
1961
            if ($this->prepared_queries[$index]['IsNULL'][$position]) {
1962
                $query .= $value;
1963
            } else {
1964
                switch ($this->prepared_queries[$index]['Types'][$position]) {
1965
                    case 'clob':
1966
                        if (!MDB::isError($success = $this->getClobValue($prepared_query, $position + 1, $value))) {
1967
                            $this->clobs[$prepared_query][$position + 1] = $success;
1968
                            $query .= $this->clobs[$prepared_query][$position + 1];
1969
                        }
1970
                        break;
1971
                    case 'blob':
1972
                        if (!MDB::isError($success = $this->getBlobValue($prepared_query, $position + 1, $value))) {
1973
                            $this->blobs[$prepared_query][$position + 1] = $success;
1974
                            $query .= $this->blobs[$prepared_query][$position + 1];
1975
                        }
1976
                        break;
1977
                    default:
1978
                        $query .= $value;
1979
                        break;
1980
                }
1981
            }
1982
            $last_position = $current_position + 1;
1983
        }
1984
        if (!MDB::isError($success)) {
1985
            $query .= substr($this->prepared_queries[$index]['Query'], $last_position);
1986
            if ($this->selected_row_limit > 0) {
1987
                $this->prepared_queries[$index]['First'] = $this->first_selected_row;
1988
                $this->prepared_queries[$index]['Limit'] = $this->selected_row_limit;
1989
            }
1990
            if (isset($this->prepared_queries[$index]['Limit'])
1991
                && $this->prepared_queries[$index]['Limit'] > 0
1992
            ) {
1993
                $this->first_selected_row = $this->prepared_queries[$index]['First'];
1994
                $this->selected_row_limit = $this->prepared_queries[$index]['Limit'];
1995
            } else {
1996
                $this->first_selected_row = $this->selected_row_limit = 0;
1997
            }
1998
            $success = $this->_executePreparedQuery($prepared_query, $query, $types);
1999
        }
2000
        for(reset($this->clobs[$prepared_query]), $clob = 0;
2001
            $clob < count($this->clobs[$prepared_query]);
2002
            $clob++, next($this->clobs[$prepared_query])) {
2003
            $this->freeClobValue($prepared_query, key($this->clobs[$prepared_query]), $this->clobs[$prepared_query][key($this->clobs[$prepared_query])], $success);
2004
        }
2005
        unset($this->clobs[$prepared_query]);
2006
        for(reset($this->blobs[$prepared_query]), $blob = 0;
2007
            $blob < count($this->blobs[$prepared_query]);
2008
            $blob++, next($this->blobs[$prepared_query])) {
2009
            $this->freeBlobValue($prepared_query, key($this->blobs[$prepared_query]), $this->blobs[$prepared_query][key($this->blobs[$prepared_query])], $success);
2010
        }
2011
        unset($this->blobs[$prepared_query]);
2012
        return($success);
2013
    }
2014
 
2015
    // }}}
2016
    // {{{ execute()
2017
 
2018
    /**
2019
     * Executes a prepared SQL query
2020
     * With execute() the generic query of prepare is assigned with the given
2021
     * data array. The values of the array inserted into the query in the same
2022
     * order like the array order
2023
     *
2024
     * @param resource $prepared_query query handle from prepare()
2025
     * @param array $types array that contains the types of the columns in
2026
     *        the result set
2027
     * @param array $params numeric array containing the data to insert into
2028
     *        the query
2029
     * @param array $param_types array that contains the types of the values
2030
     *        defined in $params
2031
     * @return mixed a new result handle or a MDB_Error when fail
2032
     * @access public
2033
     * @see prepare()
2034
     */
2035
    function execute($prepared_query, $types = NULL, $params = FALSE, $param_types = NULL)
2036
    {
2037
        $this->setParamArray($prepared_query, $params, $param_types);
2038
 
2039
        return($this->executeQuery($prepared_query, $types));
2040
    }
2041
 
2042
    // }}}
2043
    // {{{ executeMultiple()
2044
 
2045
    /**
2046
     * This function does several execute() calls on the same statement handle.
2047
     * $params must be an array indexed numerically from 0, one execute call is
2048
     * done for every 'row' in the array.
2049
     *
2050
     * If an error occurs during execute(), executeMultiple() does not execute
2051
     * the unfinished rows, but rather returns that error.
2052
     *
2053
     * @param resource $stmt query handle from prepare()
2054
     * @param array $types array that contains the types of the columns in
2055
     *        the result set
2056
     * @param array $params numeric array containing the
2057
     *        data to insert into the query
2058
     * @param array $parAM_types array that contains the types of the values
2059
     *        defined in $params
2060
     * @return mixed a result handle or MDB_OK on success, a MDB error on failure
2061
     * @access public
2062
     * @see prepare(), execute()
2063
     */
2064
    function executeMultiple($prepared_query, $types = NULL, $params, $param_types = NULL)
2065
    {
2066
        for($i = 0, $j = count($params); $i < $j; $i++) {
2067
            $result = $this->execute($prepared_query, $types, $params[$i], $param_types);
2068
            if (MDB::isError($result)) {
2069
                return($result);
2070
            }
2071
        }
2072
        return(MDB_OK);
2073
    }
2074
 
2075
    // }}}
2076
    // {{{ setParam()
2077
 
2078
    /**
2079
     * Set the value of a parameter of a prepared query.
2080
     *
2081
     * @param int $prepared_query argument is a handle that was returned
2082
     *       by the function prepareQuery()
2083
     * @param int $parameter the order number of the parameter in the query
2084
     *       statement. The order number of the first parameter is 1.
2085
     * @param string $type designation of the type of the parameter to be set.
2086
     *       The designation of the currently supported types is as follows:
2087
     *           text, boolean, integer, decimal, float, date, time, timestamp,
2088
     *           clob, blob
2089
     * @param mixed $value value that is meant to be assigned to specified
2090
     *       parameter. The type of the value depends on the $type argument.
2091
     * @param boolean $is_null flag that indicates whether whether the
2092
     *       parameter is a NULL
2093
     * @param string $field name of the field that is meant to be assigned
2094
     *       with this parameter value when it is of type clob or blob
2095
     * @return mixed MDB_OK on success, a MDB error on failure
2096
     * @access public
2097
     */
2098
    function setParam($prepared_query, $parameter, $type, $value, $is_null = 0, $field = '')
2099
    {
2100
        $result = $this->_validatePreparedQuery($prepared_query);
2101
        if (MDB::isError($result)) {
2102
            return($result);
2103
        }
2104
        $index = $prepared_query - 1;
2105
        if ($parameter < 1 || $parameter > count($this->prepared_queries[$index]['Positions'])) {
2106
            return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
2107
                'Query set: it was not specified a valid argument number'));
2108
        }
2109
        $this->prepared_queries[$index]['Values'][$parameter-1] = $value;
2110
        $this->prepared_queries[$index]['Types'][$parameter-1] = $type;
2111
        $this->prepared_queries[$index]['Fields'][$parameter-1] = $field;
2112
        $this->prepared_queries[$index]['IsNULL'][$parameter-1] = $is_null;
2113
        return(MDB_OK);
2114
    }
2115
 
2116
    // }}}
2117
    // {{{ setParamArray()
2118
 
2119
    /**
2120
     * Set the values of multiple a parameter of a prepared query in bulk.
2121
     *
2122
     * @param int $prepared_query argument is a handle that was returned by
2123
     *       the function prepareQuery()
2124
     * @param array $params array thats specifies all necessary infromation
2125
     *       for setParam() the array elements must use keys corresponding to
2126
     *       the number of the position of the parameter.
2127
     * @param array $types array thats specifies the types of the fields
2128
     * @return mixed MDB_OK on success, a MDB error on failure
2129
     * @access public
2130
     * @see setParam()
2131
     */
2132
    function setParamArray($prepared_query, $params, $types = NULL)
2133
    {
2134
        if (is_array($types)) {
2135
            if (count($params) != count($types)) {
2136
                return $this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
2137
                    'setParamArray: the number of given types ('.count($types).')'
2138
                    .'is not corresponding to the number of given parameters ('.count($params).')');
2139
            }
2140
            for($i = 0, $j = count($params); $i < $j; ++$i) {
2141
                switch ($types[$i]) {
2142
                    case 'NULL':
2143
                        $success = $this->setParam($prepared_query, $i + 1, $params[$i][0], 'NULL', 1, '');
2144
                        break;
2145
                    case 'text':
2146
                        $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
2147
                        break;
2148
                    case 'clob':
2149
                        $success = $this->setParam($prepared_query, $i + 1, 'clob', $params[$i][0], 0, $params[$i][1]);
2150
                        break;
2151
                    case 'blob':
2152
                        $success = $this->setParam($prepared_query, $i + 1, 'blob', $params[$i][0], 0, $params[$i][1]);
2153
                        break;
2154
                    case 'integer':
2155
                        $success = $this->setParam($prepared_query, $i + 1, 'integer', $this->getIntegerValue($params[$i]));
2156
                        break;
2157
                    case 'boolean':
2158
                        $success = $this->setParam($prepared_query, $i + 1, 'boolean', $this->getBooleanValue($params[$i]));
2159
                        break;
2160
                    case 'date':
2161
                        $success = $this->setParam($prepared_query, $i + 1, 'date', $this->getDateValue($params[$i]));
2162
                        break;
2163
                    case 'timestamp':
2164
                        $success = $this->setParam($prepared_query, $i + 1, 'timestamp', $this->getTimestampValue($params[$i]));
2165
                        break;
2166
                    case 'time':
2167
                        $success = $this->setParam($prepared_query, $i + 1, 'time', $this->getTimeValue($params[$i]));
2168
                        break;
2169
                    case 'float':
2170
                        $success = $this->setParam($prepared_query, $i + 1, 'float', $this->getFloatValue($params[$i]));
2171
                        break;
2172
                    case 'decimal':
2173
                        $success = $this->setParam($prepared_query, $i + 1, 'decimal', $this->getDecimalValue($params[$i]));
2174
                        break;
2175
                    default:
2176
                        $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
2177
                        break;
2178
                }
2179
                if (MDB::isError($success)) {
2180
                    return($success);
2181
                }
2182
            }
2183
        } else {
2184
            for($i = 0, $j = count($params); $i < $j; ++$i) {
2185
                $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
2186
                if (MDB::isError($success)) {
2187
                    return($success);
2188
                }
2189
            }
2190
        }
2191
        return(MDB_OK);
2192
    }
2193
 
2194
    // }}}
2195
    // {{{ setParamNull()
2196
 
2197
    /**
2198
     * Set the value of a parameter of a prepared query to NULL.
2199
     *
2200
     * @param int $prepared_query argument is a handle that was returned by
2201
     *       the function prepareQuery()
2202
     * @param int $parameter order number of the parameter in the query
2203
     *       statement. The order number of the first parameter is 1.
2204
     * @param string $type designation of the type of the parameter to be set.
2205
     *       The designation of the currently supported types is list in the
2206
     *       usage of the function  setParam()
2207
     * @return mixed MDB_OK on success, a MDB error on failure
2208
     * @access public
2209
     * @see setParam()
2210
     */
2211
    function setParamNull($prepared_query, $parameter, $type)
2212
    {
2213
        return($this->setParam($prepared_query, $parameter, $type, 'NULL', 1, ''));
2214
    }
2215
 
2216
    // }}}
2217
    // {{{ setParamText()
2218
 
2219
    /**
2220
     * Set a parameter of a prepared query with a text value.
2221
     *
2222
     * @param int $prepared_query argument is a handle that was returned by
2223
     *       the function prepareQuery()
2224
     * @param int $parameter order number of the parameter in the query
2225
     *       statement. The order number of the first parameter is 1.
2226
     * @param string $value text value that is meant to be assigned to
2227
     *       specified parameter.
2228
     * @return mixed MDB_OK on success, a MDB error on failure
2229
     * @access public
2230
     * @see setParam()
2231
     */
2232
    function setParamText($prepared_query, $parameter, $value)
2233
    {
2234
        return($this->setParam($prepared_query, $parameter, 'text', $this->getTextValue($value)));
2235
    }
2236
 
2237
    // }}}
2238
    // {{{ setParamClob()
2239
 
2240
    /**
2241
     * Set a parameter of a prepared query with a character large object value.
2242
     *
2243
     * @param int $prepared_query argument is a handle that was returned by
2244
     *       the function prepareQuery()
2245
     * @param int $parameter order number of the parameter in the query
2246
     *       statement. The order number of the first parameter is 1.
2247
     * @param int $value handle of large object created with createLOB()
2248
     *       function from which it will be read the data value that is meant
2249
     *       to be assigned to specified parameter.
2250
     * @param string $field name of the field of a INSERT or UPDATE query to
2251
     *       which it will be assigned the value to specified parameter.
2252
     * @return mixed MDB_OK on success, a MDB error on failure
2253
     * @access public
2254
     * @see setParam()
2255
     */
2256
    function setParamClob($prepared_query, $parameter, $value, $field)
2257
    {
2258
        return($this->setParam($prepared_query, $parameter, 'clob', $value, 0, $field));
2259
    }
2260
 
2261
    // }}}
2262
    // {{{ setParamBlob()
2263
 
2264
    /**
2265
     * Set a parameter of a prepared query with a binary large object value.
2266
     *
2267
     * @param int $prepared_query argument is a handle that was returned by
2268
     *       the function prepareQuery()
2269
     * @param int $parameter order number of the parameter in the query
2270
     *       statement. The order number of the first parameter is 1.
2271
     * @param int $value handle of large object created with createLOB()
2272
     *       function from which it will be read the data value that is meant
2273
     *       to be assigned to specified parameter.
2274
     * @param string $field name of the field of a INSERT or UPDATE query to
2275
     *       which it will be assigned the value to specified parameter.
2276
     * @return mixed MDB_OK on success, a MDB error on failure
2277
     * @access public
2278
     * @see setParam()
2279
     */
2280
    function setParamBlob($prepared_query, $parameter, $value, $field)
2281
    {
2282
        return($this->setParam($prepared_query, $parameter, 'blob', $value, 0, $field));
2283
    }
2284
 
2285
    // }}}
2286
    // {{{ setParamInteger()
2287
 
2288
    /**
2289
     * Set a parameter of a prepared query with a text value.
2290
     *
2291
     * @param int $prepared_query argument is a handle that was returned by
2292
     *       the function prepareQuery()
2293
     * @param int $parameter order number of the parameter in the query
2294
     *       statement. The order number of the first parameter is 1.
2295
     * @param int $value an integer value that is meant to be assigned to
2296
     *       specified parameter.
2297
     * @return mixed MDB_OK on success, a MDB error on failure
2298
     * @access public
2299
     * @see setParam()
2300
     */
2301
    function setParamInteger($prepared_query, $parameter, $value)
2302
    {
2303
        return($this->setParam($prepared_query, $parameter, 'integer', $this->getIntegerValue($value)));
2304
    }
2305
 
2306
    // }}}
2307
    // {{{ setParamBoolean()
2308
 
2309
    /**
2310
     * Set a parameter of a prepared query with a boolean value.
2311
     *
2312
     * @param int $prepared_query argument is a handle that was returned by
2313
     *       the function prepareQuery()
2314
     * @param int $parameter order number of the parameter in the query
2315
     *       statement. The order number of the first parameter is 1.
2316
     * @param boolean $value boolean value that is meant to be assigned to
2317
     *       specified parameter.
2318
     * @return mixed MDB_OK on success, a MDB error on failure
2319
     * @access public
2320
     * @see setParam()
2321
     */
2322
    function setParamBoolean($prepared_query, $parameter, $value)
2323
    {
2324
        return($this->setParam($prepared_query, $parameter, 'boolean', $this->getBooleanValue($value)));
2325
    }
2326
 
2327
    // }}}
2328
    // {{{ setParamDate()
2329
 
2330
    /**
2331
     * Set a parameter of a prepared query with a date value.
2332
     *
2333
     * @param int $prepared_query argument is a handle that was returned by
2334
     *       the function prepareQuery()
2335
     * @param int $parameter order number of the parameter in the query
2336
     *       statement. The order number of the first parameter is 1.
2337
     * @param string $value date value that is meant to be assigned to
2338
     *       specified parameter.
2339
     * @return mixed MDB_OK on success, a MDB error on failure
2340
     * @access public
2341
     * @see setParam()
2342
     */
2343
    function setParamDate($prepared_query, $parameter, $value)
2344
    {
2345
        return($this->setParam($prepared_query, $parameter, 'date', $this->getDateValue($value)));
2346
    }
2347
 
2348
    // }}}
2349
    // {{{ setParamTimestamp()
2350
 
2351
    /**
2352
     * Set a parameter of a prepared query with a time stamp value.
2353
     *
2354
     * @param int $prepared_query argument is a handle that was returned by
2355
     *       the function prepareQuery()
2356
     * @param int $parameter order number of the parameter in the query
2357
     *       statement. The order number of the first parameter is 1.
2358
     * @param string $value time stamp value that is meant to be assigned to
2359
     *       specified parameter.
2360
     * @return mixed MDB_OK on success, a MDB error on failure
2361
     * @access public
2362
     * @see setParam()
2363
     */
2364
    function setParamTimestamp($prepared_query, $parameter, $value)
2365
    {
2366
        return($this->setParam($prepared_query, $parameter, 'timestamp', $this->getTimestampValue($value)));
2367
    }
2368
 
2369
    // }}}
2370
    // {{{ setParamTime()
2371
 
2372
    /**
2373
     * Set a parameter of a prepared query with a time value.
2374
     *
2375
     * @param int $prepared_query argument is a handle that was returned by
2376
     *       the function prepareQuery()
2377
     * @param int $parameter order number of the parameter in the query
2378
     *       statement. The order number of the first parameter is 1.
2379
     * @param string $value time value that is meant to be assigned to
2380
     *       specified parameter.
2381
     * @return mixed MDB_OK on success, a MDB error on failure
2382
     * @access public
2383
     * @see setParam()
2384
     */
2385
    function setParamTime($prepared_query, $parameter, $value)
2386
    {
2387
        return($this->setParam($prepared_query, $parameter, 'time', $this->getTimeValue($value)));
2388
    }
2389
 
2390
    // }}}
2391
    // {{{ setParamFloat()
2392
 
2393
    /**
2394
     * Set a parameter of a prepared query with a float value.
2395
     *
2396
     * @param int $prepared_query argument is a handle that was returned by
2397
     *       the function prepareQuery()
2398
     * @param int $parameter order number of the parameter in the query
2399
     *       statement. The order number of the first parameter is 1.
2400
     * @param string $value float value that is meant to be assigned to
2401
     *       specified parameter.
2402
     * @return mixed MDB_OK on success, a MDB error on failure
2403
     * @access public
2404
     * @see setParam()
2405
     */
2406
    function setParamFloat($prepared_query, $parameter, $value)
2407
    {
2408
        return($this->setParam($prepared_query, $parameter, 'float', $this->getFloatValue($value)));
2409
    }
2410
 
2411
    // }}}
2412
    // {{{ setParamDecimal()
2413
 
2414
    /**
2415
     * Set a parameter of a prepared query with a decimal value.
2416
     *
2417
     * @param int $prepared_query argument is a handle that was returned by
2418
     *       the function prepareQuery()
2419
     * @param int $parameter order number of the parameter in the query
2420
     *       statement. The order number of the first parameter is 1.
2421
     * @param string $value decimal value that is meant to be assigned to
2422
     *       specified parameter.
2423
     * @return mixed MDB_OK on success, a MDB error on failure
2424
     * @access public
2425
     * @see setParam()
2426
     */
2427
    function setParamDecimal($prepared_query, $parameter, $value)
2428
    {
2429
        return($this->setParam($prepared_query, $parameter, 'decimal', $this->getDecimalValue($value)));
2430
    }
2431
 
2432
    // }}}
2433
    // {{{ setResultTypes()
2434
 
2435
    /**
2436
     * Define the list of types to be associated with the columns of a given
2437
     * result set.
2438
     *
2439
     * This function may be called before invoking fetchInto(), fetchOne(),
2440
     * fetchRow(), fetchCol() and fetchAll() so that the necessary data type
2441
     * conversions are performed on the data to be retrieved by them. If this
2442
     * function is not called, the type of all result set columns is assumed
2443
     * to be text, thus leading to not perform any conversions.
2444
     *
2445
     * @param resource $result result identifier
2446
     * @param string $types array variable that lists the
2447
     *       data types to be expected in the result set columns. If this array
2448
     *       contains less types than the number of columns that are returned
2449
     *       in the result set, the remaining columns are assumed to be of the
2450
     *       type text. Currently, the types clob and blob are not fully
2451
     *       supported.
2452
     * @return mixed MDB_OK on success, a MDB error on failure
2453
     * @access public
2454
     */
2455
    function setResultTypes($result, $types)
2456
    {
2457
        $result_value = intval($result);
2458
        if (isset($this->result_types[$result_value])) {
2459
            return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
2460
                'Set result types: attempted to redefine the types of the columns of a result set'));
2461
        }
2462
        $columns = $this->numCols($result);
2463
        if (MDB::isError($columns)) {
2464
            return($columns);
2465
        }
2466
        if ($columns < count($types)) {
2467
            return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
2468
                'Set result types: it were specified more result types (' . count($types) . ') than result columns (' . $columns . ')'));
2469
        }
2470
        $valid_types = array(
2471
            'text'      => MDB_TYPE_TEXT,
2472
            'boolean'   => MDB_TYPE_BOOLEAN,
2473
            'integer'   => MDB_TYPE_INTEGER,
2474
            'decimal'   => MDB_TYPE_DECIMAL,
2475
            'float'     => MDB_TYPE_FLOAT,
2476
            'date'      => MDB_TYPE_DATE,
2477
            'time'      => MDB_TYPE_TIME,
2478
            'timestamp' => MDB_TYPE_TIMESTAMP,
2479
            'clob'      => MDB_TYPE_CLOB,
2480
            'blob'      => MDB_TYPE_BLOB
2481
        );
2482
        for($column = 0; $column < count($types); $column++) {
2483
            if (!isset($valid_types[$types[$column]])) {
2484
                return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2485
                    'Set result types: ' . $types[$column] . ' is not a supported column type'));
2486
            }
2487
            $this->result_types[$result_value][$column] = $valid_types[$types[$column]];
2488
        }
2489
        while ($column < $columns) {
2490
            $this->result_types[$result_value][$column] = MDB_TYPE_TEXT;
2491
            $column++;
2492
        }
2493
        return(MDB_OK);
2494
    }
2495
 
2496
    // }}}
2497
    // {{{ affectedRows()
2498
 
2499
    /**
2500
     * returns the affected rows of a query
2501
     *
2502
     * @return mixed MDB_Error or number of rows
2503
     * @access public
2504
     */
2505
    function affectedRows()
2506
    {
2507
        if ($this->affected_rows == -1) {
2508
            return($this->raiseError(MDB_ERROR_NEED_MORE_DATA));
2509
        }
2510
        return($this->affected_rows);
2511
    }
2512
 
2513
    // }}}
2514
    // {{{ getColumnNames()
2515
 
2516
    /**
2517
     * Retrieve the names of columns returned by the DBMS in a query result.
2518
     *
2519
     * @param resource $result result identifier
2520
     * @return mixed associative array variable
2521
     *       that holds the names of columns. The indexes of the array are
2522
     *       the column names mapped to lower case and the values are the
2523
     *       respective numbers of the columns starting from 0. Some DBMS may
2524
     *       not return any columns when the result set does not contain any
2525
     *       rows.
2526
     *      a MDB error on failure
2527
     * @access public
2528
     */
2529
    function getColumnNames($result)
2530
    {
2531
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2532
            'Get column names: obtaining result column names is not implemented'));
2533
    }
2534
 
2535
    // }}}
2536
    // {{{ numCols()
2537
 
2538
    /**
2539
     * Count the number of columns returned by the DBMS in a query result.
2540
     *
2541
     * @param resource $result result identifier
2542
     * @return mixed integer value with the number of columns, a MDB error
2543
     *       on failure
2544
     * @access public
2545
     */
2546
    function numCols($result)
2547
    {
2548
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2549
            'Number of columns: obtaining the number of result columns is not implemented'));
2550
    }
2551
 
2552
    // }}}
2553
    // {{{ endOfResult()
2554
 
2555
    /**
2556
     * check if the end of the result set has been reached
2557
     *
2558
     * @param resource $result result identifier
2559
     * @return mixed TRUE or FALSE on sucess, a MDB error on failure
2560
     * @access public
2561
     */
2562
    function endOfResult($result)
2563
    {
2564
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2565
            'End of result: end of result method not implemented'));
2566
    }
2567
 
2568
    // }}}
2569
    // {{{ setFetchMode()
2570
 
2571
    /**
2572
     * Sets which fetch mode should be used by default on queries
2573
     * on this connection.
2574
     *
2575
     * @param integer $fetchmode MDB_FETCHMODE_ORDERED or MDB_FETCHMODE_ASSOC,
2576
     *       possibly bit-wise OR'ed with MDB_FETCHMODE_FLIPPED.
2577
     * @access public
2578
     * @see MDB_FETCHMODE_ORDERED
2579
     * @see MDB_FETCHMODE_ASSOC
2580
     * @see MDB_FETCHMODE_FLIPPED
2581
     */
2582
    function setFetchMode($fetchmode)
2583
    {
2584
        switch ($fetchmode) {
2585
            case MDB_FETCHMODE_ORDERED:
2586
            case MDB_FETCHMODE_ASSOC:
2587
                $this->fetchmode = $fetchmode;
2588
                break;
2589
            default:
2590
                return($this->raiseError('invalid fetchmode mode'));
2591
        }
2592
    }
2593
 
2594
    // }}}
2595
    // {{{ fetch()
2596
 
2597
    /**
2598
     * fetch value from a result set
2599
     *
2600
     * @param resource $result result identifier
2601
     * @param int $row number of the row where the data can be found
2602
     * @param int $field field number where the data can be found
2603
     * @return mixed string on success, a MDB error on failure
2604
     * @access public
2605
     */
2606
    function fetch($result, $row, $field)
2607
    {
2608
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2609
            'Fetch: fetch result method not implemented'));
2610
    }
2611
 
2612
    // }}}
2613
    // {{{ fetchLob()
2614
 
2615
    /**
2616
     * fetch a lob value from a result set
2617
     *
2618
     * @param resource $result result identifier
2619
     * @param int $row number of the row where the data can be found
2620
     * @param int $field field number where the data can be found
2621
     * @return mixed string on success, a MDB error on failure
2622
     * @access public
2623
     */
2624
    function fetchLob($result, $row, $field)
2625
    {
2626
        $lob = count($this->lobs) + 1;
2627
        $this->lobs[$lob] = array(
2628
            'Result' => $result,
2629
            'Row' => $row,
2630
            'Field' => $field,
2631
            'Position' => 0
2632
        );
2633
        $dst_lob = array(
2634
            'Database' => $this,
2635
            'Error' => '',
2636
            'Type' => 'resultlob',
2637
            'ResultLOB' => $lob
2638
        );
2639
        if (MDB::isError($lob = $this->createLob($dst_lob))) {
2640
            return($this->raiseError(MDB_ERROR, NULL, NULL,
2641
                'Fetch LOB result: ' . $dst_lob['Error']));
2642
        }
2643
        return($lob);
2644
    }
2645
 
2646
    // }}}
2647
    // {{{ _retrieveLob()
2648
 
2649
    /**
2650
     * fetch a float value from a result set
2651
     *
2652
     * @param int $lob handle to a lob created by the createLob() function
2653
     * @return mixed MDB_OK on success, a MDB error on failure
2654
     * @access private
2655
     */
2656
    function _retrieveLob($lob)
2657
    {
2658
        if (!isset($this->lobs[$lob])) {
2659
            return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
2660
                'Fetch LOB result: it was not specified a valid lob'));
2661
        }
2662
        if (!isset($this->lobs[$lob]['Value'])) {
2663
            $this->lobs[$lob]['Value'] = $this->fetch($this->lobs[$lob]['Result'], $this->lobs[$lob]['Row'], $this->lobs[$lob]['Field']);
2664
        }
2665
        return(MDB_OK);
2666
    }
2667
 
2668
    // }}}
2669
    // {{{ endOfResultLob()
2670
 
2671
    /**
2672
     * Determine whether it was reached the end of the large object and
2673
     * therefore there is no more data to be read for the its input stream.
2674
     *
2675
     * @param int $lob handle to a lob created by the createLob() function
2676
     * @return mixed TRUE or FALSE on success, a MDB error on failure
2677
     * @access public
2678
     */
2679
    function endOfResultLob($lob)
2680
    {
2681
        $result = $this->_retrieveLob($lob);
2682
        if (MDB::isError($result)) {
2683
            return($result);
2684
        }
2685
        return($this->lobs[$lob]['Position'] >= strlen($this->lobs[$lob]['Value']));
2686
    }
2687
 
2688
    // }}}
2689
    // {{{ _readResultLob()
2690
 
2691
    /**
2692
     * Read data from large object input stream.
2693
     *
2694
     * @param int $lob handle to a lob created by the createLob() function
2695
     * @param blob $data reference to a variable that will hold data to be
2696
     *       read from the large object input stream
2697
     * @param int $length integer value that indicates the largest ammount of
2698
     *       data to be read from the large object input stream.
2699
     * @return mixed length on success, a MDB error on failure
2700
     * @access private
2701
     */
2702
    function _readResultLob($lob, &$data, $length)
2703
    {
2704
        $result = $this->_retrieveLob($lob);
2705
        if (MDB::isError($result)) {
2706
            return($result);
2707
        }
2708
        $length = min($length, strlen($this->lobs[$lob]['Value']) - $this->lobs[$lob]['Position']);
2709
        $data = substr($this->lobs[$lob]['Value'], $this->lobs[$lob]['Position'], $length);
2710
        $this->lobs[$lob]['Position'] += $length;
2711
        return($length);
2712
    }
2713
 
2714
    // }}}
2715
    // {{{ _destroyResultLob()
2716
 
2717
    /**
2718
     * Free any resources allocated during the lifetime of the large object
2719
     * handler object.
2720
     *
2721
     * @param int $lob handle to a lob created by the createLob() function
2722
     * @access private
2723
     */
2724
    function _destroyResultLob($lob)
2725
    {
2726
        if (isset($this->lobs[$lob])) {
2727
            $this->lobs[$lob] = '';
2728
        }
2729
    }
2730
 
2731
    // }}}
2732
    // {{{ fetchClob()
2733
 
2734
    /**
2735
     * fetch a clob value from a result set
2736
     *
2737
     * @param resource $result result identifier
2738
     * @param int $row number of the row where the data can be found
2739
     * @param int $field field number where the data can be found
2740
     * @return mixed content of the specified data cell, a MDB error on failure,
2741
     *        a MDB error on failure
2742
     * @access public
2743
     */
2744
    function fetchClob($result, $row, $field)
2745
    {
2746
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2747
            'fetch clob result method is not implemented'));
2748
    }
2749
 
2750
    // }}}
2751
    // {{{ fetchBlob()
2752
 
2753
    /**
2754
     * fetch a blob value from a result set
2755
     *
2756
     * @param resource $result result identifier
2757
     * @param int $row number of the row where the data can be found
2758
     * @param int $field field number where the data can be found
2759
     * @return mixed content of the specified data cell, a MDB error on failure
2760
     * @access public
2761
     */
2762
    function fetchBlob($result, $row, $field)
2763
    {
2764
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
2765
            'fetch blob result method is not implemented'));
2766
    }
2767
 
2768
    // }}}
2769
    // {{{ resultIsNull()
2770
 
2771
    /**
2772
     * Determine whether the value of a query result located in given row and
2773
     *    field is a NULL.
2774
     *
2775
     * @param resource $result result identifier
2776
     * @param int $row number of the row where the data can be found
2777
     * @param int $field field number where the data can be found
2778
     * @return mixed TRUE or FALSE on success, a MDB error on failure
2779
     * @access public
2780
     */
2781
    function resultIsNull($result, $row, $field)
2782
    {
2783
        $result = $this->fetch($result, $row, $field);
2784
        if (MDB::isError($result)) {
2785
            return($result);
2786
        }
2787
        return(!isset($result));
2788
    }
2789
 
2790
    // }}}
2791
    // {{{ _baseConvertResult()
2792
 
2793
    /**
2794
     * general type conversion method
2795
     *
2796
     * @param mixed $value refernce to a value to be converted
2797
     * @param int $type constant that specifies which type to convert to
2798
     * @return object a MDB error on failure
2799
     * @access private
2800
     */
2801
    function _baseConvertResult($value, $type)
2802
    {
2803
        switch ($type) {
2804
            case MDB_TYPE_TEXT:
2805
                return($value);
2806
            case MDB_TYPE_BLOB:
2807
                return($value);
2808
            case MDB_TYPE_CLOB:
2809
                return($value);
2810
            case MDB_TYPE_INTEGER:
2811
                return(intval($value));
2812
            case MDB_TYPE_BOOLEAN:
2813
                return ($value == 'Y') ? TRUE : FALSE;
2814
            case MDB_TYPE_DECIMAL:
2815
                return($value);
2816
            case MDB_TYPE_FLOAT:
2817
                return(doubleval($value));
2818
            case MDB_TYPE_DATE:
2819
                return($value);
2820
            case MDB_TYPE_TIME:
2821
                return($value);
2822
            case MDB_TYPE_TIMESTAMP:
2823
                return($value);
2824
            case MDB_TYPE_CLOB:
2825
                return($value);
2826
            case MDB_TYPE_BLOB:
2827
                return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
2828
                    'BaseConvertResult: attempt to convert result value to an unsupported type ' . $type));
2829
            default:
2830
                return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
2831
                    'BaseConvertResult: attempt to convert result value to an unknown type ' . $type));
2832
        }
2833
    }
2834
 
2835
    // }}}
2836
    // {{{ convertResult()
2837
 
2838
    /**
2839
     * convert a value to a RDBMS indepdenant MDB type
2840
     *
2841
     * @param mixed $value value to be converted
2842
     * @param int $type constant that specifies which type to convert to
2843
     * @return mixed converted value or a MDB error on failure
2844
     * @access public
2845
     */
2846
    function convertResult($value, $type)
2847
    {
2848
        return($this->_baseConvertResult($value, $type));
2849
    }
2850
 
2851
    // }}}
2852
    // {{{ convertResultRow()
2853
 
2854
    /**
2855
     * convert a result row
2856
     *
2857
     * @param resource $result result identifier
2858
     * @param array $row array with data
2859
     * @return mixed MDB_OK on success,  a MDB error on failure
2860
     * @access public
2861
     */
2862
    function convertResultRow($result, $row)
2863
    {
2864
        $result_value = intval($result);
2865
        if (isset($this->result_types[$result_value])) {
2866
            $current_column = -1;
2867
            foreach($row as $key => $column) {
2868
                ++$current_column;
2869
                if (!isset($this->result_types[$result_value][$current_column])
2870
                   ||!isset($column)
2871
                ) {
2872
                    continue;
2873
                }
2874
                switch ($type = $this->result_types[$result_value][$current_column]) {
2875
                    case MDB_TYPE_TEXT:
2876
                    case MDB_TYPE_BLOB:
2877
                    case MDB_TYPE_CLOB:
2878
                        break;
2879
                    case MDB_TYPE_INTEGER:
2880
                        $row[$key] = intval($row[$key]);
2881
                        break;
2882
                    default:
2883
                        $value = $this->convertResult($row[$key], $type);
2884
                        if (MDB::isError($value)) {
2885
                            return $value;
2886
                        }
2887
                        $row[$key] = $value;
2888
                        break;
2889
                }
2890
            }
2891
        }
2892
        return ($row);
2893
    }
2894
 
2895
    // }}}
2896
    // {{{ fetchDate()
2897
 
2898
    /**
2899
     * fetch a date value from a result set
2900
     *
2901
     * @param resource $result result identifier
2902
     * @param int $row number of the row where the data can be found
2903
     * @param int $field field number where the data can be found
2904
     * @return mixed content of the specified data cell, a MDB error on failure
2905
     * @access public
2906
     */
2907
    function fetchDate($result, $row, $field)
2908
    {
2909
        $value = $this->fetch($result, $row, $field);
2910
        return($this->convertResult($value, MDB_TYPE_DATE));
2911
    }
2912
 
2913
    // }}}
2914
    // {{{ fetchTimestamp()
2915
 
2916
    /**
2917
     * fetch a timestamp value from a result set
2918
     *
2919
     * @param resource $result result identifier
2920
     * @param int $row number of the row where the data can be found
2921
     * @param int $field field number where the data can be found
2922
     * @return mixed content of the specified data cell, a MDB error on failure
2923
     * @access public
2924
     */
2925
    function fetchTimestamp($result, $row, $field)
2926
    {
2927
        $value = $this->fetch($result, $row, $field);
2928
        return($this->convertResult($value, MDB_TYPE_TIMESTAMP));
2929
    }
2930
 
2931
    // }}}
2932
    // {{{ fetchTime()
2933
 
2934
    /**
2935
     * fetch a time value from a result set
2936
     *
2937
     * @param resource $result result identifier
2938
     * @param int $row number of the row where the data can be found
2939
     * @param int $field field number where the data can be found
2940
     * @return mixed content of the specified data cell, a MDB error on failure
2941
     * @access public
2942
     */
2943
    function fetchTime($result, $row, $field)
2944
    {
2945
        $value = $this->fetch($result, $row, $field);
2946
        return($this->convertResult($value, MDB_TYPE_TIME));
2947
    }
2948
 
2949
    // }}}
2950
    // {{{ fetchBoolean()
2951
 
2952
    /**
2953
     * fetch a boolean value from a result set
2954
     *
2955
     * @param resource $result result identifier
2956
     * @param int $row number of the row where the data can be found
2957
     * @param int $field field number where the data can be found
2958
     * @return mixed content of the specified data cell, a MDB error on failure
2959
     * @access public
2960
     */
2961
    function fetchBoolean($result, $row, $field)
2962
    {
2963
        $value = $this->fetch($result, $row, $field);
2964
        return($this->convertResult($value, MDB_TYPE_BOOLEAN));
2965
    }
2966
 
2967
    // }}}
2968
    // {{{ fetchFloat()
2969
 
2970
    /**
2971
     * fetch a float value from a result set
2972
     *
2973
     * @param resource $result result identifier
2974
     * @param int $row number of the row where the data can be found
2975
     * @param int $field field number where the data can be found
2976
     * @return mixed content of the specified data cell, a MDB error on failure
2977
     * @access public
2978
     */
2979
    function fetchFloat($result, $row, $field)
2980
    {
2981
        $value = $this->fetch($result, $row, $field);
2982
        return($this->convertResult($value, MDB_TYPE_FLOAT));
2983
    }
2984
 
2985
    // }}}
2986
    // {{{ fetchDecimal()
2987
 
2988
    /**
2989
     * fetch a decimal value from a result set
2990
     *
2991
     * @param resource $result result identifier
2992
     * @param int $row number of the row where the data can be found
2993
     * @param int $field field number where the data can be found
2994
     * @return mixed content of the specified data cell, a MDB error on failure
2995
     * @access public
2996
     */
2997
    function fetchDecimal($result, $row, $field)
2998
    {
2999
        $value = $this->fetch($result, $row, $field);
3000
        return($this->convertResult($value, MDB_TYPE_DECIMAL));
3001
    }
3002
 
3003
    // }}}
3004
    // {{{ numRows()
3005
 
3006
    /**
3007
     * returns the number of rows in a result object
3008
     *
3009
     * @param ressource $result a valid result ressouce pointer
3010
     * @return mixed MDB_Error or the number of rows
3011
     * @access public
3012
     */
3013
    function numRows($result)
3014
    {
3015
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Num Rows: number of rows method not implemented'));
3016
    }
3017
 
3018
    // }}}
3019
    // {{{ freeResult()
3020
 
3021
    /**
3022
     * Free the internal resources associated with $result.
3023
     *
3024
     * @param  $result result identifier
3025
     * @return boolean TRUE on success, FALSE if $result is invalid
3026
     * @access public
3027
     */
3028
    function freeResult($result)
3029
    {
3030
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Free Result: free result method not implemented'));
3031
    }
3032
 
3033
    // }}}
3034
    // {{{ getIntegerDeclaration()
3035
 
3036
    /**
3037
     * Obtain DBMS specific SQL code portion needed to declare an integer type
3038
     * field to be used in statements like CREATE TABLE.
3039
     *
3040
     * @param string $name name the field to be declared.
3041
     * @param string $field associative array with the name of the properties
3042
     *       of the field being declared as array indexes. Currently, the types
3043
     *       of supported field properties are as follows:
3044
     *
3045
     *       unsigned
3046
     *           Boolean flag that indicates whether the field should be
3047
     *           declared as unsigned integer if possible.
3048
     *
3049
     *       default
3050
     *           Integer value to be used as default for this field.
3051
     *
3052
     *       notnull
3053
     *           Boolean flag that indicates whether this field is constrained
3054
     *           to not be set to NULL.
3055
     * @return string DBMS specific SQL code portion that should be used to
3056
     *       declare the specified field.
3057
     * @access public
3058
     */
3059
    function getIntegerDeclaration($name, $field)
3060
    {
3061
        if (isset($field['unsigned'])) {
3062
            $this->warnings[] = "unsigned integer field \"$name\" is being
3063
                declared as signed integer";
3064
        }
3065
        return("$name INT" . (isset($field['default']) ? ' DEFAULT ' . $field['default'] : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3066
    }
3067
 
3068
    // }}}
3069
    // {{{ getTextDeclaration()
3070
 
3071
    /**
3072
     * Obtain DBMS specific SQL code portion needed to declare an text type
3073
     * field to be used in statements like CREATE TABLE.
3074
     *
3075
     * @param string $name name the field to be declared.
3076
     * @param string $field associative array with the name of the properties
3077
     *       of the field being declared as array indexes. Currently, the types
3078
     *       of supported field properties are as follows:
3079
     *
3080
     *       length
3081
     *           Integer value that determines the maximum length of the text
3082
     *           field. If this argument is missing the field should be
3083
     *           declared to have the longest length allowed by the DBMS.
3084
     *
3085
     *       default
3086
     *           Text value to be used as default for this field.
3087
     *
3088
     *       notnull
3089
     *           Boolean flag that indicates whether this field is constrained
3090
     *           to not be set to NULL.
3091
     * @return string DBMS specific SQL code portion that should be used to
3092
     *       declare the specified field.
3093
     * @access public
3094
     */
3095
    function getTextDeclaration($name, $field)
3096
    {
3097
        return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3098
    }
3099
 
3100
    // }}}
3101
    // {{{ getClobDeclaration()
3102
 
3103
    /**
3104
     * Obtain DBMS specific SQL code portion needed to declare an character
3105
     * large object type field to be used in statements like CREATE TABLE.
3106
     *
3107
     * @param string $name name the field to be declared.
3108
     * @param string $field associative array with the name of the properties
3109
     *       of the field being declared as array indexes. Currently, the types
3110
     *       of supported field properties are as follows:
3111
     *
3112
     *       length
3113
     *           Integer value that determines the maximum length of the large
3114
     *           object field. If this argument is missing the field should be
3115
     *           declared to have the longest length allowed by the DBMS.
3116
     *
3117
     *       notnull
3118
     *           Boolean flag that indicates whether this field is constrained
3119
     *           to not be set to NULL.
3120
     * @return string DBMS specific SQL code portion that should be used to
3121
     *       declare the specified field.
3122
     * @access public
3123
     */
3124
    function getClobDeclaration($name, $field)
3125
    {
3126
        return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3127
    }
3128
 
3129
    // }}}
3130
    // {{{ getBlobDeclaration()
3131
 
3132
    /**
3133
     * Obtain DBMS specific SQL code portion needed to declare an binary large
3134
     * object type field to be used in statements like CREATE TABLE.
3135
     *
3136
     * @param string $name name the field to be declared.
3137
     * @param string $field associative array with the name of the properties
3138
     *       of the field being declared as array indexes. Currently, the types
3139
     *       of supported field properties are as follows:
3140
     *
3141
     *       length
3142
     *           Integer value that determines the maximum length of the large
3143
     *           object field. If this argument is missing the field should be
3144
     *           declared to have the longest length allowed by the DBMS.
3145
     *
3146
     *       notnull
3147
     *           Boolean flag that indicates whether this field is constrained
3148
     *           to not be set to NULL.
3149
     * @return string DBMS specific SQL code portion that should be used to
3150
     *       declare the specified field.
3151
     * @access public
3152
     */
3153
    function getBlobDeclaration($name, $field)
3154
    {
3155
        return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3156
    }
3157
 
3158
    // }}}
3159
    // {{{ getBooleanDeclaration()
3160
 
3161
    /**
3162
     * Obtain DBMS specific SQL code portion needed to declare a boolean type
3163
     * field to be used in statements like CREATE TABLE.
3164
     *
3165
     * @param string $name name the field to be declared.
3166
     * @param string $field associative array with the name of the properties
3167
     *       of the field being declared as array indexes. Currently, the types
3168
     *       of supported field properties are as follows:
3169
     *
3170
     *       default
3171
     *           Boolean value to be used as default for this field.
3172
     *
3173
     *       notnullL
3174
     *           Boolean flag that indicates whether this field is constrained
3175
     *           to not be set to NULL.
3176
     * @return string DBMS specific SQL code portion that should be used to
3177
     *       declare the specified field.
3178
     * @access public
3179
     */
3180
    function getBooleanDeclaration($name, $field)
3181
    {
3182
        return("$name CHAR (1)" . (isset($field['default']) ? ' DEFAULT ' . $this->getBooleanValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3183
    }
3184
 
3185
    // }}}
3186
    // {{{ getDateDeclaration()
3187
 
3188
    /**
3189
     * Obtain DBMS specific SQL code portion needed to declare a date type
3190
     * field to be used in statements like CREATE TABLE.
3191
     *
3192
     * @param string $name name the field to be declared.
3193
     * @param string $field associative array with the name of the properties
3194
     *       of the field being declared as array indexes. Currently, the types
3195
     *       of supported field properties are as follows:
3196
     *
3197
     *       default
3198
     *           Date value to be used as default for this field.
3199
     *
3200
     *       notnull
3201
     *           Boolean flag that indicates whether this field is constrained
3202
     *           to not be set to NULL.
3203
     * @return string DBMS specific SQL code portion that should be used to
3204
     *       declare the specified field.
3205
     * @access public
3206
     */
3207
    function getDateDeclaration($name, $field)
3208
    {
3209
        return("$name CHAR (" . strlen("YYYY-MM-DD") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getDateValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3210
    }
3211
 
3212
    // }}}
3213
    // {{{ getTimestampDeclaration()
3214
 
3215
    /**
3216
     * Obtain DBMS specific SQL code portion needed to declare a timestamp
3217
     * field to be used in statements like CREATE TABLE.
3218
     *
3219
     * @param string $name name the field to be declared.
3220
     * @param string $field associative array with the name of the properties
3221
     *       of the field being declared as array indexes. Currently, the types
3222
     *       of supported field properties are as follows:
3223
     *
3224
     *       default
3225
     *           Timestamp value to be used as default for this field.
3226
     *
3227
     *       notnull
3228
     *           Boolean flag that indicates whether this field is constrained
3229
     *           to not be set to NULL.
3230
     * @return string DBMS specific SQL code portion that should be used to
3231
     *       declare the specified field.
3232
     * @access public
3233
     */
3234
    function getTimestampDeclaration($name, $field)
3235
    {
3236
        return("$name CHAR (" . strlen("YYYY-MM-DD HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimestampValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3237
    }
3238
 
3239
    // }}}
3240
    // {{{ getTimeDeclaration()
3241
 
3242
    /**
3243
     * Obtain DBMS specific SQL code portion needed to declare a time
3244
     * field to be used in statements like CREATE TABLE.
3245
     *
3246
     * @param string $name name the field to be declared.
3247
     * @param string $field associative array with the name of the properties
3248
     *       of the field being declared as array indexes. Currently, the types
3249
     *       of supported field properties are as follows:
3250
     *
3251
     *       default
3252
     *           Time value to be used as default for this field.
3253
     *
3254
     *       notnull
3255
     *           Boolean flag that indicates whether this field is constrained
3256
     *           to not be set to NULL.
3257
     * @return string DBMS specific SQL code portion that should be used to
3258
     *       declare the specified field.
3259
     * @access public
3260
     */
3261
    function getTimeDeclaration($name, $field)
3262
    {
3263
        return("$name CHAR (" . strlen("HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimeValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3264
    }
3265
 
3266
    // }}}
3267
    // {{{ getFloatDeclaration()
3268
 
3269
    /**
3270
     * Obtain DBMS specific SQL code portion needed to declare a float type
3271
     * field to be used in statements like CREATE TABLE.
3272
     *
3273
     * @param string $name name the field to be declared.
3274
     * @param string $field associative array with the name of the properties
3275
     *       of the field being declared as array indexes. Currently, the types
3276
     *       of supported field properties are as follows:
3277
     *
3278
     *       default
3279
     *           Float value to be used as default for this field.
3280
     *
3281
     *       notnull
3282
     *           Boolean flag that indicates whether this field is constrained
3283
     *           to not be set to NULL.
3284
     * @return string DBMS specific SQL code portion that should be used to
3285
     *       declare the specified field.
3286
     * @access public
3287
     */
3288
    function getFloatDeclaration($name, $field)
3289
    {
3290
        return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getFloatValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3291
    }
3292
 
3293
    // }}}
3294
    // {{{ getDecimalDeclaration()
3295
 
3296
    /**
3297
     * Obtain DBMS specific SQL code portion needed to declare a decimal type
3298
     * field to be used in statements like CREATE TABLE.
3299
     *
3300
     * @param string $name name the field to be declared.
3301
     * @param string $field associative array with the name of the properties
3302
     *       of the field being declared as array indexes. Currently, the types
3303
     *       of supported field properties are as follows:
3304
     *
3305
     *       default
3306
     *           Decimal value to be used as default for this field.
3307
     *
3308
     *       notnull
3309
     *           Boolean flag that indicates whether this field is constrained
3310
     *           to not be set to NULL.
3311
     * @return string DBMS specific SQL code portion that should be used to
3312
     *       declare the specified field.
3313
     * @access public
3314
     */
3315
    function getDecimalDeclaration($name, $field)
3316
    {
3317
        return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getDecimalValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
3318
    }
3319
 
3320
    // }}}
3321
    // {{{ getIntegerValue()
3322
 
3323
    /**
3324
     * Convert a text value into a DBMS specific format that is suitable to
3325
     * compose query statements.
3326
     *
3327
     * @param string $value text string value that is intended to be converted.
3328
     * @return string text string that represents the given argument value in
3329
     *       a DBMS specific format.
3330
     * @access public
3331
     */
3332
    function getIntegerValue($value)
3333
    {
3334
        return(($value === NULL) ? 'NULL' : (int)$value);
3335
    }
3336
 
3337
    // }}}
3338
    // {{{ getTextValue()
3339
 
3340
    /**
3341
     * Convert a text value into a DBMS specific format that is suitable to
3342
     * compose query statements.
3343
     *
3344
     * @param string $value text string value that is intended to be converted.
3345
     * @return string text string that already contains any DBMS specific
3346
     *       escaped character sequences.
3347
     * @access public
3348
     */
3349
    function getTextValue($value)
3350
    {
3351
        return(($value === NULL) ? 'NULL' : "'".$this->_quote($value)."'");
3352
    }
3353
 
3354
    // }}}
3355
    // {{{ getClobValue()
3356
 
3357
    /**
3358
     * Convert a text value into a DBMS specific format that is suitable to
3359
     * compose query statements.
3360
     *
3361
     * @param resource $prepared_query query handle from prepare()
3362
     * @param  $parameter
3363
     * @param  $clob
3364
     * @return string text string that represents the given argument value in
3365
     *       a DBMS specific format.
3366
     * @access public
3367
     */
3368
    function getClobValue($prepared_query, $parameter, $clob)
3369
    {
3370
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
3371
            'Get CLOB field value: prepared queries with values of type "clob" are not yet supported'));
3372
    }
3373
 
3374
    // }}}
3375
    // {{{ freeClobValue()
3376
 
3377
    /**
3378
     * free a character large object
3379
     *
3380
     * @param resource $prepared_query query handle from prepare()
3381
     * @param string $blob
3382
     * @param string $value
3383
     * @access public
3384
     */
3385
    function freeClobValue($prepared_query, $clob, &$value)
3386
    {
3387
    }
3388
 
3389
    // }}}
3390
    // {{{ getBlobValue()
3391
 
3392
    /**
3393
     * Convert a text value into a DBMS specific format that is suitable to
3394
     * compose query statements.
3395
     *
3396
     * @param resource $prepared_query query handle from prepare()
3397
     * @param  $parameter
3398
     * @param  $blob
3399
     * @return string text string that represents the given argument value in
3400
     *       a DBMS specific format.
3401
     * @access public
3402
     */
3403
    function getBlobValue($prepared_query, $parameter, $blob)
3404
    {
3405
        return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
3406
            'Get BLOB field value: prepared queries with values of type "blob" are not yet supported'));
3407
    }
3408
 
3409
    // }}}
3410
    // {{{ freeBlobValue()
3411
 
3412
    /**
3413
     * free a binary large object
3414
     *
3415
     * @param resource $prepared_query query handle from prepare()
3416
     * @param string $blob
3417
     * @param string $value
3418
     * @access public
3419
     */
3420
    function freeBlobValue($prepared_query, $blob, &$value)
3421
    {
3422
    }
3423
 
3424
    // }}}
3425
    // {{{ getBooleanValue()
3426
 
3427
    /**
3428
     * Convert a text value into a DBMS specific format that is suitable to
3429
     * compose query statements.
3430
     *
3431
     * @param string $value text string value that is intended to be converted.
3432
     * @return string text string that represents the given argument value in
3433
     *       a DBMS specific format.
3434
     * @access public
3435
     */
3436
    function getBooleanValue($value)
3437
    {
3438
        return(($value === NULL) ? 'NULL' : ($value ? "'Y'" : "'N'"));
3439
    }
3440
 
3441
    // }}}
3442
    // {{{ getDateValue()
3443
 
3444
    /**
3445
     * Convert a text value into a DBMS specific format that is suitable to
3446
     * compose query statements.
3447
     *
3448
     * @param string $value text string value that is intended to be converted.
3449
     * @return string text string that represents the given argument value in
3450
     *       a DBMS specific format.
3451
     * @access public
3452
     */
3453
    function getDateValue($value)
3454
    {
3455
        return(($value === NULL) ? 'NULL' : "'$value'");
3456
    }
3457
 
3458
    // }}}
3459
    // {{{ getTimestampValue()
3460
 
3461
    /**
3462
     * Convert a text value into a DBMS specific format that is suitable to
3463
     * compose query statements.
3464
     *
3465
     * @param string $value text string value that is intended to be converted.
3466
     * @return string text string that represents the given argument value in
3467
     *       a DBMS specific format.
3468
     * @access public
3469
     */
3470
    function getTimestampValue($value)
3471
    {
3472
        return(($value === NULL) ? 'NULL' : "'$value'");
3473
    }
3474
 
3475
    // }}}
3476
    // {{{ getTimeValue()
3477
 
3478
    /**
3479
     * Convert a text value into a DBMS specific format that is suitable to
3480
     *       compose query statements.
3481
     *
3482
     * @param string $value text string value that is intended to be converted.
3483
     * @return string text string that represents the given argument value in
3484
     *       a DBMS specific format.
3485
     * @access public
3486
     */
3487
    function getTimeValue($value)
3488
    {
3489
        return(($value === NULL) ? 'NULL' : "'$value'");
3490
    }
3491
 
3492
    // }}}
3493
    // {{{ getFloatValue()
3494
 
3495
    /**
3496
     * Convert a text value into a DBMS specific format that is suitable to
3497
     * compose query statements.
3498
     *
3499
     * @param string $value text string value that is intended to be converted.
3500
     * @return string text string that represents the given argument value in
3501
     *       a DBMS specific format.
3502
     * @access public
3503
     */
3504
    function getFloatValue($value)
3505
    {
3506
        return(($value === NULL) ? 'NULL' : "'$value'");
3507
    }
3508
 
3509
    // }}}
3510
    // {{{ getDecimalValue()
3511
 
3512
    /**
3513
     * Convert a text value into a DBMS specific format that is suitable to
3514
     * compose query statements.
3515
     *
3516
     * @param string $value text string value that is intended to be converted.
3517
     * @return string text string that represents the given argument value in
3518
     *       a DBMS specific format.
3519
     * @access public
3520
     */
3521
    function getDecimalValue($value)
3522
    {
3523
        return(($value === NULL) ? 'NULL' : "'$value'");
3524
    }
3525
 
3526
    // }}}
3527
    // {{{ getValue()
3528
 
3529
    /**
3530
     * Convert a text value into a DBMS specific format that is suitable to
3531
     * compose query statements.
3532
     *
3533
     * @param string $type type to which the value should be converted to
3534
     * @param string $value text string value that is intended to be converted.
3535
     * @return string text string that represents the given argument value in
3536
     *       a DBMS specific format.
3537
     * @access public
3538
     */
3539
    function getValue($type, $value)
3540
    {
3541
        if (empty($type)) {
3542
            return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
3543
                'getValue: called without type to convert to'));
3544
        }
3545
        if (method_exists($this,"get{$type}Value")) {
3546
            return $this->{"get{$type}Value"}($value);
3547
        }
3548
        return $value;
3549
    }
3550
 
3551
    // }}}
3552
    // {{{ support()
3553
 
3554
    /**
3555
     * Tell whether a DB implementation or its backend extension
3556
     * supports a given feature.
3557
     *
3558
     * @param string $feature name of the feature (see the MDB class doc)
3559
     * @return boolean whether this DB implementation supports $feature
3560
     * @access public
3561
     */
3562
    function support($feature)
3563
    {
3564
        return(isset($this->supported[$feature]) && $this->supported[$feature]);
3565
    }
3566
 
3567
    // }}}
3568
    // {{{ getSequenceName()
3569
 
3570
    /**
3571
     * adds sequence name formating to a sequence name
3572
     *
3573
     * @param string $sqn name of the sequence
3574
     * @return string formatted sequence name
3575
     * @access public
3576
     */
3577
    function getSequenceName($sqn)
3578
    {
3579
        return sprintf($this->options['seqname_format'],
3580
            preg_replace('/[^a-z0-9_]/i', '_', $sqn));
3581
    }
3582
 
3583
    // }}}
3584
    // {{{ nextId()
3585
 
3586
    /**
3587
     * returns the next free id of a sequence
3588
     *
3589
     * @param string $seq_name name of the sequence
3590
     * @param boolean $ondemand when TRUE the seqence is
3591
     *                           automatic created, if it
3592
     *                           not exists
3593
     * @return mixed MDB_Error or id
3594
     * @access public
3595
     */
3596
    function nextId($seq_name, $ondemand = FALSE)
3597
    {
3598
        return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
3599
            'Next Sequence: getting next sequence value not supported'));
3600
    }
3601
 
3602
    // }}}
3603
    // {{{ currId()
3604
 
3605
    /**
3606
     * returns the current id of a sequence
3607
     *
3608
     * @param string $seq_name name of the sequence
3609
     * @return mixed MDB_Error or id
3610
     * @access public
3611
     */
3612
    function currId($seq_name)
3613
    {
3614
        $this->warnings[] = 'database does not support getting current
3615
            sequence value, the sequence value was incremented';
3616
        $this->expectError(MDB_ERROR_NOT_CAPABLE);
3617
        $id = $this->nextId($seq_name);
3618
        $this->popExpect(MDB_ERROR_NOT_CAPABLE);
3619
        if (MDB::isError($id)) {
3620
            if ($id->getCode() == MDB_ERROR_NOT_CAPABLE) {
3621
                return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
3622
                    'Current Sequence: getting current sequence value not supported'));
3623
            }
3624
            return($id);
3625
        }
3626
        return($id);
3627
    }
3628
 
3629
    // }}}
3630
    // {{{ fetchInto()
3631
 
3632
    /**
3633
     * Fetch a row and return data in an array.
3634
     *
3635
     * @param resource $result result identifier
3636
     * @param int $fetchmode ignored
3637
     * @param int $rownum the row number to fetch
3638
     * @return mixed data array or NULL on success, a MDB error on failure
3639
     * @access public
3640
     */
3641
    function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
3642
    {
3643
        $result_value = intval($result);
3644
        if (MDB::isError($this->endOfResult($result))) {
3645
            $this->freeResult($result);
3646
            $result = $this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
3647
                'Fetch field: result set is empty');
3648
        }
3649
        if ($rownum == NULL) {
3650
            ++$this->highest_fetched_row[$result_value];
3651
            $rownum = $this->highest_fetched_row[$result_value];
3652
        } else {
3653
            $this->highest_fetched_row[$result_value] =
3654
                max($this->highest_fetched_row[$result_value], $row);
3655
        }
3656
        if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
3657
            $fetchmode = $this->fetchmode;
3658
        }
3659
        $columns = $this->numCols($result);
3660
        if (MDB::isError($columns)) {
3661
            return($columns);
3662
        }
3663
        if ($fetchmode & MDB_FETCHMODE_ASSOC) {
3664
            $column_names = $this->getColumnNames($result);
3665
        }
3666
        for($column = 0; $column < $columns; $column++) {
3667
            if (!$this->resultIsNull($result, $rownum, $column)) {
3668
                $value = $this->fetch($result, $rownum, $column);
3669
                if ($value === FALSE) {
3670
                    if ($this->options['autofree']) {
3671
                        $this->freeResult($result);
3672
                    }
3673
                    return(NULL);
3674
                } elseif (MDB::isError($value)) {
3675
                    if ($value->getMessage() == '') {
3676
                        if ($this->options['autofree']) {
3677
                            $this->freeResult($result);
3678
                        }
3679
                        return(NULL);
3680
                    } else {
3681
                        return($value);
3682
                    }
3683
                }
3684
            }
3685
            $row[$column] = $value;
3686
        }
3687
        if ($fetchmode & MDB_FETCHMODE_ASSOC) {
3688
            $row = array_combine($column_names, $row);
3689
            if (is_array($row) && $this->options['optimize'] == 'portability') {
3690
                $row = array_change_key_case($row, CASE_LOWER);
3691
            }
3692
        }
3693
        if (isset($this->result_types[$result_value])) {
3694
            $row = $this->convertResultRow($result, $row);
3695
        }
3696
        return($row);
3697
    }
3698
 
3699
    // }}}
3700
    // {{{ fetchOne()
3701
 
3702
    /**
3703
     * Fetch and return a field of data (it uses fetchInto for that)
3704
     *
3705
     * @param resource $result result identifier
3706
     * @return mixed data on success, a MDB error on failure
3707
     * @access public
3708
     */
3709
    function fetchOne($result)
3710
    {
3711
        $row = $this->fetchInto($result, MDB_FETCHMODE_ORDERED);
3712
        if (!$this->options['autofree'] || $row != NULL) {
3713
            $this->freeResult($result);
3714
        }
3715
        if (is_array($row)) {
3716
            return($row[0]);
3717
        }
3718
        return($row);
3719
    }
3720
 
3721
    // }}}
3722
    // {{{ fetchRow()
3723
 
3724
    /**
3725
     * Fetch and return a row of data (it uses fetchInto for that)
3726
     *
3727
     * @param resource $result result identifier
3728
     * @param int $fetchmode how the array data should be indexed
3729
     * @param int $rownum the row number to fetch
3730
     * @return mixed data array on success, a MDB error on failure
3731
     * @access public
3732
     */
3733
    function fetchRow($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
3734
    {
3735
        $row = $this->fetchInto($result, $fetchmode, $rownum);
3736
        if (!$this->options['autofree'] || $row != NULL) {
3737
            $this->freeResult($result);
3738
        }
3739
        return($row);
3740
    }
3741
 
3742
    // }}}
3743
    // {{{ fetchCol()
3744
 
3745
    /**
3746
     * Fetch and return a column of data (it uses fetchInto for that)
3747
     *
3748
     * @param resource $result result identifier
3749
     * @param int $colnum the row number to fetch
3750
     * @return mixed data array on success, a MDB error on failure
3751
     * @access public
3752
     */
3753
    function fetchCol($result, $colnum = 0)
3754
    {
3755
        $fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC;
3756
        $column = array();
3757
        $row = $this->fetchInto($result, $fetchmode);
3758
        if (is_array($row)) {
3759
            if (!array_key_exists($colnum, $row)) {
3760
                return($this->raiseError(MDB_ERROR_TRUNCATED));
3761
            }
3762
            do {
3763
                $column[] = $row[$colnum];
3764
            } while (is_array($row = $this->fetchInto($result, $fetchmode)));
3765
        }
3766
        if (!$this->options['autofree']) {
3767
            $this->freeResult($result);
3768
        }
3769
        if (MDB::isError($row)) {
3770
            return($row);
3771
        }
3772
        return($column);
3773
    }
3774
 
3775
    // }}}
3776
    // {{{ fetchAll()
3777
 
3778
    /**
3779
     * Fetch and return a column of data (it uses fetchInto for that)
3780
     *
3781
     * @param resource $result result identifier
3782
     * @param int $fetchmode how the array data should be indexed
3783
     * @param boolean $rekey if set to TRUE, the $all will have the first
3784
     *       column as its first dimension
3785
     * @param boolean $force_array used only when the query returns exactly
3786
     *       two columns. If TRUE, the values of the returned array will be
3787
     *       one-element arrays instead of scalars.
3788
     * @param boolean $group if TRUE, the values of the returned array is
3789
     *       wrapped in another array.  If the same key value (in the first
3790
     *       column) repeats itself, the values will be appended to this array
3791
     *       instead of overwriting the existing values.
3792
     * @return mixed data array on success, a MDB error on failure
3793
     * @access public
3794
     * @see getAssoc()
3795
     */
3796
    function fetchAll($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rekey = FALSE, $force_array = FALSE, $group = FALSE)
3797
    {
3798
        if ($rekey) {
3799
            $cols = $this->numCols($result);
3800
            if (MDB::isError($cols)) {
3801
                return($cols);
3802
            }
3803
            if ($cols < 2) {
3804
                return($this->raiseError(MDB_ERROR_TRUNCATED));
3805
            }
3806
        }
3807
        $all = array();
3808
        while (is_array($row = $this->fetchInto($result, $fetchmode))) {
3809
            if ($rekey) {
3810
                if ($fetchmode & MDB_FETCHMODE_ASSOC) {
3811
                    $key = reset($row);
3812
                    unset($row[key($row)]);
3813
                } else {
3814
                    $key = array_shift($row);
3815
                }
3816
                if (!$force_array && count($row) == 1) {
3817
                    $row = array_shift($row);
3818
                }
3819
                if ($group) {
3820
                    $all[$key][] = $row;
3821
                } else {
3822
                    $all[$key] = $row;
3823
                }
3824
            } else {
3825
                if ($fetchmode & MDB_FETCHMODE_FLIPPED) {
3826
                    foreach ($row as $key => $val) {
3827
                        $all[$key][] = $val;
3828
                    }
3829
                } else {
3830
                   $all[] = $row;
3831
                }
3832
            }
3833
        }
3834
        if (!$this->options['autofree']) {
3835
            $this->freeResult($result);
3836
        }
3837
        if (MDB::isError($row)) {
3838
            return($row);
3839
        }
3840
        return($all);
3841
    }
3842
 
3843
    // }}}
3844
    // {{{ queryOne()
3845
 
3846
    /**
3847
     * Execute the specified query, fetch the value from the first column of
3848
     * the first row of the result set and then frees
3849
     * the result set.
3850
     *
3851
     * @param string $query the SELECT query statement to be executed.
3852
     * @param string $type optional argument that specifies the expected
3853
     *       datatype of the result set field, so that an eventual conversion
3854
     *       may be performed. The default datatype is text, meaning that no
3855
     *       conversion is performed
3856
     * @return mixed field value on success, a MDB error on failure
3857
     * @access public
3858
     */
3859
    function queryOne($query, $type = NULL)
3860
    {
3861
        if ($type != NULL) {
3862
            $type = array($type);
3863
        }
3864
        $result = $this->query($query, $type);
3865
        if (MDB::isError($result)) {
3866
            return($result);
3867
        }
3868
        return($this->fetchOne($result));
3869
    }
3870
 
3871
    // }}}
3872
    // {{{ queryRow()
3873
 
3874
    /**
3875
     * Execute the specified query, fetch the values from the first
3876
     * row of the result set into an array and then frees
3877
     * the result set.
3878
     *
3879
     * @param string $query the SELECT query statement to be executed.
3880
     * @param array $types optional array argument that specifies a list of
3881
     *       expected datatypes of the result set columns, so that the eventual
3882
     *       conversions may be performed. The default list of datatypes is
3883
     *       empty, meaning that no conversion is performed.
3884
     * @param int $fetchmode how the array data should be indexed
3885
     * @return mixed data array on success, a MDB error on failure
3886
     * @access public
3887
     */
3888
    function queryRow($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
3889
    {
3890
        $result = $this->query($query, $types);
3891
        if (MDB::isError($result)) {
3892
            return($result);
3893
        }
3894
        return($this->fetchRow($result, $fetchmode));
3895
    }
3896
 
3897
    // }}}
3898
    // {{{ queryCol()
3899
 
3900
    /**
3901
     * Execute the specified query, fetch the value from the first column of
3902
     * each row of the result set into an array and then frees the result set.
3903
     *
3904
     * @param string $query the SELECT query statement to be executed.
3905
     * @param string $type optional argument that specifies the expected
3906
     *       datatype of the result set field, so that an eventual conversion
3907
     *       may be performed. The default datatype is text, meaning that no
3908
     *       conversion is performed
3909
     * @param int $colnum the row number to fetch
3910
     * @return mixed data array on success, a MDB error on failure
3911
     * @access public
3912
     */
3913
    function queryCol($query, $type = NULL, $colnum = 0)
3914
    {
3915
        if ($type != NULL) {
3916
            $type = array($type);
3917
        }
3918
        $result = $this->query($query, $type);
3919
        if (MDB::isError($result)) {
3920
            return($result);
3921
        }
3922
        return($this->fetchCol($result, $colnum));
3923
    }
3924
 
3925
    // }}}
3926
    // {{{ queryAll()
3927
 
3928
    /**
3929
     * Execute the specified query, fetch all the rows of the result set into
3930
     * a two dimensional array and then frees the result set.
3931
     *
3932
     * @param string $query the SELECT query statement to be executed.
3933
     * @param array $types optional array argument that specifies a list of
3934
     *       expected datatypes of the result set columns, so that the eventual
3935
     *       conversions may be performed. The default list of datatypes is
3936
     *       empty, meaning that no conversion is performed.
3937
     * @param int $fetchmode how the array data should be indexed
3938
     * @param boolean $rekey if set to TRUE, the $all will have the first
3939
     *       column as its first dimension
3940
     * @param boolean $force_array used only when the query returns exactly
3941
     *       two columns. If TRUE, the values of the returned array will be
3942
     *       one-element arrays instead of scalars.
3943
     * @param boolean $group if TRUE, the values of the returned array is
3944
     *       wrapped in another array.  If the same key value (in the first
3945
     *       column) repeats itself, the values will be appended to this array
3946
     *       instead of overwriting the existing values.
3947
     * @return mixed data array on success, a MDB error on failure
3948
     * @access public
3949
     */
3950
    function queryAll($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT,
3951
        $rekey = FALSE, $force_array = FALSE, $group = FALSE)
3952
    {
3953
        if (MDB::isError($result = $this->query($query, $types))) {
3954
            return($result);
3955
        }
3956
        return($this->fetchAll($result, $fetchmode, $rekey, $force_array, $group));
3957
    }
3958
 
3959
    // }}}
3960
    // {{{ getOne()
3961
 
3962
    /**
3963
     * Fetch the first column of the first row of data returned from
3964
     * a query.  Takes care of doing the query and freeing the results
3965
     * when finished.
3966
     *
3967
     * @param string $query the SQL query
3968
     * @param string $type string that contains the type of the column in the
3969
     *       result set
3970
     * @param array $params if supplied, prepare/execute will be used
3971
     *       with this array as execute parameters
3972
     * @param array $param_types array that contains the types of the values
3973
     *       defined in $params
3974
     * @return mixed MDB_Error or the returned value of the query
3975
     * @access public
3976
     */
3977
    function getOne($query, $type = NULL, $params = array(), $param_types = NULL)
3978
    {
3979
        if ($type != NULL) {
3980
            $type = array($type);
3981
        }
3982
        settype($params, 'array');
3983
        if (count($params) > 0) {
3984
            $prepared_query = $this->prepareQuery($query);
3985
            if (MDB::isError($prepared_query)) {
3986
                return($prepared_query);
3987
            }
3988
            $this->setParamArray($prepared_query, $params, $param_types);
3989
            $result = $this->executeQuery($prepared_query, $type);
3990
        } else {
3991
            $result = $this->query($query, $type);
3992
        }
3993
 
3994
        if (MDB::isError($result)) {
3995
            return($result);
3996
        }
3997
 
3998
        $value = $this->fetchOne($result, MDB_FETCHMODE_ORDERED);
3999
        if (MDB::isError($value)) {
4000
            return($value);
4001
        }
4002
        if (isset($prepared_query)) {
4003
            $result = $this->freePreparedQuery($prepared_query);
4004
            if (MDB::isError($result)) {
4005
                return($result);
4006
            }
4007
        }
4008
 
4009
        return($value);
4010
    }
4011
 
4012
    // }}}
4013
    // {{{ getRow()
4014
 
4015
    /**
4016
     * Fetch the first row of data returned from a query.  Takes care
4017
     * of doing the query and freeing the results when finished.
4018
     *
4019
     * @param string $query the SQL query
4020
     * @param array $types array that contains the types of the columns in
4021
     *       the result set
4022
     * @param array $params array if supplied, prepare/execute will be used
4023
     *       with this array as execute parameters
4024
     * @param array $param_types array that contains the types of the values
4025
     *       defined in $params
4026
     * @param integer $fetchmode the fetch mode to use
4027
     * @return array the first row of results as an array indexed from
4028
     * 0, or a MDB error code.
4029
     * @access public
4030
     */
4031
    function getRow($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
4032
    {
4033
        settype($params, 'array');
4034
        if (count($params) > 0) {
4035
            $prepared_query = $this->prepareQuery($query);
4036
            if (MDB::isError($prepared_query)) {
4037
                return($prepared_query);
4038
            }
4039
            $this->setParamArray($prepared_query, $params, $param_types);
4040
            $result = $this->executeQuery($prepared_query, $types);
4041
        } else {
4042
            $result = $this->query($query, $types);
4043
        }
4044
 
4045
        if (MDB::isError($result)) {
4046
            return($result);
4047
        }
4048
 
4049
        $row = $this->fetchRow($result, $fetchmode);
4050
        if (MDB::isError($row)) {
4051
            return($row);
4052
        }
4053
        if (isset($prepared_query)) {
4054
            $result = $this->freePreparedQuery($prepared_query);
4055
            if (MDB::isError($result)) {
4056
                return($result);
4057
            }
4058
        }
4059
 
4060
        return($row);
4061
    }
4062
 
4063
    // }}}
4064
    // {{{ getCol()
4065
 
4066
    /**
4067
     * Fetch a single column from a result set and return it as an
4068
     * indexed array.
4069
     *
4070
     * @param string $query the SQL query
4071
     * @param string $type string that contains the type of the column in the
4072
     *       result set
4073
     * @param array $params array if supplied, prepare/execute will be used
4074
     *       with this array as execute parameters
4075
     * @param array $param_types array that contains the types of the values
4076
     *       defined in $params
4077
     * @param mixed $colnum which column to return(integer [column number,
4078
     *       starting at 0] or string [column name])
4079
     * @return array an indexed array with the data from the first
4080
     * row at index 0, or a MDB error code.
4081
     * @access public
4082
     */
4083
    function getCol($query, $type = NULL, $params = array(), $param_types = NULL, $colnum = 0)
4084
    {
4085
        if ($type != NULL) {
4086
            $type = array($type);
4087
        }
4088
        settype($params, 'array');
4089
        if (count($params) > 0) {
4090
            $prepared_query = $this->prepareQuery($query);
4091
 
4092
            if (MDB::isError($prepared_query)) {
4093
                return($prepared_query);
4094
            }
4095
            $this->setParamArray($prepared_query, $params, $param_types);
4096
            $result = $this->executeQuery($prepared_query, $type);
4097
        } else {
4098
            $result = $this->query($query, $type);
4099
        }
4100
 
4101
        if (MDB::isError($result)) {
4102
            return($result);
4103
        }
4104
 
4105
        $col = $this->fetchCol($result, $colnum);
4106
        if (MDB::isError($col)) {
4107
            return($col);
4108
        }
4109
        if (isset($prepared_query)) {
4110
            $result = $this->freePreparedQuery($prepared_query);
4111
            if (MDB::isError($result)) {
4112
                return($result);
4113
            }
4114
        }
4115
        return($col);
4116
    }
4117
 
4118
    // }}}
4119
    // {{{ getAssoc()
4120
 
4121
    /**
4122
     * Fetch the entire result set of a query and return it as an
4123
     * associative array using the first column as the key.
4124
     *
4125
     * If the result set contains more than two columns, the value
4126
     * will be an array of the values from column 2-n.  If the result
4127
     * set contains only two columns, the returned value will be a
4128
     * scalar with the value of the second column (unless forced to an
4129
     * array with the $force_array parameter).  A MDB error code is
4130
     * returned on errors.  If the result set contains fewer than two
4131
     * columns, a MDB_ERROR_TRUNCATED error is returned.
4132
     *
4133
     * For example, if the table 'mytable' contains:
4134
     *
4135
     *   ID      TEXT       DATE
4136
     * --------------------------------
4137
     *   1       'one'      944679408
4138
     *   2       'two'      944679408
4139
     *   3       'three'    944679408
4140
     *
4141
     * Then the call getAssoc('SELECT id,text FROM mytable') returns:
4142
     *    array(
4143
     *      '1' => 'one',
4144
     *      '2' => 'two',
4145
     *      '3' => 'three',
4146
     *    )
4147
     *
4148
     * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
4149
     *    array(
4150
     *      '1' => array('one', '944679408'),
4151
     *      '2' => array('two', '944679408'),
4152
     *      '3' => array('three', '944679408')
4153
     *    )
4154
     *
4155
     * If the more than one row occurs with the same value in the
4156
     * first column, the last row overwrites all previous ones by
4157
     * default.  Use the $group parameter if you don't want to
4158
     * overwrite like this.  Example:
4159
     *
4160
     * getAssoc('SELECT category,id,name FROM mytable', NULL, NULL
4161
     *           MDB_FETCHMODE_ASSOC, FALSE, TRUE) returns:
4162
     *    array(
4163
     *      '1' => array(array('id' => '4', 'name' => 'number four'),
4164
     *                   array('id' => '6', 'name' => 'number six')
4165
     *             ),
4166
     *      '9' => array(array('id' => '4', 'name' => 'number four'),
4167
     *                   array('id' => '6', 'name' => 'number six')
4168
     *             )
4169
     *    )
4170
     *
4171
     * Keep in mind that database functions in PHP usually return string
4172
     * values for results regardless of the database's internal type.
4173
     *
4174
     * @param string $query the SQL query
4175
     * @param array $types array that contains the types of the columns in
4176
     *       the result set
4177
     * @param array $params array if supplied, prepare/execute will be used
4178
     *       with this array as execute parameters
4179
     * @param array $param_types array that contains the types of the values
4180
     *       defined in $params
4181
     * @param boolean $force_array used only when the query returns
4182
     * exactly two columns.  If TRUE, the values of the returned array
4183
     * will be one-element arrays instead of scalars.
4184
     * @param boolean $group if TRUE, the values of the returned array
4185
     *       is wrapped in another array.  If the same key value (in the first
4186
     *       column) repeats itself, the values will be appended to this array
4187
     *       instead of overwriting the existing values.
4188
     * @return array associative array with results from the query.
4189
     * @access public
4190
     */
4191
    function getAssoc($query, $types = NULL, $params = array(), $param_types = NULL,
4192
        $fetchmode = MDB_FETCHMODE_ORDERED, $force_array = FALSE, $group = FALSE)
4193
    {
4194
        settype($params, 'array');
4195
        if (count($params) > 0) {
4196
            $prepared_query = $this->prepareQuery($query);
4197
 
4198
            if (MDB::isError($prepared_query)) {
4199
                return($prepared_query);
4200
            }
4201
            $this->setParamArray($prepared_query, $params, $param_types);
4202
            $result = $this->executeQuery($prepared_query, $types);
4203
        } else {
4204
            $result = $this->query($query, $types);
4205
        }
4206
 
4207
        if (MDB::isError($result)) {
4208
            return($result);
4209
        }
4210
 
4211
        $all = $this->fetchAll($result, $fetchmode, TRUE, $force_array, $group);
4212
        if (MDB::isError($all)) {
4213
            return($all);
4214
        }
4215
        if (isset($prepared_query)) {
4216
            $result = $this->freePreparedQuery($prepared_query);
4217
            if (MDB::isError($result)) {
4218
                return($result);
4219
            }
4220
        }
4221
        return($all);
4222
    }
4223
 
4224
    // }}}
4225
    // {{{ getAll()
4226
 
4227
    /**
4228
     * Fetch all the rows returned from a query.
4229
     *
4230
     * @param string $query the SQL query
4231
     * @param array $types array that contains the types of the columns in
4232
     *       the result set
4233
     * @param array $params array if supplied, prepare/execute will be used
4234
     *       with this array as execute parameters
4235
     * @param array $param_types array that contains the types of the values
4236
     *       defined in $params
4237
     * @param integer $fetchmode the fetch mode to use
4238
     * @return array an nested array, or a MDB error
4239
     * @access public
4240
     */
4241
    function getAll($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
4242
    {
4243
        settype($params, 'array');
4244
        if (count($params) > 0) {
4245
            $prepared_query = $this->prepareQuery($query);
4246
 
4247
            if (MDB::isError($prepared_query)) {
4248
                return($prepared_query);
4249
            }
4250
            $this->setParamArray($prepared_query, $params, $param_types);
4251
            $result = $this->executeQuery($prepared_query, $types);
4252
        } else {
4253
            $result = $this->query($query, $types);
4254
        }
4255
 
4256
        if (MDB::isError($result)) {
4257
            return($result);
4258
        }
4259
 
4260
        $all = $this->fetchAll($result, $fetchmode);
4261
        if (MDB::isError($all)) {
4262
            return($all);
4263
        }
4264
        if (isset($prepared_query)) {
4265
            $result = $this->freePreparedQuery($prepared_query);
4266
            if (MDB::isError($result)) {
4267
                return($result);
4268
            }
4269
        }
4270
        return($all);
4271
    }
4272
 
4273
    // }}}
4274
    // {{{ tableInfo()
4275
 
4276
    /**
4277
     * returns meta data about the result set
4278
     *
4279
     * @param resource $result result identifier
4280
     * @param mixed $mode depends on implementation
4281
     * @return array an nested array, or a MDB error
4282
     * @access public
4283
     */
4284
    function tableInfo($result, $mode = NULL)
4285
    {
4286
        return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
4287
    }
4288
 
4289
    // }}}
4290
    // {{{ createLob()
4291
 
4292
    /**
4293
     * Create a handler object of a specified class with functions to
4294
     * retrieve data from a large object data stream.
4295
     *
4296
     * @param array $arguments An associative array with parameters to create
4297
     *                  the handler object. The array indexes are the names of
4298
     *                  the parameters and the array values are the respective
4299
     *                  parameter values.
4300
     *
4301
     *                  Some parameters are specific of the class of each type
4302
     *                  of handler object that is created. The following
4303
     *                  parameters are common to all handler object classes:
4304
     *
4305
     *                  Type
4306
     *
4307
     *                      Name of the type of the built-in supported class
4308
     *                      that will be used to create the handler object.
4309
     *                      There are currently four built-in types of handler
4310
     *                      object classes: data, resultlob, inputfile and
4311
     *                      outputfile.
4312
     *
4313
     *                      The data handler class is the default class. It
4314
     *                      simply reads data from a given data string.
4315
     *
4316
     *                      The resultlob handler class is meant to read data
4317
     *                      from a large object retrieved from a query result.
4318
     *                      This class is not used directly by applications.
4319
     *
4320
     *                      The inputfile handler class is meant to read data
4321
     *                      from a file to use in prepared queries with large
4322
     *                      object field parameters.
4323
     *
4324
     *                      The outputfile handler class is meant to write to
4325
     *                      a file data from result columns with large object
4326
     *                      fields. The functions to read from this type of
4327
     *                      large object do not return any data. Instead, the
4328
     *                      data is just written to the output file with the
4329
     *                      data retrieved from a specified large object handle.
4330
     *
4331
     *                  Class
4332
     *
4333
     *                      Name of the class of the handler object that will be
4334
     *                      created if the Type argument is not specified. This
4335
     *                      argument should be used when you need to specify a
4336
     *                      custom handler class.
4337
     *
4338
     *                  Database
4339
     *
4340
     *                      Database object as returned by MDB::connect.
4341
     *                      This is an option argument needed by some handler
4342
     *                      classes like resultlob.
4343
     *
4344
     *                  The following arguments are specific of the inputfile
4345
     *                  handler class:
4346
     *
4347
     *                      File
4348
     *
4349
     *                          Integer handle value of a file already opened
4350
     *                          for writing.
4351
     *
4352
     *                      FileName
4353
     *
4354
     *                          Name of a file to be opened for writing if the
4355
     *                          File argument is not specified.
4356
     *
4357
     *                  The following arguments are specific of the outputfile
4358
     *                  handler class:
4359
     *
4360
     *                      File
4361
     *
4362
     *                          Integer handle value of a file already opened
4363
     *                          for writing.
4364
     *
4365
     *                      FileName
4366
     *
4367
     *                          Name of a file to be opened for writing if the
4368
     *                          File argument is not specified.
4369
     *
4370
     *                      BufferLength
4371
     *
4372
     *                          Integer value that specifies the length of a
4373
     *                          buffer that will be used to read from the
4374
     *                          specified large object.
4375
     *
4376
     *                      LOB
4377
     *
4378
     *                          Integer handle value that specifies a large
4379
     *                          object from which the data to be stored in the
4380
     *                          output file will be written.
4381
     *
4382
     *                      Result
4383
     *
4384
     *                          Integer handle value as returned by the function
4385
     *                          MDB::query() or MDB::executeQuery() that specifies
4386
     *                          the result set that contains the large object value
4387
     *                          to be retrieved. If the LOB argument is specified,
4388
     *                          this argument is ignored.
4389
     *
4390
     *                      Row
4391
     *
4392
     *                          Integer value that specifies the number of the
4393
     *                          row of the result set that contains the large
4394
     *                          object value to be retrieved. If the LOB
4395
     *                          argument is specified, this argument is ignored.
4396
     *
4397
     *                      Field
4398
     *
4399
     *                          Integer or string value that specifies the
4400
     *                          number or the name of the column of the result
4401
     *                          set that contains the large object value to be
4402
     *                          retrieved. If the LOB argument is specified,
4403
     *                          this argument is ignored.
4404
     *
4405
     *                      Binary
4406
     *
4407
     *                          Boolean value that specifies whether the large
4408
     *                          object column to be retrieved is of binary type
4409
     *                          (blob) or otherwise is of character type (clob).
4410
     *                          If the LOB argument is specified, this argument
4411
     *                          is ignored.
4412
     *
4413
     *                  The following argument is specific of the data
4414
     *                  handler class:
4415
     *
4416
     *                  Data
4417
     *
4418
     *                      String of data that will be returned by the class
4419
     *                      when it requested with the readLOB() method.
4420
     *
4421
     *                  The following argument is specific of the resultlob
4422
     *                  handler class:
4423
     *
4424
     *                      ResultLOB
4425
     *
4426
     *                          Integer handle value of a large object result
4427
     *                          row field.
4428
     * @return integer handle value that should be passed as argument insubsequent
4429
     * calls to functions that retrieve data from the large object input stream.
4430
     * @access public
4431
     */
4432
    function createLob($arguments)
4433
    {
4434
        $result = $this->loadLob('Create LOB');
4435
        if (MDB::isError($result)) {
4436
            return($result);
4437
        }
4438
        $class_name = 'MDB_LOB';
4439
        if (isset($arguments['Type'])) {
4440
            switch ($arguments['Type']) {
4441
                case 'data':
4442
                    break;
4443
                case 'resultlob':
4444
                    $class_name = 'MDB_LOB_Result';
4445
                    break;
4446
                case 'inputfile':
4447
                    $class_name = 'MDB_LOB_Input_File';
4448
                    break;
4449
                case 'outputfile':
4450
                    $class_name = 'MDB_LOB_Output_File';
4451
                    break;
4452
                default:
4453
                    if (isset($arguments['Error'])) {
4454
                        $arguments['Error'] = $arguments['Type'] . ' is not a valid type of large object';
4455
                    }
4456
                    return($this->raiseError());
4457
            }
4458
        } else {
4459
            if (isset($arguments['Class'])) {
4460
                $class = $arguments['Class'];
4461
            }
4462
        }
4463
        $lob = count($GLOBALS['_MDB_lobs']) + 1;
4464
        $GLOBALS['_MDB_lobs'][$lob] = &new $class_name;
4465
        if (isset($arguments['Database'])) {
4466
            $GLOBALS['_MDB_lobs'][$lob]->database = $arguments['Database'];
4467
        } else {
4468
            $GLOBALS['_MDB_lobs'][$lob]->database = &$this;
4469
        }
4470
        if (MDB::isError($result = $GLOBALS['_MDB_lobs'][$lob]->create($arguments))) {
4471
            $GLOBALS['_MDB_lobs'][$lob]->database->destroyLob($lob);
4472
            return($result);
4473
        }
4474
        return($lob);
4475
    }
4476
 
4477
    // }}}
4478
    // {{{ readLob()
4479
 
4480
    /**
4481
     * Read data from large object input stream.
4482
     *
4483
     * @param integer $lob argument handle that is returned by the
4484
     *                          MDB::createLob() method.
4485
     * @param string $data reference to a variable that will hold data
4486
     *                          to be read from the large object input stream
4487
     * @param integer $length    value that indicates the largest ammount ofdata
4488
     *                          to be read from the large object input stream.
4489
     * @return mixed the effective number of bytes read from the large object
4490
     *                      input stream on sucess or an MDB error object.
4491
     * @access public
4492
     * @see endOfLob()
4493
     */
4494
    function readLob($lob, &$data, $length)
4495
    {
4496
        return($GLOBALS['_MDB_lobs'][$lob]->readLob($data, $length));
4497
    }
4498
 
4499
    // }}}
4500
    // {{{ endOfLob()
4501
 
4502
    /**
4503
     * Determine whether it was reached the end of the large object and
4504
     * therefore there is no more data to be read for the its input stream.
4505
     *
4506
     * @param integer $lob argument handle that is returned by the
4507
     *                          MDB::createLob() method.
4508
     * @access public
4509
     * @return boolean flag that indicates whether it was reached the end of the large object input stream
4510
     */
4511
    function endOfLob($lob)
4512
    {
4513
        return($GLOBALS['_MDB_lobs'][$lob]->endOfLob());
4514
    }
4515
 
4516
    // }}}
4517
    // {{{ destroyLob()
4518
 
4519
    /**
4520
     * Free any resources allocated during the lifetime of the large object
4521
     * handler object.
4522
     *
4523
     * @param integer $lob argument handle that is returned by the
4524
     *                          MDB::createLob() method.
4525
     * @access public
4526
     */
4527
    function destroyLob($lob)
4528
    {
4529
        $GLOBALS['_MDB_lobs'][$lob]->destroy();
4530
        unset($GLOBALS['_MDB_lobs'][$lob]);
4531
    }
4532
 
4533
    // }}}
4534
    // {{{ Destructor
4535
 
4536
    /**
4537
    * this function closes open transactions to be executed at shutdown
4538
    *
4539
    * @access private
4540
    */
4541
    function _MDB_Common()
4542
    {
4543
        if ($this->in_transaction && !MDB::isError($this->rollback())) {
4544
            $this->autoCommit(TRUE);
4545
        }
4546
    }
4547
};
4548
?>