~chroot64bit/zivios/gentoo-experimental

« back to all changes in this revision

Viewing changes to application/library/Zend/Db/Statement.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 Statement
 
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
 */
 
21
 
 
22
/**
 
23
 * @see Zend_Db
 
24
 */
 
25
require_once 'Zend/Db.php';
 
26
 
 
27
/**
 
28
 * @see Zend_Db_Statement_Interface
 
29
 */
 
30
require_once 'Zend/Db/Statement/Interface.php';
 
31
 
 
32
/**
 
33
 * Abstract class to emulate a PDOStatement for native database adapters.
 
34
 *
 
35
 * @category   Zend
 
36
 * @package    Zend_Db
 
37
 * @subpackage Statement
 
38
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 
39
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 
40
 */
 
41
abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
 
42
{
 
43
 
 
44
    /**
 
45
     * @var Zend_Db_Adapter_Abstract
 
46
     */
 
47
    protected $_adapter = null;
 
48
 
 
49
    /**
 
50
     * The current fetch mode.
 
51
     *
 
52
     * @var integer
 
53
     */
 
54
    protected $_fetchMode = Zend_Db::FETCH_ASSOC;
 
55
 
 
56
    /**
 
57
     * Attributes.
 
58
     *
 
59
     * @var array
 
60
     */
 
61
    protected $_attribute = array();
 
62
 
 
63
    /**
 
64
     * Column result bindings.
 
65
     *
 
66
     * @var array
 
67
     */
 
68
    protected $_bindColumn = array();
 
69
 
 
70
    /**
 
71
     * Query parameter bindings; covers bindParam() and bindValue().
 
72
     *
 
73
     * @var array
 
74
     */
 
75
    protected $_bindParam = array();
 
76
 
 
77
    /**
 
78
     * SQL string split into an array at placeholders.
 
79
     *
 
80
     * @var array
 
81
     */
 
82
    protected $_sqlSplit = array();
 
83
 
 
84
    /**
 
85
     * Parameter placeholders in the SQL string by position in the split array.
 
86
     *
 
87
     * @var array
 
88
     */
 
89
    protected $_sqlParam = array();
 
90
 
 
91
    /**
 
92
     * @var Zend_Db_Profiler_Query
 
93
     */
 
94
    protected $_queryId = null;
 
95
 
 
96
    /**
 
97
     * Constructor for a statement.
 
98
     *
 
99
     * @param Zend_Db_Adapter_Abstract $adapter
 
100
     * @param mixed $sql Either a string or Zend_Db_Select.
 
101
     */
 
102
    public function __construct($adapter, $sql)
 
103
    {
 
104
        $this->_adapter = $adapter;
 
105
        if ($sql instanceof Zend_Db_Select) {
 
106
            $sql = $sql->assemble();
 
107
        }
 
108
        $this->_parseParameters($sql);
 
109
        $this->_prepare($sql);
 
110
 
 
111
        $this->_queryId = $this->_adapter->getProfiler()->queryStart($sql);
 
112
    }
 
113
 
 
114
    /**
 
115
     * @param string $sql
 
116
     * @return void
 
117
     */
 
118
    protected function _parseParameters($sql)
 
119
    {
 
120
        $sql = $this->_stripQuoted($sql);
 
121
 
 
122
        // split into text and params
 
123
        $this->_sqlSplit = preg_split('/(\?|\:[a-zA-Z0-9_]+)/',
 
124
            $sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
 
125
 
 
126
        // map params
 
127
        $this->_sqlParam = array();
 
128
        foreach ($this->_sqlSplit as $key => $val) {
 
129
            if ($val == '?') {
 
130
                if ($this->_adapter->supportsParameters('positional') === false) {
 
131
                    /**
 
132
                     * @see Zend_Db_Statement_Exception
 
133
                     */
 
134
                    require_once 'Zend/Db/Statement/Exception.php';
 
135
                    throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$val'");
 
136
                }
 
137
            } else if ($val[0] == ':') {
 
138
                if ($this->_adapter->supportsParameters('named') === false) {
 
139
                    /**
 
140
                     * @see Zend_Db_Statement_Exception
 
141
                     */
 
142
                    require_once 'Zend/Db/Statement/Exception.php';
 
143
                    throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
 
144
                }
 
145
            }
 
146
            $this->_sqlParam[] = $val;
 
147
        }
 
148
 
 
149
        // set up for binding
 
150
        $this->_bindParam = array();
 
151
    }
 
152
 
 
153
    /**
 
154
     * Remove parts of a SQL string that contain quoted strings
 
155
     * of values or identifiers.
 
156
     *
 
157
     * @param string $sql
 
158
     * @return string
 
159
     */
 
160
    protected function _stripQuoted($sql)
 
161
    {
 
162
        // get the character for delimited id quotes,
 
163
        // this is usually " but in MySQL is `
 
164
        $d = $this->_adapter->quoteIdentifier('a');
 
165
        $d = $d[0];
 
166
 
 
167
        // get the value used as an escaped delimited id quote,
 
168
        // e.g. \" or "" or \`
 
169
        $de = $this->_adapter->quoteIdentifier($d);
 
170
        $de = substr($de, 1, 2);
 
171
        $de = str_replace('\\', '\\\\', $de);
 
172
 
 
173
        // get the character for value quoting
 
174
        // this should be '
 
175
        $q = $this->_adapter->quote('a');
 
176
        $q = $q[0];
 
177
 
 
178
        // get the value used as an escaped quote,
 
179
        // e.g. \' or ''
 
180
        $qe = $this->_adapter->quote($q);
 
181
        $qe = substr($qe, 1, 2);
 
182
        $qe = str_replace('\\', '\\\\', $qe);
 
183
 
 
184
        // get a version of the SQL statement with all quoted
 
185
        // values and delimited identifiers stripped out
 
186
        // remove "foo\"bar"
 
187
        $sql = preg_replace("/$q($qe|\\\\{2}|[^$q])*$q/", '', $sql);
 
188
        // remove 'foo\'bar'
 
189
        if (!empty($q)) {
 
190
            $sql = preg_replace("/$q($qe|[^$q])*$q/", '', $sql);
 
191
        }
 
192
 
 
193
        return $sql;
 
194
    }
 
195
 
 
196
    /**
 
197
     * Bind a column of the statement result set to a PHP variable.
 
198
     *
 
199
     * @param string $column Name the column in the result set, either by
 
200
     *                       position or by name.
 
201
     * @param mixed  $param  Reference to the PHP variable containing the value.
 
202
     * @param mixed  $type   OPTIONAL
 
203
     * @return bool
 
204
     */
 
205
    public function bindColumn($column, &$param, $type = null)
 
206
    {
 
207
        $this->_bindColumn[$column] =& $param;
 
208
        return true;
 
209
    }
 
210
 
 
211
    /**
 
212
     * Binds a parameter to the specified variable name.
 
213
     *
 
214
     * @param mixed $parameter Name the parameter, either integer or string.
 
215
     * @param mixed $variable  Reference to PHP variable containing the value.
 
216
     * @param mixed $type      OPTIONAL Datatype of SQL parameter.
 
217
     * @param mixed $length    OPTIONAL Length of SQL parameter.
 
218
     * @param mixed $options   OPTIONAL Other options.
 
219
     * @return bool
 
220
     */
 
221
    public function bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
 
222
    {
 
223
        if (!is_int($parameter) && !is_string($parameter)) {
 
224
            /**
 
225
             * @see Zend_Db_Statement_Exception
 
226
             */
 
227
            require_once 'Zend/Db/Statement/Exception.php';
 
228
            throw new Zend_Db_Statement_Exception('Invalid bind-variable position');
 
229
        }
 
230
 
 
231
        $position = null;
 
232
        if (($intval = (int) $parameter) > 0 && $this->_adapter->supportsParameters('positional')) {
 
233
            if ($intval >= 1 || $intval <= count($this->_sqlParam)) {
 
234
                $position = $intval;
 
235
            }
 
236
        } else if ($this->_adapter->supportsParameters('named')) {
 
237
            if ($parameter[0] != ':') {
 
238
                $parameter = ':' . $parameter;
 
239
            }
 
240
            if (in_array($parameter, $this->_sqlParam) !== false) {
 
241
                $position = $parameter;
 
242
            }
 
243
        }
 
244
 
 
245
        if ($position === null) {
 
246
            /**
 
247
             * @see Zend_Db_Statement_Exception
 
248
             */
 
249
            require_once 'Zend/Db/Statement/Exception.php';
 
250
            throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$parameter'");
 
251
        }
 
252
 
 
253
        // Finally we are assured that $position is valid
 
254
        $this->_bindParam[$position] =& $variable;
 
255
        return $this->_bindParam($position, $variable, $type, $length, $options);
 
256
    }
 
257
 
 
258
    /**
 
259
     * Binds a value to a parameter.
 
260
     *
 
261
     * @param mixed $parameter Name the parameter, either integer or string.
 
262
     * @param mixed $value     Scalar value to bind to the parameter.
 
263
     * @param mixed $type      OPTIONAL Datatype of the parameter.
 
264
     * @return bool
 
265
     */
 
266
    public function bindValue($parameter, $value, $type = null)
 
267
    {
 
268
        return $this->bindParam($parameter, $value, $type);
 
269
    }
 
270
 
 
271
    /**
 
272
     * Executes a prepared statement.
 
273
     *
 
274
     * @param array $params OPTIONAL Values to bind to parameter placeholders.
 
275
     * @return bool
 
276
     */
 
277
    public function execute(array $params = null)
 
278
    {
 
279
        /*
 
280
         * Simple case - no query profiler to manage.
 
281
         */
 
282
        if ($this->_queryId === null) {
 
283
            return $this->_execute($params);
 
284
        }
 
285
 
 
286
        /*
 
287
         * Do the same thing, but with query profiler
 
288
         * management before and after the execute.
 
289
         */
 
290
        $prof = $this->_adapter->getProfiler();
 
291
        $qp = $prof->getQueryProfile($this->_queryId);
 
292
        if ($qp->hasEnded()) {
 
293
            $this->_queryId = $prof->queryClone($qp);
 
294
            $qp = $prof->getQueryProfile($this->_queryId);
 
295
        }
 
296
        if ($params !== null) {
 
297
            $qp->bindParams($params);
 
298
        } else {
 
299
            $qp->bindParams($this->_bindParam);
 
300
        }
 
301
        $qp->start($this->_queryId);
 
302
 
 
303
        $retval = $this->_execute($params);
 
304
 
 
305
        $prof->queryEnd($this->_queryId);
 
306
 
 
307
        return $retval;
 
308
    }
 
309
 
 
310
    /**
 
311
     * Returns an array containing all of the result set rows.
 
312
     *
 
313
     * @param int $style OPTIONAL Fetch mode.
 
314
     * @param int $col   OPTIONAL Column number, if fetch mode is by column.
 
315
     * @return array Collection of rows, each in a format by the fetch mode.
 
316
     */
 
317
    public function fetchAll($style = null, $col = null)
 
318
    {
 
319
        $data = array();
 
320
        if ($style === Zend_Db::FETCH_COLUMN && $col === null) {
 
321
            $col = 0;
 
322
        }
 
323
        if ($col === null) {
 
324
            while ($row = $this->fetch($style)) {
 
325
                $data[] = $row;
 
326
            }
 
327
        } else {
 
328
            while ($val = $this->fetchColumn($col)) {
 
329
                $data[] = $val;
 
330
            }
 
331
        }
 
332
        return $data;
 
333
    }
 
334
 
 
335
    /**
 
336
     * Returns a single column from the next row of a result set.
 
337
     *
 
338
     * @param int $col OPTIONAL Position of the column to fetch.
 
339
     * @return string One value from the next row of result set, or false.
 
340
     */
 
341
    public function fetchColumn($col = 0)
 
342
    {
 
343
        $data = array();
 
344
        $col = (int) $col;
 
345
        $row = $this->fetch(Zend_Db::FETCH_NUM);
 
346
        if (!is_array($row)) {
 
347
            return false;
 
348
        }
 
349
        return $row[$col];
 
350
    }
 
351
 
 
352
    /**
 
353
     * Fetches the next row and returns it as an object.
 
354
     *
 
355
     * @param string $class  OPTIONAL Name of the class to create.
 
356
     * @param array  $config OPTIONAL Constructor arguments for the class.
 
357
     * @return mixed One object instance of the specified class, or false.
 
358
     */
 
359
    public function fetchObject($class = 'stdClass', array $config = array())
 
360
    {
 
361
        $obj = new $class($config);
 
362
        $row = $this->fetch(Zend_Db::FETCH_ASSOC);
 
363
        if (!is_array($row)) {
 
364
            return false;
 
365
        }
 
366
        foreach ($row as $key => $val) {
 
367
            $obj->$key = $val;
 
368
        }
 
369
        return $obj;
 
370
    }
 
371
 
 
372
    /**
 
373
     * Retrieve a statement attribute.
 
374
     *
 
375
     * @param string $key Attribute name.
 
376
     * @return mixed      Attribute value.
 
377
     */
 
378
    public function getAttribute($key)
 
379
    {
 
380
        if (array_key_exists($key, $this->_attribute)) {
 
381
            return $this->_attribute[$key];
 
382
        }
 
383
    }
 
384
 
 
385
    /**
 
386
     * Set a statement attribute.
 
387
     *
 
388
     * @param string $key Attribute name.
 
389
     * @param mixed  $val Attribute value.
 
390
     * @return bool
 
391
     */
 
392
    public function setAttribute($key, $val)
 
393
    {
 
394
        $this->_attribute[$key] = $val;
 
395
    }
 
396
 
 
397
    /**
 
398
     * Set the default fetch mode for this statement.
 
399
     *
 
400
     * @param int   $mode The fetch mode.
 
401
     * @return bool
 
402
     * @throws Zend_Db_Statement_Exception
 
403
     */
 
404
    public function setFetchMode($mode)
 
405
    {
 
406
        switch ($mode) {
 
407
            case Zend_Db::FETCH_NUM:
 
408
            case Zend_Db::FETCH_ASSOC:
 
409
            case Zend_Db::FETCH_BOTH:
 
410
            case Zend_Db::FETCH_OBJ:
 
411
                $this->_fetchMode = $mode;
 
412
                break;
 
413
            case Zend_Db::FETCH_BOUND:
 
414
            default:
 
415
                $this->closeCursor();
 
416
                /**
 
417
                 * @see Zend_Db_Statement_Exception
 
418
                 */
 
419
                require_once 'Zend/Db/Statement/Exception.php';
 
420
                throw new Zend_Db_Statement_Exception('invalid fetch mode');
 
421
                break;
 
422
        }
 
423
    }
 
424
 
 
425
    /**
 
426
     * Helper function to map retrieved row
 
427
     * to bound column variables
 
428
     *
 
429
     * @param array $row
 
430
     * @return bool True
 
431
     */
 
432
    public function _fetchBound($row)
 
433
    {
 
434
        foreach ($row as $key => $value) {
 
435
            // bindColumn() takes 1-based integer positions
 
436
            // but fetch() returns 0-based integer indexes
 
437
            if (is_int($key)) {
 
438
                $key++;
 
439
            }
 
440
            // set results only to variables that were bound previously
 
441
            if (isset($this->_bindColumn[$key])) {
 
442
                $this->_bindColumn[$key] = $value;
 
443
            }
 
444
        }
 
445
        return true;
 
446
    }
 
447
 
 
448
}