Subversion Repositories Applications.gtt

Rev

Rev 94 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 94 Rev 187
1
<?php
1
<?php
2
 
2
 
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
 
4
 
5
/**
5
/**
6
 * The PEAR DB driver for PHP's odbc extension
6
 * The PEAR DB driver for PHP's odbc extension
7
 * for interacting with databases via ODBC connections
7
 * for interacting with databases via ODBC connections
8
 *
8
 *
9
 * PHP versions 4 and 5
9
 * PHP version 5
10
 *
10
 *
11
 * LICENSE: This source file is subject to version 3.0 of the PHP license
11
 * LICENSE: This source file is subject to version 3.0 of the PHP license
12
 * that is available through the world-wide-web at the following URI:
12
 * that is available through the world-wide-web at the following URI:
13
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
13
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
14
 * the PHP License and are unable to obtain it through the web, please
14
 * the PHP License and are unable to obtain it through the web, please
15
 * send a note to license@php.net so we can mail you a copy immediately.
15
 * send a note to license@php.net so we can mail you a copy immediately.
16
 *
16
 *
17
 * @category   Database
17
 * @category   Database
18
 * @package    DB
18
 * @package    DB
19
 * @author     Stig Bakken <ssb@php.net>
19
 * @author     Stig Bakken <ssb@php.net>
20
 * @author     Daniel Convissor <danielc@php.net>
20
 * @author     Daniel Convissor <danielc@php.net>
21
 * @copyright  1997-2005 The PHP Group
21
 * @copyright  1997-2007 The PHP Group
22
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
23
 * @version    CVS: $Id: odbc.php,v 1.78 2005/02/28 01:42:17 danielc Exp $
23
 * @version    CVS: $Id$
24
 * @link       http://pear.php.net/package/DB
24
 * @link       http://pear.php.net/package/DB
25
 */
25
 */
26
 
26
 
27
/**
27
/**
28
 * Obtain the DB_common class so it can be extended from
28
 * Obtain the DB_common class so it can be extended from
29
 */
29
 */
30
require_once 'DB/common.php';
30
require_once 'DB/common.php';
31
 
31
 
32
/**
32
/**
33
 * The methods PEAR DB uses to interact with PHP's odbc extension
33
 * The methods PEAR DB uses to interact with PHP's odbc extension
34
 * for interacting with databases via ODBC connections
34
 * for interacting with databases via ODBC connections
35
 *
35
 *
36
 * These methods overload the ones declared in DB_common.
36
 * These methods overload the ones declared in DB_common.
37
 *
37
 *
38
 * More info on ODBC errors could be found here:
38
 * More info on ODBC errors could be found here:
39
 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
39
 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
40
 *
40
 *
41
 * @category   Database
41
 * @category   Database
42
 * @package    DB
42
 * @package    DB
43
 * @author     Stig Bakken <ssb@php.net>
43
 * @author     Stig Bakken <ssb@php.net>
44
 * @author     Daniel Convissor <danielc@php.net>
44
 * @author     Daniel Convissor <danielc@php.net>
45
 * @copyright  1997-2005 The PHP Group
45
 * @copyright  1997-2007 The PHP Group
46
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
46
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
47
 * @version    Release: 1.7.6
47
 * @version    Release: 1.9.2
48
 * @link       http://pear.php.net/package/DB
48
 * @link       http://pear.php.net/package/DB
49
 */
49
 */
50
class DB_odbc extends DB_common
50
class DB_odbc extends DB_common
51
{
51
{
52
    // {{{ properties
52
    // {{{ properties
53
 
53
 
54
    /**
54
    /**
55
     * The DB driver type (mysql, oci8, odbc, etc.)
55
     * The DB driver type (mysql, oci8, odbc, etc.)
56
     * @var string
56
     * @var string
57
     */
57
     */
58
    var $phptype = 'odbc';
58
    var $phptype = 'odbc';
59
 
59
 
60
    /**
60
    /**
61
     * The database syntax variant to be used (db2, access, etc.), if any
61
     * The database syntax variant to be used (db2, access, etc.), if any
62
     * @var string
62
     * @var string
63
     */
63
     */
64
    var $dbsyntax = 'sql92';
64
    var $dbsyntax = 'sql92';
65
 
65
 
66
    /**
66
    /**
67
     * The capabilities of this DB implementation
67
     * The capabilities of this DB implementation
68
     *
68
     *
69
     * The 'new_link' element contains the PHP version that first provided
69
     * The 'new_link' element contains the PHP version that first provided
70
     * new_link support for this DBMS.  Contains false if it's unsupported.
70
     * new_link support for this DBMS.  Contains false if it's unsupported.
71
     *
71
     *
72
     * Meaning of the 'limit' element:
72
     * Meaning of the 'limit' element:
73
     *   + 'emulate' = emulate with fetch row by number
73
     *   + 'emulate' = emulate with fetch row by number
74
     *   + 'alter'   = alter the query
74
     *   + 'alter'   = alter the query
75
     *   + false     = skip rows
75
     *   + false     = skip rows
76
     *
76
     *
77
     * NOTE: The feature set of the following drivers are different than
77
     * NOTE: The feature set of the following drivers are different than
78
     * the default:
78
     * the default:
79
     *   + solid: 'transactions' = true
79
     *   + solid: 'transactions' = true
80
     *   + navision: 'limit' = false
80
     *   + navision: 'limit' = false
81
     *
81
     *
82
     * @var array
82
     * @var array
83
     */
83
     */
84
    var $features = array(
84
    var $features = array(
85
        'limit'         => 'emulate',
85
        'limit'         => 'emulate',
86
        'new_link'      => false,
86
        'new_link'      => false,
87
        'numrows'       => true,
87
        'numrows'       => true,
88
        'pconnect'      => true,
88
        'pconnect'      => true,
89
        'prepare'       => false,
89
        'prepare'       => false,
90
        'ssl'           => false,
90
        'ssl'           => false,
91
        'transactions'  => false,
91
        'transactions'  => false,
92
    );
92
    );
93
 
93
 
94
    /**
94
    /**
95
     * A mapping of native error codes to DB error codes
95
     * A mapping of native error codes to DB error codes
96
     * @var array
96
     * @var array
97
     */
97
     */
98
    var $errorcode_map = array(
98
    var $errorcode_map = array(
99
        '01004' => DB_ERROR_TRUNCATED,
99
        '01004' => DB_ERROR_TRUNCATED,
100
        '07001' => DB_ERROR_MISMATCH,
100
        '07001' => DB_ERROR_MISMATCH,
101
        '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
101
        '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
102
        '21S02' => DB_ERROR_MISMATCH,
102
        '21S02' => DB_ERROR_MISMATCH,
103
        '22001' => DB_ERROR_INVALID,
103
        '22001' => DB_ERROR_INVALID,
104
        '22003' => DB_ERROR_INVALID_NUMBER,
104
        '22003' => DB_ERROR_INVALID_NUMBER,
105
        '22005' => DB_ERROR_INVALID_NUMBER,
105
        '22005' => DB_ERROR_INVALID_NUMBER,
106
        '22008' => DB_ERROR_INVALID_DATE,
106
        '22008' => DB_ERROR_INVALID_DATE,
107
        '22012' => DB_ERROR_DIVZERO,
107
        '22012' => DB_ERROR_DIVZERO,
108
        '23000' => DB_ERROR_CONSTRAINT,
108
        '23000' => DB_ERROR_CONSTRAINT,
109
        '23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
109
        '23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
110
        '23503' => DB_ERROR_CONSTRAINT,
110
        '23503' => DB_ERROR_CONSTRAINT,
111
        '23504' => DB_ERROR_CONSTRAINT,
111
        '23504' => DB_ERROR_CONSTRAINT,
112
        '23505' => DB_ERROR_CONSTRAINT,
112
        '23505' => DB_ERROR_CONSTRAINT,
113
        '24000' => DB_ERROR_INVALID,
113
        '24000' => DB_ERROR_INVALID,
114
        '34000' => DB_ERROR_INVALID,
114
        '34000' => DB_ERROR_INVALID,
115
        '37000' => DB_ERROR_SYNTAX,
115
        '37000' => DB_ERROR_SYNTAX,
116
        '42000' => DB_ERROR_SYNTAX,
116
        '42000' => DB_ERROR_SYNTAX,
117
        '42601' => DB_ERROR_SYNTAX,
117
        '42601' => DB_ERROR_SYNTAX,
118
        'IM001' => DB_ERROR_UNSUPPORTED,
118
        'IM001' => DB_ERROR_UNSUPPORTED,
119
        'S0000' => DB_ERROR_NOSUCHTABLE,
119
        'S0000' => DB_ERROR_NOSUCHTABLE,
120
        'S0001' => DB_ERROR_ALREADY_EXISTS,
120
        'S0001' => DB_ERROR_ALREADY_EXISTS,
121
        'S0002' => DB_ERROR_NOSUCHTABLE,
121
        'S0002' => DB_ERROR_NOSUCHTABLE,
122
        'S0011' => DB_ERROR_ALREADY_EXISTS,
122
        'S0011' => DB_ERROR_ALREADY_EXISTS,
123
        'S0012' => DB_ERROR_NOT_FOUND,
123
        'S0012' => DB_ERROR_NOT_FOUND,
124
        'S0021' => DB_ERROR_ALREADY_EXISTS,
124
        'S0021' => DB_ERROR_ALREADY_EXISTS,
125
        'S0022' => DB_ERROR_NOSUCHFIELD,
125
        'S0022' => DB_ERROR_NOSUCHFIELD,
126
        'S1009' => DB_ERROR_INVALID,
126
        'S1009' => DB_ERROR_INVALID,
127
        'S1090' => DB_ERROR_INVALID,
127
        'S1090' => DB_ERROR_INVALID,
128
        'S1C00' => DB_ERROR_NOT_CAPABLE,
128
        'S1C00' => DB_ERROR_NOT_CAPABLE,
129
    );
129
    );
130
 
130
 
131
    /**
131
    /**
132
     * The raw database connection created by PHP
132
     * The raw database connection created by PHP
133
     * @var resource
133
     * @var resource
134
     */
134
     */
135
    var $connection;
135
    var $connection;
136
 
136
 
137
    /**
137
    /**
138
     * The DSN information for connecting to a database
138
     * The DSN information for connecting to a database
139
     * @var array
139
     * @var array
140
     */
140
     */
141
    var $dsn = array();
141
    var $dsn = array();
142
 
142
 
143
 
143
 
144
    /**
144
    /**
145
     * The number of rows affected by a data manipulation query
145
     * The number of rows affected by a data manipulation query
146
     * @var integer
146
     * @var integer
147
     * @access private
147
     * @access private
148
     */
148
     */
149
    var $affected = 0;
149
    var $affected = 0;
150
 
150
 
151
 
151
 
152
    // }}}
152
    // }}}
153
    // {{{ constructor
153
    // {{{ constructor
154
 
154
 
155
    /**
155
    /**
156
     * This constructor calls <kbd>$this->DB_common()</kbd>
156
     * This constructor calls <kbd>parent::__construct()</kbd>
157
     *
157
     *
158
     * @return void
158
     * @return void
159
     */
159
     */
160
    function DB_odbc()
160
    function __construct()
161
    {
161
    {
162
        $this->DB_common();
162
        parent::__construct();
163
    }
163
    }
164
 
164
 
165
    // }}}
165
    // }}}
166
    // {{{ connect()
166
    // {{{ connect()
167
 
167
 
168
    /**
168
    /**
169
     * Connect to the database server, log in and open the database
169
     * Connect to the database server, log in and open the database
170
     *
170
     *
171
     * Don't call this method directly.  Use DB::connect() instead.
171
     * Don't call this method directly.  Use DB::connect() instead.
172
     *
172
     *
173
     * PEAR DB's odbc driver supports the following extra DSN options:
173
     * PEAR DB's odbc driver supports the following extra DSN options:
174
     *   + cursor  The type of cursor to be used for this connection.
174
     *   + cursor  The type of cursor to be used for this connection.
175
     *
175
     *
176
     * @param array $dsn         the data source name
176
     * @param array $dsn         the data source name
177
     * @param bool  $persistent  should the connection be persistent?
177
     * @param bool  $persistent  should the connection be persistent?
178
     *
178
     *
179
     * @return int  DB_OK on success. A DB_Error object on failure.
179
     * @return int  DB_OK on success. A DB_Error object on failure.
180
     */
180
     */
181
    function connect($dsn, $persistent = false)
181
    function connect($dsn, $persistent = false)
182
    {
182
    {
183
        if (!PEAR::loadExtension('odbc')) {
183
        if (!PEAR::loadExtension('odbc')) {
184
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
184
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
185
        }
185
        }
186
 
186
 
187
        $this->dsn = $dsn;
187
        $this->dsn = $dsn;
188
        if ($dsn['dbsyntax']) {
188
        if ($dsn['dbsyntax']) {
189
            $this->dbsyntax = $dsn['dbsyntax'];
189
            $this->dbsyntax = $dsn['dbsyntax'];
190
        }
190
        }
191
        switch ($this->dbsyntax) {
191
        switch ($this->dbsyntax) {
192
            case 'access':
192
            case 'access':
193
            case 'db2':
193
            case 'db2':
194
            case 'solid':
194
            case 'solid':
195
                $this->features['transactions'] = true;
195
                $this->features['transactions'] = true;
196
                break;
196
                break;
197
            case 'navision':
197
            case 'navision':
198
                $this->features['limit'] = false;
198
                $this->features['limit'] = false;
199
        }
199
        }
200
 
200
 
201
        /*
201
        /*
202
         * This is hear for backwards compatibility. Should have been using
202
         * This is hear for backwards compatibility. Should have been using
203
         * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
203
         * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
204
         */
204
         */
205
        if ($dsn['database']) {
205
        if ($dsn['database']) {
206
            $odbcdsn = $dsn['database'];
206
            $odbcdsn = $dsn['database'];
207
        } elseif ($dsn['hostspec']) {
207
        } elseif ($dsn['hostspec']) {
208
            $odbcdsn = $dsn['hostspec'];
208
            $odbcdsn = $dsn['hostspec'];
209
        } else {
209
        } else {
210
            $odbcdsn = 'localhost';
210
            $odbcdsn = 'localhost';
211
        }
211
        }
212
 
212
 
213
        $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
213
        $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
214
 
214
 
215
        if (empty($dsn['cursor'])) {
215
        if (empty($dsn['cursor'])) {
216
            $this->connection = @$connect_function($odbcdsn, $dsn['username'],
216
            $this->connection = @$connect_function($odbcdsn, $dsn['username'],
217
                                                   $dsn['password']);
217
                                                   $dsn['password']);
218
        } else {
218
        } else {
219
            $this->connection = @$connect_function($odbcdsn, $dsn['username'],
219
            $this->connection = @$connect_function($odbcdsn, $dsn['username'],
220
                                                   $dsn['password'],
220
                                                   $dsn['password'],
221
                                                   $dsn['cursor']);
221
                                                   $dsn['cursor']);
222
        }
222
        }
223
 
223
 
224
        if (!is_resource($this->connection)) {
224
        if (!is_resource($this->connection)) {
225
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
225
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
226
                                     null, null, null,
226
                                     null, null, null,
227
                                     $this->errorNative());
227
                                     $this->errorNative());
228
        }
228
        }
229
        return DB_OK;
229
        return DB_OK;
230
    }
230
    }
231
 
231
 
232
    // }}}
232
    // }}}
233
    // {{{ disconnect()
233
    // {{{ disconnect()
234
 
234
 
235
    /**
235
    /**
236
     * Disconnects from the database server
236
     * Disconnects from the database server
237
     *
237
     *
238
     * @return bool  TRUE on success, FALSE on failure
238
     * @return bool  TRUE on success, FALSE on failure
239
     */
239
     */
240
    function disconnect()
240
    function disconnect()
241
    {
241
    {
242
        $err = @odbc_close($this->connection);
242
        $err = @odbc_close($this->connection);
243
        $this->connection = null;
243
        $this->connection = null;
244
        return $err;
244
        return $err;
245
    }
245
    }
246
 
246
 
247
    // }}}
247
    // }}}
248
    // {{{ simpleQuery()
248
    // {{{ simpleQuery()
249
 
249
 
250
    /**
250
    /**
251
     * Sends a query to the database server
251
     * Sends a query to the database server
252
     *
252
     *
253
     * @param string  the SQL query string
253
     * @param string  the SQL query string
254
     *
254
     *
255
     * @return mixed  + a PHP result resrouce for successful SELECT queries
255
     * @return mixed  + a PHP result resrouce for successful SELECT queries
256
     *                + the DB_OK constant for other successful queries
256
     *                + the DB_OK constant for other successful queries
257
     *                + a DB_Error object on failure
257
     *                + a DB_Error object on failure
258
     */
258
     */
259
    function simpleQuery($query)
259
    function simpleQuery($query)
260
    {
260
    {
261
        $this->last_query = $query;
261
        $this->last_query = $query;
262
        $query = $this->modifyQuery($query);
262
        $query = $this->modifyQuery($query);
263
        $result = @odbc_exec($this->connection, $query);
263
        $result = @odbc_exec($this->connection, $query);
264
        if (!$result) {
264
        if (!$result) {
265
            return $this->odbcRaiseError(); // XXX ERRORMSG
265
            return $this->odbcRaiseError(); // XXX ERRORMSG
266
        }
266
        }
267
        // Determine which queries that should return data, and which
267
        // Determine which queries that should return data, and which
268
        // should return an error code only.
268
        // should return an error code only.
269
        if (DB::isManip($query)) {
269
        if ($this->_checkManip($query)) {
270
            $this->affected = $result; // For affectedRows()
270
            $this->affected = $result; // For affectedRows()
271
            return DB_OK;
271
            return DB_OK;
272
        }
272
        }
273
        $this->affected = 0;
273
        $this->affected = 0;
274
        return $result;
274
        return $result;
275
    }
275
    }
276
 
276
 
277
    // }}}
277
    // }}}
278
    // {{{ nextResult()
278
    // {{{ nextResult()
279
 
279
 
280
    /**
280
    /**
281
     * Move the internal odbc result pointer to the next available result
281
     * Move the internal odbc result pointer to the next available result
282
     *
282
     *
283
     * @param a valid fbsql result resource
283
     * @param a valid fbsql result resource
284
     *
284
     *
285
     * @access public
285
     * @access public
286
     *
286
     *
287
     * @return true if a result is available otherwise return false
287
     * @return true if a result is available otherwise return false
288
     */
288
     */
289
    function nextResult($result)
289
    function nextResult($result)
290
    {
290
    {
291
        return @odbc_next_result($result);
291
        return @odbc_next_result($result);
292
    }
292
    }
293
 
293
 
294
    // }}}
294
    // }}}
295
    // {{{ fetchInto()
295
    // {{{ fetchInto()
296
 
296
 
297
    /**
297
    /**
298
     * Places a row from the result set into the given array
298
     * Places a row from the result set into the given array
299
     *
299
     *
300
     * Formating of the array and the data therein are configurable.
300
     * Formating of the array and the data therein are configurable.
301
     * See DB_result::fetchInto() for more information.
301
     * See DB_result::fetchInto() for more information.
302
     *
302
     *
303
     * This method is not meant to be called directly.  Use
303
     * This method is not meant to be called directly.  Use
304
     * DB_result::fetchInto() instead.  It can't be declared "protected"
304
     * DB_result::fetchInto() instead.  It can't be declared "protected"
305
     * because DB_result is a separate object.
305
     * because DB_result is a separate object.
306
     *
306
     *
307
     * @param resource $result    the query result resource
307
     * @param resource $result    the query result resource
308
     * @param array    $arr       the referenced array to put the data in
308
     * @param array    $arr       the referenced array to put the data in
309
     * @param int      $fetchmode how the resulting array should be indexed
309
     * @param int      $fetchmode how the resulting array should be indexed
310
     * @param int      $rownum    the row number to fetch (0 = first row)
310
     * @param int      $rownum    the row number to fetch (0 = first row)
311
     *
311
     *
312
     * @return mixed  DB_OK on success, NULL when the end of a result set is
312
     * @return mixed  DB_OK on success, NULL when the end of a result set is
313
     *                 reached or on failure
313
     *                 reached or on failure
314
     *
314
     *
315
     * @see DB_result::fetchInto()
315
     * @see DB_result::fetchInto()
316
     */
316
     */
317
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
317
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
318
    {
318
    {
319
        $arr = array();
319
        $arr = array();
320
        if ($rownum !== null) {
320
        if ($rownum !== null) {
321
            $rownum++; // ODBC first row is 1
321
            $rownum++; // ODBC first row is 1
322
            if (version_compare(phpversion(), '4.2.0', 'ge')) {
322
            if (version_compare(phpversion(), '4.2.0', 'ge')) {
323
                $cols = @odbc_fetch_into($result, $arr, $rownum);
323
                $cols = @odbc_fetch_into($result, $arr, $rownum);
324
            } else {
324
            } else {
325
                $cols = @odbc_fetch_into($result, $rownum, $arr);
325
                $cols = @odbc_fetch_into($result, $rownum, $arr);
326
            }
326
            }
327
        } else {
327
        } else {
328
            $cols = @odbc_fetch_into($result, $arr);
328
            $cols = @odbc_fetch_into($result, $arr);
329
        }
329
        }
330
        if (!$cols) {
330
        if (!$cols) {
331
            return null;
331
            return null;
332
        }
332
        }
333
        if ($fetchmode !== DB_FETCHMODE_ORDERED) {
333
        if ($fetchmode !== DB_FETCHMODE_ORDERED) {
334
            for ($i = 0; $i < count($arr); $i++) {
334
            for ($i = 0; $i < count($arr); $i++) {
335
                $colName = @odbc_field_name($result, $i+1);
335
                $colName = @odbc_field_name($result, $i+1);
336
                $a[$colName] = $arr[$i];
336
                $a[$colName] = $arr[$i];
337
            }
337
            }
338
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
338
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
339
                $a = array_change_key_case($a, CASE_LOWER);
339
                $a = array_change_key_case($a, CASE_LOWER);
340
            }
340
            }
341
            $arr = $a;
341
            $arr = $a;
342
        }
342
        }
343
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
343
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
344
            $this->_rtrimArrayValues($arr);
344
            $this->_rtrimArrayValues($arr);
345
        }
345
        }
346
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
346
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
347
            $this->_convertNullArrayValuesToEmpty($arr);
347
            $this->_convertNullArrayValuesToEmpty($arr);
348
        }
348
        }
349
        return DB_OK;
349
        return DB_OK;
350
    }
350
    }
351
 
351
 
352
    // }}}
352
    // }}}
353
    // {{{ freeResult()
353
    // {{{ freeResult()
354
 
354
 
355
    /**
355
    /**
356
     * Deletes the result set and frees the memory occupied by the result set
356
     * Deletes the result set and frees the memory occupied by the result set
357
     *
357
     *
358
     * This method is not meant to be called directly.  Use
358
     * This method is not meant to be called directly.  Use
359
     * DB_result::free() instead.  It can't be declared "protected"
359
     * DB_result::free() instead.  It can't be declared "protected"
360
     * because DB_result is a separate object.
360
     * because DB_result is a separate object.
361
     *
361
     *
362
     * @param resource $result  PHP's query result resource
362
     * @param resource $result  PHP's query result resource
363
     *
363
     *
364
     * @return bool  TRUE on success, FALSE if $result is invalid
364
     * @return bool  TRUE on success, FALSE if $result is invalid
365
     *
365
     *
366
     * @see DB_result::free()
366
     * @see DB_result::free()
367
     */
367
     */
368
    function freeResult($result)
368
    function freeResult($result)
369
    {
369
    {
370
        return @odbc_free_result($result);
370
        return is_resource($result) ? odbc_free_result($result) : false;
371
    }
371
    }
372
 
372
 
373
    // }}}
373
    // }}}
374
    // {{{ numCols()
374
    // {{{ numCols()
375
 
375
 
376
    /**
376
    /**
377
     * Gets the number of columns in a result set
377
     * Gets the number of columns in a result set
378
     *
378
     *
379
     * This method is not meant to be called directly.  Use
379
     * This method is not meant to be called directly.  Use
380
     * DB_result::numCols() instead.  It can't be declared "protected"
380
     * DB_result::numCols() instead.  It can't be declared "protected"
381
     * because DB_result is a separate object.
381
     * because DB_result is a separate object.
382
     *
382
     *
383
     * @param resource $result  PHP's query result resource
383
     * @param resource $result  PHP's query result resource
384
     *
384
     *
385
     * @return int  the number of columns.  A DB_Error object on failure.
385
     * @return int  the number of columns.  A DB_Error object on failure.
386
     *
386
     *
387
     * @see DB_result::numCols()
387
     * @see DB_result::numCols()
388
     */
388
     */
389
    function numCols($result)
389
    function numCols($result)
390
    {
390
    {
391
        $cols = @odbc_num_fields($result);
391
        $cols = @odbc_num_fields($result);
392
        if (!$cols) {
392
        if (!$cols) {
393
            return $this->odbcRaiseError();
393
            return $this->odbcRaiseError();
394
        }
394
        }
395
        return $cols;
395
        return $cols;
396
    }
396
    }
397
 
397
 
398
    // }}}
398
    // }}}
399
    // {{{ affectedRows()
399
    // {{{ affectedRows()
400
 
400
 
401
    /**
401
    /**
402
     * Determines the number of rows affected by a data maniuplation query
402
     * Determines the number of rows affected by a data maniuplation query
403
     *
403
     *
404
     * 0 is returned for queries that don't manipulate data.
404
     * 0 is returned for queries that don't manipulate data.
405
     *
405
     *
406
     * @return int  the number of rows.  A DB_Error object on failure.
406
     * @return int  the number of rows.  A DB_Error object on failure.
407
     */
407
     */
408
    function affectedRows()
408
    function affectedRows()
409
    {
409
    {
410
        if (empty($this->affected)) {  // In case of SELECT stms
410
        if (empty($this->affected)) {  // In case of SELECT stms
411
            return 0;
411
            return 0;
412
        }
412
        }
413
        $nrows = @odbc_num_rows($this->affected);
413
        $nrows = @odbc_num_rows($this->affected);
414
        if ($nrows == -1) {
414
        if ($nrows == -1) {
415
            return $this->odbcRaiseError();
415
            return $this->odbcRaiseError();
416
        }
416
        }
417
        return $nrows;
417
        return $nrows;
418
    }
418
    }
419
 
419
 
420
    // }}}
420
    // }}}
421
    // {{{ numRows()
421
    // {{{ numRows()
422
 
422
 
423
    /**
423
    /**
424
     * Gets the number of rows in a result set
424
     * Gets the number of rows in a result set
425
     *
425
     *
426
     * Not all ODBC drivers support this functionality.  If they don't
426
     * Not all ODBC drivers support this functionality.  If they don't
427
     * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
427
     * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
428
     *
428
     *
429
     * This method is not meant to be called directly.  Use
429
     * This method is not meant to be called directly.  Use
430
     * DB_result::numRows() instead.  It can't be declared "protected"
430
     * DB_result::numRows() instead.  It can't be declared "protected"
431
     * because DB_result is a separate object.
431
     * because DB_result is a separate object.
432
     *
432
     *
433
     * @param resource $result  PHP's query result resource
433
     * @param resource $result  PHP's query result resource
434
     *
434
     *
435
     * @return int  the number of rows.  A DB_Error object on failure.
435
     * @return int  the number of rows.  A DB_Error object on failure.
436
     *
436
     *
437
     * @see DB_result::numRows()
437
     * @see DB_result::numRows()
438
     */
438
     */
439
    function numRows($result)
439
    function numRows($result)
440
    {
440
    {
441
        $nrows = @odbc_num_rows($result);
441
        $nrows = @odbc_num_rows($result);
442
        if ($nrows == -1) {
442
        if ($nrows == -1) {
443
            return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
443
            return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
444
        }
444
        }
445
        if ($nrows === false) {
445
        if ($nrows === false) {
446
            return $this->odbcRaiseError();
446
            return $this->odbcRaiseError();
447
        }
447
        }
448
        return $nrows;
448
        return $nrows;
449
    }
449
    }
450
 
450
 
451
    // }}}
451
    // }}}
452
    // {{{ quoteIdentifier()
452
    // {{{ quoteIdentifier()
453
 
453
 
454
    /**
454
    /**
455
     * Quotes a string so it can be safely used as a table or column name
455
     * Quotes a string so it can be safely used as a table or column name
456
     *
456
     *
457
     * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
457
     * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
458
     * "Use ANSI quoted identifiers" when setting up the ODBC data source.
458
     * "Use ANSI quoted identifiers" when setting up the ODBC data source.
459
     *
459
     *
460
     * @param string $str  identifier name to be quoted
460
     * @param string $str  identifier name to be quoted
461
     *
461
     *
462
     * @return string  quoted identifier string
462
     * @return string  quoted identifier string
463
     *
463
     *
464
     * @see DB_common::quoteIdentifier()
464
     * @see DB_common::quoteIdentifier()
465
     * @since Method available since Release 1.6.0
465
     * @since Method available since Release 1.6.0
466
     */
466
     */
467
    function quoteIdentifier($str)
467
    function quoteIdentifier($str)
468
    {
468
    {
469
        switch ($this->dsn['dbsyntax']) {
469
        switch ($this->dsn['dbsyntax']) {
470
            case 'access':
470
            case 'access':
471
                return '[' . $str . ']';
471
                return '[' . $str . ']';
472
            case 'mssql':
472
            case 'mssql':
473
            case 'sybase':
473
            case 'sybase':
474
                return '[' . str_replace(']', ']]', $str) . ']';
474
                return '[' . str_replace(']', ']]', $str) . ']';
475
            case 'mysql':
475
            case 'mysql':
476
            case 'mysqli':
476
            case 'mysqli':
477
                return '`' . $str . '`';
477
                return '`' . $str . '`';
478
            default:
478
            default:
479
                return '"' . str_replace('"', '""', $str) . '"';
479
                return '"' . str_replace('"', '""', $str) . '"';
480
        }
480
        }
481
    }
481
    }
482
 
-
 
483
    // }}}
-
 
484
    // {{{ quote()
-
 
485
 
-
 
486
    /**
-
 
487
     * @deprecated  Deprecated in release 1.6.0
-
 
488
     * @internal
-
 
489
     */
-
 
490
    function quote($str)
-
 
491
    {
-
 
492
        return $this->quoteSmart($str);
-
 
493
    }
-
 
494
 
482
 
495
    // }}}
483
    // }}}
496
    // {{{ nextId()
484
    // {{{ nextId()
497
 
485
 
498
    /**
486
    /**
499
     * Returns the next free id in a sequence
487
     * Returns the next free id in a sequence
500
     *
488
     *
501
     * @param string  $seq_name  name of the sequence
489
     * @param string  $seq_name  name of the sequence
502
     * @param boolean $ondemand  when true, the seqence is automatically
490
     * @param boolean $ondemand  when true, the seqence is automatically
503
     *                            created if it does not exist
491
     *                            created if it does not exist
504
     *
492
     *
505
     * @return int  the next id number in the sequence.
493
     * @return int  the next id number in the sequence.
506
     *               A DB_Error object on failure.
494
     *               A DB_Error object on failure.
507
     *
495
     *
508
     * @see DB_common::nextID(), DB_common::getSequenceName(),
496
     * @see DB_common::nextID(), DB_common::getSequenceName(),
509
     *      DB_odbc::createSequence(), DB_odbc::dropSequence()
497
     *      DB_odbc::createSequence(), DB_odbc::dropSequence()
510
     */
498
     */
511
    function nextId($seq_name, $ondemand = true)
499
    function nextId($seq_name, $ondemand = true)
512
    {
500
    {
513
        $seqname = $this->getSequenceName($seq_name);
501
        $seqname = $this->getSequenceName($seq_name);
514
        $repeat = 0;
502
        $repeat = 0;
515
        do {
503
        do {
516
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
504
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
517
            $result = $this->query("update ${seqname} set id = id + 1");
505
            $result = $this->query("update ${seqname} set id = id + 1");
518
            $this->popErrorHandling();
506
            $this->popErrorHandling();
519
            if ($ondemand && DB::isError($result) &&
507
            if ($ondemand && DB::isError($result) &&
520
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
508
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
521
                $repeat = 1;
509
                $repeat = 1;
522
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
510
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
523
                $result = $this->createSequence($seq_name);
511
                $result = $this->createSequence($seq_name);
524
                $this->popErrorHandling();
512
                $this->popErrorHandling();
525
                if (DB::isError($result)) {
513
                if (DB::isError($result)) {
526
                    return $this->raiseError($result);
514
                    return $this->raiseError($result);
527
                }
515
                }
528
                $result = $this->query("insert into ${seqname} (id) values(0)");
516
                $result = $this->query("insert into ${seqname} (id) values(0)");
529
            } else {
517
            } else {
530
                $repeat = 0;
518
                $repeat = 0;
531
            }
519
            }
532
        } while ($repeat);
520
        } while ($repeat);
533
 
521
 
534
        if (DB::isError($result)) {
522
        if (DB::isError($result)) {
535
            return $this->raiseError($result);
523
            return $this->raiseError($result);
536
        }
524
        }
537
 
525
 
538
        $result = $this->query("select id from ${seqname}");
526
        $result = $this->query("select id from ${seqname}");
539
        if (DB::isError($result)) {
527
        if (DB::isError($result)) {
540
            return $result;
528
            return $result;
541
        }
529
        }
542
 
530
 
543
        $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
531
        $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
544
        if (DB::isError($row || !$row)) {
532
        if (DB::isError($row || !$row)) {
545
            return $row;
533
            return $row;
546
        }
534
        }
547
 
535
 
548
        return $row[0];
536
        return $row[0];
549
    }
537
    }
550
 
538
 
551
    /**
539
    /**
552
     * Creates a new sequence
540
     * Creates a new sequence
553
     *
541
     *
554
     * @param string $seq_name  name of the new sequence
542
     * @param string $seq_name  name of the new sequence
555
     *
543
     *
556
     * @return int  DB_OK on success.  A DB_Error object on failure.
544
     * @return int  DB_OK on success.  A DB_Error object on failure.
557
     *
545
     *
558
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
546
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
559
     *      DB_odbc::nextID(), DB_odbc::dropSequence()
547
     *      DB_odbc::nextID(), DB_odbc::dropSequence()
560
     */
548
     */
561
    function createSequence($seq_name)
549
    function createSequence($seq_name)
562
    {
550
    {
563
        return $this->query('CREATE TABLE '
551
        return $this->query('CREATE TABLE '
564
                            . $this->getSequenceName($seq_name)
552
                            . $this->getSequenceName($seq_name)
565
                            . ' (id integer NOT NULL,'
553
                            . ' (id integer NOT NULL,'
566
                            . ' PRIMARY KEY(id))');
554
                            . ' PRIMARY KEY(id))');
567
    }
555
    }
568
 
556
 
569
    // }}}
557
    // }}}
570
    // {{{ dropSequence()
558
    // {{{ dropSequence()
571
 
559
 
572
    /**
560
    /**
573
     * Deletes a sequence
561
     * Deletes a sequence
574
     *
562
     *
575
     * @param string $seq_name  name of the sequence to be deleted
563
     * @param string $seq_name  name of the sequence to be deleted
576
     *
564
     *
577
     * @return int  DB_OK on success.  A DB_Error object on failure.
565
     * @return int  DB_OK on success.  A DB_Error object on failure.
578
     *
566
     *
579
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
567
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
580
     *      DB_odbc::nextID(), DB_odbc::createSequence()
568
     *      DB_odbc::nextID(), DB_odbc::createSequence()
581
     */
569
     */
582
    function dropSequence($seq_name)
570
    function dropSequence($seq_name)
583
    {
571
    {
584
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
572
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
585
    }
573
    }
586
 
574
 
587
    // }}}
575
    // }}}
588
    // {{{ autoCommit()
576
    // {{{ autoCommit()
589
 
577
 
590
    /**
578
    /**
591
     * Enables or disables automatic commits
579
     * Enables or disables automatic commits
592
     *
580
     *
593
     * @param bool $onoff  true turns it on, false turns it off
581
     * @param bool $onoff  true turns it on, false turns it off
594
     *
582
     *
595
     * @return int  DB_OK on success.  A DB_Error object if the driver
583
     * @return int  DB_OK on success.  A DB_Error object if the driver
596
     *               doesn't support auto-committing transactions.
584
     *               doesn't support auto-committing transactions.
597
     */
585
     */
598
    function autoCommit($onoff = false)
586
    function autoCommit($onoff = false)
599
    {
587
    {
600
        if (!@odbc_autocommit($this->connection, $onoff)) {
588
        if (!@odbc_autocommit($this->connection, $onoff)) {
601
            return $this->odbcRaiseError();
589
            return $this->odbcRaiseError();
602
        }
590
        }
603
        return DB_OK;
591
        return DB_OK;
604
    }
592
    }
605
 
593
 
606
    // }}}
594
    // }}}
607
    // {{{ commit()
595
    // {{{ commit()
608
 
596
 
609
    /**
597
    /**
610
     * Commits the current transaction
598
     * Commits the current transaction
611
     *
599
     *
612
     * @return int  DB_OK on success.  A DB_Error object on failure.
600
     * @return int  DB_OK on success.  A DB_Error object on failure.
613
     */
601
     */
614
    function commit()
602
    function commit()
615
    {
603
    {
616
        if (!@odbc_commit($this->connection)) {
604
        if (!@odbc_commit($this->connection)) {
617
            return $this->odbcRaiseError();
605
            return $this->odbcRaiseError();
618
        }
606
        }
619
        return DB_OK;
607
        return DB_OK;
620
    }
608
    }
621
 
609
 
622
    // }}}
610
    // }}}
623
    // {{{ rollback()
611
    // {{{ rollback()
624
 
612
 
625
    /**
613
    /**
626
     * Reverts the current transaction
614
     * Reverts the current transaction
627
     *
615
     *
628
     * @return int  DB_OK on success.  A DB_Error object on failure.
616
     * @return int  DB_OK on success.  A DB_Error object on failure.
629
     */
617
     */
630
    function rollback()
618
    function rollback()
631
    {
619
    {
632
        if (!@odbc_rollback($this->connection)) {
620
        if (!@odbc_rollback($this->connection)) {
633
            return $this->odbcRaiseError();
621
            return $this->odbcRaiseError();
634
        }
622
        }
635
        return DB_OK;
623
        return DB_OK;
636
    }
624
    }
637
 
625
 
638
    // }}}
626
    // }}}
639
    // {{{ odbcRaiseError()
627
    // {{{ odbcRaiseError()
640
 
628
 
641
    /**
629
    /**
642
     * Produces a DB_Error object regarding the current problem
630
     * Produces a DB_Error object regarding the current problem
643
     *
631
     *
644
     * @param int $errno  if the error is being manually raised pass a
632
     * @param int $errno  if the error is being manually raised pass a
645
     *                     DB_ERROR* constant here.  If this isn't passed
633
     *                     DB_ERROR* constant here.  If this isn't passed
646
     *                     the error information gathered from the DBMS.
634
     *                     the error information gathered from the DBMS.
647
     *
635
     *
648
     * @return object  the DB_Error object
636
     * @return object  the DB_Error object
649
     *
637
     *
650
     * @see DB_common::raiseError(),
638
     * @see DB_common::raiseError(),
651
     *      DB_odbc::errorNative(), DB_common::errorCode()
639
     *      DB_odbc::errorNative(), DB_common::errorCode()
652
     */
640
     */
653
    function odbcRaiseError($errno = null)
641
    function odbcRaiseError($errno = null)
654
    {
642
    {
655
        if ($errno === null) {
643
        if ($errno === null) {
656
            switch ($this->dbsyntax) {
644
            switch ($this->dbsyntax) {
657
                case 'access':
645
                case 'access':
658
                    if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
646
                    if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
659
                        $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
647
                        $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
660
                    } else {
648
                    } else {
661
                        // Doing this in case mode changes during runtime.
649
                        // Doing this in case mode changes during runtime.
662
                        $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
650
                        $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
663
                    }
651
                    }
664
 
652
 
665
                    $native_code = odbc_error($this->connection);
653
                    $native_code = odbc_error($this->connection);
666
 
654
 
667
                    // S1000 is for "General Error."  Let's be more specific.
655
                    // S1000 is for "General Error."  Let's be more specific.
668
                    if ($native_code == 'S1000') {
656
                    if ($native_code == 'S1000') {
669
                        $errormsg = odbc_errormsg($this->connection);
657
                        $errormsg = odbc_errormsg($this->connection);
670
                        static $error_regexps;
658
                        static $error_regexps;
671
                        if (!isset($error_regexps)) {
659
                        if (!isset($error_regexps)) {
672
                            $error_regexps = array(
660
                            $error_regexps = array(
673
                                '/includes related records.$/i'  => DB_ERROR_CONSTRAINT,
661
                                '/includes related records.$/i'  => DB_ERROR_CONSTRAINT,
674
                                '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
662
                                '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
675
                            );
663
                            );
676
                        }
664
                        }
677
                        foreach ($error_regexps as $regexp => $code) {
665
                        foreach ($error_regexps as $regexp => $code) {
678
                            if (preg_match($regexp, $errormsg)) {
666
                            if (preg_match($regexp, $errormsg)) {
679
                                return $this->raiseError($code,
667
                                return $this->raiseError($code,
680
                                        null, null, null,
668
                                        null, null, null,
681
                                        $native_code . ' ' . $errormsg);
669
                                        $native_code . ' ' . $errormsg);
682
                            }
670
                            }
683
                        }
671
                        }
684
                        $errno = DB_ERROR;
672
                        $errno = DB_ERROR;
685
                    } else {
673
                    } else {
686
                        $errno = $this->errorCode($native_code);
674
                        $errno = $this->errorCode($native_code);
687
                    }
675
                    }
688
                    break;
676
                    break;
689
                default:
677
                default:
690
                    $errno = $this->errorCode(odbc_error($this->connection));
678
                    $errno = $this->errorCode(odbc_error($this->connection));
691
            }
679
            }
692
        }
680
        }
693
        return $this->raiseError($errno, null, null, null,
681
        return $this->raiseError($errno, null, null, null,
694
                                 $this->errorNative());
682
                                 $this->errorNative());
695
    }
683
    }
696
 
684
 
697
    // }}}
685
    // }}}
698
    // {{{ errorNative()
686
    // {{{ errorNative()
699
 
687
 
700
    /**
688
    /**
701
     * Gets the DBMS' native error code and message produced by the last query
689
     * Gets the DBMS' native error code and message produced by the last query
702
     *
690
     *
703
     * @return string  the DBMS' error code and message
691
     * @return string  the DBMS' error code and message
704
     */
692
     */
705
    function errorNative()
693
    function errorNative()
706
    {
694
    {
707
        if (!is_resource($this->connection)) {
695
        if (!is_resource($this->connection)) {
708
            return @odbc_error() . ' ' . @odbc_errormsg();
696
            return @odbc_error() . ' ' . @odbc_errormsg();
709
        }
697
        }
710
        return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
698
        return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
711
    }
699
    }
712
 
700
 
713
    // }}}
701
    // }}}
714
    // {{{ tableInfo()
702
    // {{{ tableInfo()
715
 
703
 
716
    /**
704
    /**
717
     * Returns information about a table or a result set
705
     * Returns information about a table or a result set
718
     *
706
     *
719
     * @param object|string  $result  DB_result object from a query or a
707
     * @param object|string  $result  DB_result object from a query or a
720
     *                                 string containing the name of a table.
708
     *                                 string containing the name of a table.
721
     *                                 While this also accepts a query result
709
     *                                 While this also accepts a query result
722
     *                                 resource identifier, this behavior is
710
     *                                 resource identifier, this behavior is
723
     *                                 deprecated.
711
     *                                 deprecated.
724
     * @param int            $mode    a valid tableInfo mode
712
     * @param int            $mode    a valid tableInfo mode
725
     *
713
     *
726
     * @return array  an associative array with the information requested.
714
     * @return array  an associative array with the information requested.
727
     *                 A DB_Error object on failure.
715
     *                 A DB_Error object on failure.
728
     *
716
     *
729
     * @see DB_common::tableInfo()
717
     * @see DB_common::tableInfo()
730
     * @since Method available since Release 1.7.0
718
     * @since Method available since Release 1.7.0
731
     */
719
     */
732
    function tableInfo($result, $mode = null)
720
    function tableInfo($result, $mode = null)
733
    {
721
    {
734
        if (is_string($result)) {
722
        if (is_string($result)) {
735
            /*
723
            /*
736
             * Probably received a table name.
724
             * Probably received a table name.
737
             * Create a result resource identifier.
725
             * Create a result resource identifier.
738
             */
726
             */
739
            $id = @odbc_exec($this->connection, "SELECT * FROM $result");
727
            $id = @odbc_exec($this->connection, "SELECT * FROM $result");
740
            if (!$id) {
728
            if (!$id) {
741
                return $this->odbcRaiseError();
729
                return $this->odbcRaiseError();
742
            }
730
            }
743
            $got_string = true;
731
            $got_string = true;
744
        } elseif (isset($result->result)) {
732
        } elseif (isset($result->result)) {
745
            /*
733
            /*
746
             * Probably received a result object.
734
             * Probably received a result object.
747
             * Extract the result resource identifier.
735
             * Extract the result resource identifier.
748
             */
736
             */
749
            $id = $result->result;
737
            $id = $result->result;
750
            $got_string = false;
738
            $got_string = false;
751
        } else {
739
        } else {
752
            /*
740
            /*
753
             * Probably received a result resource identifier.
741
             * Probably received a result resource identifier.
754
             * Copy it.
742
             * Copy it.
755
             * Deprecated.  Here for compatibility only.
743
             * Deprecated.  Here for compatibility only.
756
             */
744
             */
757
            $id = $result;
745
            $id = $result;
758
            $got_string = false;
746
            $got_string = false;
759
        }
747
        }
760
 
748
 
761
        if (!is_resource($id)) {
749
        if (!is_resource($id)) {
762
            return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
750
            return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
763
        }
751
        }
764
 
752
 
765
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
753
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
766
            $case_func = 'strtolower';
754
            $case_func = 'strtolower';
767
        } else {
755
        } else {
768
            $case_func = 'strval';
756
            $case_func = 'strval';
769
        }
757
        }
770
 
758
 
771
        $count = @odbc_num_fields($id);
759
        $count = @odbc_num_fields($id);
772
        $res   = array();
760
        $res   = array();
773
 
761
 
774
        if ($mode) {
762
        if ($mode) {
775
            $res['num_fields'] = $count;
763
            $res['num_fields'] = $count;
776
        }
764
        }
777
 
765
 
778
        for ($i = 0; $i < $count; $i++) {
766
        for ($i = 0; $i < $count; $i++) {
779
            $col = $i + 1;
767
            $col = $i + 1;
780
            $res[$i] = array(
768
            $res[$i] = array(
781
                'table' => $got_string ? $case_func($result) : '',
769
                'table' => $got_string ? $case_func($result) : '',
782
                'name'  => $case_func(@odbc_field_name($id, $col)),
770
                'name'  => $case_func(@odbc_field_name($id, $col)),
783
                'type'  => @odbc_field_type($id, $col),
771
                'type'  => @odbc_field_type($id, $col),
784
                'len'   => @odbc_field_len($id, $col),
772
                'len'   => @odbc_field_len($id, $col),
785
                'flags' => '',
773
                'flags' => '',
786
            );
774
            );
787
            if ($mode & DB_TABLEINFO_ORDER) {
775
            if ($mode & DB_TABLEINFO_ORDER) {
788
                $res['order'][$res[$i]['name']] = $i;
776
                $res['order'][$res[$i]['name']] = $i;
789
            }
777
            }
790
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
778
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
791
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
779
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
792
            }
780
            }
793
        }
781
        }
794
 
782
 
795
        // free the result only if we were called on a table
783
        // free the result only if we were called on a table
796
        if ($got_string) {
784
        if ($got_string) {
797
            @odbc_free_result($id);
785
            @odbc_free_result($id);
798
        }
786
        }
799
        return $res;
787
        return $res;
800
    }
788
    }
801
 
789
 
802
    // }}}
790
    // }}}
803
    // {{{ getSpecialQuery()
791
    // {{{ getSpecialQuery()
804
 
792
 
805
    /**
793
    /**
806
     * Obtains the query string needed for listing a given type of objects
794
     * Obtains the query string needed for listing a given type of objects
807
     *
795
     *
808
     * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
796
     * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
809
     *
797
     *
810
     * @param string $type  the kind of objects you want to retrieve
798
     * @param string $type  the kind of objects you want to retrieve
811
     *
799
     *
812
     * @return string  the list of objects requested
800
     * @return string  the list of objects requested
813
     *
801
     *
814
     * @access protected
802
     * @access protected
815
     * @see DB_common::getListOf()
803
     * @see DB_common::getListOf()
816
     * @since Method available since Release 1.7.0
804
     * @since Method available since Release 1.7.0
817
     */
805
     */
818
    function getSpecialQuery($type)
806
    function getSpecialQuery($type)
819
    {
807
    {
820
        switch ($type) {
808
        switch ($type) {
821
            case 'databases':
809
            case 'databases':
822
                if (!function_exists('odbc_data_source')) {
810
                if (!function_exists('odbc_data_source')) {
823
                    return null;
811
                    return null;
824
                }
812
                }
825
                $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
813
                $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
826
                if (is_array($res)) {
814
                if (is_array($res)) {
827
                    $out = array($res['server']);
815
                    $out = array($res['server']);
828
                    while($res = @odbc_data_source($this->connection,
816
                    while($res = @odbc_data_source($this->connection,
829
                                                   SQL_FETCH_NEXT))
817
                                                   SQL_FETCH_NEXT))
830
                    {
818
                    {
831
                        $out[] = $res['server'];
819
                        $out[] = $res['server'];
832
                    }
820
                    }
833
                    return $out;
821
                    return $out;
834
                } else {
822
                } else {
835
                    return $this->odbcRaiseError();
823
                    return $this->odbcRaiseError();
836
                }
824
                }
837
                break;
825
                break;
838
            case 'tables':
826
            case 'tables':
839
            case 'schema.tables':
827
            case 'schema.tables':
840
                $keep = 'TABLE';
828
                $keep = 'TABLE';
841
                break;
829
                break;
842
            case 'views':
830
            case 'views':
843
                $keep = 'VIEW';
831
                $keep = 'VIEW';
844
                break;
832
                break;
845
            default:
833
            default:
846
                return null;
834
                return null;
847
        }
835
        }
848
 
836
 
849
        /*
837
        /*
850
         * Removing non-conforming items in the while loop rather than
838
         * Removing non-conforming items in the while loop rather than
851
         * in the odbc_tables() call because some backends choke on this:
839
         * in the odbc_tables() call because some backends choke on this:
852
         *     odbc_tables($this->connection, '', '', '', 'TABLE')
840
         *     odbc_tables($this->connection, '', '', '', 'TABLE')
853
         */
841
         */
854
        $res  = @odbc_tables($this->connection);
842
        $res  = @odbc_tables($this->connection);
855
        if (!$res) {
843
        if (!$res) {
856
            return $this->odbcRaiseError();
844
            return $this->odbcRaiseError();
857
        }
845
        }
858
        $out = array();
846
        $out = array();
859
        while ($row = odbc_fetch_array($res)) {
847
        while ($row = odbc_fetch_array($res)) {
860
            if ($row['TABLE_TYPE'] != $keep) {
848
            if ($row['TABLE_TYPE'] != $keep) {
861
                continue;
849
                continue;
862
            }
850
            }
863
            if ($type == 'schema.tables') {
851
            if ($type == 'schema.tables') {
864
                $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
852
                $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
865
            } else {
853
            } else {
866
                $out[] = $row['TABLE_NAME'];
854
                $out[] = $row['TABLE_NAME'];
867
            }
855
            }
868
        }
856
        }
869
        return $out;
857
        return $out;
870
    }
858
    }
871
 
859
 
872
    // }}}
860
    // }}}
873
 
861
 
874
}
862
}
875
 
863
 
876
/*
864
/*
877
 * Local variables:
865
 * Local variables:
878
 * tab-width: 4
866
 * tab-width: 4
879
 * c-basic-offset: 4
867
 * c-basic-offset: 4
880
 * End:
868
 * End:
881
 */
869
 */
882
 
870
 
883
?>
871
?>