~chroot64bit/zivios/gentoo-experimental

« back to all changes in this revision

Viewing changes to application/library/Zend/Db/Adapter/Db2.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
 * @package    Zend_Db
 
16
 * @subpackage Adapter
 
17
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 
18
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 
19
 *
 
20
 */
 
21
 
 
22
/**
 
23
 * @see Zend_Db
 
24
 */
 
25
require_once 'Zend/Db.php';
 
26
 
 
27
/**
 
28
 * @see Zend_Db_Adapter_Abstract
 
29
 */
 
30
require_once 'Zend/Db/Adapter/Abstract.php';
 
31
 
 
32
/**
 
33
 * @see Zend_Loader
 
34
 */
 
35
require_once 'Zend/Loader.php';
 
36
 
 
37
/**
 
38
 * @see Zend_Db_Statement_Db2
 
39
 */
 
40
require_once 'Zend/Db/Statement/Db2.php';
 
41
 
 
42
 
 
43
/**
 
44
 * @package    Zend_Db
 
45
 * @copyright  Copyright (c) 2005-2008 Zend Technologies Inc. (http://www.zend.com)
 
46
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 
47
 */
 
48
 
 
49
class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
 
50
{
 
51
    /**
 
52
     * User-provided configuration.
 
53
     *
 
54
     * Basic keys are:
 
55
     *
 
56
     * username   => (string)  Connect to the database as this username.
 
57
     * password   => (string)  Password associated with the username.
 
58
     * host       => (string)  What host to connect to (default 127.0.0.1)
 
59
     * dbname     => (string)  The name of the database to user
 
60
     * protocol   => (string)  Protocol to use, defaults to "TCPIP"
 
61
     * port       => (integer) Port number to use for TCP/IP if protocol is "TCPIP"
 
62
     * persistent => (boolean) Set TRUE to use a persistent connection (db2_pconnect)
 
63
     *
 
64
     * @var array
 
65
     */
 
66
    protected $_config = array(
 
67
        'dbname'       => null,
 
68
        'username'     => null,
 
69
        'password'     => null,
 
70
        'host'         => 'localhost',
 
71
        'port'         => '50000',
 
72
        'protocol'     => 'TCPIP',
 
73
        'persistent'   => false
 
74
    );
 
75
 
 
76
    /**
 
77
     * Execution mode
 
78
     *
 
79
     * @var int execution flag (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
 
80
     */
 
81
    protected $_execute_mode = DB2_AUTOCOMMIT_ON;
 
82
 
 
83
    /**
 
84
     * Default class name for a DB statement.
 
85
     *
 
86
     * @var string
 
87
     */
 
88
    protected $_defaultStmtClass = 'Zend_Db_Statement_Db2';
 
89
 
 
90
    /**
 
91
     * Keys are UPPERCASE SQL datatypes or the constants
 
92
     * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
 
93
     *
 
94
     * Values are:
 
95
     * 0 = 32-bit integer
 
96
     * 1 = 64-bit integer
 
97
     * 2 = float or decimal
 
98
     *
 
99
     * @var array Associative array of datatypes to values 0, 1, or 2.
 
100
     */
 
101
    protected $_numericDataTypes = array(
 
102
        Zend_Db::INT_TYPE    => Zend_Db::INT_TYPE,
 
103
        Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
 
104
        Zend_Db::FLOAT_TYPE  => Zend_Db::FLOAT_TYPE,
 
105
        'INTEGER'            => Zend_Db::INT_TYPE,
 
106
        'SMALLINT'           => Zend_Db::INT_TYPE,
 
107
        'BIGINT'             => Zend_Db::BIGINT_TYPE,
 
108
        'DECIMAL'            => Zend_Db::FLOAT_TYPE,
 
109
        'NUMERIC'            => Zend_Db::FLOAT_TYPE
 
110
    );
 
111
 
 
112
    /**
 
113
     * Creates a connection resource.
 
114
     *
 
115
     * @return void
 
116
     */
 
117
    protected function _connect()
 
118
    {
 
119
        if (is_resource($this->_connection)) {
 
120
            // connection already exists
 
121
            return;
 
122
        }
 
123
 
 
124
        if (!extension_loaded('ibm_db2')) {
 
125
            /**
 
126
             * @see Zend_Db_Adapter_Db2_Exception
 
127
             */
 
128
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
129
            throw new Zend_Db_Adapter_Db2_Exception('The IBM DB2 extension is required for this adapter but the extension is not loaded');
 
130
        }
 
131
 
 
132
        if ($this->_config['persistent']) {
 
133
            // use persistent connection
 
134
            $conn_func_name = 'db2_pconnect';
 
135
        } else {
 
136
            // use "normal" connection
 
137
            $conn_func_name = 'db2_connect';
 
138
        }
 
139
 
 
140
        if (!isset($this->_config['driver_options']['autocommit'])) {
 
141
            // set execution mode
 
142
            $this->_config['driver_options']['autocommit'] = &$this->_execute_mode;
 
143
        }
 
144
 
 
145
        if (isset($this->_config['options'][Zend_Db::CASE_FOLDING])) {
 
146
            $caseAttrMap = array(
 
147
                Zend_Db::CASE_NATURAL => DB2_CASE_NATURAL,
 
148
                Zend_Db::CASE_UPPER   => DB2_CASE_UPPER,
 
149
                Zend_Db::CASE_LOWER   => DB2_CASE_LOWER
 
150
            );
 
151
            $this->_config['driver_options']['DB2_ATTR_CASE'] = $caseAttrMap[$this->_config['options'][Zend_Db::CASE_FOLDING]];
 
152
        }
 
153
 
 
154
        if ($this->_config['host'] !== 'localhost') {
 
155
            // if the host isn't localhost, use extended connection params
 
156
            $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' .
 
157
                     ';DATABASE=' . $this->_config['dbname'] .
 
158
                     ';HOSTNAME=' . $this->_config['host'] .
 
159
                     ';PORT='     . $this->_config['port'] .
 
160
                     ';PROTOCOL=' . $this->_config['protocol'] .
 
161
                     ';UID='      . $this->_config['username'] .
 
162
                     ';PWD='      . $this->_config['password'] .';';
 
163
            $this->_connection = $conn_func_name(
 
164
                $dbname,
 
165
                null,
 
166
                null,
 
167
                $this->_config['driver_options']
 
168
            );
 
169
        } else {
 
170
            // host is localhost, so use standard connection params
 
171
            $this->_connection = $conn_func_name(
 
172
                $this->_config['dbname'],
 
173
                $this->_config['username'],
 
174
                $this->_config['password'],
 
175
                $this->_config['driver_options']
 
176
            );
 
177
        }
 
178
 
 
179
        // check the connection
 
180
        if (!$this->_connection) {
 
181
            /**
 
182
             * @see Zend_Db_Adapter_Db2_Exception
 
183
             */
 
184
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
185
            throw new Zend_Db_Adapter_Db2_Exception(db2_conn_errormsg(), db2_conn_error());
 
186
        }
 
187
    }
 
188
 
 
189
    /**
 
190
     * Force the connection to close.
 
191
     *
 
192
     * @return void
 
193
     */
 
194
    public function closeConnection()
 
195
    {
 
196
        db2_close($this->_connection);
 
197
        $this->_connection = null;
 
198
    }
 
199
 
 
200
    /**
 
201
     * Returns an SQL statement for preparation.
 
202
     *
 
203
     * @param string $sql The SQL statement with placeholders.
 
204
     * @return Zend_Db_Statement_Db2
 
205
     */
 
206
    public function prepare($sql)
 
207
    {
 
208
        $this->_connect();
 
209
        $stmtClass = $this->_defaultStmtClass;
 
210
        Zend_Loader::loadClass($stmtClass);
 
211
        $stmt = new $stmtClass($this, $sql);
 
212
        $stmt->setFetchMode($this->_fetchMode);
 
213
        return $stmt;
 
214
    }
 
215
 
 
216
    /**
 
217
     * Gets the execution mode
 
218
     *
 
219
     * @return int the execution mode (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
 
220
     */
 
221
    public function _getExecuteMode()
 
222
    {
 
223
        return $this->_execute_mode;
 
224
    }
 
225
 
 
226
    /**
 
227
     * @param integer $mode
 
228
     * @return void
 
229
     */
 
230
    public function _setExecuteMode($mode)
 
231
    {
 
232
        switch ($mode) {
 
233
            case DB2_AUTOCOMMIT_OFF:
 
234
            case DB2_AUTOCOMMIT_ON:
 
235
                $this->_execute_mode = $mode;
 
236
                db2_autocommit($this->_connection, $mode);
 
237
                break;
 
238
            default:
 
239
                /**
 
240
                 * @see Zend_Db_Adapter_Db2_Exception
 
241
                 */
 
242
                require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
243
                throw new Zend_Db_Adapter_Db2_Exception("execution mode not supported");
 
244
                break;
 
245
        }
 
246
    }
 
247
 
 
248
    /**
 
249
     * Quote a raw string.
 
250
     *
 
251
     * @param string $value     Raw string
 
252
     * @return string           Quoted string
 
253
     */
 
254
    protected function _quote($value)
 
255
    {
 
256
        if (is_int($value) || is_float($value)) {
 
257
            return $value;
 
258
        }
 
259
        /**
 
260
         * Use db2_escape_string() if it is present in the IBM DB2 extension.
 
261
         * But some supported versions of PHP do not include this function,
 
262
         * so fall back to default quoting in the parent class.
 
263
         */
 
264
        if (function_exists('db2_escape_string')) {
 
265
            return "'" . db2_escape_string($value) . "'";
 
266
        }
 
267
        return parent::_quote($value);
 
268
    }
 
269
 
 
270
    /**
 
271
     * @return string
 
272
     */
 
273
    public function getQuoteIdentifierSymbol()
 
274
    {
 
275
        $this->_connect();
 
276
        $info = db2_server_info($this->_connection);
 
277
        $identQuote = $info->IDENTIFIER_QUOTE_CHAR;
 
278
        return $identQuote;
 
279
    }
 
280
 
 
281
    /**
 
282
     * Returns a list of the tables in the database.
 
283
     *
 
284
     * @return array
 
285
     */
 
286
    public function listTables()
 
287
    {
 
288
        $this->_connect();
 
289
 
 
290
        // take the most general case and assume no z/OS
 
291
        // since listTables() takes no parameters
 
292
        $stmt = db2_tables($this->_connection);
 
293
 
 
294
        $tables = array();
 
295
 
 
296
        while ($row = db2_fetch_assoc($stmt)) {
 
297
            $tables[] = $row['TABLE_NAME'];
 
298
        }
 
299
 
 
300
        return $tables;
 
301
    }
 
302
 
 
303
    /**
 
304
     * Returns the column descriptions for a table.
 
305
     *
 
306
     * The return value is an associative array keyed by the column name,
 
307
     * as returned by the RDBMS.
 
308
     *
 
309
     * The value of each array element is an associative array
 
310
     * with the following keys:
 
311
     *
 
312
     * SCHEMA_NAME      => string; name of database or schema
 
313
     * TABLE_NAME       => string;
 
314
     * COLUMN_NAME      => string; column name
 
315
     * COLUMN_POSITION  => number; ordinal position of column in table
 
316
     * DATA_TYPE        => string; SQL datatype name of column
 
317
     * DEFAULT          => string; default expression of column, null if none
 
318
     * NULLABLE         => boolean; true if column can have nulls
 
319
     * LENGTH           => number; length of CHAR/VARCHAR
 
320
     * SCALE            => number; scale of NUMERIC/DECIMAL
 
321
     * PRECISION        => number; precision of NUMERIC/DECIMAL
 
322
     * UNSIGNED         => boolean; unsigned property of an integer type
 
323
     * PRIMARY          => boolean; true if column is part of the primary key
 
324
     * PRIMARY_POSITION => integer; position of column in primary key
 
325
     * IDENTITY         => integer; true if column is auto-generated with unique values
 
326
     *
 
327
     * @todo Discover integer unsigned property.
 
328
     *
 
329
     * @param string $tableName
 
330
     * @param string $schemaName OPTIONAL
 
331
     * @return array
 
332
     */
 
333
    public function describeTable($tableName, $schemaName = null)
 
334
    {
 
335
        $sql = "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
 
336
              c.typename, c.default, c.nulls, c.length, c.scale,
 
337
              c.identity, tc.type AS tabconsttype, k.colseq
 
338
            FROM syscat.columns c
 
339
              LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
 
340
                ON (k.tabschema = tc.tabschema
 
341
                  AND k.tabname = tc.tabname
 
342
                  AND tc.type = 'P'))
 
343
              ON (c.tabschema = k.tabschema
 
344
                AND c.tabname = k.tabname
 
345
                AND c.colname = k.colname)
 
346
            WHERE "
 
347
            . $this->quoteInto('UPPER(c.tabname) = UPPER(?)', $tableName);
 
348
        if ($schemaName) {
 
349
            $sql .= $this->quoteInto(' AND UPPER(c.tabschema) = UPPER(?)', $schemaName);
 
350
        }
 
351
        $sql .= " ORDER BY c.colno";
 
352
 
 
353
        $desc = array();
 
354
        $stmt = $this->query($sql);
 
355
 
 
356
        /**
 
357
         * To avoid case issues, fetch using FETCH_NUM
 
358
         */
 
359
        $result = $stmt->fetchAll(Zend_Db::FETCH_NUM);
 
360
 
 
361
        /**
 
362
         * The ordering of columns is defined by the query so we can map
 
363
         * to variables to improve readability
 
364
         */
 
365
        $tabschema      = 0;
 
366
        $tabname        = 1;
 
367
        $colname        = 2;
 
368
        $colno          = 3;
 
369
        $typename       = 4;
 
370
        $default        = 5;
 
371
        $nulls          = 6;
 
372
        $length         = 7;
 
373
        $scale          = 8;
 
374
        $identityCol    = 9;
 
375
        $tabconstype    = 10;
 
376
        $colseq         = 11;
 
377
 
 
378
        foreach ($result as $key => $row) {
 
379
            list ($primary, $primaryPosition, $identity) = array(false, null, false);
 
380
            if ($row[$tabconstype] == 'P') {
 
381
                $primary = true;
 
382
                $primaryPosition = $row[$colseq];
 
383
            }
 
384
            /**
 
385
             * In IBM DB2, an column can be IDENTITY
 
386
             * even if it is not part of the PRIMARY KEY.
 
387
             */
 
388
            if ($row[$identityCol] == 'Y') {
 
389
                $identity = true;
 
390
            }
 
391
 
 
392
            // only colname needs to be case adjusted
 
393
            $desc[$this->foldCase($row[$colname])] = array(
 
394
                'SCHEMA_NAME'      => $this->foldCase($row[$tabschema]),
 
395
                'TABLE_NAME'       => $this->foldCase($row[$tabname]),
 
396
                'COLUMN_NAME'      => $this->foldCase($row[$colname]),
 
397
                'COLUMN_POSITION'  => $row[$colno]+1,
 
398
                'DATA_TYPE'        => $row[$typename],
 
399
                'DEFAULT'          => $row[$default],
 
400
                'NULLABLE'         => (bool) ($row[$nulls] == 'Y'),
 
401
                'LENGTH'           => $row[$length],
 
402
                'SCALE'            => $row[$scale],
 
403
                'PRECISION'        => ($row[$typename] == 'DECIMAL' ? $row[$length] : 0),
 
404
                'UNSIGNED'         => null, // @todo
 
405
                'PRIMARY'          => $primary,
 
406
                'PRIMARY_POSITION' => $primaryPosition,
 
407
                'IDENTITY'         => $identity
 
408
            );
 
409
        }
 
410
 
 
411
        return $desc;
 
412
    }
 
413
 
 
414
    /**
 
415
     * Return the most recent value from the specified sequence in the database.
 
416
     * This is supported only on RDBMS brands that support sequences
 
417
     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
 
418
     *
 
419
     * @param string $sequenceName
 
420
     * @return string
 
421
     */
 
422
    public function lastSequenceId($sequenceName)
 
423
    {
 
424
        $this->_connect();
 
425
        $sql = 'SELECT PREVVAL FOR '.$this->quoteIdentifier($sequenceName, true).' AS VAL FROM SYSIBM.SYSDUMMY1';
 
426
        $value = $this->fetchOne($sql);
 
427
        return (string) $value;
 
428
    }
 
429
 
 
430
    /**
 
431
     * Generate a new value from the specified sequence in the database, and return it.
 
432
     * This is supported only on RDBMS brands that support sequences
 
433
     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
 
434
     *
 
435
     * @param string $sequenceName
 
436
     * @return string
 
437
     */
 
438
    public function nextSequenceId($sequenceName)
 
439
    {
 
440
        $this->_connect();
 
441
        $sql = 'SELECT NEXTVAL FOR '.$this->quoteIdentifier($sequenceName, true).' AS VAL FROM SYSIBM.SYSDUMMY1';
 
442
        $value = $this->fetchOne($sql);
 
443
        return (string) $value;
 
444
    }
 
445
 
 
446
    /**
 
447
     * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
 
448
     *
 
449
     * As a convention, on RDBMS brands that support sequences
 
450
     * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
 
451
     * from the arguments and returns the last id generated by that sequence.
 
452
     * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
 
453
     * returns the last value generated for such a column, and the table name
 
454
     * argument is disregarded.
 
455
     *
 
456
     * The IDENTITY_VAL_LOCAL() function gives the last generated identity value
 
457
     * in the current process, even if it was for a GENERATED column.
 
458
     *
 
459
     * @param string $tableName OPTIONAL
 
460
     * @param string $primaryKey OPTIONAL
 
461
     * @return string
 
462
     */
 
463
    public function lastInsertId($tableName = null, $primaryKey = null)
 
464
    {
 
465
        $this->_connect();
 
466
 
 
467
        if ($tableName !== null) {
 
468
            $sequenceName = $tableName;
 
469
            if ($primaryKey) {
 
470
                $sequenceName .= "_$primaryKey";
 
471
            }
 
472
            $sequenceName .= '_seq';
 
473
            return $this->lastSequenceId($sequenceName);
 
474
        }
 
475
 
 
476
        $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
 
477
        $value = $this->fetchOne($sql);
 
478
        return (string) $value;
 
479
    }
 
480
 
 
481
    /**
 
482
     * Begin a transaction.
 
483
     *
 
484
     * @return void
 
485
     */
 
486
    protected function _beginTransaction()
 
487
    {
 
488
        $this->_setExecuteMode(DB2_AUTOCOMMIT_OFF);
 
489
    }
 
490
 
 
491
    /**
 
492
     * Commit a transaction.
 
493
     *
 
494
     * @return void
 
495
     */
 
496
    protected function _commit()
 
497
    {
 
498
        if (!db2_commit($this->_connection)) {
 
499
            /**
 
500
             * @see Zend_Db_Adapter_Db2_Exception
 
501
             */
 
502
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
503
            throw new Zend_Db_Adapter_Db2_Exception(
 
504
                db2_conn_errormsg($this->_connection),
 
505
                db2_conn_error($this->_connection));
 
506
        }
 
507
 
 
508
        $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
 
509
    }
 
510
 
 
511
    /**
 
512
     * Rollback a transaction.
 
513
     *
 
514
     * @return void
 
515
     */
 
516
    protected function _rollBack()
 
517
    {
 
518
        if (!db2_rollback($this->_connection)) {
 
519
            /**
 
520
             * @see Zend_Db_Adapter_Db2_Exception
 
521
             */
 
522
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
523
            throw new Zend_Db_Adapter_Db2_Exception(
 
524
                db2_conn_errormsg($this->_connection),
 
525
                db2_conn_error($this->_connection));
 
526
        }
 
527
        $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
 
528
    }
 
529
 
 
530
    /**
 
531
     * Set the fetch mode.
 
532
     *
 
533
     * @param integer $mode
 
534
     * @return void
 
535
     * @throws Zend_Db_Adapter_Db2_Exception
 
536
     */
 
537
    public function setFetchMode($mode)
 
538
    {
 
539
        switch ($mode) {
 
540
            case Zend_Db::FETCH_NUM:   // seq array
 
541
            case Zend_Db::FETCH_ASSOC: // assoc array
 
542
            case Zend_Db::FETCH_BOTH:  // seq+assoc array
 
543
            case Zend_Db::FETCH_OBJ:   // object
 
544
                $this->_fetchMode = $mode;
 
545
                break;
 
546
            case Zend_Db::FETCH_BOUND:   // bound to PHP variable
 
547
                /**
 
548
                 * @see Zend_Db_Adapter_Db2_Exception
 
549
                 */
 
550
                require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
551
                throw new Zend_Db_Adapter_Db2_Exception('FETCH_BOUND is not supported yet');
 
552
                break;
 
553
            default:
 
554
                /**
 
555
                 * @see Zend_Db_Adapter_Db2_Exception
 
556
                 */
 
557
                require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
558
                throw new Zend_Db_Adapter_Db2_Exception("Invalid fetch mode '$mode' specified");
 
559
                break;
 
560
        }
 
561
    }
 
562
 
 
563
    /**
 
564
     * Adds an adapter-specific LIMIT clause to the SELECT statement.
 
565
     *
 
566
     * @param string $sql
 
567
     * @param integer $count
 
568
     * @param integer $offset OPTIONAL
 
569
     * @return string
 
570
     */
 
571
    public function limit($sql, $count, $offset = 0)
 
572
    {
 
573
        $count = intval($count);
 
574
        if ($count <= 0) {
 
575
            /**
 
576
             * @see Zend_Db_Adapter_Db2_Exception
 
577
             */
 
578
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
579
            throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument count=$count is not valid");
 
580
        }
 
581
 
 
582
        $offset = intval($offset);
 
583
        if ($offset < 0) {
 
584
            /**
 
585
             * @see Zend_Db_Adapter_Db2_Exception
 
586
             */
 
587
            require_once 'Zend/Db/Adapter/Db2/Exception.php';
 
588
            throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument offset=$offset is not valid");
 
589
        }
 
590
 
 
591
        if ($offset == 0) {
 
592
            $limit_sql = $sql . " FETCH FIRST $count ROWS ONLY";
 
593
            return $limit_sql;
 
594
        }
 
595
 
 
596
        /**
 
597
         * DB2 does not implement the LIMIT clause as some RDBMS do.
 
598
         * We have to simulate it with subqueries and ROWNUM.
 
599
         * Unfortunately because we use the column wildcard "*",
 
600
         * this puts an extra column into the query result set.
 
601
         */
 
602
        $limit_sql = "SELECT z2.*
 
603
            FROM (
 
604
                SELECT ROW_NUMBER() OVER() AS \"ZEND_DB_ROWNUM\", z1.*
 
605
                FROM (
 
606
                    " . $sql . "
 
607
                ) z1
 
608
            ) z2
 
609
            WHERE z2.zend_db_rownum BETWEEN " . ($offset+1) . " AND " . ($offset+$count);
 
610
        return $limit_sql;
 
611
    }
 
612
 
 
613
    /**
 
614
     * Check if the adapter supports real SQL parameters.
 
615
     *
 
616
     * @param string $type 'positional' or 'named'
 
617
     * @return bool
 
618
     */
 
619
    public function supportsParameters($type)
 
620
    {
 
621
        switch ($type) {
 
622
            case 'positional':
 
623
                return true;
 
624
            case 'named':
 
625
            default:
 
626
                return false;
 
627
        }
 
628
    }
 
629
 
 
630
}