Хранилища 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 mysqli extension
6
 * The PEAR DB driver for PHP's mysqli extension
7
 * for interacting with MySQL databases
7
 * for interacting with MySQL 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     Daniel Convissor <danielc@php.net>
19
 * @author     Daniel Convissor <danielc@php.net>
20
 * @copyright  1997-2007 The PHP Group
20
 * @copyright  1997-2007 The PHP Group
21
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
21
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22
 * @version    CVS: $Id: mysqli.php,v 1.82 2007/09/21 13:40:41 aharvey Exp $
22
 * @version    CVS: $Id: mysqli.php,v 1.82 2007/09/21 13:40:41 aharvey Exp $
23
 * @link       http://pear.php.net/package/DB
23
 * @link       http://pear.php.net/package/DB
24
 */
24
 */
25
25
26
/**
26
/**
27
 * Obtain the DB_common class so it can be extended from
27
 * Obtain the DB_common class so it can be extended from
28
 */
28
 */
29
require_once 'DB/common.php';
29
require_once 'DB/common.php';
30
30
31
/**
31
/**
32
 * The methods PEAR DB uses to interact with PHP's mysqli extension
32
 * The methods PEAR DB uses to interact with PHP's mysqli extension
33
 * for interacting with MySQL databases
33
 * for interacting with MySQL databases
34
 *
34
 *
35
 * This is for MySQL versions 4.1 and above.  Requires PHP 5.
35
 * This is for MySQL versions 4.1 and above.  Requires PHP 5.
36
 *
36
 *
37
 * Note that persistent connections no longer exist.
37
 * Note that persistent connections no longer exist.
38
 *
38
 *
39
 * These methods overload the ones declared in DB_common.
39
 * These methods overload the ones declared in DB_common.
40
 *
40
 *
41
 * @category   Database
41
 * @category   Database
42
 * @package    DB
42
 * @package    DB
43
 * @author     Daniel Convissor <danielc@php.net>
43
 * @author     Daniel Convissor <danielc@php.net>
44
 * @copyright  1997-2007 The PHP Group
44
 * @copyright  1997-2007 The PHP Group
45
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
45
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
46
 * @version    Release: 1.7.13
46
 * @version    Release: 1.7.13
47
 * @link       http://pear.php.net/package/DB
47
 * @link       http://pear.php.net/package/DB
48
 * @since      Class functional since Release 1.6.3
48
 * @since      Class functional since Release 1.6.3
49
 */
49
 */
50
class DB_mysqli extends DB_common
50
class DB_mysqli 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 = 'mysqli';
58
    var $phptype = 'mysqli';
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 = 'mysqli';
64
    var $dbsyntax = 'mysqli';
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
     * @var array
77
     * @var array
78
     */
78
     */
79
    var $features = array(
79
    var $features = array(
80
        'limit'         => 'alter',
80
        'limit'         => 'alter',
81
        'new_link'      => false,
81
        'new_link'      => false,
82
        'numrows'       => true,
82
        'numrows'       => true,
83
        'pconnect'      => false,
83
        'pconnect'      => false,
84
        'prepare'       => false,
84
        'prepare'       => false,
85
        'ssl'           => true,
85
        'ssl'           => true,
86
        'transactions'  => true,
86
        'transactions'  => true,
87
    );
87
    );
88
88
89
    /**
89
    /**
90
     * A mapping of native error codes to DB error codes
90
     * A mapping of native error codes to DB error codes
91
     * @var array
91
     * @var array
92
     */
92
     */
93
    var $errorcode_map = array(
93
    var $errorcode_map = array(
94
        1004 => DB_ERROR_CANNOT_CREATE,
94
        1004 => DB_ERROR_CANNOT_CREATE,
95
        1005 => DB_ERROR_CANNOT_CREATE,
95
        1005 => DB_ERROR_CANNOT_CREATE,
96
        1006 => DB_ERROR_CANNOT_CREATE,
96
        1006 => DB_ERROR_CANNOT_CREATE,
97
        1007 => DB_ERROR_ALREADY_EXISTS,
97
        1007 => DB_ERROR_ALREADY_EXISTS,
98
        1008 => DB_ERROR_CANNOT_DROP,
98
        1008 => DB_ERROR_CANNOT_DROP,
99
        1022 => DB_ERROR_ALREADY_EXISTS,
99
        1022 => DB_ERROR_ALREADY_EXISTS,
100
        1044 => DB_ERROR_ACCESS_VIOLATION,
100
        1044 => DB_ERROR_ACCESS_VIOLATION,
101
        1046 => DB_ERROR_NODBSELECTED,
101
        1046 => DB_ERROR_NODBSELECTED,
102
        1048 => DB_ERROR_CONSTRAINT,
102
        1048 => DB_ERROR_CONSTRAINT,
103
        1049 => DB_ERROR_NOSUCHDB,
103
        1049 => DB_ERROR_NOSUCHDB,
104
        1050 => DB_ERROR_ALREADY_EXISTS,
104
        1050 => DB_ERROR_ALREADY_EXISTS,
105
        1051 => DB_ERROR_NOSUCHTABLE,
105
        1051 => DB_ERROR_NOSUCHTABLE,
106
        1054 => DB_ERROR_NOSUCHFIELD,
106
        1054 => DB_ERROR_NOSUCHFIELD,
107
        1061 => DB_ERROR_ALREADY_EXISTS,
107
        1061 => DB_ERROR_ALREADY_EXISTS,
108
        1062 => DB_ERROR_ALREADY_EXISTS,
108
        1062 => DB_ERROR_ALREADY_EXISTS,
109
        1064 => DB_ERROR_SYNTAX,
109
        1064 => DB_ERROR_SYNTAX,
110
        1091 => DB_ERROR_NOT_FOUND,
110
        1091 => DB_ERROR_NOT_FOUND,
111
        1100 => DB_ERROR_NOT_LOCKED,
111
        1100 => DB_ERROR_NOT_LOCKED,
112
        1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
112
        1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
113
        1142 => DB_ERROR_ACCESS_VIOLATION,
113
        1142 => DB_ERROR_ACCESS_VIOLATION,
114
        1146 => DB_ERROR_NOSUCHTABLE,
114
        1146 => DB_ERROR_NOSUCHTABLE,
115
        1216 => DB_ERROR_CONSTRAINT,
115
        1216 => DB_ERROR_CONSTRAINT,
116
        1217 => DB_ERROR_CONSTRAINT,
116
        1217 => DB_ERROR_CONSTRAINT,
117
        1356 => DB_ERROR_DIVZERO,
117
        1356 => DB_ERROR_DIVZERO,
118
        1451 => DB_ERROR_CONSTRAINT,
118
        1451 => DB_ERROR_CONSTRAINT,
119
        1452 => DB_ERROR_CONSTRAINT,
119
        1452 => DB_ERROR_CONSTRAINT,
120
    );
120
    );
121
121
122
    /**
122
    /**
123
     * The raw database connection created by PHP
123
     * The raw database connection created by PHP
124
     * @var resource
124
     * @var resource
125
     */
125
     */
126
    var $connection;
126
    var $connection;
127
127
128
    /**
128
    /**
129
     * The DSN information for connecting to a database
129
     * The DSN information for connecting to a database
130
     * @var array
130
     * @var array
131
     */
131
     */
132
    var $dsn = array();
132
    var $dsn = array();
133
133
134
134
135
    /**
135
    /**
136
     * Should data manipulation queries be committed automatically?
136
     * Should data manipulation queries be committed automatically?
137
     * @var bool
137
     * @var bool
138
     * @access private
138
     * @access private
139
     */
139
     */
140
    var $autocommit = true;
140
    var $autocommit = true;
141
141
142
    /**
142
    /**
143
     * The quantity of transactions begun
143
     * The quantity of transactions begun
144
     *
144
     *
145
     * {@internal  While this is private, it can't actually be designated
145
     * {@internal  While this is private, it can't actually be designated
146
     * private in PHP 5 because it is directly accessed in the test suite.}}
146
     * private in PHP 5 because it is directly accessed in the test suite.}}
147
     *
147
     *
148
     * @var integer
148
     * @var integer
149
     * @access private
149
     * @access private
150
     */
150
     */
151
    var $transaction_opcount = 0;
151
    var $transaction_opcount = 0;
152
152
153
    /**
153
    /**
154
     * The database specified in the DSN
154
     * The database specified in the DSN
155
     *
155
     *
156
     * It's a fix to allow calls to different databases in the same script.
156
     * It's a fix to allow calls to different databases in the same script.
157
     *
157
     *
158
     * @var string
158
     * @var string
159
     * @access private
159
     * @access private
160
     */
160
     */
161
    var $_db = '';
161
    var $_db = '';
162
162
163
    /**
163
    /**
164
     * Array for converting MYSQLI_*_FLAG constants to text values
164
     * Array for converting MYSQLI_*_FLAG constants to text values
165
     * @var    array
165
     * @var    array
166
     * @access public
166
     * @access public
167
     * @since  Property available since Release 1.6.5
167
     * @since  Property available since Release 1.6.5
168
     */
168
     */
169
    var $mysqli_flags = array(
169
    var $mysqli_flags = array(
170
        MYSQLI_NOT_NULL_FLAG        => 'not_null',
170
        MYSQLI_NOT_NULL_FLAG        => 'not_null',
171
        MYSQLI_PRI_KEY_FLAG         => 'primary_key',
171
        MYSQLI_PRI_KEY_FLAG         => 'primary_key',
172
        MYSQLI_UNIQUE_KEY_FLAG      => 'unique_key',
172
        MYSQLI_UNIQUE_KEY_FLAG      => 'unique_key',
173
        MYSQLI_MULTIPLE_KEY_FLAG    => 'multiple_key',
173
        MYSQLI_MULTIPLE_KEY_FLAG    => 'multiple_key',
174
        MYSQLI_BLOB_FLAG            => 'blob',
174
        MYSQLI_BLOB_FLAG            => 'blob',
175
        MYSQLI_UNSIGNED_FLAG        => 'unsigned',
175
        MYSQLI_UNSIGNED_FLAG        => 'unsigned',
176
        MYSQLI_ZEROFILL_FLAG        => 'zerofill',
176
        MYSQLI_ZEROFILL_FLAG        => 'zerofill',
177
        MYSQLI_AUTO_INCREMENT_FLAG  => 'auto_increment',
177
        MYSQLI_AUTO_INCREMENT_FLAG  => 'auto_increment',
178
        MYSQLI_TIMESTAMP_FLAG       => 'timestamp',
178
        MYSQLI_TIMESTAMP_FLAG       => 'timestamp',
179
        MYSQLI_SET_FLAG             => 'set',
179
        MYSQLI_SET_FLAG             => 'set',
180
        // MYSQLI_NUM_FLAG             => 'numeric',  // unnecessary
180
        // MYSQLI_NUM_FLAG             => 'numeric',  // unnecessary
181
        // MYSQLI_PART_KEY_FLAG        => 'multiple_key',  // duplicatvie
181
        // MYSQLI_PART_KEY_FLAG        => 'multiple_key',  // duplicatvie
182
        MYSQLI_GROUP_FLAG           => 'group_by'
182
        MYSQLI_GROUP_FLAG           => 'group_by'
183
    );
183
    );
184
184
185
    /**
185
    /**
186
     * Array for converting MYSQLI_TYPE_* constants to text values
186
     * Array for converting MYSQLI_TYPE_* constants to text values
187
     * @var    array
187
     * @var    array
188
     * @access public
188
     * @access public
189
     * @since  Property available since Release 1.6.5
189
     * @since  Property available since Release 1.6.5
190
     */
190
     */
191
    var $mysqli_types = array(
191
    var $mysqli_types = array(
192
        MYSQLI_TYPE_DECIMAL     => 'decimal',
192
        MYSQLI_TYPE_DECIMAL     => 'decimal',
193
        MYSQLI_TYPE_TINY        => 'tinyint',
193
        MYSQLI_TYPE_TINY        => 'tinyint',
194
        MYSQLI_TYPE_SHORT       => 'int',
194
        MYSQLI_TYPE_SHORT       => 'int',
195
        MYSQLI_TYPE_LONG        => 'int',
195
        MYSQLI_TYPE_LONG        => 'int',
196
        MYSQLI_TYPE_FLOAT       => 'float',
196
        MYSQLI_TYPE_FLOAT       => 'float',
197
        MYSQLI_TYPE_DOUBLE      => 'double',
197
        MYSQLI_TYPE_DOUBLE      => 'double',
198
        // MYSQLI_TYPE_NULL        => 'DEFAULT NULL',  // let flags handle it
198
        // MYSQLI_TYPE_NULL        => 'DEFAULT NULL',  // let flags handle it
199
        MYSQLI_TYPE_TIMESTAMP   => 'timestamp',
199
        MYSQLI_TYPE_TIMESTAMP   => 'timestamp',
200
        MYSQLI_TYPE_LONGLONG    => 'bigint',
200
        MYSQLI_TYPE_LONGLONG    => 'bigint',
201
        MYSQLI_TYPE_INT24       => 'mediumint',
201
        MYSQLI_TYPE_INT24       => 'mediumint',
202
        MYSQLI_TYPE_DATE        => 'date',
202
        MYSQLI_TYPE_DATE        => 'date',
203
        MYSQLI_TYPE_TIME        => 'time',
203
        MYSQLI_TYPE_TIME        => 'time',
204
        MYSQLI_TYPE_DATETIME    => 'datetime',
204
        MYSQLI_TYPE_DATETIME    => 'datetime',
205
        MYSQLI_TYPE_YEAR        => 'year',
205
        MYSQLI_TYPE_YEAR        => 'year',
206
        MYSQLI_TYPE_NEWDATE     => 'date',
206
        MYSQLI_TYPE_NEWDATE     => 'date',
207
        MYSQLI_TYPE_ENUM        => 'enum',
207
        MYSQLI_TYPE_ENUM        => 'enum',
208
        MYSQLI_TYPE_SET         => 'set',
208
        MYSQLI_TYPE_SET         => 'set',
209
        MYSQLI_TYPE_TINY_BLOB   => 'tinyblob',
209
        MYSQLI_TYPE_TINY_BLOB   => 'tinyblob',
210
        MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob',
210
        MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob',
211
        MYSQLI_TYPE_LONG_BLOB   => 'longblob',
211
        MYSQLI_TYPE_LONG_BLOB   => 'longblob',
212
        MYSQLI_TYPE_BLOB        => 'blob',
212
        MYSQLI_TYPE_BLOB        => 'blob',
213
        MYSQLI_TYPE_VAR_STRING  => 'varchar',
213
        MYSQLI_TYPE_VAR_STRING  => 'varchar',
214
        MYSQLI_TYPE_STRING      => 'char',
214
        MYSQLI_TYPE_STRING      => 'char',
215
        MYSQLI_TYPE_GEOMETRY    => 'geometry',
215
        MYSQLI_TYPE_GEOMETRY    => 'geometry',
216
        /* These constants are conditionally compiled in ext/mysqli, so we'll
216
        /* These constants are conditionally compiled in ext/mysqli, so we'll
217
         * define them by number rather than constant. */
217
         * define them by number rather than constant. */
218
        16                      => 'bit',
218
        16                      => 'bit',
219
        246                     => 'decimal',
219
        246                     => 'decimal',
220
    );
220
    );
221
221
222
222
223
    // }}}
223
    // }}}
224
    // {{{ constructor
224
    // {{{ constructor
225
225
226
    /**
226
    /**
227
     * This constructor calls <kbd>$this->DB_common()</kbd>
227
     * This constructor calls <kbd>$this->DB_common()</kbd>
228
     *
228
     *
229
     * @return void
229
     * @return void
230
     */
230
     */
231
    function DB_mysqli()
231
    function DB_mysqli()
232
    {
232
    {
233
        $this->DB_common();
233
        $this->DB_common();
234
    }
234
    }
235
235
236
    // }}}
236
    // }}}
237
    // {{{ connect()
237
    // {{{ connect()
238
238
239
    /**
239
    /**
240
     * Connect to the database server, log in and open the database
240
     * Connect to the database server, log in and open the database
241
     *
241
     *
242
     * Don't call this method directly.  Use DB::connect() instead.
242
     * Don't call this method directly.  Use DB::connect() instead.
243
     *
243
     *
244
     * PEAR DB's mysqli driver supports the following extra DSN options:
244
     * PEAR DB's mysqli driver supports the following extra DSN options:
245
     *   + When the 'ssl' $option passed to DB::connect() is true:
245
     *   + When the 'ssl' $option passed to DB::connect() is true:
246
     *     + key      The path to the key file.
246
     *     + key      The path to the key file.
247
     *     + cert     The path to the certificate file.
247
     *     + cert     The path to the certificate file.
248
     *     + ca       The path to the certificate authority file.
248
     *     + ca       The path to the certificate authority file.
249
     *     + capath   The path to a directory that contains trusted SSL
249
     *     + capath   The path to a directory that contains trusted SSL
250
     *                 CA certificates in pem format.
250
     *                 CA certificates in pem format.
251
     *     + cipher   The list of allowable ciphers for SSL encryption.
251
     *     + cipher   The list of allowable ciphers for SSL encryption.
252
     *
252
     *
253
     * Example of how to connect using SSL:
253
     * Example of how to connect using SSL:
254
     * <code>
254
     * <code>
255
     * require_once 'DB.php';
255
     * require_once 'DB.php';
256
     *
256
     *
257
     * $dsn = array(
257
     * $dsn = array(
258
     *     'phptype'  => 'mysqli',
258
     *     'phptype'  => 'mysqli',
259
     *     'username' => 'someuser',
259
     *     'username' => 'someuser',
260
     *     'password' => 'apasswd',
260
     *     'password' => 'apasswd',
261
     *     'hostspec' => 'localhost',
261
     *     'hostspec' => 'localhost',
262
     *     'database' => 'thedb',
262
     *     'database' => 'thedb',
263
     *     'key'      => 'client-key.pem',
263
     *     'key'      => 'client-key.pem',
264
     *     'cert'     => 'client-cert.pem',
264
     *     'cert'     => 'client-cert.pem',
265
     *     'ca'       => 'cacert.pem',
265
     *     'ca'       => 'cacert.pem',
266
     *     'capath'   => '/path/to/ca/dir',
266
     *     'capath'   => '/path/to/ca/dir',
267
     *     'cipher'   => 'AES',
267
     *     'cipher'   => 'AES',
268
     * );
268
     * );
269
     *
269
     *
270
     * $options = array(
270
     * $options = array(
271
     *     'ssl' => true,
271
     *     'ssl' => true,
272
     * );
272
     * );
273
     *
273
     *
274
     * $db = DB::connect($dsn, $options);
274
     * $db = DB::connect($dsn, $options);
275
     * if (PEAR::isError($db)) {
275
     * if (PEAR::isError($db)) {
276
     *     die($db->getMessage());
276
     *     die($db->getMessage());
277
     * }
277
     * }
278
     * </code>
278
     * </code>
279
     *
279
     *
280
     * @param array $dsn         the data source name
280
     * @param array $dsn         the data source name
281
     * @param bool  $persistent  should the connection be persistent?
281
     * @param bool  $persistent  should the connection be persistent?
282
     *
282
     *
283
     * @return int  DB_OK on success. A DB_Error object on failure.
283
     * @return int  DB_OK on success. A DB_Error object on failure.
284
     */
284
     */
285
    function connect($dsn, $persistent = false)
285
    function connect($dsn, $persistent = false)
286
    {
286
    {
287
        if (!PEAR::loadExtension('mysqli')) {
287
        if (!PEAR::loadExtension('mysqli')) {
288
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
288
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
289
        }
289
        }
290
290
291
        $this->dsn = $dsn;
291
        $this->dsn = $dsn;
292
        if ($dsn['dbsyntax']) {
292
        if ($dsn['dbsyntax']) {
293
            $this->dbsyntax = $dsn['dbsyntax'];
293
            $this->dbsyntax = $dsn['dbsyntax'];
294
        }
294
        }
295
295
296
        $ini = ini_get('track_errors');
296
        $ini = ini_get('track_errors');
297
        @ini_set('track_errors', 1);
297
        @ini_set('track_errors', 1);
298
        $php_errormsg = '';
298
        $php_errormsg = '';
299
299
300
        if (((int) $this->getOption('ssl')) === 1) {
300
        if (((int) $this->getOption('ssl')) === 1) {
301
            $init = mysqli_init();
301
            $init = mysqli_init();
302
            mysqli_ssl_set(
302
            mysqli_ssl_set(
303
                $init,
303
                $init,
304
                empty($dsn['key'])    ? null : $dsn['key'],
304
                empty($dsn['key'])    ? null : $dsn['key'],
305
                empty($dsn['cert'])   ? null : $dsn['cert'],
305
                empty($dsn['cert'])   ? null : $dsn['cert'],
306
                empty($dsn['ca'])     ? null : $dsn['ca'],
306
                empty($dsn['ca'])     ? null : $dsn['ca'],
307
                empty($dsn['capath']) ? null : $dsn['capath'],
307
                empty($dsn['capath']) ? null : $dsn['capath'],
308
                empty($dsn['cipher']) ? null : $dsn['cipher']
308
                empty($dsn['cipher']) ? null : $dsn['cipher']
309
            );
309
            );
310
            if ($this->connection = @mysqli_real_connect(
310
            if ($this->connection = @mysqli_real_connect(
311
                    $init,
311
                    $init,
312
                    $dsn['hostspec'],
312
                    $dsn['hostspec'],
313
                    $dsn['username'],
313
                    $dsn['username'],
314
                    $dsn['password'],
314
                    $dsn['password'],
315
                    $dsn['database'],
315
                    $dsn['database'],
316
                    $dsn['port'],
316
                    $dsn['port'],
317
                    $dsn['socket']))
317
                    $dsn['socket']))
318
            {
318
            {
319
                $this->connection = $init;
319
                $this->connection = $init;
320
            }
320
            }
321
        } else {
321
        } else {
322
            $this->connection = @mysqli_connect(
322
            $this->connection = @mysqli_connect(
323
                $dsn['hostspec'],
323
                $dsn['hostspec'],
324
                $dsn['username'],
324
                $dsn['username'],
325
                $dsn['password'],
325
                $dsn['password'],
326
                $dsn['database'],
326
                $dsn['database'],
327
                $dsn['port'],
327
                $dsn['port'],
328
                $dsn['socket']
328
                $dsn['socket']
329
            );
329
            );
330
        }
330
        }
331
331
332
        @ini_set('track_errors', $ini);
332
        @ini_set('track_errors', $ini);
333
333
334
        if (!$this->connection) {
334
        if (!$this->connection) {
335
            if (($err = @mysqli_connect_error()) != '') {
335
            if (($err = @mysqli_connect_error()) != '') {
336
                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
336
                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
337
                                         null, null, null,
337
                                         null, null, null,
338
                                         $err);
338
                                         $err);
339
            } else {
339
            } else {
340
                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
340
                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
341
                                         null, null, null,
341
                                         null, null, null,
342
                                         $php_errormsg);
342
                                         $php_errormsg);
343
            }
343
            }
344
        }
344
        }
345
345
346
        if ($dsn['database']) {
346
        if ($dsn['database']) {
347
            $this->_db = $dsn['database'];
347
            $this->_db = $dsn['database'];
348
        }
348
        }
349
349
350
        return DB_OK;
350
        return DB_OK;
351
    }
351
    }
352
352
353
    // }}}
353
    // }}}
354
    // {{{ disconnect()
354
    // {{{ disconnect()
355
355
356
    /**
356
    /**
357
     * Disconnects from the database server
357
     * Disconnects from the database server
358
     *
358
     *
359
     * @return bool  TRUE on success, FALSE on failure
359
     * @return bool  TRUE on success, FALSE on failure
360
     */
360
     */
361
    function disconnect()
361
    function disconnect()
362
    {
362
    {
363
        $ret = @mysqli_close($this->connection);
363
        $ret = @mysqli_close($this->connection);
364
        $this->connection = null;
364
        $this->connection = null;
365
        return $ret;
365
        return $ret;
366
    }
366
    }
367
367
368
    // }}}
368
    // }}}
369
    // {{{ simpleQuery()
369
    // {{{ simpleQuery()
370
370
371
    /**
371
    /**
372
     * Sends a query to the database server
372
     * Sends a query to the database server
373
     *
373
     *
374
     * @param string  the SQL query string
374
     * @param string  the SQL query string
375
     *
375
     *
376
     * @return mixed  + a PHP result resrouce for successful SELECT queries
376
     * @return mixed  + a PHP result resrouce for successful SELECT queries
377
     *                + the DB_OK constant for other successful queries
377
     *                + the DB_OK constant for other successful queries
378
     *                + a DB_Error object on failure
378
     *                + a DB_Error object on failure
379
     */
379
     */
380
    function simpleQuery($query)
380
    function simpleQuery($query)
381
    {
381
    {
382
        $ismanip = $this->_checkManip($query);
382
        $ismanip = $this->_checkManip($query);
383
        $this->last_query = $query;
383
        $this->last_query = $query;
384
        $query = $this->modifyQuery($query);
384
        $query = $this->modifyQuery($query);
385
        if ($this->_db) {
385
        if ($this->_db) {
386
            if (!@mysqli_select_db($this->connection, $this->_db)) {
386
            if (!@mysqli_select_db($this->connection, $this->_db)) {
387
                return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
387
                return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
388
            }
388
            }
389
        }
389
        }
390
        if (!$this->autocommit && $ismanip) {
390
        if (!$this->autocommit && $ismanip) {
391
            if ($this->transaction_opcount == 0) {
391
            if ($this->transaction_opcount == 0) {
392
                $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0');
392
                $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0');
393
                $result = @mysqli_query($this->connection, 'BEGIN');
393
                $result = @mysqli_query($this->connection, 'BEGIN');
394
                if (!$result) {
394
                if (!$result) {
395
                    return $this->mysqliRaiseError();
395
                    return $this->mysqliRaiseError();
396
                }
396
                }
397
            }
397
            }
398
            $this->transaction_opcount++;
398
            $this->transaction_opcount++;
399
        }
399
        }
400
        $result = @mysqli_query($this->connection, $query);
400
        $result = @mysqli_query($this->connection, $query);
401
        if (!$result) {
401
        if (!$result) {
402
            return $this->mysqliRaiseError();
402
            return $this->mysqliRaiseError();
403
        }
403
        }
404
        if (is_object($result)) {
404
        if (is_object($result)) {
405
            return $result;
405
            return $result;
406
        }
406
        }
407
        return DB_OK;
407
        return DB_OK;
408
    }
408
    }
409
409
410
    // }}}
410
    // }}}
411
    // {{{ nextResult()
411
    // {{{ nextResult()
412
412
413
    /**
413
    /**
414
     * Move the internal mysql result pointer to the next available result.
414
     * Move the internal mysql result pointer to the next available result.
415
     *
415
     *
416
     * This method has not been implemented yet.
416
     * This method has not been implemented yet.
417
     *
417
     *
418
     * @param resource $result a valid sql result resource
418
     * @param resource $result a valid sql result resource
419
     * @return false
419
     * @return false
420
     * @access public
420
     * @access public
421
     */
421
     */
422
    function nextResult($result)
422
    function nextResult($result)
423
    {
423
    {
424
        return false;
424
        return false;
425
    }
425
    }
426
426
427
    // }}}
427
    // }}}
428
    // {{{ fetchInto()
428
    // {{{ fetchInto()
429
429
430
    /**
430
    /**
431
     * Places a row from the result set into the given array
431
     * Places a row from the result set into the given array
432
     *
432
     *
433
     * Formating of the array and the data therein are configurable.
433
     * Formating of the array and the data therein are configurable.
434
     * See DB_result::fetchInto() for more information.
434
     * See DB_result::fetchInto() for more information.
435
     *
435
     *
436
     * This method is not meant to be called directly.  Use
436
     * This method is not meant to be called directly.  Use
437
     * DB_result::fetchInto() instead.  It can't be declared "protected"
437
     * DB_result::fetchInto() instead.  It can't be declared "protected"
438
     * because DB_result is a separate object.
438
     * because DB_result is a separate object.
439
     *
439
     *
440
     * @param resource $result    the query result resource
440
     * @param resource $result    the query result resource
441
     * @param array    $arr       the referenced array to put the data in
441
     * @param array    $arr       the referenced array to put the data in
442
     * @param int      $fetchmode how the resulting array should be indexed
442
     * @param int      $fetchmode how the resulting array should be indexed
443
     * @param int      $rownum    the row number to fetch (0 = first row)
443
     * @param int      $rownum    the row number to fetch (0 = first row)
444
     *
444
     *
445
     * @return mixed  DB_OK on success, NULL when the end of a result set is
445
     * @return mixed  DB_OK on success, NULL when the end of a result set is
446
     *                 reached or on failure
446
     *                 reached or on failure
447
     *
447
     *
448
     * @see DB_result::fetchInto()
448
     * @see DB_result::fetchInto()
449
     */
449
     */
450
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
450
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
451
    {
451
    {
452
        if ($rownum !== null) {
452
        if ($rownum !== null) {
453
            if (!@mysqli_data_seek($result, $rownum)) {
453
            if (!@mysqli_data_seek($result, $rownum)) {
454
                return null;
454
                return null;
455
            }
455
            }
456
        }
456
        }
457
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
457
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
458
            $arr = @mysqli_fetch_array($result, MYSQLI_ASSOC);
458
            $arr = @mysqli_fetch_array($result, MYSQLI_ASSOC);
459
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
459
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
460
                $arr = array_change_key_case($arr, CASE_LOWER);
460
                $arr = array_change_key_case($arr, CASE_LOWER);
461
            }
461
            }
462
        } else {
462
        } else {
463
            $arr = @mysqli_fetch_row($result);
463
            $arr = @mysqli_fetch_row($result);
464
        }
464
        }
465
        if (!$arr) {
465
        if (!$arr) {
466
            return null;
466
            return null;
467
        }
467
        }
468
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
468
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
469
            /*
469
            /*
470
             * Even though this DBMS already trims output, we do this because
470
             * Even though this DBMS already trims output, we do this because
471
             * a field might have intentional whitespace at the end that
471
             * a field might have intentional whitespace at the end that
472
             * gets removed by DB_PORTABILITY_RTRIM under another driver.
472
             * gets removed by DB_PORTABILITY_RTRIM under another driver.
473
             */
473
             */
474
            $this->_rtrimArrayValues($arr);
474
            $this->_rtrimArrayValues($arr);
475
        }
475
        }
476
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
476
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
477
            $this->_convertNullArrayValuesToEmpty($arr);
477
            $this->_convertNullArrayValuesToEmpty($arr);
478
        }
478
        }
479
        return DB_OK;
479
        return DB_OK;
480
    }
480
    }
481
481
482
    // }}}
482
    // }}}
483
    // {{{ freeResult()
483
    // {{{ freeResult()
484
484
485
    /**
485
    /**
486
     * Deletes the result set and frees the memory occupied by the result set
486
     * Deletes the result set and frees the memory occupied by the result set
487
     *
487
     *
488
     * This method is not meant to be called directly.  Use
488
     * This method is not meant to be called directly.  Use
489
     * DB_result::free() instead.  It can't be declared "protected"
489
     * DB_result::free() instead.  It can't be declared "protected"
490
     * because DB_result is a separate object.
490
     * because DB_result is a separate object.
491
     *
491
     *
492
     * @param resource $result  PHP's query result resource
492
     * @param resource $result  PHP's query result resource
493
     *
493
     *
494
     * @return bool  TRUE on success, FALSE if $result is invalid
494
     * @return bool  TRUE on success, FALSE if $result is invalid
495
     *
495
     *
496
     * @see DB_result::free()
496
     * @see DB_result::free()
497
     */
497
     */
498
    function freeResult($result)
498
    function freeResult($result)
499
    {
499
    {
500
        return is_resource($result) ? mysqli_free_result($result) : false;
500
        return is_resource($result) ? mysqli_free_result($result) : false;
501
    }
501
    }
502
502
503
    // }}}
503
    // }}}
504
    // {{{ numCols()
504
    // {{{ numCols()
505
505
506
    /**
506
    /**
507
     * Gets the number of columns in a result set
507
     * Gets the number of columns in a result set
508
     *
508
     *
509
     * This method is not meant to be called directly.  Use
509
     * This method is not meant to be called directly.  Use
510
     * DB_result::numCols() instead.  It can't be declared "protected"
510
     * DB_result::numCols() instead.  It can't be declared "protected"
511
     * because DB_result is a separate object.
511
     * because DB_result is a separate object.
512
     *
512
     *
513
     * @param resource $result  PHP's query result resource
513
     * @param resource $result  PHP's query result resource
514
     *
514
     *
515
     * @return int  the number of columns.  A DB_Error object on failure.
515
     * @return int  the number of columns.  A DB_Error object on failure.
516
     *
516
     *
517
     * @see DB_result::numCols()
517
     * @see DB_result::numCols()
518
     */
518
     */
519
    function numCols($result)
519
    function numCols($result)
520
    {
520
    {
521
        $cols = @mysqli_num_fields($result);
521
        $cols = @mysqli_num_fields($result);
522
        if (!$cols) {
522
        if (!$cols) {
523
            return $this->mysqliRaiseError();
523
            return $this->mysqliRaiseError();
524
        }
524
        }
525
        return $cols;
525
        return $cols;
526
    }
526
    }
527
527
528
    // }}}
528
    // }}}
529
    // {{{ numRows()
529
    // {{{ numRows()
530
530
531
    /**
531
    /**
532
     * Gets the number of rows in a result set
532
     * Gets the number of rows in a result set
533
     *
533
     *
534
     * This method is not meant to be called directly.  Use
534
     * This method is not meant to be called directly.  Use
535
     * DB_result::numRows() instead.  It can't be declared "protected"
535
     * DB_result::numRows() instead.  It can't be declared "protected"
536
     * because DB_result is a separate object.
536
     * because DB_result is a separate object.
537
     *
537
     *
538
     * @param resource $result  PHP's query result resource
538
     * @param resource $result  PHP's query result resource
539
     *
539
     *
540
     * @return int  the number of rows.  A DB_Error object on failure.
540
     * @return int  the number of rows.  A DB_Error object on failure.
541
     *
541
     *
542
     * @see DB_result::numRows()
542
     * @see DB_result::numRows()
543
     */
543
     */
544
    function numRows($result)
544
    function numRows($result)
545
    {
545
    {
546
        $rows = @mysqli_num_rows($result);
546
        $rows = @mysqli_num_rows($result);
547
        if ($rows === null) {
547
        if ($rows === null) {
548
            return $this->mysqliRaiseError();
548
            return $this->mysqliRaiseError();
549
        }
549
        }
550
        return $rows;
550
        return $rows;
551
    }
551
    }
552
552
553
    // }}}
553
    // }}}
554
    // {{{ autoCommit()
554
    // {{{ autoCommit()
555
555
556
    /**
556
    /**
557
     * Enables or disables automatic commits
557
     * Enables or disables automatic commits
558
     *
558
     *
559
     * @param bool $onoff  true turns it on, false turns it off
559
     * @param bool $onoff  true turns it on, false turns it off
560
     *
560
     *
561
     * @return int  DB_OK on success.  A DB_Error object if the driver
561
     * @return int  DB_OK on success.  A DB_Error object if the driver
562
     *               doesn't support auto-committing transactions.
562
     *               doesn't support auto-committing transactions.
563
     */
563
     */
564
    function autoCommit($onoff = false)
564
    function autoCommit($onoff = false)
565
    {
565
    {
566
        // XXX if $this->transaction_opcount > 0, we should probably
566
        // XXX if $this->transaction_opcount > 0, we should probably
567
        // issue a warning here.
567
        // issue a warning here.
568
        $this->autocommit = $onoff ? true : false;
568
        $this->autocommit = $onoff ? true : false;
569
        return DB_OK;
569
        return DB_OK;
570
    }
570
    }
571
571
572
    // }}}
572
    // }}}
573
    // {{{ commit()
573
    // {{{ commit()
574
574
575
    /**
575
    /**
576
     * Commits the current transaction
576
     * Commits the current transaction
577
     *
577
     *
578
     * @return int  DB_OK on success.  A DB_Error object on failure.
578
     * @return int  DB_OK on success.  A DB_Error object on failure.
579
     */
579
     */
580
    function commit()
580
    function commit()
581
    {
581
    {
582
        if ($this->transaction_opcount > 0) {
582
        if ($this->transaction_opcount > 0) {
583
            if ($this->_db) {
583
            if ($this->_db) {
584
                if (!@mysqli_select_db($this->connection, $this->_db)) {
584
                if (!@mysqli_select_db($this->connection, $this->_db)) {
585
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
585
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
586
                }
586
                }
587
            }
587
            }
588
            $result = @mysqli_query($this->connection, 'COMMIT');
588
            $result = @mysqli_query($this->connection, 'COMMIT');
589
            $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1');
589
            $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1');
590
            $this->transaction_opcount = 0;
590
            $this->transaction_opcount = 0;
591
            if (!$result) {
591
            if (!$result) {
592
                return $this->mysqliRaiseError();
592
                return $this->mysqliRaiseError();
593
            }
593
            }
594
        }
594
        }
595
        return DB_OK;
595
        return DB_OK;
596
    }
596
    }
597
597
598
    // }}}
598
    // }}}
599
    // {{{ rollback()
599
    // {{{ rollback()
600
600
601
    /**
601
    /**
602
     * Reverts the current transaction
602
     * Reverts the current transaction
603
     *
603
     *
604
     * @return int  DB_OK on success.  A DB_Error object on failure.
604
     * @return int  DB_OK on success.  A DB_Error object on failure.
605
     */
605
     */
606
    function rollback()
606
    function rollback()
607
    {
607
    {
608
        if ($this->transaction_opcount > 0) {
608
        if ($this->transaction_opcount > 0) {
609
            if ($this->_db) {
609
            if ($this->_db) {
610
                if (!@mysqli_select_db($this->connection, $this->_db)) {
610
                if (!@mysqli_select_db($this->connection, $this->_db)) {
611
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
611
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
612
                }
612
                }
613
            }
613
            }
614
            $result = @mysqli_query($this->connection, 'ROLLBACK');
614
            $result = @mysqli_query($this->connection, 'ROLLBACK');
615
            $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1');
615
            $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1');
616
            $this->transaction_opcount = 0;
616
            $this->transaction_opcount = 0;
617
            if (!$result) {
617
            if (!$result) {
618
                return $this->mysqliRaiseError();
618
                return $this->mysqliRaiseError();
619
            }
619
            }
620
        }
620
        }
621
        return DB_OK;
621
        return DB_OK;
622
    }
622
    }
623
623
624
    // }}}
624
    // }}}
625
    // {{{ affectedRows()
625
    // {{{ affectedRows()
626
626
627
    /**
627
    /**
628
     * Determines the number of rows affected by a data maniuplation query
628
     * Determines the number of rows affected by a data maniuplation query
629
     *
629
     *
630
     * 0 is returned for queries that don't manipulate data.
630
     * 0 is returned for queries that don't manipulate data.
631
     *
631
     *
632
     * @return int  the number of rows.  A DB_Error object on failure.
632
     * @return int  the number of rows.  A DB_Error object on failure.
633
     */
633
     */
634
    function affectedRows()
634
    function affectedRows()
635
    {
635
    {
636
        if ($this->_last_query_manip) {
636
        if ($this->_last_query_manip) {
637
            return @mysqli_affected_rows($this->connection);
637
            return @mysqli_affected_rows($this->connection);
638
        } else {
638
        } else {
639
            return 0;
639
            return 0;
640
        }
640
        }
641
     }
641
     }
642
642
643
    // }}}
643
    // }}}
644
    // {{{ nextId()
644
    // {{{ nextId()
645
645
646
    /**
646
    /**
647
     * Returns the next free id in a sequence
647
     * Returns the next free id in a sequence
648
     *
648
     *
649
     * @param string  $seq_name  name of the sequence
649
     * @param string  $seq_name  name of the sequence
650
     * @param boolean $ondemand  when true, the seqence is automatically
650
     * @param boolean $ondemand  when true, the seqence is automatically
651
     *                            created if it does not exist
651
     *                            created if it does not exist
652
     *
652
     *
653
     * @return int  the next id number in the sequence.
653
     * @return int  the next id number in the sequence.
654
     *               A DB_Error object on failure.
654
     *               A DB_Error object on failure.
655
     *
655
     *
656
     * @see DB_common::nextID(), DB_common::getSequenceName(),
656
     * @see DB_common::nextID(), DB_common::getSequenceName(),
657
     *      DB_mysqli::createSequence(), DB_mysqli::dropSequence()
657
     *      DB_mysqli::createSequence(), DB_mysqli::dropSequence()
658
     */
658
     */
659
    function nextId($seq_name, $ondemand = true)
659
    function nextId($seq_name, $ondemand = true)
660
    {
660
    {
661
        $seqname = $this->getSequenceName($seq_name);
661
        $seqname = $this->getSequenceName($seq_name);
662
        do {
662
        do {
663
            $repeat = 0;
663
            $repeat = 0;
664
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
664
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
665
            $result = $this->query('UPDATE ' . $seqname
665
            $result = $this->query('UPDATE ' . $seqname
666
                                   . ' SET id = LAST_INSERT_ID(id + 1)');
666
                                   . ' SET id = LAST_INSERT_ID(id + 1)');
667
            $this->popErrorHandling();
667
            $this->popErrorHandling();
668
            if ($result === DB_OK) {
668
            if ($result === DB_OK) {
669
                // COMMON CASE
669
                // COMMON CASE
670
                $id = @mysqli_insert_id($this->connection);
670
                $id = @mysqli_insert_id($this->connection);
671
                if ($id != 0) {
671
                if ($id != 0) {
672
                    return $id;
672
                    return $id;
673
                }
673
                }
674
674
675
                // EMPTY SEQ TABLE
675
                // EMPTY SEQ TABLE
676
                // Sequence table must be empty for some reason,
676
                // Sequence table must be empty for some reason,
677
                // so fill it and return 1
677
                // so fill it and return 1
678
                // Obtain a user-level lock
678
                // Obtain a user-level lock
679
                $result = $this->getOne('SELECT GET_LOCK('
679
                $result = $this->getOne('SELECT GET_LOCK('
680
                                        . "'${seqname}_lock', 10)");
680
                                        . "'${seqname}_lock', 10)");
681
                if (DB::isError($result)) {
681
                if (DB::isError($result)) {
682
                    return $this->raiseError($result);
682
                    return $this->raiseError($result);
683
                }
683
                }
684
                if ($result == 0) {
684
                if ($result == 0) {
685
                    return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED);
685
                    return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED);
686
                }
686
                }
687
687
688
                // add the default value
688
                // add the default value
689
                $result = $this->query('REPLACE INTO ' . $seqname
689
                $result = $this->query('REPLACE INTO ' . $seqname
690
                                       . ' (id) VALUES (0)');
690
                                       . ' (id) VALUES (0)');
691
                if (DB::isError($result)) {
691
                if (DB::isError($result)) {
692
                    return $this->raiseError($result);
692
                    return $this->raiseError($result);
693
                }
693
                }
694
694
695
                // Release the lock
695
                // Release the lock
696
                $result = $this->getOne('SELECT RELEASE_LOCK('
696
                $result = $this->getOne('SELECT RELEASE_LOCK('
697
                                        . "'${seqname}_lock')");
697
                                        . "'${seqname}_lock')");
698
                if (DB::isError($result)) {
698
                if (DB::isError($result)) {
699
                    return $this->raiseError($result);
699
                    return $this->raiseError($result);
700
                }
700
                }
701
                // We know what the result will be, so no need to try again
701
                // We know what the result will be, so no need to try again
702
                return 1;
702
                return 1;
703
703
704
            } elseif ($ondemand && DB::isError($result) &&
704
            } elseif ($ondemand && DB::isError($result) &&
705
                $result->getCode() == DB_ERROR_NOSUCHTABLE)
705
                $result->getCode() == DB_ERROR_NOSUCHTABLE)
706
            {
706
            {
707
                // ONDEMAND TABLE CREATION
707
                // ONDEMAND TABLE CREATION
708
                $result = $this->createSequence($seq_name);
708
                $result = $this->createSequence($seq_name);
709
709
710
                // Since createSequence initializes the ID to be 1,
710
                // Since createSequence initializes the ID to be 1,
711
                // we do not need to retrieve the ID again (or we will get 2)
711
                // we do not need to retrieve the ID again (or we will get 2)
712
                if (DB::isError($result)) {
712
                if (DB::isError($result)) {
713
                    return $this->raiseError($result);
713
                    return $this->raiseError($result);
714
                } else {
714
                } else {
715
                    // First ID of a newly created sequence is 1
715
                    // First ID of a newly created sequence is 1
716
                    return 1;
716
                    return 1;
717
                }
717
                }
718
718
719
            } elseif (DB::isError($result) &&
719
            } elseif (DB::isError($result) &&
720
                      $result->getCode() == DB_ERROR_ALREADY_EXISTS)
720
                      $result->getCode() == DB_ERROR_ALREADY_EXISTS)
721
            {
721
            {
722
                // BACKWARDS COMPAT
722
                // BACKWARDS COMPAT
723
                // see _BCsequence() comment
723
                // see _BCsequence() comment
724
                $result = $this->_BCsequence($seqname);
724
                $result = $this->_BCsequence($seqname);
725
                if (DB::isError($result)) {
725
                if (DB::isError($result)) {
726
                    return $this->raiseError($result);
726
                    return $this->raiseError($result);
727
                }
727
                }
728
                $repeat = 1;
728
                $repeat = 1;
729
            }
729
            }
730
        } while ($repeat);
730
        } while ($repeat);
731
731
732
        return $this->raiseError($result);
732
        return $this->raiseError($result);
733
    }
733
    }
734
734
735
    /**
735
    /**
736
     * Creates a new sequence
736
     * Creates a new sequence
737
     *
737
     *
738
     * @param string $seq_name  name of the new sequence
738
     * @param string $seq_name  name of the new sequence
739
     *
739
     *
740
     * @return int  DB_OK on success.  A DB_Error object on failure.
740
     * @return int  DB_OK on success.  A DB_Error object on failure.
741
     *
741
     *
742
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
742
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
743
     *      DB_mysqli::nextID(), DB_mysqli::dropSequence()
743
     *      DB_mysqli::nextID(), DB_mysqli::dropSequence()
744
     */
744
     */
745
    function createSequence($seq_name)
745
    function createSequence($seq_name)
746
    {
746
    {
747
        $seqname = $this->getSequenceName($seq_name);
747
        $seqname = $this->getSequenceName($seq_name);
748
        $res = $this->query('CREATE TABLE ' . $seqname
748
        $res = $this->query('CREATE TABLE ' . $seqname
749
                            . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'
749
                            . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'
750
                            . ' PRIMARY KEY(id))');
750
                            . ' PRIMARY KEY(id))');
751
        if (DB::isError($res)) {
751
        if (DB::isError($res)) {
752
            return $res;
752
            return $res;
753
        }
753
        }
754
        // insert yields value 1, nextId call will generate ID 2
754
        // insert yields value 1, nextId call will generate ID 2
755
        return $this->query("INSERT INTO ${seqname} (id) VALUES (0)");
755
        return $this->query("INSERT INTO ${seqname} (id) VALUES (0)");
756
    }
756
    }
757
757
758
    // }}}
758
    // }}}
759
    // {{{ dropSequence()
759
    // {{{ dropSequence()
760
760
761
    /**
761
    /**
762
     * Deletes a sequence
762
     * Deletes a sequence
763
     *
763
     *
764
     * @param string $seq_name  name of the sequence to be deleted
764
     * @param string $seq_name  name of the sequence to be deleted
765
     *
765
     *
766
     * @return int  DB_OK on success.  A DB_Error object on failure.
766
     * @return int  DB_OK on success.  A DB_Error object on failure.
767
     *
767
     *
768
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
768
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
769
     *      DB_mysql::nextID(), DB_mysql::createSequence()
769
     *      DB_mysql::nextID(), DB_mysql::createSequence()
770
     */
770
     */
771
    function dropSequence($seq_name)
771
    function dropSequence($seq_name)
772
    {
772
    {
773
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
773
        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
774
    }
774
    }
775
775
776
    // }}}
776
    // }}}
777
    // {{{ _BCsequence()
777
    // {{{ _BCsequence()
778
778
779
    /**
779
    /**
780
     * Backwards compatibility with old sequence emulation implementation
780
     * Backwards compatibility with old sequence emulation implementation
781
     * (clean up the dupes)
781
     * (clean up the dupes)
782
     *
782
     *
783
     * @param string $seqname  the sequence name to clean up
783
     * @param string $seqname  the sequence name to clean up
784
     *
784
     *
785
     * @return bool  true on success.  A DB_Error object on failure.
785
     * @return bool  true on success.  A DB_Error object on failure.
786
     *
786
     *
787
     * @access private
787
     * @access private
788
     */
788
     */
789
    function _BCsequence($seqname)
789
    function _BCsequence($seqname)
790
    {
790
    {
791
        // Obtain a user-level lock... this will release any previous
791
        // Obtain a user-level lock... this will release any previous
792
        // application locks, but unlike LOCK TABLES, it does not abort
792
        // application locks, but unlike LOCK TABLES, it does not abort
793
        // the current transaction and is much less frequently used.
793
        // the current transaction and is much less frequently used.
794
        $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
794
        $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
795
        if (DB::isError($result)) {
795
        if (DB::isError($result)) {
796
            return $result;
796
            return $result;
797
        }
797
        }
798
        if ($result == 0) {
798
        if ($result == 0) {
799
            // Failed to get the lock, can't do the conversion, bail
799
            // Failed to get the lock, can't do the conversion, bail
800
            // with a DB_ERROR_NOT_LOCKED error
800
            // with a DB_ERROR_NOT_LOCKED error
801
            return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED);
801
            return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED);
802
        }
802
        }
803
803
804
        $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
804
        $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
805
        if (DB::isError($highest_id)) {
805
        if (DB::isError($highest_id)) {
806
            return $highest_id;
806
            return $highest_id;
807
        }
807
        }
808
808
809
        // This should kill all rows except the highest
809
        // This should kill all rows except the highest
810
        // We should probably do something if $highest_id isn't
810
        // We should probably do something if $highest_id isn't
811
        // numeric, but I'm at a loss as how to handle that...
811
        // numeric, but I'm at a loss as how to handle that...
812
        $result = $this->query('DELETE FROM ' . $seqname
812
        $result = $this->query('DELETE FROM ' . $seqname
813
                               . " WHERE id <> $highest_id");
813
                               . " WHERE id <> $highest_id");
814
        if (DB::isError($result)) {
814
        if (DB::isError($result)) {
815
            return $result;
815
            return $result;
816
        }
816
        }
817
817
818
        // If another thread has been waiting for this lock,
818
        // If another thread has been waiting for this lock,
819
        // it will go thru the above procedure, but will have no
819
        // it will go thru the above procedure, but will have no
820
        // real effect
820
        // real effect
821
        $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
821
        $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
822
        if (DB::isError($result)) {
822
        if (DB::isError($result)) {
823
            return $result;
823
            return $result;
824
        }
824
        }
825
        return true;
825
        return true;
826
    }
826
    }
827
827
828
    // }}}
828
    // }}}
829
    // {{{ quoteIdentifier()
829
    // {{{ quoteIdentifier()
830
830
831
    /**
831
    /**
832
     * Quotes a string so it can be safely used as a table or column name
832
     * Quotes a string so it can be safely used as a table or column name
833
     * (WARNING: using names that require this is a REALLY BAD IDEA)
833
     * (WARNING: using names that require this is a REALLY BAD IDEA)
834
     *
834
     *
835
     * WARNING:  Older versions of MySQL can't handle the backtick
835
     * WARNING:  Older versions of MySQL can't handle the backtick
836
     * character (<kbd>`</kbd>) in table or column names.
836
     * character (<kbd>`</kbd>) in table or column names.
837
     *
837
     *
838
     * @param string $str  identifier name to be quoted
838
     * @param string $str  identifier name to be quoted
839
     *
839
     *
840
     * @return string  quoted identifier string
840
     * @return string  quoted identifier string
841
     *
841
     *
842
     * @see DB_common::quoteIdentifier()
842
     * @see DB_common::quoteIdentifier()
843
     * @since Method available since Release 1.6.0
843
     * @since Method available since Release 1.6.0
844
     */
844
     */
845
    function quoteIdentifier($str)
845
    function quoteIdentifier($str)
846
    {
846
    {
847
        return '`' . str_replace('`', '``', $str) . '`';
847
        return '`' . str_replace('`', '``', $str) . '`';
848
    }
848
    }
849
849
850
    // }}}
850
    // }}}
851
    // {{{ escapeSimple()
851
    // {{{ escapeSimple()
852
852
853
    /**
853
    /**
854
     * Escapes a string according to the current DBMS's standards
854
     * Escapes a string according to the current DBMS's standards
855
     *
855
     *
856
     * @param string $str  the string to be escaped
856
     * @param string $str  the string to be escaped
857
     *
857
     *
858
     * @return string  the escaped string
858
     * @return string  the escaped string
859
     *
859
     *
860
     * @see DB_common::quoteSmart()
860
     * @see DB_common::quoteSmart()
861
     * @since Method available since Release 1.6.0
861
     * @since Method available since Release 1.6.0
862
     */
862
     */
863
    function escapeSimple($str)
863
    function escapeSimple($str)
864
    {
864
    {
865
        return @mysqli_real_escape_string($this->connection, $str);
865
        return @mysqli_real_escape_string($this->connection, $str);
866
    }
866
    }
867
867
868
    // }}}
868
    // }}}
869
    // {{{ modifyLimitQuery()
869
    // {{{ modifyLimitQuery()
870
870
871
    /**
871
    /**
872
     * Adds LIMIT clauses to a query string according to current DBMS standards
872
     * Adds LIMIT clauses to a query string according to current DBMS standards
873
     *
873
     *
874
     * @param string $query   the query to modify
874
     * @param string $query   the query to modify
875
     * @param int    $from    the row to start to fetching (0 = the first row)
875
     * @param int    $from    the row to start to fetching (0 = the first row)
876
     * @param int    $count   the numbers of rows to fetch
876
     * @param int    $count   the numbers of rows to fetch
877
     * @param mixed  $params  array, string or numeric data to be used in
877
     * @param mixed  $params  array, string or numeric data to be used in
878
     *                         execution of the statement.  Quantity of items
878
     *                         execution of the statement.  Quantity of items
879
     *                         passed must match quantity of placeholders in
879
     *                         passed must match quantity of placeholders in
880
     *                         query:  meaning 1 placeholder for non-array
880
     *                         query:  meaning 1 placeholder for non-array
881
     *                         parameters or 1 placeholder per array element.
881
     *                         parameters or 1 placeholder per array element.
882
     *
882
     *
883
     * @return string  the query string with LIMIT clauses added
883
     * @return string  the query string with LIMIT clauses added
884
     *
884
     *
885
     * @access protected
885
     * @access protected
886
     */
886
     */
887
    function modifyLimitQuery($query, $from, $count, $params = array())
887
    function modifyLimitQuery($query, $from, $count, $params = array())
888
    {
888
    {
889
        if (DB::isManip($query) || $this->_next_query_manip) {
889
        if (DB::isManip($query) || $this->_next_query_manip) {
890
            return $query . " LIMIT $count";
890
            return $query . " LIMIT $count";
891
        } else {
891
        } else {
892
            return $query . " LIMIT $from, $count";
892
            return $query . " LIMIT $from, $count";
893
        }
893
        }
894
    }
894
    }
895
895
896
    // }}}
896
    // }}}
897
    // {{{ mysqliRaiseError()
897
    // {{{ mysqliRaiseError()
898
898
899
    /**
899
    /**
900
     * Produces a DB_Error object regarding the current problem
900
     * Produces a DB_Error object regarding the current problem
901
     *
901
     *
902
     * @param int $errno  if the error is being manually raised pass a
902
     * @param int $errno  if the error is being manually raised pass a
903
     *                     DB_ERROR* constant here.  If this isn't passed
903
     *                     DB_ERROR* constant here.  If this isn't passed
904
     *                     the error information gathered from the DBMS.
904
     *                     the error information gathered from the DBMS.
905
     *
905
     *
906
     * @return object  the DB_Error object
906
     * @return object  the DB_Error object
907
     *
907
     *
908
     * @see DB_common::raiseError(),
908
     * @see DB_common::raiseError(),
909
     *      DB_mysqli::errorNative(), DB_common::errorCode()
909
     *      DB_mysqli::errorNative(), DB_common::errorCode()
910
     */
910
     */
911
    function mysqliRaiseError($errno = null)
911
    function mysqliRaiseError($errno = null)
912
    {
912
    {
913
        if ($errno === null) {
913
        if ($errno === null) {
914
            if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
914
            if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
915
                $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT;
915
                $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT;
916
                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL;
916
                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL;
917
                $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT;
917
                $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT;
918
            } else {
918
            } else {
919
                // Doing this in case mode changes during runtime.
919
                // Doing this in case mode changes during runtime.
920
                $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS;
920
                $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS;
921
                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT;
921
                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT;
922
                $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS;
922
                $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS;
923
            }
923
            }
924
            $errno = $this->errorCode(mysqli_errno($this->connection));
924
            $errno = $this->errorCode(mysqli_errno($this->connection));
925
        }
925
        }
926
        return $this->raiseError($errno, null, null, null,
926
        return $this->raiseError($errno, null, null, null,
927
                                 @mysqli_errno($this->connection) . ' ** ' .
927
                                 @mysqli_errno($this->connection) . ' ** ' .
928
                                 @mysqli_error($this->connection));
928
                                 @mysqli_error($this->connection));
929
    }
929
    }
930
930
931
    // }}}
931
    // }}}
932
    // {{{ errorNative()
932
    // {{{ errorNative()
933
933
934
    /**
934
    /**
935
     * Gets the DBMS' native error code produced by the last query
935
     * Gets the DBMS' native error code produced by the last query
936
     *
936
     *
937
     * @return int  the DBMS' error code
937
     * @return int  the DBMS' error code
938
     */
938
     */
939
    function errorNative()
939
    function errorNative()
940
    {
940
    {
941
        return @mysqli_errno($this->connection);
941
        return @mysqli_errno($this->connection);
942
    }
942
    }
943
943
944
    // }}}
944
    // }}}
945
    // {{{ tableInfo()
945
    // {{{ tableInfo()
946
946
947
    /**
947
    /**
948
     * Returns information about a table or a result set
948
     * Returns information about a table or a result set
949
     *
949
     *
950
     * @param object|string  $result  DB_result object from a query or a
950
     * @param object|string  $result  DB_result object from a query or a
951
     *                                 string containing the name of a table.
951
     *                                 string containing the name of a table.
952
     *                                 While this also accepts a query result
952
     *                                 While this also accepts a query result
953
     *                                 resource identifier, this behavior is
953
     *                                 resource identifier, this behavior is
954
     *                                 deprecated.
954
     *                                 deprecated.
955
     * @param int            $mode    a valid tableInfo mode
955
     * @param int            $mode    a valid tableInfo mode
956
     *
956
     *
957
     * @return array  an associative array with the information requested.
957
     * @return array  an associative array with the information requested.
958
     *                 A DB_Error object on failure.
958
     *                 A DB_Error object on failure.
959
     *
959
     *
960
     * @see DB_common::setOption()
960
     * @see DB_common::setOption()
961
     */
961
     */
962
    function tableInfo($result, $mode = null)
962
    function tableInfo($result, $mode = null)
963
    {
963
    {
964
        if (is_string($result)) {
964
        if (is_string($result)) {
965
            // Fix for bug #11580.
965
            // Fix for bug #11580.
966
            if ($this->_db) {
966
            if ($this->_db) {
967
                if (!@mysqli_select_db($this->connection, $this->_db)) {
967
                if (!@mysqli_select_db($this->connection, $this->_db)) {
968
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
968
                    return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED);
969
                }
969
                }
970
            }
970
            }
971
971
972
            /*
972
            /*
973
             * Probably received a table name.
973
             * Probably received a table name.
974
             * Create a result resource identifier.
974
             * Create a result resource identifier.
975
             */
975
             */
976
            $id = @mysqli_query($this->connection,
976
            $id = @mysqli_query($this->connection,
977
                                "SELECT * FROM $result LIMIT 0");
977
                                "SELECT * FROM $result LIMIT 0");
978
            $got_string = true;
978
            $got_string = true;
979
        } elseif (isset($result->result)) {
979
        } elseif (isset($result->result)) {
980
            /*
980
            /*
981
             * Probably received a result object.
981
             * Probably received a result object.
982
             * Extract the result resource identifier.
982
             * Extract the result resource identifier.
983
             */
983
             */
984
            $id = $result->result;
984
            $id = $result->result;
985
            $got_string = false;
985
            $got_string = false;
986
        } else {
986
        } else {
987
            /*
987
            /*
988
             * Probably received a result resource identifier.
988
             * Probably received a result resource identifier.
989
             * Copy it.
989
             * Copy it.
990
             * Deprecated.  Here for compatibility only.
990
             * Deprecated.  Here for compatibility only.
991
             */
991
             */
992
            $id = $result;
992
            $id = $result;
993
            $got_string = false;
993
            $got_string = false;
994
        }
994
        }
995
995
996
        if (!is_a($id, 'mysqli_result')) {
996
        if (!is_a($id, 'mysqli_result')) {
997
            return $this->mysqliRaiseError(DB_ERROR_NEED_MORE_DATA);
997
            return $this->mysqliRaiseError(DB_ERROR_NEED_MORE_DATA);
998
        }
998
        }
999
999
1000
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
1000
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
1001
            $case_func = 'strtolower';
1001
            $case_func = 'strtolower';
1002
        } else {
1002
        } else {
1003
            $case_func = 'strval';
1003
            $case_func = 'strval';
1004
        }
1004
        }
1005
1005
1006
        $count = @mysqli_num_fields($id);
1006
        $count = @mysqli_num_fields($id);
1007
        $res   = array();
1007
        $res   = array();
1008
1008
1009
        if ($mode) {
1009
        if ($mode) {
1010
            $res['num_fields'] = $count;
1010
            $res['num_fields'] = $count;
1011
        }
1011
        }
1012
1012
1013
        for ($i = 0; $i < $count; $i++) {
1013
        for ($i = 0; $i < $count; $i++) {
1014
            $tmp = @mysqli_fetch_field($id);
1014
            $tmp = @mysqli_fetch_field($id);
1015
1015
1016
            $flags = '';
1016
            $flags = '';
1017
            foreach ($this->mysqli_flags as $const => $means) {
1017
            foreach ($this->mysqli_flags as $const => $means) {
1018
                if ($tmp->flags & $const) {
1018
                if ($tmp->flags & $const) {
1019
                    $flags .= $means . ' ';
1019
                    $flags .= $means . ' ';
1020
                }
1020
                }
1021
            }
1021
            }
1022
            if ($tmp->def) {
1022
            if ($tmp->def) {
1023
                $flags .= 'default_' . rawurlencode($tmp->def);
1023
                $flags .= 'default_' . rawurlencode($tmp->def);
1024
            }
1024
            }
1025
            $flags = trim($flags);
1025
            $flags = trim($flags);
1026
1026
1027
            $res[$i] = array(
1027
            $res[$i] = array(
1028
                'table' => $case_func($tmp->table),
1028
                'table' => $case_func($tmp->table),
1029
                'name'  => $case_func($tmp->name),
1029
                'name'  => $case_func($tmp->name),
1030
                'type'  => isset($this->mysqli_types[$tmp->type])
1030
                'type'  => isset($this->mysqli_types[$tmp->type])
1031
                                    ? $this->mysqli_types[$tmp->type]
1031
                                    ? $this->mysqli_types[$tmp->type]
1032
                                    : 'unknown',
1032
                                    : 'unknown',
1033
                // http://bugs.php.net/?id=36579
1033
                // http://bugs.php.net/?id=36579
1034
                'len'   => $tmp->length,
1034
                'len'   => $tmp->length,
1035
                'flags' => $flags,
1035
                'flags' => $flags,
1036
            );
1036
            );
1037
1037
1038
            if ($mode & DB_TABLEINFO_ORDER) {
1038
            if ($mode & DB_TABLEINFO_ORDER) {
1039
                $res['order'][$res[$i]['name']] = $i;
1039
                $res['order'][$res[$i]['name']] = $i;
1040
            }
1040
            }
1041
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
1041
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
1042
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1042
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1043
            }
1043
            }
1044
        }
1044
        }
1045
1045
1046
        // free the result only if we were called on a table
1046
        // free the result only if we were called on a table
1047
        if ($got_string) {
1047
        if ($got_string) {
1048
            @mysqli_free_result($id);
1048
            @mysqli_free_result($id);
1049
        }
1049
        }
1050
        return $res;
1050
        return $res;
1051
    }
1051
    }
1052
1052
1053
    // }}}
1053
    // }}}
1054
    // {{{ getSpecialQuery()
1054
    // {{{ getSpecialQuery()
1055
1055
1056
    /**
1056
    /**
1057
     * Obtains the query string needed for listing a given type of objects
1057
     * Obtains the query string needed for listing a given type of objects
1058
     *
1058
     *
1059
     * @param string $type  the kind of objects you want to retrieve
1059
     * @param string $type  the kind of objects you want to retrieve
1060
     *
1060
     *
1061
     * @return string  the SQL query string or null if the driver doesn't
1061
     * @return string  the SQL query string or null if the driver doesn't
1062
     *                  support the object type requested
1062
     *                  support the object type requested
1063
     *
1063
     *
1064
     * @access protected
1064
     * @access protected
1065
     * @see DB_common::getListOf()
1065
     * @see DB_common::getListOf()
1066
     */
1066
     */
1067
    function getSpecialQuery($type)
1067
    function getSpecialQuery($type)
1068
    {
1068
    {
1069
        switch ($type) {
1069
        switch ($type) {
1070
            case 'tables':
1070
            case 'tables':
1071
                return 'SHOW TABLES';
1071
                return 'SHOW TABLES';
1072
            case 'users':
1072
            case 'users':
1073
                return 'SELECT DISTINCT User FROM mysql.user';
1073
                return 'SELECT DISTINCT User FROM mysql.user';
1074
            case 'databases':
1074
            case 'databases':
1075
                return 'SHOW DATABASES';
1075
                return 'SHOW DATABASES';
1076
            default:
1076
            default:
1077
                return null;
1077
                return null;
1078
        }
1078
        }
1079
    }
1079
    }
1080
1080
1081
    // }}}
1081
    // }}}
1082
1082
1083
}
1083
}
1084
1084
1085
/*
1085
/*
1086
 * Local variables:
1086
 * Local variables:
1087
 * tab-width: 4
1087
 * tab-width: 4
1088
 * c-basic-offset: 4
1088
 * c-basic-offset: 4
1089
 * End:
1089
 * End:
1090
 */
1090
 */
1091
1091
1092
?>
1092
?>
1093
 
1093