Хранилища 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 sybase extension
6
 * The PEAR DB driver for PHP's sybase extension
7
 * for interacting with Sybase databases
7
 * for interacting with Sybase databases
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     Sterling Hughes <sterling@php.net>
19
 * @author     Sterling Hughes <sterling@php.net>
20
 * @author     Antônio Carlos Venâncio Júnior <floripa@php.net>
20
 * @author     Antônio Carlos Venâncio Júnior <floripa@php.net>
21
 * @author     Daniel Convissor <danielc@php.net>
21
 * @author     Daniel Convissor <danielc@php.net>
22
 * @copyright  1997-2007 The PHP Group
22
 * @copyright  1997-2007 The PHP Group
23
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
23
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
24
 * @version    CVS: $Id: sybase.php,v 1.87 2007/09/21 13:40:42 aharvey Exp $
24
 * @version    CVS: $Id: sybase.php,v 1.87 2007/09/21 13:40:42 aharvey Exp $
25
 * @link       http://pear.php.net/package/DB
25
 * @link       http://pear.php.net/package/DB
26
 */
26
 */
27
27
28
/**
28
/**
29
 * Obtain the DB_common class so it can be extended from
29
 * Obtain the DB_common class so it can be extended from
30
 */
30
 */
31
require_once 'DB/common.php';
31
require_once 'DB/common.php';
32
32
33
/**
33
/**
34
 * The methods PEAR DB uses to interact with PHP's sybase extension
34
 * The methods PEAR DB uses to interact with PHP's sybase extension
35
 * for interacting with Sybase databases
35
 * for interacting with Sybase databases
36
 *
36
 *
37
 * These methods overload the ones declared in DB_common.
37
 * These methods overload the ones declared in DB_common.
38
 *
38
 *
39
 * WARNING:  This driver may fail with multiple connections under the
39
 * WARNING:  This driver may fail with multiple connections under the
40
 * same user/pass/host and different databases.
40
 * same user/pass/host and different databases.
41
 *
41
 *
42
 * @category   Database
42
 * @category   Database
43
 * @package    DB
43
 * @package    DB
44
 * @author     Sterling Hughes <sterling@php.net>
44
 * @author     Sterling Hughes <sterling@php.net>
45
 * @author     Antônio Carlos Venâncio Júnior <floripa@php.net>
45
 * @author     Antônio Carlos Venâncio Júnior <floripa@php.net>
46
 * @author     Daniel Convissor <danielc@php.net>
46
 * @author     Daniel Convissor <danielc@php.net>
47
 * @copyright  1997-2007 The PHP Group
47
 * @copyright  1997-2007 The PHP Group
48
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
48
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
49
 * @version    Release: 1.7.13
49
 * @version    Release: 1.7.13
50
 * @link       http://pear.php.net/package/DB
50
 * @link       http://pear.php.net/package/DB
51
 */
51
 */
52
class DB_sybase extends DB_common
52
class DB_sybase extends DB_common
53
{
53
{
54
    // {{{ properties
54
    // {{{ properties
55
55
56
    /**
56
    /**
57
     * The DB driver type (mysql, oci8, odbc, etc.)
57
     * The DB driver type (mysql, oci8, odbc, etc.)
58
     * @var string
58
     * @var string
59
     */
59
     */
60
    var $phptype = 'sybase';
60
    var $phptype = 'sybase';
61
61
62
    /**
62
    /**
63
     * The database syntax variant to be used (db2, access, etc.), if any
63
     * The database syntax variant to be used (db2, access, etc.), if any
64
     * @var string
64
     * @var string
65
     */
65
     */
66
    var $dbsyntax = 'sybase';
66
    var $dbsyntax = 'sybase';
67
67
68
    /**
68
    /**
69
     * The capabilities of this DB implementation
69
     * The capabilities of this DB implementation
70
     *
70
     *
71
     * The 'new_link' element contains the PHP version that first provided
71
     * The 'new_link' element contains the PHP version that first provided
72
     * new_link support for this DBMS.  Contains false if it's unsupported.
72
     * new_link support for this DBMS.  Contains false if it's unsupported.
73
     *
73
     *
74
     * Meaning of the 'limit' element:
74
     * Meaning of the 'limit' element:
75
     *   + 'emulate' = emulate with fetch row by number
75
     *   + 'emulate' = emulate with fetch row by number
76
     *   + 'alter'   = alter the query
76
     *   + 'alter'   = alter the query
77
     *   + false     = skip rows
77
     *   + false     = skip rows
78
     *
78
     *
79
     * @var array
79
     * @var array
80
     */
80
     */
81
    var $features = array(
81
    var $features = array(
82
        'limit'         => 'emulate',
82
        'limit'         => 'emulate',
83
        'new_link'      => false,
83
        'new_link'      => false,
84
        'numrows'       => true,
84
        'numrows'       => true,
85
        'pconnect'      => true,
85
        'pconnect'      => true,
86
        'prepare'       => false,
86
        'prepare'       => false,
87
        'ssl'           => false,
87
        'ssl'           => false,
88
        'transactions'  => true,
88
        'transactions'  => true,
89
    );
89
    );
90
90
91
    /**
91
    /**
92
     * A mapping of native error codes to DB error codes
92
     * A mapping of native error codes to DB error codes
93
     * @var array
93
     * @var array
94
     */
94
     */
95
    var $errorcode_map = array(
95
    var $errorcode_map = array(
96
    );
96
    );
97
97
98
    /**
98
    /**
99
     * The raw database connection created by PHP
99
     * The raw database connection created by PHP
100
     * @var resource
100
     * @var resource
101
     */
101
     */
102
    var $connection;
102
    var $connection;
103
103
104
    /**
104
    /**
105
     * The DSN information for connecting to a database
105
     * The DSN information for connecting to a database
106
     * @var array
106
     * @var array
107
     */
107
     */
108
    var $dsn = array();
108
    var $dsn = array();
109
109
110
110
111
    /**
111
    /**
112
     * Should data manipulation queries be committed automatically?
112
     * Should data manipulation queries be committed automatically?
113
     * @var bool
113
     * @var bool
114
     * @access private
114
     * @access private
115
     */
115
     */
116
    var $autocommit = true;
116
    var $autocommit = true;
117
117
118
    /**
118
    /**
119
     * The quantity of transactions begun
119
     * The quantity of transactions begun
120
     *
120
     *
121
     * {@internal  While this is private, it can't actually be designated
121
     * {@internal  While this is private, it can't actually be designated
122
     * private in PHP 5 because it is directly accessed in the test suite.}}
122
     * private in PHP 5 because it is directly accessed in the test suite.}}
123
     *
123
     *
124
     * @var integer
124
     * @var integer
125
     * @access private
125
     * @access private
126
     */
126
     */
127
    var $transaction_opcount = 0;
127
    var $transaction_opcount = 0;
128
128
129
    /**
129
    /**
130
     * The database specified in the DSN
130
     * The database specified in the DSN
131
     *
131
     *
132
     * It's a fix to allow calls to different databases in the same script.
132
     * It's a fix to allow calls to different databases in the same script.
133
     *
133
     *
134
     * @var string
134
     * @var string
135
     * @access private
135
     * @access private
136
     */
136
     */
137
    var $_db = '';
137
    var $_db = '';
138
138
139
139
140
    // }}}
140
    // }}}
141
    // {{{ constructor
141
    // {{{ constructor
142
142
143
    /**
143
    /**
144
     * This constructor calls <kbd>$this->DB_common()</kbd>
144
     * This constructor calls <kbd>$this->DB_common()</kbd>
145
     *
145
     *
146
     * @return void
146
     * @return void
147
     */
147
     */
148
    function DB_sybase()
148
    function DB_sybase()
149
    {
149
    {
150
        $this->DB_common();
150
        $this->DB_common();
151
    }
151
    }
152
152
153
    // }}}
153
    // }}}
154
    // {{{ connect()
154
    // {{{ connect()
155
155
156
    /**
156
    /**
157
     * Connect to the database server, log in and open the database
157
     * Connect to the database server, log in and open the database
158
     *
158
     *
159
     * Don't call this method directly.  Use DB::connect() instead.
159
     * Don't call this method directly.  Use DB::connect() instead.
160
     *
160
     *
161
     * PEAR DB's sybase driver supports the following extra DSN options:
161
     * PEAR DB's sybase driver supports the following extra DSN options:
162
     *   + appname       The application name to use on this connection.
162
     *   + appname       The application name to use on this connection.
163
     *                   Available since PEAR DB 1.7.0.
163
     *                   Available since PEAR DB 1.7.0.
164
     *   + charset       The character set to use on this connection.
164
     *   + charset       The character set to use on this connection.
165
     *                   Available since PEAR DB 1.7.0.
165
     *                   Available since PEAR DB 1.7.0.
166
     *
166
     *
167
     * @param array $dsn         the data source name
167
     * @param array $dsn         the data source name
168
     * @param bool  $persistent  should the connection be persistent?
168
     * @param bool  $persistent  should the connection be persistent?
169
     *
169
     *
170
     * @return int  DB_OK on success. A DB_Error object on failure.
170
     * @return int  DB_OK on success. A DB_Error object on failure.
171
     */
171
     */
172
    function connect($dsn, $persistent = false)
172
    function connect($dsn, $persistent = false)
173
    {
173
    {
174
        if (!PEAR::loadExtension('sybase') &&
174
        if (!PEAR::loadExtension('sybase') &&
175
            !PEAR::loadExtension('sybase_ct'))
175
            !PEAR::loadExtension('sybase_ct'))
176
        {
176
        {
177
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
177
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
178
        }
178
        }
179
179
180
        $this->dsn = $dsn;
180
        $this->dsn = $dsn;
181
        if ($dsn['dbsyntax']) {
181
        if ($dsn['dbsyntax']) {
182
            $this->dbsyntax = $dsn['dbsyntax'];
182
            $this->dbsyntax = $dsn['dbsyntax'];
183
        }
183
        }
184
184
185
        $dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost';
185
        $dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost';
186
        $dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false;
186
        $dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false;
187
        $dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false;
187
        $dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false;
188
        $dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false;
188
        $dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false;
189
189
190
        $connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
190
        $connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
191
191
192
        if ($dsn['username']) {
192
        if ($dsn['username']) {
193
            $this->connection = @$connect_function($dsn['hostspec'],
193
            $this->connection = @$connect_function($dsn['hostspec'],
194
                                                   $dsn['username'],
194
                                                   $dsn['username'],
195
                                                   $dsn['password'],
195
                                                   $dsn['password'],
196
                                                   $dsn['charset'],
196
                                                   $dsn['charset'],
197
                                                   $dsn['appname']);
197
                                                   $dsn['appname']);
198
        } else {
198
        } else {
199
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
199
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
200
                                     null, null, null,
200
                                     null, null, null,
201
                                     'The DSN did not contain a username.');
201
                                     'The DSN did not contain a username.');
202
        }
202
        }
203
203
204
        if (!$this->connection) {
204
        if (!$this->connection) {
205
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
205
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
206
                                     null, null, null,
206
                                     null, null, null,
207
                                     @sybase_get_last_message());
207
                                     @sybase_get_last_message());
208
        }
208
        }
209
209
210
        if ($dsn['database']) {
210
        if ($dsn['database']) {
211
            if (!@sybase_select_db($dsn['database'], $this->connection)) {
211
            if (!@sybase_select_db($dsn['database'], $this->connection)) {
212
                return $this->raiseError(DB_ERROR_NODBSELECTED,
212
                return $this->raiseError(DB_ERROR_NODBSELECTED,
213
                                         null, null, null,
213
                                         null, null, null,
214
                                         @sybase_get_last_message());
214
                                         @sybase_get_last_message());
215
            }
215
            }
216
            $this->_db = $dsn['database'];
216
            $this->_db = $dsn['database'];
217
        }
217
        }
218
218
219
        return DB_OK;
219
        return DB_OK;
220
    }
220
    }
221
221
222
    // }}}
222
    // }}}
223
    // {{{ disconnect()
223
    // {{{ disconnect()
224
224
225
    /**
225
    /**
226
     * Disconnects from the database server
226
     * Disconnects from the database server
227
     *
227
     *
228
     * @return bool  TRUE on success, FALSE on failure
228
     * @return bool  TRUE on success, FALSE on failure
229
     */
229
     */
230
    function disconnect()
230
    function disconnect()
231
    {
231
    {
232
        $ret = @sybase_close($this->connection);
232
        $ret = @sybase_close($this->connection);
233
        $this->connection = null;
233
        $this->connection = null;
234
        return $ret;
234
        return $ret;
235
    }
235
    }
236
236
237
    // }}}
237
    // }}}
238
    // {{{ simpleQuery()
238
    // {{{ simpleQuery()
239
239
240
    /**
240
    /**
241
     * Sends a query to the database server
241
     * Sends a query to the database server
242
     *
242
     *
243
     * @param string  the SQL query string
243
     * @param string  the SQL query string
244
     *
244
     *
245
     * @return mixed  + a PHP result resrouce for successful SELECT queries
245
     * @return mixed  + a PHP result resrouce for successful SELECT queries
246
     *                + the DB_OK constant for other successful queries
246
     *                + the DB_OK constant for other successful queries
247
     *                + a DB_Error object on failure
247
     *                + a DB_Error object on failure
248
     */
248
     */
249
    function simpleQuery($query)
249
    function simpleQuery($query)
250
    {
250
    {
251
        $ismanip = $this->_checkManip($query);
251
        $ismanip = $this->_checkManip($query);
252
        $this->last_query = $query;
252
        $this->last_query = $query;
253
        if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
253
        if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
254
            return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
254
            return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
255
        }
255
        }
256
        $query = $this->modifyQuery($query);
256
        $query = $this->modifyQuery($query);
257
        if (!$this->autocommit && $ismanip) {
257
        if (!$this->autocommit && $ismanip) {
258
            if ($this->transaction_opcount == 0) {
258
            if ($this->transaction_opcount == 0) {
259
                $result = @sybase_query('BEGIN TRANSACTION', $this->connection);
259
                $result = @sybase_query('BEGIN TRANSACTION', $this->connection);
260
                if (!$result) {
260
                if (!$result) {
261
                    return $this->sybaseRaiseError();
261
                    return $this->sybaseRaiseError();
262
                }
262
                }
263
            }
263
            }
264
            $this->transaction_opcount++;
264
            $this->transaction_opcount++;
265
        }
265
        }
266
        $result = @sybase_query($query, $this->connection);
266
        $result = @sybase_query($query, $this->connection);
267
        if (!$result) {
267
        if (!$result) {
268
            return $this->sybaseRaiseError();
268
            return $this->sybaseRaiseError();
269
        }
269
        }
270
        if (is_resource($result)) {
270
        if (is_resource($result)) {
271
            return $result;
271
            return $result;
272
        }
272
        }
273
        // Determine which queries that should return data, and which
273
        // Determine which queries that should return data, and which
274
        // should return an error code only.
274
        // should return an error code only.
275
        return $ismanip ? DB_OK : $result;
275
        return $ismanip ? DB_OK : $result;
276
    }
276
    }
277
277
278
    // }}}
278
    // }}}
279
    // {{{ nextResult()
279
    // {{{ nextResult()
280
280
281
    /**
281
    /**
282
     * Move the internal sybase result pointer to the next available result
282
     * Move the internal sybase result pointer to the next available result
283
     *
283
     *
284
     * @param a valid sybase result resource
284
     * @param a valid sybase result resource
285
     *
285
     *
286
     * @access public
286
     * @access public
287
     *
287
     *
288
     * @return true if a result is available otherwise return false
288
     * @return true if a result is available otherwise return false
289
     */
289
     */
290
    function nextResult($result)
290
    function nextResult($result)
291
    {
291
    {
292
        return false;
292
        return false;
293
    }
293
    }
294
294
295
    // }}}
295
    // }}}
296
    // {{{ fetchInto()
296
    // {{{ fetchInto()
297
297
298
    /**
298
    /**
299
     * Places a row from the result set into the given array
299
     * Places a row from the result set into the given array
300
     *
300
     *
301
     * Formating of the array and the data therein are configurable.
301
     * Formating of the array and the data therein are configurable.
302
     * See DB_result::fetchInto() for more information.
302
     * See DB_result::fetchInto() for more information.
303
     *
303
     *
304
     * This method is not meant to be called directly.  Use
304
     * This method is not meant to be called directly.  Use
305
     * DB_result::fetchInto() instead.  It can't be declared "protected"
305
     * DB_result::fetchInto() instead.  It can't be declared "protected"
306
     * because DB_result is a separate object.
306
     * because DB_result is a separate object.
307
     *
307
     *
308
     * @param resource $result    the query result resource
308
     * @param resource $result    the query result resource
309
     * @param array    $arr       the referenced array to put the data in
309
     * @param array    $arr       the referenced array to put the data in
310
     * @param int      $fetchmode how the resulting array should be indexed
310
     * @param int      $fetchmode how the resulting array should be indexed
311
     * @param int      $rownum    the row number to fetch (0 = first row)
311
     * @param int      $rownum    the row number to fetch (0 = first row)
312
     *
312
     *
313
     * @return mixed  DB_OK on success, NULL when the end of a result set is
313
     * @return mixed  DB_OK on success, NULL when the end of a result set is
314
     *                 reached or on failure
314
     *                 reached or on failure
315
     *
315
     *
316
     * @see DB_result::fetchInto()
316
     * @see DB_result::fetchInto()
317
     */
317
     */
318
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
318
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
319
    {
319
    {
320
        if ($rownum !== null) {
320
        if ($rownum !== null) {
321
            if (!@sybase_data_seek($result, $rownum)) {
321
            if (!@sybase_data_seek($result, $rownum)) {
322
                return null;
322
                return null;
323
            }
323
            }
324
        }
324
        }
325
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
325
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
326
            if (function_exists('sybase_fetch_assoc')) {
326
            if (function_exists('sybase_fetch_assoc')) {
327
                $arr = @sybase_fetch_assoc($result);
327
                $arr = @sybase_fetch_assoc($result);
328
            } else {
328
            } else {
329
                if ($arr = @sybase_fetch_array($result)) {
329
                if ($arr = @sybase_fetch_array($result)) {
330
                    foreach ($arr as $key => $value) {
330
                    foreach ($arr as $key => $value) {
331
                        if (is_int($key)) {
331
                        if (is_int($key)) {
332
                            unset($arr[$key]);
332
                            unset($arr[$key]);
333
                        }
333
                        }
334
                    }
334
                    }
335
                }
335
                }
336
            }
336
            }
337
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
337
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
338
                $arr = array_change_key_case($arr, CASE_LOWER);
338
                $arr = array_change_key_case($arr, CASE_LOWER);
339
            }
339
            }
340
        } else {
340
        } else {
341
            $arr = @sybase_fetch_row($result);
341
            $arr = @sybase_fetch_row($result);
342
        }
342
        }
343
        if (!$arr) {
343
        if (!$arr) {
344
            return null;
344
            return null;
345
        }
345
        }
346
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
346
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
347
            $this->_rtrimArrayValues($arr);
347
            $this->_rtrimArrayValues($arr);
348
        }
348
        }
349
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
349
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
350
            $this->_convertNullArrayValuesToEmpty($arr);
350
            $this->_convertNullArrayValuesToEmpty($arr);
351
        }
351
        }
352
        return DB_OK;
352
        return DB_OK;
353
    }
353
    }
354
354
355
    // }}}
355
    // }}}
356
    // {{{ freeResult()
356
    // {{{ freeResult()
357
357
358
    /**
358
    /**
359
     * Deletes the result set and frees the memory occupied by the result set
359
     * Deletes the result set and frees the memory occupied by the result set
360
     *
360
     *
361
     * This method is not meant to be called directly.  Use
361
     * This method is not meant to be called directly.  Use
362
     * DB_result::free() instead.  It can't be declared "protected"
362
     * DB_result::free() instead.  It can't be declared "protected"
363
     * because DB_result is a separate object.
363
     * because DB_result is a separate object.
364
     *
364
     *
365
     * @param resource $result  PHP's query result resource
365
     * @param resource $result  PHP's query result resource
366
     *
366
     *
367
     * @return bool  TRUE on success, FALSE if $result is invalid
367
     * @return bool  TRUE on success, FALSE if $result is invalid
368
     *
368
     *
369
     * @see DB_result::free()
369
     * @see DB_result::free()
370
     */
370
     */
371
    function freeResult($result)
371
    function freeResult($result)
372
    {
372
    {
373
        return is_resource($result) ? sybase_free_result($result) : false;
373
        return is_resource($result) ? sybase_free_result($result) : false;
374
    }
374
    }
375
375
376
    // }}}
376
    // }}}
377
    // {{{ numCols()
377
    // {{{ numCols()
378
378
379
    /**
379
    /**
380
     * Gets the number of columns in a result set
380
     * Gets the number of columns in a result set
381
     *
381
     *
382
     * This method is not meant to be called directly.  Use
382
     * This method is not meant to be called directly.  Use
383
     * DB_result::numCols() instead.  It can't be declared "protected"
383
     * DB_result::numCols() instead.  It can't be declared "protected"
384
     * because DB_result is a separate object.
384
     * because DB_result is a separate object.
385
     *
385
     *
386
     * @param resource $result  PHP's query result resource
386
     * @param resource $result  PHP's query result resource
387
     *
387
     *
388
     * @return int  the number of columns.  A DB_Error object on failure.
388
     * @return int  the number of columns.  A DB_Error object on failure.
389
     *
389
     *
390
     * @see DB_result::numCols()
390
     * @see DB_result::numCols()
391
     */
391
     */
392
    function numCols($result)
392
    function numCols($result)
393
    {
393
    {
394
        $cols = @sybase_num_fields($result);
394
        $cols = @sybase_num_fields($result);
395
        if (!$cols) {
395
        if (!$cols) {
396
            return $this->sybaseRaiseError();
396
            return $this->sybaseRaiseError();
397
        }
397
        }
398
        return $cols;
398
        return $cols;
399
    }
399
    }
400
400
401
    // }}}
401
    // }}}
402
    // {{{ numRows()
402
    // {{{ numRows()
403
403
404
    /**
404
    /**
405
     * Gets the number of rows in a result set
405
     * Gets the number of rows in a result set
406
     *
406
     *
407
     * This method is not meant to be called directly.  Use
407
     * This method is not meant to be called directly.  Use
408
     * DB_result::numRows() instead.  It can't be declared "protected"
408
     * DB_result::numRows() instead.  It can't be declared "protected"
409
     * because DB_result is a separate object.
409
     * because DB_result is a separate object.
410
     *
410
     *
411
     * @param resource $result  PHP's query result resource
411
     * @param resource $result  PHP's query result resource
412
     *
412
     *
413
     * @return int  the number of rows.  A DB_Error object on failure.
413
     * @return int  the number of rows.  A DB_Error object on failure.
414
     *
414
     *
415
     * @see DB_result::numRows()
415
     * @see DB_result::numRows()
416
     */
416
     */
417
    function numRows($result)
417
    function numRows($result)
418
    {
418
    {
419
        $rows = @sybase_num_rows($result);
419
        $rows = @sybase_num_rows($result);
420
        if ($rows === false) {
420
        if ($rows === false) {
421
            return $this->sybaseRaiseError();
421
            return $this->sybaseRaiseError();
422
        }
422
        }
423
        return $rows;
423
        return $rows;
424
    }
424
    }
425
425
426
    // }}}
426
    // }}}
427
    // {{{ affectedRows()
427
    // {{{ affectedRows()
428
428
429
    /**
429
    /**
430
     * Determines the number of rows affected by a data maniuplation query
430
     * Determines the number of rows affected by a data maniuplation query
431
     *
431
     *
432
     * 0 is returned for queries that don't manipulate data.
432
     * 0 is returned for queries that don't manipulate data.
433
     *
433
     *
434
     * @return int  the number of rows.  A DB_Error object on failure.
434
     * @return int  the number of rows.  A DB_Error object on failure.
435
     */
435
     */
436
    function affectedRows()
436
    function affectedRows()
437
    {
437
    {
438
        if ($this->_last_query_manip) {
438
        if ($this->_last_query_manip) {
439
            $result = @sybase_affected_rows($this->connection);
439
            $result = @sybase_affected_rows($this->connection);
440
        } else {
440
        } else {
441
            $result = 0;
441
            $result = 0;
442
        }
442
        }
443
        return $result;
443
        return $result;
444
     }
444
     }
445
445
446
    // }}}
446
    // }}}
447
    // {{{ nextId()
447
    // {{{ nextId()
448
448
449
    /**
449
    /**
450
     * Returns the next free id in a sequence
450
     * Returns the next free id in a sequence
451
     *
451
     *
452
     * @param string  $seq_name  name of the sequence
452
     * @param string  $seq_name  name of the sequence
453
     * @param boolean $ondemand  when true, the seqence is automatically
453
     * @param boolean $ondemand  when true, the seqence is automatically
454
     *                            created if it does not exist
454
     *                            created if it does not exist
455
     *
455
     *
456
     * @return int  the next id number in the sequence.
456
     * @return int  the next id number in the sequence.
457
     *               A DB_Error object on failure.
457
     *               A DB_Error object on failure.
458
     *
458
     *
459
     * @see DB_common::nextID(), DB_common::getSequenceName(),
459
     * @see DB_common::nextID(), DB_common::getSequenceName(),
460
     *      DB_sybase::createSequence(), DB_sybase::dropSequence()
460
     *      DB_sybase::createSequence(), DB_sybase::dropSequence()
461
     */
461
     */
462
    function nextId($seq_name, $ondemand = true)
462
    function nextId($seq_name, $ondemand = true)
463
    {
463
    {
464
        $seqname = $this->getSequenceName($seq_name);
464
        $seqname = $this->getSequenceName($seq_name);
465
        if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
465
        if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
466
            return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
466
            return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
467
        }
467
        }
468
        $repeat = 0;
468
        $repeat = 0;
469
        do {
469
        do {
470
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
470
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
471
            $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
471
            $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
472
            $this->popErrorHandling();
472
            $this->popErrorHandling();
473
            if ($ondemand && DB::isError($result) &&
473
            if ($ondemand && DB::isError($result) &&
474
                ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
474
                ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
475
            {
475
            {
476
                $repeat = 1;
476
                $repeat = 1;
477
                $result = $this->createSequence($seq_name);
477
                $result = $this->createSequence($seq_name);
478
                if (DB::isError($result)) {
478
                if (DB::isError($result)) {
479
                    return $this->raiseError($result);
479
                    return $this->raiseError($result);
480
                }
480
                }
481
            } elseif (!DB::isError($result)) {
481
            } elseif (!DB::isError($result)) {
482
                $result = $this->query("SELECT @@IDENTITY FROM $seqname");
482
                $result = $this->query("SELECT @@IDENTITY FROM $seqname");
483
                $repeat = 0;
483
                $repeat = 0;
484
            } else {
484
            } else {
485
                $repeat = false;
485
                $repeat = false;
486
            }
486
            }
487
        } while ($repeat);
487
        } while ($repeat);
488
        if (DB::isError($result)) {
488
        if (DB::isError($result)) {
489
            return $this->raiseError($result);
489
            return $this->raiseError($result);
490
        }
490
        }
491
        $result = $result->fetchRow(DB_FETCHMODE_ORDERED);
491
        $result = $result->fetchRow(DB_FETCHMODE_ORDERED);
492
        return $result[0];
492
        return $result[0];
493
    }
493
    }
494
494
495
    /**
495
    /**
496
     * Creates a new sequence
496
     * Creates a new sequence
497
     *
497
     *
498
     * @param string $seq_name  name of the new sequence
498
     * @param string $seq_name  name of the new sequence
499
     *
499
     *
500
     * @return int  DB_OK on success.  A DB_Error object on failure.
500
     * @return int  DB_OK on success.  A DB_Error object on failure.
501
     *
501
     *
502
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
502
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
503
     *      DB_sybase::nextID(), DB_sybase::dropSequence()
503
     *      DB_sybase::nextID(), DB_sybase::dropSequence()
504
     */
504
     */
505
    function createSequence($seq_name)
505
    function createSequence($seq_name)
506
    {
506
    {
507
        return $this->query('CREATE TABLE '
507
        return $this->query('CREATE TABLE '
508
                            . $this->getSequenceName($seq_name)
508
                            . $this->getSequenceName($seq_name)
509
                            . ' (id numeric(10, 0) IDENTITY NOT NULL,'
509
                            . ' (id numeric(10, 0) IDENTITY NOT NULL,'
510
                            . ' vapor int NULL)');
510
                            . ' vapor int NULL)');
511
    }
511
    }
512
512
513
    // }}}
513
    // }}}
514
    // {{{ dropSequence()
514
    // {{{ dropSequence()
515
515
516
    /**
516
    /**
517
     * Deletes a sequence
517
     * Deletes a sequence
518
     *
518
     *
519
     * @param string $seq_name  name of the sequence to be deleted
519
     * @param string $seq_name  name of the sequence to be deleted
520
     *
520
     *
521
     * @return int  DB_OK on success.  A DB_Error object on failure.
521
     * @return int  DB_OK on success.  A DB_Error object on failure.
522
     *
522
     *
523
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
523
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
524
     *      DB_sybase::nextID(), DB_sybase::createSequence()
524
     *      DB_sybase::nextID(), DB_sybase::createSequence()
525
     */
525
     */
526
    function dropSequence($seq_name)
526
    function dropSequence($seq_name)
527
    {
527
    {
528
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
528
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
529
    }
529
    }
530
530
531
    // }}}
531
    // }}}
532
    // {{{ quoteFloat()
532
    // {{{ quoteFloat()
533
533
534
    /**
534
    /**
535
     * Formats a float value for use within a query in a locale-independent
535
     * Formats a float value for use within a query in a locale-independent
536
     * manner.
536
     * manner.
537
     *
537
     *
538
     * @param float the float value to be quoted.
538
     * @param float the float value to be quoted.
539
     * @return string the quoted string.
539
     * @return string the quoted string.
540
     * @see DB_common::quoteSmart()
540
     * @see DB_common::quoteSmart()
541
     * @since Method available since release 1.7.8.
541
     * @since Method available since release 1.7.8.
542
     */
542
     */
543
    function quoteFloat($float) {
543
    function quoteFloat($float) {
544
        return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
544
        return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
545
    }
545
    }
546
     
546
     
547
    // }}}
547
    // }}}
548
    // {{{ autoCommit()
548
    // {{{ autoCommit()
549
549
550
    /**
550
    /**
551
     * Enables or disables automatic commits
551
     * Enables or disables automatic commits
552
     *
552
     *
553
     * @param bool $onoff  true turns it on, false turns it off
553
     * @param bool $onoff  true turns it on, false turns it off
554
     *
554
     *
555
     * @return int  DB_OK on success.  A DB_Error object if the driver
555
     * @return int  DB_OK on success.  A DB_Error object if the driver
556
     *               doesn't support auto-committing transactions.
556
     *               doesn't support auto-committing transactions.
557
     */
557
     */
558
    function autoCommit($onoff = false)
558
    function autoCommit($onoff = false)
559
    {
559
    {
560
        // XXX if $this->transaction_opcount > 0, we should probably
560
        // XXX if $this->transaction_opcount > 0, we should probably
561
        // issue a warning here.
561
        // issue a warning here.
562
        $this->autocommit = $onoff ? true : false;
562
        $this->autocommit = $onoff ? true : false;
563
        return DB_OK;
563
        return DB_OK;
564
    }
564
    }
565
565
566
    // }}}
566
    // }}}
567
    // {{{ commit()
567
    // {{{ commit()
568
568
569
    /**
569
    /**
570
     * Commits the current transaction
570
     * Commits the current transaction
571
     *
571
     *
572
     * @return int  DB_OK on success.  A DB_Error object on failure.
572
     * @return int  DB_OK on success.  A DB_Error object on failure.
573
     */
573
     */
574
    function commit()
574
    function commit()
575
    {
575
    {
576
        if ($this->transaction_opcount > 0) {
576
        if ($this->transaction_opcount > 0) {
577
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
577
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
578
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
578
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
579
            }
579
            }
580
            $result = @sybase_query('COMMIT', $this->connection);
580
            $result = @sybase_query('COMMIT', $this->connection);
581
            $this->transaction_opcount = 0;
581
            $this->transaction_opcount = 0;
582
            if (!$result) {
582
            if (!$result) {
583
                return $this->sybaseRaiseError();
583
                return $this->sybaseRaiseError();
584
            }
584
            }
585
        }
585
        }
586
        return DB_OK;
586
        return DB_OK;
587
    }
587
    }
588
588
589
    // }}}
589
    // }}}
590
    // {{{ rollback()
590
    // {{{ rollback()
591
591
592
    /**
592
    /**
593
     * Reverts the current transaction
593
     * Reverts the current transaction
594
     *
594
     *
595
     * @return int  DB_OK on success.  A DB_Error object on failure.
595
     * @return int  DB_OK on success.  A DB_Error object on failure.
596
     */
596
     */
597
    function rollback()
597
    function rollback()
598
    {
598
    {
599
        if ($this->transaction_opcount > 0) {
599
        if ($this->transaction_opcount > 0) {
600
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
600
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
601
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
601
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
602
            }
602
            }
603
            $result = @sybase_query('ROLLBACK', $this->connection);
603
            $result = @sybase_query('ROLLBACK', $this->connection);
604
            $this->transaction_opcount = 0;
604
            $this->transaction_opcount = 0;
605
            if (!$result) {
605
            if (!$result) {
606
                return $this->sybaseRaiseError();
606
                return $this->sybaseRaiseError();
607
            }
607
            }
608
        }
608
        }
609
        return DB_OK;
609
        return DB_OK;
610
    }
610
    }
611
611
612
    // }}}
612
    // }}}
613
    // {{{ sybaseRaiseError()
613
    // {{{ sybaseRaiseError()
614
614
615
    /**
615
    /**
616
     * Produces a DB_Error object regarding the current problem
616
     * Produces a DB_Error object regarding the current problem
617
     *
617
     *
618
     * @param int $errno  if the error is being manually raised pass a
618
     * @param int $errno  if the error is being manually raised pass a
619
     *                     DB_ERROR* constant here.  If this isn't passed
619
     *                     DB_ERROR* constant here.  If this isn't passed
620
     *                     the error information gathered from the DBMS.
620
     *                     the error information gathered from the DBMS.
621
     *
621
     *
622
     * @return object  the DB_Error object
622
     * @return object  the DB_Error object
623
     *
623
     *
624
     * @see DB_common::raiseError(),
624
     * @see DB_common::raiseError(),
625
     *      DB_sybase::errorNative(), DB_sybase::errorCode()
625
     *      DB_sybase::errorNative(), DB_sybase::errorCode()
626
     */
626
     */
627
    function sybaseRaiseError($errno = null)
627
    function sybaseRaiseError($errno = null)
628
    {
628
    {
629
        $native = $this->errorNative();
629
        $native = $this->errorNative();
630
        if ($errno === null) {
630
        if ($errno === null) {
631
            $errno = $this->errorCode($native);
631
            $errno = $this->errorCode($native);
632
        }
632
        }
633
        return $this->raiseError($errno, null, null, null, $native);
633
        return $this->raiseError($errno, null, null, null, $native);
634
    }
634
    }
635
635
636
    // }}}
636
    // }}}
637
    // {{{ errorNative()
637
    // {{{ errorNative()
638
638
639
    /**
639
    /**
640
     * Gets the DBMS' native error message produced by the last query
640
     * Gets the DBMS' native error message produced by the last query
641
     *
641
     *
642
     * @return string  the DBMS' error message
642
     * @return string  the DBMS' error message
643
     */
643
     */
644
    function errorNative()
644
    function errorNative()
645
    {
645
    {
646
        return @sybase_get_last_message();
646
        return @sybase_get_last_message();
647
    }
647
    }
648
648
649
    // }}}
649
    // }}}
650
    // {{{ errorCode()
650
    // {{{ errorCode()
651
651
652
    /**
652
    /**
653
     * Determines PEAR::DB error code from the database's text error message.
653
     * Determines PEAR::DB error code from the database's text error message.
654
     *
654
     *
655
     * @param  string  $errormsg  error message returned from the database
655
     * @param  string  $errormsg  error message returned from the database
656
     * @return integer  an error number from a DB error constant
656
     * @return integer  an error number from a DB error constant
657
     */
657
     */
658
    function errorCode($errormsg)
658
    function errorCode($errormsg)
659
    {
659
    {
660
        static $error_regexps;
660
        static $error_regexps;
661
       
661
       
662
        // PHP 5.2+ prepends the function name to $php_errormsg, so we need
662
        // PHP 5.2+ prepends the function name to $php_errormsg, so we need
663
        // this hack to work around it, per bug #9599.
663
        // this hack to work around it, per bug #9599.
664
        $errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg);
664
        $errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg);
665
       
665
       
666
        if (!isset($error_regexps)) {
666
        if (!isset($error_regexps)) {
667
            $error_regexps = array(
667
            $error_regexps = array(
668
                '/Incorrect syntax near/'
668
                '/Incorrect syntax near/'
669
                    => DB_ERROR_SYNTAX,
669
                    => DB_ERROR_SYNTAX,
670
                '/^Unclosed quote before the character string [\"\'].*[\"\']\./'
670
                '/^Unclosed quote before the character string [\"\'].*[\"\']\./'
671
                    => DB_ERROR_SYNTAX,
671
                    => DB_ERROR_SYNTAX,
672
                '/Implicit conversion (from datatype|of NUMERIC value)/i'
672
                '/Implicit conversion (from datatype|of NUMERIC value)/i'
673
                    => DB_ERROR_INVALID_NUMBER,
673
                    => DB_ERROR_INVALID_NUMBER,
674
                '/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./'
674
                '/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./'
675
                    => DB_ERROR_NOSUCHTABLE,
675
                    => DB_ERROR_NOSUCHTABLE,
676
                '/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./'
676
                '/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./'
677
                    => DB_ERROR_ACCESS_VIOLATION,
677
                    => DB_ERROR_ACCESS_VIOLATION,
678
                '/^.+ permission denied on object .+, database .+, owner .+/'
678
                '/^.+ permission denied on object .+, database .+, owner .+/'
679
                    => DB_ERROR_ACCESS_VIOLATION,
679
                    => DB_ERROR_ACCESS_VIOLATION,
680
                '/^.* permission denied, database .+, owner .+/'
680
                '/^.* permission denied, database .+, owner .+/'
681
                    => DB_ERROR_ACCESS_VIOLATION,
681
                    => DB_ERROR_ACCESS_VIOLATION,
682
                '/[^.*] not found\./'
682
                '/[^.*] not found\./'
683
                    => DB_ERROR_NOSUCHTABLE,
683
                    => DB_ERROR_NOSUCHTABLE,
684
                '/There is already an object named/'
684
                '/There is already an object named/'
685
                    => DB_ERROR_ALREADY_EXISTS,
685
                    => DB_ERROR_ALREADY_EXISTS,
686
                '/Invalid column name/'
686
                '/Invalid column name/'
687
                    => DB_ERROR_NOSUCHFIELD,
687
                    => DB_ERROR_NOSUCHFIELD,
688
                '/does not allow null values/'
688
                '/does not allow null values/'
689
                    => DB_ERROR_CONSTRAINT_NOT_NULL,
689
                    => DB_ERROR_CONSTRAINT_NOT_NULL,
690
                '/Command has been aborted/'
690
                '/Command has been aborted/'
691
                    => DB_ERROR_CONSTRAINT,
691
                    => DB_ERROR_CONSTRAINT,
692
                '/^Cannot drop the index .* because it doesn\'t exist/i'
692
                '/^Cannot drop the index .* because it doesn\'t exist/i'
693
                    => DB_ERROR_NOT_FOUND,
693
                    => DB_ERROR_NOT_FOUND,
694
                '/^There is already an index/i'
694
                '/^There is already an index/i'
695
                    => DB_ERROR_ALREADY_EXISTS,
695
                    => DB_ERROR_ALREADY_EXISTS,
696
                '/^There are fewer columns in the INSERT statement than values specified/i'
696
                '/^There are fewer columns in the INSERT statement than values specified/i'
697
                    => DB_ERROR_VALUE_COUNT_ON_ROW,
697
                    => DB_ERROR_VALUE_COUNT_ON_ROW,
698
                '/Divide by zero/i'
698
                '/Divide by zero/i'
699
                    => DB_ERROR_DIVZERO,
699
                    => DB_ERROR_DIVZERO,
700
            );
700
            );
701
        }
701
        }
702
702
703
        foreach ($error_regexps as $regexp => $code) {
703
        foreach ($error_regexps as $regexp => $code) {
704
            if (preg_match($regexp, $errormsg)) {
704
            if (preg_match($regexp, $errormsg)) {
705
                return $code;
705
                return $code;
706
            }
706
            }
707
        }
707
        }
708
        return DB_ERROR;
708
        return DB_ERROR;
709
    }
709
    }
710
710
711
    // }}}
711
    // }}}
712
    // {{{ tableInfo()
712
    // {{{ tableInfo()
713
713
714
    /**
714
    /**
715
     * Returns information about a table or a result set
715
     * Returns information about a table or a result set
716
     *
716
     *
717
     * NOTE: only supports 'table' and 'flags' if <var>$result</var>
717
     * NOTE: only supports 'table' and 'flags' if <var>$result</var>
718
     * is a table name.
718
     * is a table name.
719
     *
719
     *
720
     * @param object|string  $result  DB_result object from a query or a
720
     * @param object|string  $result  DB_result object from a query or a
721
     *                                 string containing the name of a table.
721
     *                                 string containing the name of a table.
722
     *                                 While this also accepts a query result
722
     *                                 While this also accepts a query result
723
     *                                 resource identifier, this behavior is
723
     *                                 resource identifier, this behavior is
724
     *                                 deprecated.
724
     *                                 deprecated.
725
     * @param int            $mode    a valid tableInfo mode
725
     * @param int            $mode    a valid tableInfo mode
726
     *
726
     *
727
     * @return array  an associative array with the information requested.
727
     * @return array  an associative array with the information requested.
728
     *                 A DB_Error object on failure.
728
     *                 A DB_Error object on failure.
729
     *
729
     *
730
     * @see DB_common::tableInfo()
730
     * @see DB_common::tableInfo()
731
     * @since Method available since Release 1.6.0
731
     * @since Method available since Release 1.6.0
732
     */
732
     */
733
    function tableInfo($result, $mode = null)
733
    function tableInfo($result, $mode = null)
734
    {
734
    {
735
        if (is_string($result)) {
735
        if (is_string($result)) {
736
            /*
736
            /*
737
             * Probably received a table name.
737
             * Probably received a table name.
738
             * Create a result resource identifier.
738
             * Create a result resource identifier.
739
             */
739
             */
740
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
740
            if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
741
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
741
                return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
742
            }
742
            }
743
            $id = @sybase_query("SELECT * FROM $result WHERE 1=0",
743
            $id = @sybase_query("SELECT * FROM $result WHERE 1=0",
744
                                $this->connection);
744
                                $this->connection);
745
            $got_string = true;
745
            $got_string = true;
746
        } elseif (isset($result->result)) {
746
        } elseif (isset($result->result)) {
747
            /*
747
            /*
748
             * Probably received a result object.
748
             * Probably received a result object.
749
             * Extract the result resource identifier.
749
             * Extract the result resource identifier.
750
             */
750
             */
751
            $id = $result->result;
751
            $id = $result->result;
752
            $got_string = false;
752
            $got_string = false;
753
        } else {
753
        } else {
754
            /*
754
            /*
755
             * Probably received a result resource identifier.
755
             * Probably received a result resource identifier.
756
             * Copy it.
756
             * Copy it.
757
             * Deprecated.  Here for compatibility only.
757
             * Deprecated.  Here for compatibility only.
758
             */
758
             */
759
            $id = $result;
759
            $id = $result;
760
            $got_string = false;
760
            $got_string = false;
761
        }
761
        }
762
762
763
        if (!is_resource($id)) {
763
        if (!is_resource($id)) {
764
            return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA);
764
            return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA);
765
        }
765
        }
766
766
767
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
767
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
768
            $case_func = 'strtolower';
768
            $case_func = 'strtolower';
769
        } else {
769
        } else {
770
            $case_func = 'strval';
770
            $case_func = 'strval';
771
        }
771
        }
772
772
773
        $count = @sybase_num_fields($id);
773
        $count = @sybase_num_fields($id);
774
        $res   = array();
774
        $res   = array();
775
775
776
        if ($mode) {
776
        if ($mode) {
777
            $res['num_fields'] = $count;
777
            $res['num_fields'] = $count;
778
        }
778
        }
779
779
780
        for ($i = 0; $i < $count; $i++) {
780
        for ($i = 0; $i < $count; $i++) {
781
            $f = @sybase_fetch_field($id, $i);
781
            $f = @sybase_fetch_field($id, $i);
782
            // column_source is often blank
782
            // column_source is often blank
783
            $res[$i] = array(
783
            $res[$i] = array(
784
                'table' => $got_string
784
                'table' => $got_string
785
                           ? $case_func($result)
785
                           ? $case_func($result)
786
                           : $case_func($f->column_source),
786
                           : $case_func($f->column_source),
787
                'name'  => $case_func($f->name),
787
                'name'  => $case_func($f->name),
788
                'type'  => $f->type,
788
                'type'  => $f->type,
789
                'len'   => $f->max_length,
789
                'len'   => $f->max_length,
790
                'flags' => '',
790
                'flags' => '',
791
            );
791
            );
792
            if ($res[$i]['table']) {
792
            if ($res[$i]['table']) {
793
                $res[$i]['flags'] = $this->_sybase_field_flags(
793
                $res[$i]['flags'] = $this->_sybase_field_flags(
794
                        $res[$i]['table'], $res[$i]['name']);
794
                        $res[$i]['table'], $res[$i]['name']);
795
            }
795
            }
796
            if ($mode & DB_TABLEINFO_ORDER) {
796
            if ($mode & DB_TABLEINFO_ORDER) {
797
                $res['order'][$res[$i]['name']] = $i;
797
                $res['order'][$res[$i]['name']] = $i;
798
            }
798
            }
799
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
799
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
800
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
800
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
801
            }
801
            }
802
        }
802
        }
803
803
804
        // free the result only if we were called on a table
804
        // free the result only if we were called on a table
805
        if ($got_string) {
805
        if ($got_string) {
806
            @sybase_free_result($id);
806
            @sybase_free_result($id);
807
        }
807
        }
808
        return $res;
808
        return $res;
809
    }
809
    }
810
810
811
    // }}}
811
    // }}}
812
    // {{{ _sybase_field_flags()
812
    // {{{ _sybase_field_flags()
813
813
814
    /**
814
    /**
815
     * Get the flags for a field
815
     * Get the flags for a field
816
     *
816
     *
817
     * Currently supports:
817
     * Currently supports:
818
     *  + <samp>unique_key</samp>    (unique index, unique check or primary_key)
818
     *  + <samp>unique_key</samp>    (unique index, unique check or primary_key)
819
     *  + <samp>multiple_key</samp>  (multi-key index)
819
     *  + <samp>multiple_key</samp>  (multi-key index)
820
     *
820
     *
821
     * @param string  $table   the table name
821
     * @param string  $table   the table name
822
     * @param string  $column  the field name
822
     * @param string  $column  the field name
823
     *
823
     *
824
     * @return string  space delimited string of flags.  Empty string if none.
824
     * @return string  space delimited string of flags.  Empty string if none.
825
     *
825
     *
826
     * @access private
826
     * @access private
827
     */
827
     */
828
    function _sybase_field_flags($table, $column)
828
    function _sybase_field_flags($table, $column)
829
    {
829
    {
830
        static $tableName = null;
830
        static $tableName = null;
831
        static $flags = array();
831
        static $flags = array();
832
832
833
        if ($table != $tableName) {
833
        if ($table != $tableName) {
834
            $flags = array();
834
            $flags = array();
835
            $tableName = $table;
835
            $tableName = $table;
836
836
837
            /* We're running sp_helpindex directly because it doesn't exist in
837
            /* We're running sp_helpindex directly because it doesn't exist in
838
             * older versions of ASE -- unfortunately, we can't just use
838
             * older versions of ASE -- unfortunately, we can't just use
839
             * DB::isError() because the user may be using callback error
839
             * DB::isError() because the user may be using callback error
840
             * handling. */
840
             * handling. */
841
            $res = @sybase_query("sp_helpindex $table", $this->connection);
841
            $res = @sybase_query("sp_helpindex $table", $this->connection);
842
842
843
            if ($res === false || $res === true) {
843
            if ($res === false || $res === true) {
844
                // Fake a valid response for BC reasons.
844
                // Fake a valid response for BC reasons.
845
                return '';
845
                return '';
846
            }
846
            }
847
847
848
            while (($val = sybase_fetch_assoc($res)) !== false) {
848
            while (($val = sybase_fetch_assoc($res)) !== false) {
849
                if (!isset($val['index_keys'])) {
849
                if (!isset($val['index_keys'])) {
850
                    /* No useful information returned. Break and be done with
850
                    /* No useful information returned. Break and be done with
851
                     * it, which preserves the pre-1.7.9 behaviour. */
851
                     * it, which preserves the pre-1.7.9 behaviour. */
852
                    break;
852
                    break;
853
                }
853
                }
854
854
855
                $keys = explode(', ', trim($val['index_keys']));
855
                $keys = explode(', ', trim($val['index_keys']));
856
856
857
                if (sizeof($keys) > 1) {
857
                if (sizeof($keys) > 1) {
858
                    foreach ($keys as $key) {
858
                    foreach ($keys as $key) {
859
                        $this->_add_flag($flags[$key], 'multiple_key');
859
                        $this->_add_flag($flags[$key], 'multiple_key');
860
                    }
860
                    }
861
                }
861
                }
862
862
863
                if (strpos($val['index_description'], 'unique')) {
863
                if (strpos($val['index_description'], 'unique')) {
864
                    foreach ($keys as $key) {
864
                    foreach ($keys as $key) {
865
                        $this->_add_flag($flags[$key], 'unique_key');
865
                        $this->_add_flag($flags[$key], 'unique_key');
866
                    }
866
                    }
867
                }
867
                }
868
            }
868
            }
869
869
870
            sybase_free_result($res);
870
            sybase_free_result($res);
871
871
872
        }
872
        }
873
873
874
        if (array_key_exists($column, $flags)) {
874
        if (array_key_exists($column, $flags)) {
875
            return(implode(' ', $flags[$column]));
875
            return(implode(' ', $flags[$column]));
876
        }
876
        }
877
877
878
        return '';
878
        return '';
879
    }
879
    }
880
880
881
    // }}}
881
    // }}}
882
    // {{{ _add_flag()
882
    // {{{ _add_flag()
883
883
884
    /**
884
    /**
885
     * Adds a string to the flags array if the flag is not yet in there
885
     * Adds a string to the flags array if the flag is not yet in there
886
     * - if there is no flag present the array is created
886
     * - if there is no flag present the array is created
887
     *
887
     *
888
     * @param array  $array  reference of flags array to add a value to
888
     * @param array  $array  reference of flags array to add a value to
889
     * @param mixed  $value  value to add to the flag array
889
     * @param mixed  $value  value to add to the flag array
890
     *
890
     *
891
     * @return void
891
     * @return void
892
     *
892
     *
893
     * @access private
893
     * @access private
894
     */
894
     */
895
    function _add_flag(&$array, $value)
895
    function _add_flag(&$array, $value)
896
    {
896
    {
897
        if (!is_array($array)) {
897
        if (!is_array($array)) {
898
            $array = array($value);
898
            $array = array($value);
899
        } elseif (!in_array($value, $array)) {
899
        } elseif (!in_array($value, $array)) {
900
            array_push($array, $value);
900
            array_push($array, $value);
901
        }
901
        }
902
    }
902
    }
903
903
904
    // }}}
904
    // }}}
905
    // {{{ getSpecialQuery()
905
    // {{{ getSpecialQuery()
906
906
907
    /**
907
    /**
908
     * Obtains the query string needed for listing a given type of objects
908
     * Obtains the query string needed for listing a given type of objects
909
     *
909
     *
910
     * @param string $type  the kind of objects you want to retrieve
910
     * @param string $type  the kind of objects you want to retrieve
911
     *
911
     *
912
     * @return string  the SQL query string or null if the driver doesn't
912
     * @return string  the SQL query string or null if the driver doesn't
913
     *                  support the object type requested
913
     *                  support the object type requested
914
     *
914
     *
915
     * @access protected
915
     * @access protected
916
     * @see DB_common::getListOf()
916
     * @see DB_common::getListOf()
917
     */
917
     */
918
    function getSpecialQuery($type)
918
    function getSpecialQuery($type)
919
    {
919
    {
920
        switch ($type) {
920
        switch ($type) {
921
            case 'tables':
921
            case 'tables':
922
                return "SELECT name FROM sysobjects WHERE type = 'U'"
922
                return "SELECT name FROM sysobjects WHERE type = 'U'"
923
                       . ' ORDER BY name';
923
                       . ' ORDER BY name';
924
            case 'views':
924
            case 'views':
925
                return "SELECT name FROM sysobjects WHERE type = 'V'";
925
                return "SELECT name FROM sysobjects WHERE type = 'V'";
926
            default:
926
            default:
927
                return null;
927
                return null;
928
        }
928
        }
929
    }
929
    }
930
930
931
    // }}}
931
    // }}}
932
932
933
}
933
}
934
934
935
/*
935
/*
936
 * Local variables:
936
 * Local variables:
937
 * tab-width: 4
937
 * tab-width: 4
938
 * c-basic-offset: 4
938
 * c-basic-offset: 4
939
 * End:
939
 * End:
940
 */
940
 */
941
941
942
?>
942
?>
943
 
943