Хранилища Subversion ant

Редакция

Редакция 2 | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS

Редакция 2 Редакция 3
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 versions 4 and 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-2007 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.81 2007/07/06 05:19:21 aharvey Exp $
23
 * @version    CVS: $Id: odbc.php,v 1.81 2007/07/06 05:19:21 aharvey Exp $
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-2007 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.13
47
 * @version    Release: 1.7.13
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>$this->DB_common()</kbd>
157
     *
157
     *
158
     * @return void
158
     * @return void
159
     */
159
     */
160
    function DB_odbc()
160
    function DB_odbc()
161
    {
161
    {
162
        $this->DB_common();
162
        $this->DB_common();
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 ($this->_checkManip($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 is_resource($result) ? odbc_free_result($result) : false;
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
482
483
    // }}}
483
    // }}}
484
    // {{{ quote()
484
    // {{{ quote()
485
485
486
    /**
486
    /**
487
     * @deprecated  Deprecated in release 1.6.0
487
     * @deprecated  Deprecated in release 1.6.0
488
     * @internal
488
     * @internal
489
     */
489
     */
490
    function quote($str)
490
    function quote($str)
491
    {
491
    {
492
        return $this->quoteSmart($str);
492
        return $this->quoteSmart($str);
493
    }
493
    }
494
494
495
    // }}}
495
    // }}}
496
    // {{{ nextId()
496
    // {{{ nextId()
497
497
498
    /**
498
    /**
499
     * Returns the next free id in a sequence
499
     * Returns the next free id in a sequence
500
     *
500
     *
501
     * @param string  $seq_name  name of the sequence
501
     * @param string  $seq_name  name of the sequence
502
     * @param boolean $ondemand  when true, the seqence is automatically
502
     * @param boolean $ondemand  when true, the seqence is automatically
503
     *                            created if it does not exist
503
     *                            created if it does not exist
504
     *
504
     *
505
     * @return int  the next id number in the sequence.
505
     * @return int  the next id number in the sequence.
506
     *               A DB_Error object on failure.
506
     *               A DB_Error object on failure.
507
     *
507
     *
508
     * @see DB_common::nextID(), DB_common::getSequenceName(),
508
     * @see DB_common::nextID(), DB_common::getSequenceName(),
509
     *      DB_odbc::createSequence(), DB_odbc::dropSequence()
509
     *      DB_odbc::createSequence(), DB_odbc::dropSequence()
510
     */
510
     */
511
    function nextId($seq_name, $ondemand = true)
511
    function nextId($seq_name, $ondemand = true)
512
    {
512
    {
513
        $seqname = $this->getSequenceName($seq_name);
513
        $seqname = $this->getSequenceName($seq_name);
514
        $repeat = 0;
514
        $repeat = 0;
515
        do {
515
        do {
516
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
516
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
517
            $result = $this->query("update ${seqname} set id = id + 1");
517
            $result = $this->query("update ${seqname} set id = id + 1");
518
            $this->popErrorHandling();
518
            $this->popErrorHandling();
519
            if ($ondemand && DB::isError($result) &&
519
            if ($ondemand && DB::isError($result) &&
520
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
520
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
521
                $repeat = 1;
521
                $repeat = 1;
522
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
522
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
523
                $result = $this->createSequence($seq_name);
523
                $result = $this->createSequence($seq_name);
524
                $this->popErrorHandling();
524
                $this->popErrorHandling();
525
                if (DB::isError($result)) {
525
                if (DB::isError($result)) {
526
                    return $this->raiseError($result);
526
                    return $this->raiseError($result);
527
                }
527
                }
528
                $result = $this->query("insert into ${seqname} (id) values(0)");
528
                $result = $this->query("insert into ${seqname} (id) values(0)");
529
            } else {
529
            } else {
530
                $repeat = 0;
530
                $repeat = 0;
531
            }
531
            }
532
        } while ($repeat);
532
        } while ($repeat);
533
533
534
        if (DB::isError($result)) {
534
        if (DB::isError($result)) {
535
            return $this->raiseError($result);
535
            return $this->raiseError($result);
536
        }
536
        }
537
537
538
        $result = $this->query("select id from ${seqname}");
538
        $result = $this->query("select id from ${seqname}");
539
        if (DB::isError($result)) {
539
        if (DB::isError($result)) {
540
            return $result;
540
            return $result;
541
        }
541
        }
542
542
543
        $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
543
        $row = $result->fetchRow(DB_FETCHMODE_ORDERED);
544
        if (DB::isError($row || !$row)) {
544
        if (DB::isError($row || !$row)) {
545
            return $row;
545
            return $row;
546
        }
546
        }
547
547
548
        return $row[0];
548
        return $row[0];
549
    }
549
    }
550
550
551
    /**
551
    /**
552
     * Creates a new sequence
552
     * Creates a new sequence
553
     *
553
     *
554
     * @param string $seq_name  name of the new sequence
554
     * @param string $seq_name  name of the new sequence
555
     *
555
     *
556
     * @return int  DB_OK on success.  A DB_Error object on failure.
556
     * @return int  DB_OK on success.  A DB_Error object on failure.
557
     *
557
     *
558
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
558
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
559
     *      DB_odbc::nextID(), DB_odbc::dropSequence()
559
     *      DB_odbc::nextID(), DB_odbc::dropSequence()
560
     */
560
     */
561
    function createSequence($seq_name)
561
    function createSequence($seq_name)
562
    {
562
    {
563
        return $this->query('CREATE TABLE '
563
        return $this->query('CREATE TABLE '
564
                            . $this->getSequenceName($seq_name)
564
                            . $this->getSequenceName($seq_name)
565
                            . ' (id integer NOT NULL,'
565
                            . ' (id integer NOT NULL,'
566
                            . ' PRIMARY KEY(id))');
566
                            . ' PRIMARY KEY(id))');
567
    }
567
    }
568
568
569
    // }}}
569
    // }}}
570
    // {{{ dropSequence()
570
    // {{{ dropSequence()
571
571
572
    /**
572
    /**
573
     * Deletes a sequence
573
     * Deletes a sequence
574
     *
574
     *
575
     * @param string $seq_name  name of the sequence to be deleted
575
     * @param string $seq_name  name of the sequence to be deleted
576
     *
576
     *
577
     * @return int  DB_OK on success.  A DB_Error object on failure.
577
     * @return int  DB_OK on success.  A DB_Error object on failure.
578
     *
578
     *
579
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
579
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
580
     *      DB_odbc::nextID(), DB_odbc::createSequence()
580
     *      DB_odbc::nextID(), DB_odbc::createSequence()
581
     */
581
     */
582
    function dropSequence($seq_name)
582
    function dropSequence($seq_name)
583
    {
583
    {
584
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
584
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
585
    }
585
    }
586
586
587
    // }}}
587
    // }}}
588
    // {{{ autoCommit()
588
    // {{{ autoCommit()
589
589
590
    /**
590
    /**
591
     * Enables or disables automatic commits
591
     * Enables or disables automatic commits
592
     *
592
     *
593
     * @param bool $onoff  true turns it on, false turns it off
593
     * @param bool $onoff  true turns it on, false turns it off
594
     *
594
     *
595
     * @return int  DB_OK on success.  A DB_Error object if the driver
595
     * @return int  DB_OK on success.  A DB_Error object if the driver
596
     *               doesn't support auto-committing transactions.
596
     *               doesn't support auto-committing transactions.
597
     */
597
     */
598
    function autoCommit($onoff = false)
598
    function autoCommit($onoff = false)
599
    {
599
    {
600
        if (!@odbc_autocommit($this->connection, $onoff)) {
600
        if (!@odbc_autocommit($this->connection, $onoff)) {
601
            return $this->odbcRaiseError();
601
            return $this->odbcRaiseError();
602
        }
602
        }
603
        return DB_OK;
603
        return DB_OK;
604
    }
604
    }
605
605
606
    // }}}
606
    // }}}
607
    // {{{ commit()
607
    // {{{ commit()
608
608
609
    /**
609
    /**
610
     * Commits the current transaction
610
     * Commits the current transaction
611
     *
611
     *
612
     * @return int  DB_OK on success.  A DB_Error object on failure.
612
     * @return int  DB_OK on success.  A DB_Error object on failure.
613
     */
613
     */
614
    function commit()
614
    function commit()
615
    {
615
    {
616
        if (!@odbc_commit($this->connection)) {
616
        if (!@odbc_commit($this->connection)) {
617
            return $this->odbcRaiseError();
617
            return $this->odbcRaiseError();
618
        }
618
        }
619
        return DB_OK;
619
        return DB_OK;
620
    }
620
    }
621
621
622
    // }}}
622
    // }}}
623
    // {{{ rollback()
623
    // {{{ rollback()
624
624
625
    /**
625
    /**
626
     * Reverts the current transaction
626
     * Reverts the current transaction
627
     *
627
     *
628
     * @return int  DB_OK on success.  A DB_Error object on failure.
628
     * @return int  DB_OK on success.  A DB_Error object on failure.
629
     */
629
     */
630
    function rollback()
630
    function rollback()
631
    {
631
    {
632
        if (!@odbc_rollback($this->connection)) {
632
        if (!@odbc_rollback($this->connection)) {
633
            return $this->odbcRaiseError();
633
            return $this->odbcRaiseError();
634
        }
634
        }
635
        return DB_OK;
635
        return DB_OK;
636
    }
636
    }
637
637
638
    // }}}
638
    // }}}
639
    // {{{ odbcRaiseError()
639
    // {{{ odbcRaiseError()
640
640
641
    /**
641
    /**
642
     * Produces a DB_Error object regarding the current problem
642
     * Produces a DB_Error object regarding the current problem
643
     *
643
     *
644
     * @param int $errno  if the error is being manually raised pass a
644
     * @param int $errno  if the error is being manually raised pass a
645
     *                     DB_ERROR* constant here.  If this isn't passed
645
     *                     DB_ERROR* constant here.  If this isn't passed
646
     *                     the error information gathered from the DBMS.
646
     *                     the error information gathered from the DBMS.
647
     *
647
     *
648
     * @return object  the DB_Error object
648
     * @return object  the DB_Error object
649
     *
649
     *
650
     * @see DB_common::raiseError(),
650
     * @see DB_common::raiseError(),
651
     *      DB_odbc::errorNative(), DB_common::errorCode()
651
     *      DB_odbc::errorNative(), DB_common::errorCode()
652
     */
652
     */
653
    function odbcRaiseError($errno = null)
653
    function odbcRaiseError($errno = null)
654
    {
654
    {
655
        if ($errno === null) {
655
        if ($errno === null) {
656
            switch ($this->dbsyntax) {
656
            switch ($this->dbsyntax) {
657
                case 'access':
657
                case 'access':
658
                    if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
658
                    if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
659
                        $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
659
                        $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
660
                    } else {
660
                    } else {
661
                        // Doing this in case mode changes during runtime.
661
                        // Doing this in case mode changes during runtime.
662
                        $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
662
                        $this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
663
                    }
663
                    }
664
664
665
                    $native_code = odbc_error($this->connection);
665
                    $native_code = odbc_error($this->connection);
666
666
667
                    // S1000 is for "General Error."  Let's be more specific.
667
                    // S1000 is for "General Error."  Let's be more specific.
668
                    if ($native_code == 'S1000') {
668
                    if ($native_code == 'S1000') {
669
                        $errormsg = odbc_errormsg($this->connection);
669
                        $errormsg = odbc_errormsg($this->connection);
670
                        static $error_regexps;
670
                        static $error_regexps;
671
                        if (!isset($error_regexps)) {
671
                        if (!isset($error_regexps)) {
672
                            $error_regexps = array(
672
                            $error_regexps = array(
673
                                '/includes related records.$/i'  => DB_ERROR_CONSTRAINT,
673
                                '/includes related records.$/i'  => DB_ERROR_CONSTRAINT,
674
                                '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
674
                                '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
675
                            );
675
                            );
676
                        }
676
                        }
677
                        foreach ($error_regexps as $regexp => $code) {
677
                        foreach ($error_regexps as $regexp => $code) {
678
                            if (preg_match($regexp, $errormsg)) {
678
                            if (preg_match($regexp, $errormsg)) {
679
                                return $this->raiseError($code,
679
                                return $this->raiseError($code,
680
                                        null, null, null,
680
                                        null, null, null,
681
                                        $native_code . ' ' . $errormsg);
681
                                        $native_code . ' ' . $errormsg);
682
                            }
682
                            }
683
                        }
683
                        }
684
                        $errno = DB_ERROR;
684
                        $errno = DB_ERROR;
685
                    } else {
685
                    } else {
686
                        $errno = $this->errorCode($native_code);
686
                        $errno = $this->errorCode($native_code);
687
                    }
687
                    }
688
                    break;
688
                    break;
689
                default:
689
                default:
690
                    $errno = $this->errorCode(odbc_error($this->connection));
690
                    $errno = $this->errorCode(odbc_error($this->connection));
691
            }
691
            }
692
        }
692
        }
693
        return $this->raiseError($errno, null, null, null,
693
        return $this->raiseError($errno, null, null, null,
694
                                 $this->errorNative());
694
                                 $this->errorNative());
695
    }
695
    }
696
696
697
    // }}}
697
    // }}}
698
    // {{{ errorNative()
698
    // {{{ errorNative()
699
699
700
    /**
700
    /**
701
     * Gets the DBMS' native error code and message produced by the last query
701
     * Gets the DBMS' native error code and message produced by the last query
702
     *
702
     *
703
     * @return string  the DBMS' error code and message
703
     * @return string  the DBMS' error code and message
704
     */
704
     */
705
    function errorNative()
705
    function errorNative()
706
    {
706
    {
707
        if (!is_resource($this->connection)) {
707
        if (!is_resource($this->connection)) {
708
            return @odbc_error() . ' ' . @odbc_errormsg();
708
            return @odbc_error() . ' ' . @odbc_errormsg();
709
        }
709
        }
710
        return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
710
        return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
711
    }
711
    }
712
712
713
    // }}}
713
    // }}}
714
    // {{{ tableInfo()
714
    // {{{ tableInfo()
715
715
716
    /**
716
    /**
717
     * Returns information about a table or a result set
717
     * Returns information about a table or a result set
718
     *
718
     *
719
     * @param object|string  $result  DB_result object from a query or a
719
     * @param object|string  $result  DB_result object from a query or a
720
     *                                 string containing the name of a table.
720
     *                                 string containing the name of a table.
721
     *                                 While this also accepts a query result
721
     *                                 While this also accepts a query result
722
     *                                 resource identifier, this behavior is
722
     *                                 resource identifier, this behavior is
723
     *                                 deprecated.
723
     *                                 deprecated.
724
     * @param int            $mode    a valid tableInfo mode
724
     * @param int            $mode    a valid tableInfo mode
725
     *
725
     *
726
     * @return array  an associative array with the information requested.
726
     * @return array  an associative array with the information requested.
727
     *                 A DB_Error object on failure.
727
     *                 A DB_Error object on failure.
728
     *
728
     *
729
     * @see DB_common::tableInfo()
729
     * @see DB_common::tableInfo()
730
     * @since Method available since Release 1.7.0
730
     * @since Method available since Release 1.7.0
731
     */
731
     */
732
    function tableInfo($result, $mode = null)
732
    function tableInfo($result, $mode = null)
733
    {
733
    {
734
        if (is_string($result)) {
734
        if (is_string($result)) {
735
            /*
735
            /*
736
             * Probably received a table name.
736
             * Probably received a table name.
737
             * Create a result resource identifier.
737
             * Create a result resource identifier.
738
             */
738
             */
739
            $id = @odbc_exec($this->connection, "SELECT * FROM $result");
739
            $id = @odbc_exec($this->connection, "SELECT * FROM $result");
740
            if (!$id) {
740
            if (!$id) {
741
                return $this->odbcRaiseError();
741
                return $this->odbcRaiseError();
742
            }
742
            }
743
            $got_string = true;
743
            $got_string = true;
744
        } elseif (isset($result->result)) {
744
        } elseif (isset($result->result)) {
745
            /*
745
            /*
746
             * Probably received a result object.
746
             * Probably received a result object.
747
             * Extract the result resource identifier.
747
             * Extract the result resource identifier.
748
             */
748
             */
749
            $id = $result->result;
749
            $id = $result->result;
750
            $got_string = false;
750
            $got_string = false;
751
        } else {
751
        } else {
752
            /*
752
            /*
753
             * Probably received a result resource identifier.
753
             * Probably received a result resource identifier.
754
             * Copy it.
754
             * Copy it.
755
             * Deprecated.  Here for compatibility only.
755
             * Deprecated.  Here for compatibility only.
756
             */
756
             */
757
            $id = $result;
757
            $id = $result;
758
            $got_string = false;
758
            $got_string = false;
759
        }
759
        }
760
760
761
        if (!is_resource($id)) {
761
        if (!is_resource($id)) {
762
            return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
762
            return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
763
        }
763
        }
764
764
765
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
765
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
766
            $case_func = 'strtolower';
766
            $case_func = 'strtolower';
767
        } else {
767
        } else {
768
            $case_func = 'strval';
768
            $case_func = 'strval';
769
        }
769
        }
770
770
771
        $count = @odbc_num_fields($id);
771
        $count = @odbc_num_fields($id);
772
        $res   = array();
772
        $res   = array();
773
773
774
        if ($mode) {
774
        if ($mode) {
775
            $res['num_fields'] = $count;
775
            $res['num_fields'] = $count;
776
        }
776
        }
777
777
778
        for ($i = 0; $i < $count; $i++) {
778
        for ($i = 0; $i < $count; $i++) {
779
            $col = $i + 1;
779
            $col = $i + 1;
780
            $res[$i] = array(
780
            $res[$i] = array(
781
                'table' => $got_string ? $case_func($result) : '',
781
                'table' => $got_string ? $case_func($result) : '',
782
                'name'  => $case_func(@odbc_field_name($id, $col)),
782
                'name'  => $case_func(@odbc_field_name($id, $col)),
783
                'type'  => @odbc_field_type($id, $col),
783
                'type'  => @odbc_field_type($id, $col),
784
                'len'   => @odbc_field_len($id, $col),
784
                'len'   => @odbc_field_len($id, $col),
785
                'flags' => '',
785
                'flags' => '',
786
            );
786
            );
787
            if ($mode & DB_TABLEINFO_ORDER) {
787
            if ($mode & DB_TABLEINFO_ORDER) {
788
                $res['order'][$res[$i]['name']] = $i;
788
                $res['order'][$res[$i]['name']] = $i;
789
            }
789
            }
790
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
790
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
791
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
791
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
792
            }
792
            }
793
        }
793
        }
794
794
795
        // free the result only if we were called on a table
795
        // free the result only if we were called on a table
796
        if ($got_string) {
796
        if ($got_string) {
797
            @odbc_free_result($id);
797
            @odbc_free_result($id);
798
        }
798
        }
799
        return $res;
799
        return $res;
800
    }
800
    }
801
801
802
    // }}}
802
    // }}}
803
    // {{{ getSpecialQuery()
803
    // {{{ getSpecialQuery()
804
804
805
    /**
805
    /**
806
     * Obtains the query string needed for listing a given type of objects
806
     * Obtains the query string needed for listing a given type of objects
807
     *
807
     *
808
     * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
808
     * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
809
     *
809
     *
810
     * @param string $type  the kind of objects you want to retrieve
810
     * @param string $type  the kind of objects you want to retrieve
811
     *
811
     *
812
     * @return string  the list of objects requested
812
     * @return string  the list of objects requested
813
     *
813
     *
814
     * @access protected
814
     * @access protected
815
     * @see DB_common::getListOf()
815
     * @see DB_common::getListOf()
816
     * @since Method available since Release 1.7.0
816
     * @since Method available since Release 1.7.0
817
     */
817
     */
818
    function getSpecialQuery($type)
818
    function getSpecialQuery($type)
819
    {
819
    {
820
        switch ($type) {
820
        switch ($type) {
821
            case 'databases':
821
            case 'databases':
822
                if (!function_exists('odbc_data_source')) {
822
                if (!function_exists('odbc_data_source')) {
823
                    return null;
823
                    return null;
824
                }
824
                }
825
                $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
825
                $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
826
                if (is_array($res)) {
826
                if (is_array($res)) {
827
                    $out = array($res['server']);
827
                    $out = array($res['server']);
828
                    while($res = @odbc_data_source($this->connection,
828
                    while($res = @odbc_data_source($this->connection,
829
                                                   SQL_FETCH_NEXT))
829
                                                   SQL_FETCH_NEXT))
830
                    {
830
                    {
831
                        $out[] = $res['server'];
831
                        $out[] = $res['server'];
832
                    }
832
                    }
833
                    return $out;
833
                    return $out;
834
                } else {
834
                } else {
835
                    return $this->odbcRaiseError();
835
                    return $this->odbcRaiseError();
836
                }
836
                }
837
                break;
837
                break;
838
            case 'tables':
838
            case 'tables':
839
            case 'schema.tables':
839
            case 'schema.tables':
840
                $keep = 'TABLE';
840
                $keep = 'TABLE';
841
                break;
841
                break;
842
            case 'views':
842
            case 'views':
843
                $keep = 'VIEW';
843
                $keep = 'VIEW';
844
                break;
844
                break;
845
            default:
845
            default:
846
                return null;
846
                return null;
847
        }
847
        }
848
848
849
        /*
849
        /*
850
         * Removing non-conforming items in the while loop rather than
850
         * Removing non-conforming items in the while loop rather than
851
         * in the odbc_tables() call because some backends choke on this:
851
         * in the odbc_tables() call because some backends choke on this:
852
         *     odbc_tables($this->connection, '', '', '', 'TABLE')
852
         *     odbc_tables($this->connection, '', '', '', 'TABLE')
853
         */
853
         */
854
        $res  = @odbc_tables($this->connection);
854
        $res  = @odbc_tables($this->connection);
855
        if (!$res) {
855
        if (!$res) {
856
            return $this->odbcRaiseError();
856
            return $this->odbcRaiseError();
857
        }
857
        }
858
        $out = array();
858
        $out = array();
859
        while ($row = odbc_fetch_array($res)) {
859
        while ($row = odbc_fetch_array($res)) {
860
            if ($row['TABLE_TYPE'] != $keep) {
860
            if ($row['TABLE_TYPE'] != $keep) {
861
                continue;
861
                continue;
862
            }
862
            }
863
            if ($type == 'schema.tables') {
863
            if ($type == 'schema.tables') {
864
                $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
864
                $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
865
            } else {
865
            } else {
866
                $out[] = $row['TABLE_NAME'];
866
                $out[] = $row['TABLE_NAME'];
867
            }
867
            }
868
        }
868
        }
869
        return $out;
869
        return $out;
870
    }
870
    }
871
871
872
    // }}}
872
    // }}}
873
873
874
}
874
}
875
875
876
/*
876
/*
877
 * Local variables:
877
 * Local variables:
878
 * tab-width: 4
878
 * tab-width: 4
879
 * c-basic-offset: 4
879
 * c-basic-offset: 4
880
 * End:
880
 * End:
881
 */
881
 */
882
882
883
?>
883
?>
884
 
884