~chroot64bit/zivios/gentoo-experimental

« back to all changes in this revision

Viewing changes to application/library/Zend/Db/Adapter/Abstract.php

  • Committer: Mustafa A. Hashmi
  • Date: 2008-12-04 13:32:21 UTC
  • Revision ID: mhashmi@zivios.org-20081204133221-0nd1trunwevijj38
Inclusion of new installation framework with ties to zend layout and dojo layout

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Zend Framework
 
4
 *
 
5
 * LICENSE
 
6
 *
 
7
 * This source file is subject to the new BSD license that is bundled
 
8
 * with this package in the file LICENSE.txt.
 
9
 * It is also available through the world-wide-web at this URL:
 
10
 * http://framework.zend.com/license/new-bsd
 
11
 * If you did not receive a copy of the license and are unable to
 
12
 * obtain it through the world-wide-web, please send an email
 
13
 * to license@zend.com so we can send you a copy immediately.
 
14
 *
 
15
 * @category   Zend
 
16
 * @package    Zend_Db
 
17
 * @subpackage Adapter
 
18
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 
19
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 
20
 * @version    $Id: Abstract.php 10975 2008-08-22 15:47:04Z doctorrock83 $
 
21
 */
 
22
 
 
23
 
 
24
/**
 
25
 * @see Zend_Db
 
26
 */
 
27
require_once 'Zend/Db.php';
 
28
 
 
29
/**
 
30
 * @see Zend_Db_Select
 
31
 */
 
32
require_once 'Zend/Db/Select.php';
 
33
 
 
34
/**
 
35
 * @see Zend_Loader
 
36
 */
 
37
require_once 'Zend/Loader.php';
 
38
 
 
39
 
 
40
/**
 
41
 * Class for connecting to SQL databases and performing common operations.
 
42
 *
 
43
 * @category   Zend
 
44
 * @package    Zend_Db
 
45
 * @subpackage Adapter
 
46
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 
47
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 
48
 */
 
49
abstract class Zend_Db_Adapter_Abstract
 
50
{
 
51
 
 
52
    /**
 
53
     * User-provided configuration
 
54
     *
 
55
     * @var array
 
56
     */
 
57
    protected $_config = array();
 
58
 
 
59
    /**
 
60
     * Fetch mode
 
61
     *
 
62
     * @var integer
 
63
     */
 
64
    protected $_fetchMode = Zend_Db::FETCH_ASSOC;
 
65
 
 
66
    /**
 
67
     * Query profiler object, of type Zend_Db_Profiler
 
68
     * or a subclass of that.
 
69
     *
 
70
     * @var Zend_Db_Profiler
 
71
     */
 
72
    protected $_profiler;
 
73
 
 
74
    /**
 
75
     * Default class name for a DB statement.
 
76
     *
 
77
     * @var string
 
78
     */
 
79
    protected $_defaultStmtClass = 'Zend_Db_Statement';
 
80
 
 
81
    /**
 
82
     * Default class name for the profiler object.
 
83
     *
 
84
     * @var string
 
85
     */
 
86
    protected $_defaultProfilerClass = 'Zend_Db_Profiler';
 
87
 
 
88
    /**
 
89
     * Database connection
 
90
     *
 
91
     * @var object|resource|null
 
92
     */
 
93
    protected $_connection = null;
 
94
 
 
95
    /**
 
96
     * Specifies the case of column names retrieved in queries
 
97
     * Options
 
98
     * Zend_Db::CASE_NATURAL (default)
 
99
     * Zend_Db::CASE_LOWER
 
100
     * Zend_Db::CASE_UPPER
 
101
     *
 
102
     * @var integer
 
103
     */
 
104
    protected $_caseFolding = Zend_Db::CASE_NATURAL;
 
105
 
 
106
    /**
 
107
     * Specifies whether the adapter automatically quotes identifiers.
 
108
     * If true, most SQL generated by Zend_Db classes applies
 
109
     * identifier quoting automatically.
 
110
     * If false, developer must quote identifiers themselves
 
111
     * by calling quoteIdentifier().
 
112
     *
 
113
     * @var bool
 
114
     */
 
115
    protected $_autoQuoteIdentifiers = true;
 
116
 
 
117
    /**
 
118
     * Keys are UPPERCASE SQL datatypes or the constants
 
119
     * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
 
120
     *
 
121
     * Values are:
 
122
     * 0 = 32-bit integer
 
123
     * 1 = 64-bit integer
 
124
     * 2 = float or decimal
 
125
     *
 
126
     * @var array Associative array of datatypes to values 0, 1, or 2.
 
127
     */
 
128
    protected $_numericDataTypes = array(
 
129
        Zend_Db::INT_TYPE    => Zend_Db::INT_TYPE,
 
130
        Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
 
131
        Zend_Db::FLOAT_TYPE  => Zend_Db::FLOAT_TYPE
 
132
    );
 
133
 
 
134
    /**
 
135
     * Constructor.
 
136
     *
 
137
     * $config is an array of key/value pairs or an instance of Zend_Config
 
138
     * containing configuration options.  These options are common to most adapters:
 
139
     *
 
140
     * dbname         => (string) The name of the database to user
 
141
     * username       => (string) Connect to the database as this username.
 
142
     * password       => (string) Password associated with the username.
 
143
     * host           => (string) What host to connect to, defaults to localhost
 
144
     *
 
145
     * Some options are used on a case-by-case basis by adapters:
 
146
     *
 
147
     * port           => (string) The port of the database
 
148
     * persistent     => (boolean) Whether to use a persistent connection or not, defaults to false
 
149
     * protocol       => (string) The network protocol, defaults to TCPIP
 
150
     * caseFolding    => (int) style of case-alteration used for identifiers
 
151
     *
 
152
     * @param  array|Zend_Config $config An array or instance of Zend_Config having configuration data
 
153
     * @throws Zend_Db_Adapter_Exception
 
154
     */
 
155
    public function __construct($config)
 
156
    {
 
157
        /*
 
158
         * Verify that adapter parameters are in an array.
 
159
         */
 
160
        if (!is_array($config)) {
 
161
            /*
 
162
             * Convert Zend_Config argument to a plain array.
 
163
             */
 
164
            if ($config instanceof Zend_Config) {
 
165
                $config = $config->toArray();
 
166
            } else {
 
167
                /**
 
168
                 * @see Zend_Db_Exception
 
169
                 */
 
170
                require_once 'Zend/Db/Exception.php';
 
171
                throw new Zend_Db_Exception('Adapter parameters must be in an array or a Zend_Config object');
 
172
            }
 
173
        }
 
174
 
 
175
        $this->_checkRequiredOptions($config);
 
176
 
 
177
        $options = array(
 
178
            Zend_Db::CASE_FOLDING           => $this->_caseFolding,
 
179
            Zend_DB::AUTO_QUOTE_IDENTIFIERS => $this->_autoQuoteIdentifiers
 
180
        );
 
181
        $driverOptions = array();
 
182
 
 
183
        /*
 
184
         * normalize the config and merge it with the defaults
 
185
         */
 
186
        if (array_key_exists('options', $config)) {
 
187
            // can't use array_merge() because keys might be integers
 
188
            foreach ((array) $config['options'] as $key => $value) {
 
189
                $options[$key] = $value;
 
190
            }
 
191
        }
 
192
        if (array_key_exists('driver_options', $config)) {
 
193
            if (!empty($config['driver_options'])) {
 
194
                // can't use array_merge() because keys might be integers
 
195
                foreach ((array) $config['driver_options'] as $key => $value) {
 
196
                    $driverOptions[$key] = $value;
 
197
                }
 
198
            }
 
199
        }
 
200
        $this->_config  = array_merge($this->_config, $config);
 
201
        $this->_config['options'] = $options;
 
202
        $this->_config['driver_options'] = $driverOptions;
 
203
 
 
204
        // obtain the case setting, if there is one
 
205
        if (array_key_exists(Zend_Db::CASE_FOLDING, $options)) {
 
206
            $case = (int) $options[Zend_Db::CASE_FOLDING];
 
207
            switch ($case) {
 
208
                case Zend_Db::CASE_LOWER:
 
209
                case Zend_Db::CASE_UPPER:
 
210
                case Zend_Db::CASE_NATURAL:
 
211
                    $this->_caseFolding = $case;
 
212
                    break;
 
213
                default:
 
214
                    require_once 'Zend/Db/Adapter/Exception.php';
 
215
                    throw new Zend_Db_Adapter_Exception('Case must be one of the following constants: '
 
216
                        . 'Zend_Db::CASE_NATURAL, Zend_Db::CASE_LOWER, Zend_Db::CASE_UPPER');
 
217
            }
 
218
        }
 
219
 
 
220
        // obtain quoting property if there is one
 
221
        if (array_key_exists(Zend_Db::AUTO_QUOTE_IDENTIFIERS, $options)) {
 
222
            $this->_autoQuoteIdentifiers = (bool) $options[Zend_Db::AUTO_QUOTE_IDENTIFIERS];
 
223
        }
 
224
 
 
225
        // create a profiler object
 
226
        $profiler = false;
 
227
        if (array_key_exists(Zend_Db::PROFILER, $this->_config)) {
 
228
            $profiler = $this->_config[Zend_Db::PROFILER];
 
229
            unset($this->_config[Zend_Db::PROFILER]);
 
230
        }
 
231
        $this->setProfiler($profiler);
 
232
    }
 
233
 
 
234
    /**
 
235
     * Check for config options that are mandatory.
 
236
     * Throw exceptions if any are missing.
 
237
     *
 
238
     * @param array $config
 
239
     * @throws Zend_Db_Adapter_Exception
 
240
     */
 
241
    protected function _checkRequiredOptions(array $config)
 
242
    {
 
243
        // we need at least a dbname
 
244
        if (! array_key_exists('dbname', $config)) {
 
245
            require_once 'Zend/Db/Adapter/Exception.php';
 
246
            throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
 
247
        }
 
248
 
 
249
        if (! array_key_exists('password', $config)) {
 
250
            /**
 
251
             * @see Zend_Db_Adapter_Exception
 
252
             */
 
253
            require_once 'Zend/Db/Adapter/Exception.php';
 
254
            throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'password' for login credentials");
 
255
        }
 
256
 
 
257
        if (! array_key_exists('username', $config)) {
 
258
            /**
 
259
             * @see Zend_Db_Adapter_Exception
 
260
             */
 
261
            require_once 'Zend/Db/Adapter/Exception.php';
 
262
            throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'username' for login credentials");
 
263
        }
 
264
    }
 
265
 
 
266
    /**
 
267
     * Returns the underlying database connection object or resource.
 
268
     * If not presently connected, this initiates the connection.
 
269
     *
 
270
     * @return object|resource|null
 
271
     */
 
272
    public function getConnection()
 
273
    {
 
274
        $this->_connect();
 
275
        return $this->_connection;
 
276
    }
 
277
 
 
278
    /**
 
279
     * Returns the configuration variables in this adapter.
 
280
     *
 
281
     * @return array
 
282
     */
 
283
    public function getConfig()
 
284
    {
 
285
        return $this->_config;
 
286
    }
 
287
 
 
288
    /**
 
289
     * Set the adapter's profiler object.
 
290
     *
 
291
     * The argument may be a boolean, an associative array, an instance of
 
292
     * Zend_Db_Profiler, or an instance of Zend_Config.
 
293
     *
 
294
     * A boolean argument sets the profiler to enabled if true, or disabled if
 
295
     * false.  The profiler class is the adapter's default profiler class,
 
296
     * Zend_Db_Profiler.
 
297
     *
 
298
     * An instance of Zend_Db_Profiler sets the adapter's instance to that
 
299
     * object.  The profiler is enabled and disabled separately.
 
300
     *
 
301
     * An associative array argument may contain any of the keys 'enabled',
 
302
     * 'class', and 'instance'. The 'enabled' and 'instance' keys correspond to the
 
303
     * boolean and object types documented above. The 'class' key is used to name a
 
304
     * class to use for a custom profiler. The class must be Zend_Db_Profiler or a
 
305
     * subclass. The class is instantiated with no constructor arguments. The 'class'
 
306
     * option is ignored when the 'instance' option is supplied.
 
307
     *
 
308
     * An object of type Zend_Config may contain the properties 'enabled', 'class', and
 
309
     * 'instance', just as if an associative array had been passed instead.
 
310
     *
 
311
     * @param  Zend_Db_Profiler|Zend_Config|array|boolean $profiler
 
312
     * @return Zend_Db_Adapter_Abstract Provides a fluent interface
 
313
     * @throws Zend_Db_Profiler_Exception if the object instance or class specified
 
314
     *         is not Zend_Db_Profiler or an extension of that class.
 
315
     */
 
316
    public function setProfiler($profiler)
 
317
    {
 
318
        $enabled          = null;
 
319
        $profilerClass    = $this->_defaultProfilerClass;
 
320
        $profilerInstance = null;
 
321
 
 
322
        if ($profilerIsObject = is_object($profiler)) {
 
323
            if ($profiler instanceof Zend_Db_Profiler) {
 
324
                $profilerInstance = $profiler;
 
325
            } else if ($profiler instanceof Zend_Config) {
 
326
                $profiler = $profiler->toArray();
 
327
            } else {
 
328
                /**
 
329
                 * @see Zend_Db_Profiler_Exception
 
330
                 */
 
331
                require_once 'Zend/Db/Profiler/Exception.php';
 
332
                throw new Zend_Db_Profiler_Exception('Profiler argument must be an instance of either Zend_Db_Profiler'
 
333
                    . ' or Zend_Config when provided as an object');
 
334
            }
 
335
        }
 
336
 
 
337
        if (is_array($profiler)) {
 
338
            if (isset($profiler['enabled'])) {
 
339
                $enabled = (bool) $profiler['enabled'];
 
340
            }
 
341
            if (isset($profiler['class'])) {
 
342
                $profilerClass = $profiler['class'];
 
343
            }
 
344
            if (isset($profiler['instance'])) {
 
345
                $profilerInstance = $profiler['instance'];
 
346
            }
 
347
        } else if (!$profilerIsObject) {
 
348
            $enabled = (bool) $profiler;
 
349
        }
 
350
 
 
351
        if ($profilerInstance === null) {
 
352
            @Zend_Loader::loadClass($profilerClass);
 
353
            $profilerInstance = new $profilerClass();
 
354
        }
 
355
 
 
356
        if (!$profilerInstance instanceof Zend_Db_Profiler) {
 
357
            require_once 'Zend/Db/Profiler/Exception.php';
 
358
            throw new Zend_Db_Profiler_Exception('Class ' . get_class($profilerInstance) . ' does not extend '
 
359
                . 'Zend_Db_Profiler');
 
360
        }
 
361
 
 
362
        if (null !== $enabled) {
 
363
            $profilerInstance->setEnabled($enabled);
 
364
        }
 
365
 
 
366
        $this->_profiler = $profilerInstance;
 
367
 
 
368
        return $this;
 
369
    }
 
370
 
 
371
 
 
372
    /**
 
373
     * Returns the profiler for this adapter.
 
374
     *
 
375
     * @return Zend_Db_Profiler
 
376
     */
 
377
    public function getProfiler()
 
378
    {
 
379
        return $this->_profiler;
 
380
    }
 
381
 
 
382
    /**
 
383
     * Get the default statement class.
 
384
     *
 
385
     * @return string
 
386
     */
 
387
    public function getStatementClass()
 
388
    {
 
389
        return $this->_defaultStmtClass;
 
390
    }
 
391
 
 
392
    /**
 
393
     * Set the default statement class.
 
394
     *
 
395
     * @return Zend_Db_Abstract Fluent interface
 
396
     */
 
397
    public function setStatementClass($class)
 
398
    {
 
399
        $this->_defaultStmtClass = $class;
 
400
        return $this;
 
401
    }
 
402
 
 
403
    /**
 
404
     * Prepares and executes an SQL statement with bound data.
 
405
     *
 
406
     * @param  mixed  $sql  The SQL statement with placeholders.
 
407
     *                      May be a string or Zend_Db_Select.
 
408
     * @param  mixed  $bind An array of data to bind to the placeholders.
 
409
     * @return Zend_Db_Statement_Interface
 
410
     */
 
411
    public function query($sql, $bind = array())
 
412
    {
 
413
        // connect to the database if needed
 
414
        $this->_connect();
 
415
 
 
416
        // is the $sql a Zend_Db_Select object?
 
417
        if ($sql instanceof Zend_Db_Select) {
 
418
            $sql = $sql->assemble();
 
419
        }
 
420
 
 
421
        // make sure $bind to an array;
 
422
        // don't use (array) typecasting because
 
423
        // because $bind may be a Zend_Db_Expr object
 
424
        if (!is_array($bind)) {
 
425
            $bind = array($bind);
 
426
        }
 
427
 
 
428
        // prepare and execute the statement with profiling
 
429
        $stmt = $this->prepare($sql);
 
430
        $stmt->execute($bind);
 
431
 
 
432
        // return the results embedded in the prepared statement object
 
433
        $stmt->setFetchMode($this->_fetchMode);
 
434
        return $stmt;
 
435
    }
 
436
 
 
437
    /**
 
438
     * Leave autocommit mode and begin a transaction.
 
439
     *
 
440
     * @return bool True
 
441
     */
 
442
    public function beginTransaction()
 
443
    {
 
444
        $this->_connect();
 
445
        $q = $this->_profiler->queryStart('begin', Zend_Db_Profiler::TRANSACTION);
 
446
        $this->_beginTransaction();
 
447
        $this->_profiler->queryEnd($q);
 
448
        return true;
 
449
    }
 
450
 
 
451
    /**
 
452
     * Commit a transaction and return to autocommit mode.
 
453
     *
 
454
     * @return bool True
 
455
     */
 
456
    public function commit()
 
457
    {
 
458
        $this->_connect();
 
459
        $q = $this->_profiler->queryStart('commit', Zend_Db_Profiler::TRANSACTION);
 
460
        $this->_commit();
 
461
        $this->_profiler->queryEnd($q);
 
462
        return true;
 
463
    }
 
464
 
 
465
    /**
 
466
     * Roll back a transaction and return to autocommit mode.
 
467
     *
 
468
     * @return bool True
 
469
     */
 
470
    public function rollBack()
 
471
    {
 
472
        $this->_connect();
 
473
        $q = $this->_profiler->queryStart('rollback', Zend_Db_Profiler::TRANSACTION);
 
474
        $this->_rollBack();
 
475
        $this->_profiler->queryEnd($q);
 
476
        return true;
 
477
    }
 
478
 
 
479
    /**
 
480
     * Inserts a table row with specified data.
 
481
     *
 
482
     * @param mixed $table The table to insert data into.
 
483
     * @param array $bind Column-value pairs.
 
484
     * @return int The number of affected rows.
 
485
     */
 
486
    public function insert($table, array $bind)
 
487
    {
 
488
        // extract and quote col names from the array keys
 
489
        $cols = array();
 
490
        $vals = array();
 
491
        foreach ($bind as $col => $val) {
 
492
            $cols[] = $this->quoteIdentifier($col, true);
 
493
            if ($val instanceof Zend_Db_Expr) {
 
494
                $vals[] = $val->__toString();
 
495
                unset($bind[$col]);
 
496
            } else {
 
497
                $vals[] = '?';
 
498
            }
 
499
        }
 
500
 
 
501
        // build the statement
 
502
        $sql = "INSERT INTO "
 
503
             . $this->quoteIdentifier($table, true)
 
504
             . ' (' . implode(', ', $cols) . ') '
 
505
             . 'VALUES (' . implode(', ', $vals) . ')';
 
506
 
 
507
        // execute the statement and return the number of affected rows
 
508
        $stmt = $this->query($sql, array_values($bind));
 
509
        $result = $stmt->rowCount();
 
510
        return $result;
 
511
    }
 
512
 
 
513
    /**
 
514
     * Updates table rows with specified data based on a WHERE clause.
 
515
     *
 
516
     * @param  mixed        $table The table to update.
 
517
     * @param  array        $bind  Column-value pairs.
 
518
     * @param  mixed        $where UPDATE WHERE clause(s).
 
519
     * @return int          The number of affected rows.
 
520
     */
 
521
    public function update($table, array $bind, $where = '')
 
522
    {
 
523
        /**
 
524
         * Build "col = ?" pairs for the statement,
 
525
         * except for Zend_Db_Expr which is treated literally.
 
526
         */
 
527
        $set = array();
 
528
        foreach ($bind as $col => $val) {
 
529
            if ($val instanceof Zend_Db_Expr) {
 
530
                $val = $val->__toString();
 
531
                unset($bind[$col]);
 
532
            } else {
 
533
                $val = '?';
 
534
            }
 
535
            $set[] = $this->quoteIdentifier($col, true) . ' = ' . $val;
 
536
        }
 
537
 
 
538
        $where = $this->_whereExpr($where);
 
539
 
 
540
        /**
 
541
         * Build the UPDATE statement
 
542
         */
 
543
        $sql = "UPDATE "
 
544
             . $this->quoteIdentifier($table, true)
 
545
             . ' SET ' . implode(', ', $set)
 
546
             . (($where) ? " WHERE $where" : '');
 
547
 
 
548
        /**
 
549
         * Execute the statement and return the number of affected rows
 
550
         */
 
551
        $stmt = $this->query($sql, array_values($bind));
 
552
        $result = $stmt->rowCount();
 
553
        return $result;
 
554
    }
 
555
 
 
556
    /**
 
557
     * Deletes table rows based on a WHERE clause.
 
558
     *
 
559
     * @param  mixed        $table The table to update.
 
560
     * @param  mixed        $where DELETE WHERE clause(s).
 
561
     * @return int          The number of affected rows.
 
562
     */
 
563
    public function delete($table, $where = '')
 
564
    {
 
565
        $where = $this->_whereExpr($where);
 
566
 
 
567
        /**
 
568
         * Build the DELETE statement
 
569
         */
 
570
        $sql = "DELETE FROM "
 
571
             . $this->quoteIdentifier($table, true)
 
572
             . (($where) ? " WHERE $where" : '');
 
573
 
 
574
        /**
 
575
         * Execute the statement and return the number of affected rows
 
576
         */
 
577
        $stmt = $this->query($sql);
 
578
        $result = $stmt->rowCount();
 
579
        return $result;
 
580
    }
 
581
 
 
582
    /**
 
583
     * Convert an array, string, or Zend_Db_Expr object
 
584
     * into a string to put in a WHERE clause.
 
585
     *
 
586
     * @param mixed $where
 
587
     * @return string
 
588
     */
 
589
    protected function _whereExpr($where)
 
590
    {
 
591
        if (empty($where)) {
 
592
            return $where;
 
593
        }
 
594
        if (!is_array($where)) {
 
595
            $where = array($where);
 
596
        }
 
597
        foreach ($where as &$term) {
 
598
            if ($term instanceof Zend_Db_Expr) {
 
599
                $term = $term->__toString();
 
600
            }
 
601
            $term = '(' . $term . ')';
 
602
        }
 
603
        $where = implode(' AND ', $where);
 
604
        return $where;
 
605
    }
 
606
 
 
607
    /**
 
608
     * Creates and returns a new Zend_Db_Select object for this adapter.
 
609
     *
 
610
     * @return Zend_Db_Select
 
611
     */
 
612
    public function select()
 
613
    {
 
614
        return new Zend_Db_Select($this);
 
615
    }
 
616
 
 
617
    /**
 
618
     * Get the fetch mode.
 
619
     *
 
620
     * @return int
 
621
     */
 
622
    public function getFetchMode()
 
623
    {
 
624
        return $this->_fetchMode;
 
625
    }
 
626
 
 
627
    /**
 
628
     * Fetches all SQL result rows as a sequential array.
 
629
     * Uses the current fetchMode for the adapter.
 
630
     *
 
631
     * @param string|Zend_Db_Select $sql  An SQL SELECT statement.
 
632
     * @param mixed                 $bind Data to bind into SELECT placeholders.
 
633
     * @param mixed                 $fetchMode Override current fetch mode.
 
634
     * @return array
 
635
     */
 
636
    public function fetchAll($sql, $bind = array(), $fetchMode = null)
 
637
    {
 
638
        if ($fetchMode === null) {
 
639
            $fetchMode = $this->_fetchMode;
 
640
        }
 
641
        $stmt = $this->query($sql, $bind);
 
642
        $result = $stmt->fetchAll($fetchMode);
 
643
        return $result;
 
644
    }
 
645
 
 
646
    /**
 
647
     * Fetches the first row of the SQL result.
 
648
     * Uses the current fetchMode for the adapter.
 
649
     *
 
650
     * @param string|Zend_Db_Select $sql An SQL SELECT statement.
 
651
     * @param mixed $bind Data to bind into SELECT placeholders.
 
652
     * @param mixed                 $fetchMode Override current fetch mode.
 
653
     * @return array
 
654
     */
 
655
    public function fetchRow($sql, $bind = array(), $fetchMode = null)
 
656
    {
 
657
        if ($fetchMode === null) {
 
658
            $fetchMode = $this->_fetchMode;
 
659
        }
 
660
        $stmt = $this->query($sql, $bind);
 
661
        $result = $stmt->fetch($fetchMode);
 
662
        return $result;
 
663
    }
 
664
 
 
665
    /**
 
666
     * Fetches all SQL result rows as an associative array.
 
667
     *
 
668
     * The first column is the key, the entire row array is the
 
669
     * value.  You should construct the query to be sure that
 
670
     * the first column contains unique values, or else
 
671
     * rows with duplicate values in the first column will
 
672
     * overwrite previous data.
 
673
     *
 
674
     * @param string|Zend_Db_Select $sql An SQL SELECT statement.
 
675
     * @param mixed $bind Data to bind into SELECT placeholders.
 
676
     * @return string
 
677
     */
 
678
    public function fetchAssoc($sql, $bind = array())
 
679
    {
 
680
        $stmt = $this->query($sql, $bind);
 
681
        $data = array();
 
682
        while ($row = $stmt->fetch(Zend_Db::FETCH_ASSOC)) {
 
683
            $tmp = array_values(array_slice($row, 0, 1));
 
684
            $data[$tmp[0]] = $row;
 
685
        }
 
686
        return $data;
 
687
    }
 
688
 
 
689
    /**
 
690
     * Fetches the first column of all SQL result rows as an array.
 
691
     *
 
692
     * The first column in each row is used as the array key.
 
693
     *
 
694
     * @param string|Zend_Db_Select $sql An SQL SELECT statement.
 
695
     * @param mixed $bind Data to bind into SELECT placeholders.
 
696
     * @return array
 
697
     */
 
698
    public function fetchCol($sql, $bind = array())
 
699
    {
 
700
        $stmt = $this->query($sql, $bind);
 
701
        $result = $stmt->fetchAll(Zend_Db::FETCH_COLUMN, 0);
 
702
        return $result;
 
703
    }
 
704
 
 
705
    /**
 
706
     * Fetches all SQL result rows as an array of key-value pairs.
 
707
     *
 
708
     * The first column is the key, the second column is the
 
709
     * value.
 
710
     *
 
711
     * @param string|Zend_Db_Select $sql An SQL SELECT statement.
 
712
     * @param mixed $bind Data to bind into SELECT placeholders.
 
713
     * @return string
 
714
     */
 
715
    public function fetchPairs($sql, $bind = array())
 
716
    {
 
717
        $stmt = $this->query($sql, $bind);
 
718
        $data = array();
 
719
        while ($row = $stmt->fetch(Zend_Db::FETCH_NUM)) {
 
720
            $data[$row[0]] = $row[1];
 
721
        }
 
722
        return $data;
 
723
    }
 
724
 
 
725
    /**
 
726
     * Fetches the first column of the first row of the SQL result.
 
727
     *
 
728
     * @param string|Zend_Db_Select $sql An SQL SELECT statement.
 
729
     * @param mixed $bind Data to bind into SELECT placeholders.
 
730
     * @return string
 
731
     */
 
732
    public function fetchOne($sql, $bind = array())
 
733
    {
 
734
        $stmt = $this->query($sql, $bind);
 
735
        $result = $stmt->fetchColumn(0);
 
736
        return $result;
 
737
    }
 
738
 
 
739
    /**
 
740
     * Quote a raw string.
 
741
     *
 
742
     * @param string $value     Raw string
 
743
     * @return string           Quoted string
 
744
     */
 
745
    protected function _quote($value)
 
746
    {
 
747
        if (is_int($value)) {
 
748
            return $value;
 
749
        } elseif (is_float($value)) {
 
750
            return sprintf('%F', $value);
 
751
        }
 
752
        return "'" . addcslashes($value, "\000\n\r\\'\"\032") . "'";
 
753
    }
 
754
 
 
755
    /**
 
756
     * Safely quotes a value for an SQL statement.
 
757
     *
 
758
     * If an array is passed as the value, the array values are quoted
 
759
     * and then returned as a comma-separated string.
 
760
     *
 
761
     * @param mixed $value The value to quote.
 
762
     * @param mixed $type  OPTIONAL the SQL datatype name, or constant, or null.
 
763
     * @return mixed An SQL-safe quoted value (or string of separated values).
 
764
     */
 
765
    public function quote($value, $type = null)
 
766
    {
 
767
        $this->_connect();
 
768
 
 
769
        if ($value instanceof Zend_Db_Select) {
 
770
            return '(' . $value->assemble() . ')';
 
771
        }
 
772
 
 
773
        if ($value instanceof Zend_Db_Expr) {
 
774
            return $value->__toString();
 
775
        }
 
776
 
 
777
        if (is_array($value)) {
 
778
            foreach ($value as &$val) {
 
779
                $val = $this->quote($val, $type);
 
780
            }
 
781
            return implode(', ', $value);
 
782
        }
 
783
 
 
784
        if ($type !== null && array_key_exists($type = strtoupper($type), $this->_numericDataTypes)) {
 
785
            $quotedValue = '0';
 
786
            switch ($this->_numericDataTypes[$type]) {
 
787
                case Zend_Db::INT_TYPE: // 32-bit integer
 
788
                    $quotedValue = (string) intval($value);
 
789
                    break;
 
790
                case Zend_Db::BIGINT_TYPE: // 64-bit integer
 
791
                    // ANSI SQL-style hex literals (e.g. x'[\dA-F]+')
 
792
                    // are not supported here, because these are string
 
793
                    // literals, not numeric literals.
 
794
                    if (preg_match('/^(
 
795
                          [+-]?                  # optional sign
 
796
                          (?:
 
797
                            0[Xx][\da-fA-F]+     # ODBC-style hexadecimal
 
798
                            |\d+                 # decimal or octal, or MySQL ZEROFILL decimal
 
799
                            (?:[eE][+-]?\d+)?    # optional exponent on decimals or octals
 
800
                          )
 
801
                        )/x',
 
802
                        (string) $value, $matches)) {
 
803
                        $quotedValue = $matches[1];
 
804
                    }
 
805
                    break;
 
806
                case Zend_Db::FLOAT_TYPE: // float or decimal
 
807
                    $quotedValue = sprintf('%F', $value);
 
808
            }
 
809
            return $quotedValue;
 
810
        }
 
811
 
 
812
        return $this->_quote($value);
 
813
    }
 
814
 
 
815
    /**
 
816
     * Quotes a value and places into a piece of text at a placeholder.
 
817
     *
 
818
     * The placeholder is a question-mark; all placeholders will be replaced
 
819
     * with the quoted value.   For example:
 
820
     *
 
821
     * <code>
 
822
     * $text = "WHERE date < ?";
 
823
     * $date = "2005-01-02";
 
824
     * $safe = $sql->quoteInto($text, $date);
 
825
     * // $safe = "WHERE date < '2005-01-02'"
 
826
     * </code>
 
827
     *
 
828
     * @param string  $text  The text with a placeholder.
 
829
     * @param mixed   $value The value to quote.
 
830
     * @param string  $type  OPTIONAL SQL datatype
 
831
     * @param integer $count OPTIONAL count of placeholders to replace
 
832
     * @return string An SQL-safe quoted value placed into the orignal text.
 
833
     */
 
834
    public function quoteInto($text, $value, $type = null, $count = null)
 
835
    {
 
836
        if ($count === null) {
 
837
            return str_replace('?', $this->quote($value, $type), $text);
 
838
        } else {
 
839
            while ($count > 0) {
 
840
                if (strpos($text, '?') != false) {
 
841
                    $text = substr_replace($text, $this->quote($value, $type), strpos($text, '?'), 1);
 
842
                }
 
843
                --$count;
 
844
            }
 
845
            return $text;
 
846
        }
 
847
    }
 
848
 
 
849
    /**
 
850
     * Quotes an identifier.
 
851
     *
 
852
     * Accepts a string representing a qualified indentifier. For Example:
 
853
     * <code>
 
854
     * $adapter->quoteIdentifier('myschema.mytable')
 
855
     * </code>
 
856
     * Returns: "myschema"."mytable"
 
857
     *
 
858
     * Or, an array of one or more identifiers that may form a qualified identifier:
 
859
     * <code>
 
860
     * $adapter->quoteIdentifier(array('myschema','my.table'))
 
861
     * </code>
 
862
     * Returns: "myschema"."my.table"
 
863
     *
 
864
     * The actual quote character surrounding the identifiers may vary depending on
 
865
     * the adapter.
 
866
     *
 
867
     * @param string|array|Zend_Db_Expr $ident The identifier.
 
868
     * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
 
869
     * @return string The quoted identifier.
 
870
     */
 
871
    public function quoteIdentifier($ident, $auto=false)
 
872
    {
 
873
        return $this->_quoteIdentifierAs($ident, null, $auto);
 
874
    }
 
875
 
 
876
    /**
 
877
     * Quote a column identifier and alias.
 
878
     *
 
879
     * @param string|array|Zend_Db_Expr $ident The identifier or expression.
 
880
     * @param string $alias An alias for the column.
 
881
     * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
 
882
     * @return string The quoted identifier and alias.
 
883
     */
 
884
    public function quoteColumnAs($ident, $alias, $auto=false)
 
885
    {
 
886
        return $this->_quoteIdentifierAs($ident, $alias, $auto);
 
887
    }
 
888
 
 
889
    /**
 
890
     * Quote a table identifier and alias.
 
891
     *
 
892
     * @param string|array|Zend_Db_Expr $ident The identifier or expression.
 
893
     * @param string $alias An alias for the table.
 
894
     * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
 
895
     * @return string The quoted identifier and alias.
 
896
     */
 
897
    public function quoteTableAs($ident, $alias = null, $auto = false)
 
898
    {
 
899
        return $this->_quoteIdentifierAs($ident, $alias, $auto);
 
900
    }
 
901
 
 
902
    /**
 
903
     * Quote an identifier and an optional alias.
 
904
     *
 
905
     * @param string|array|Zend_Db_Expr $ident The identifier or expression.
 
906
     * @param string $alias An optional alias.
 
907
     * @param string $as The string to add between the identifier/expression and the alias.
 
908
     * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
 
909
     * @return string The quoted identifier and alias.
 
910
     */
 
911
    protected function _quoteIdentifierAs($ident, $alias = null, $auto = false, $as = ' AS ')
 
912
    {
 
913
        if ($ident instanceof Zend_Db_Expr) {
 
914
            $quoted = $ident->__toString();
 
915
        } elseif ($ident instanceof Zend_Db_Select) {
 
916
            $quoted = '(' . $ident->assemble() . ')';
 
917
        } else {
 
918
            if (is_string($ident)) {
 
919
                $ident = explode('.', $ident);
 
920
            }
 
921
            if (is_array($ident)) {
 
922
                $segments = array();
 
923
                foreach ($ident as $segment) {
 
924
                    if ($segment instanceof Zend_Db_Expr) {
 
925
                        $segments[] = $segment->__toString();
 
926
                    } else {
 
927
                        $segments[] = $this->_quoteIdentifier($segment, $auto);
 
928
                    }
 
929
                }
 
930
                if ($alias !== null && end($ident) == $alias) {
 
931
                    $alias = null;
 
932
                }
 
933
                $quoted = implode('.', $segments);
 
934
            } else {
 
935
                $quoted = $this->_quoteIdentifier($ident, $auto);
 
936
            }
 
937
        }
 
938
        if ($alias !== null) {
 
939
            $quoted .= $as . $this->_quoteIdentifier($alias, $auto);
 
940
        }
 
941
        return $quoted;
 
942
    }
 
943
 
 
944
    /**
 
945
     * Quote an identifier.
 
946
     *
 
947
     * @param  string $value The identifier or expression.
 
948
     * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
 
949
     * @return string        The quoted identifier and alias.
 
950
     */
 
951
    protected function _quoteIdentifier($value, $auto=false)
 
952
    {
 
953
        if ($auto === false || $this->_autoQuoteIdentifiers === true) {
 
954
            $q = $this->getQuoteIdentifierSymbol();
 
955
            return ($q . str_replace("$q", "$q$q", $value) . $q);
 
956
        }
 
957
        return $value;
 
958
    }
 
959
 
 
960
    /**
 
961
     * Returns the symbol the adapter uses for delimited identifiers.
 
962
     *
 
963
     * @return string
 
964
     */
 
965
    public function getQuoteIdentifierSymbol()
 
966
    {
 
967
        return '"';
 
968
    }
 
969
 
 
970
    /**
 
971
     * Return the most recent value from the specified sequence in the database.
 
972
     * This is supported only on RDBMS brands that support sequences
 
973
     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
 
974
     *
 
975
     * @param string $sequenceName
 
976
     * @return string
 
977
     */
 
978
    public function lastSequenceId($sequenceName)
 
979
    {
 
980
        return null;
 
981
    }
 
982
 
 
983
    /**
 
984
     * Generate a new value from the specified sequence in the database, and return it.
 
985
     * This is supported only on RDBMS brands that support sequences
 
986
     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
 
987
     *
 
988
     * @param string $sequenceName
 
989
     * @return string
 
990
     */
 
991
    public function nextSequenceId($sequenceName)
 
992
    {
 
993
        return null;
 
994
    }
 
995
 
 
996
    /**
 
997
     * Helper method to change the case of the strings used
 
998
     * when returning result sets in FETCH_ASSOC and FETCH_BOTH
 
999
     * modes.
 
1000
     *
 
1001
     * This is not intended to be used by application code,
 
1002
     * but the method must be public so the Statement class
 
1003
     * can invoke it.
 
1004
     *
 
1005
     * @param string $key
 
1006
     * @returns string
 
1007
     */
 
1008
    public function foldCase($key)
 
1009
    {
 
1010
        switch ($this->_caseFolding) {
 
1011
            case Zend_Db::CASE_LOWER:
 
1012
                $value = strtolower((string) $key);
 
1013
                break;
 
1014
            case Zend_Db::CASE_UPPER:
 
1015
                $value = strtoupper((string) $key);
 
1016
                break;
 
1017
            case Zend_Db::CASE_NATURAL:
 
1018
            default:
 
1019
                $value = (string) $key;
 
1020
        }
 
1021
        return $value;
 
1022
    }
 
1023
 
 
1024
    /**
 
1025
     * Abstract Methods
 
1026
     */
 
1027
 
 
1028
    /**
 
1029
     * Returns a list of the tables in the database.
 
1030
     *
 
1031
     * @return array
 
1032
     */
 
1033
    abstract public function listTables();
 
1034
 
 
1035
    /**
 
1036
     * Returns the column descriptions for a table.
 
1037
     *
 
1038
     * The return value is an associative array keyed by the column name,
 
1039
     * as returned by the RDBMS.
 
1040
     *
 
1041
     * The value of each array element is an associative array
 
1042
     * with the following keys:
 
1043
     *
 
1044
     * SCHEMA_NAME => string; name of database or schema
 
1045
     * TABLE_NAME  => string;
 
1046
     * COLUMN_NAME => string; column name
 
1047
     * COLUMN_POSITION => number; ordinal position of column in table
 
1048
     * DATA_TYPE   => string; SQL datatype name of column
 
1049
     * DEFAULT     => string; default expression of column, null if none
 
1050
     * NULLABLE    => boolean; true if column can have nulls
 
1051
     * LENGTH      => number; length of CHAR/VARCHAR
 
1052
     * SCALE       => number; scale of NUMERIC/DECIMAL
 
1053
     * PRECISION   => number; precision of NUMERIC/DECIMAL
 
1054
     * UNSIGNED    => boolean; unsigned property of an integer type
 
1055
     * PRIMARY     => boolean; true if column is part of the primary key
 
1056
     * PRIMARY_POSITION => integer; position of column in primary key
 
1057
     *
 
1058
     * @param string $tableName
 
1059
     * @param string $schemaName OPTIONAL
 
1060
     * @return array
 
1061
     */
 
1062
    abstract public function describeTable($tableName, $schemaName = null);
 
1063
 
 
1064
    /**
 
1065
     * Creates a connection to the database.
 
1066
     *
 
1067
     * @return void
 
1068
     */
 
1069
    abstract protected function _connect();
 
1070
 
 
1071
    /**
 
1072
     * Force the connection to close.
 
1073
     *
 
1074
     * @return void
 
1075
     */
 
1076
    abstract public function closeConnection();
 
1077
 
 
1078
    /**
 
1079
     * Prepare a statement and return a PDOStatement-like object.
 
1080
     *
 
1081
     * @param string|Zend_Db_Select $sql SQL query
 
1082
     * @return Zend_Db_Statment|PDOStatement
 
1083
     */
 
1084
    abstract public function prepare($sql);
 
1085
 
 
1086
    /**
 
1087
     * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
 
1088
     *
 
1089
     * As a convention, on RDBMS brands that support sequences
 
1090
     * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
 
1091
     * from the arguments and returns the last id generated by that sequence.
 
1092
     * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
 
1093
     * returns the last value generated for such a column, and the table name
 
1094
     * argument is disregarded.
 
1095
     *
 
1096
     * @param string $tableName   OPTIONAL Name of table.
 
1097
     * @param string $primaryKey  OPTIONAL Name of primary key column.
 
1098
     * @return string
 
1099
     */
 
1100
    abstract public function lastInsertId($tableName = null, $primaryKey = null);
 
1101
 
 
1102
    /**
 
1103
     * Begin a transaction.
 
1104
     */
 
1105
    abstract protected function _beginTransaction();
 
1106
 
 
1107
    /**
 
1108
     * Commit a transaction.
 
1109
     */
 
1110
    abstract protected function _commit();
 
1111
 
 
1112
    /**
 
1113
     * Roll-back a transaction.
 
1114
     */
 
1115
    abstract protected function _rollBack();
 
1116
 
 
1117
    /**
 
1118
     * Set the fetch mode.
 
1119
     *
 
1120
     * @param integer $mode
 
1121
     * @return void
 
1122
     * @throws Zend_Db_Adapter_Exception
 
1123
     */
 
1124
    abstract public function setFetchMode($mode);
 
1125
 
 
1126
    /**
 
1127
     * Adds an adapter-specific LIMIT clause to the SELECT statement.
 
1128
     *
 
1129
     * @param mixed $sql
 
1130
     * @param integer $count
 
1131
     * @param integer $offset
 
1132
     * @return string
 
1133
     */
 
1134
    abstract public function limit($sql, $count, $offset = 0);
 
1135
 
 
1136
    /**
 
1137
     * Check if the adapter supports real SQL parameters.
 
1138
     *
 
1139
     * @param string $type 'positional' or 'named'
 
1140
     * @return bool
 
1141
     */
 
1142
    abstract public function supportsParameters($type);
 
1143
 
 
1144
}