Subversion Repositories Applications.gtt

Rev

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

Rev 94 Rev 187
1
<?php
1
<?php
2
 
2
 
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
 
4
 
5
/**
5
/**
6
 * The PEAR DB driver for PHP's pgsql extension
6
 * The PEAR DB driver for PHP's pgsql extension
7
 * for interacting with PostgreSQL databases
7
 * for interacting with PostgreSQL databases
8
 *
8
 *
9
 * PHP versions 4 and 5
9
 * PHP version 5
10
 *
10
 *
11
 * LICENSE: This source file is subject to version 3.0 of the PHP license
11
 * LICENSE: This source file is subject to version 3.0 of the PHP license
12
 * that is available through the world-wide-web at the following URI:
12
 * that is available through the world-wide-web at the following URI:
13
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
13
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
14
 * the PHP License and are unable to obtain it through the web, please
14
 * the PHP License and are unable to obtain it through the web, please
15
 * send a note to license@php.net so we can mail you a copy immediately.
15
 * send a note to license@php.net so we can mail you a copy immediately.
16
 *
16
 *
17
 * @category   Database
17
 * @category   Database
18
 * @package    DB
18
 * @package    DB
19
 * @author     Rui Hirokawa <hirokawa@php.net>
19
 * @author     Rui Hirokawa <hirokawa@php.net>
20
 * @author     Stig Bakken <ssb@php.net>
20
 * @author     Stig Bakken <ssb@php.net>
21
 * @author     Daniel Convissor <danielc@php.net>
21
 * @author     Daniel Convissor <danielc@php.net>
22
 * @copyright  1997-2005 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: pgsql.php,v 1.126 2005/03/04 23:12:36 danielc Exp $
24
 * @version    CVS: $Id$
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 pgsql extension
34
 * The methods PEAR DB uses to interact with PHP's pgsql extension
35
 * for interacting with PostgreSQL databases
35
 * for interacting with PostgreSQL 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
 * @category   Database
39
 * @category   Database
40
 * @package    DB
40
 * @package    DB
41
 * @author     Rui Hirokawa <hirokawa@php.net>
41
 * @author     Rui Hirokawa <hirokawa@php.net>
42
 * @author     Stig Bakken <ssb@php.net>
42
 * @author     Stig Bakken <ssb@php.net>
43
 * @author     Daniel Convissor <danielc@php.net>
43
 * @author     Daniel Convissor <danielc@php.net>
44
 * @copyright  1997-2005 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.6
46
 * @version    Release: 1.9.2
47
 * @link       http://pear.php.net/package/DB
47
 * @link       http://pear.php.net/package/DB
48
 */
48
 */
49
class DB_pgsql extends DB_common
49
class DB_pgsql extends DB_common
50
{
50
{
51
    // {{{ properties
51
    // {{{ properties
52
 
52
 
53
    /**
53
    /**
54
     * The DB driver type (mysql, oci8, odbc, etc.)
54
     * The DB driver type (mysql, oci8, odbc, etc.)
55
     * @var string
55
     * @var string
56
     */
56
     */
57
    var $phptype = 'pgsql';
57
    var $phptype = 'pgsql';
58
 
58
 
59
    /**
59
    /**
60
     * The database syntax variant to be used (db2, access, etc.), if any
60
     * The database syntax variant to be used (db2, access, etc.), if any
61
     * @var string
61
     * @var string
62
     */
62
     */
63
    var $dbsyntax = 'pgsql';
63
    var $dbsyntax = 'pgsql';
64
 
64
 
65
    /**
65
    /**
66
     * The capabilities of this DB implementation
66
     * The capabilities of this DB implementation
67
     *
67
     *
68
     * The 'new_link' element contains the PHP version that first provided
68
     * The 'new_link' element contains the PHP version that first provided
69
     * new_link support for this DBMS.  Contains false if it's unsupported.
69
     * new_link support for this DBMS.  Contains false if it's unsupported.
70
     *
70
     *
71
     * Meaning of the 'limit' element:
71
     * Meaning of the 'limit' element:
72
     *   + 'emulate' = emulate with fetch row by number
72
     *   + 'emulate' = emulate with fetch row by number
73
     *   + 'alter'   = alter the query
73
     *   + 'alter'   = alter the query
74
     *   + false     = skip rows
74
     *   + false     = skip rows
75
     *
75
     *
76
     * @var array
76
     * @var array
77
     */
77
     */
78
    var $features = array(
78
    var $features = array(
79
        'limit'         => 'alter',
79
        'limit'         => 'alter',
80
        'new_link'      => '4.3.0',
80
        'new_link'      => '4.3.0',
81
        'numrows'       => true,
81
        'numrows'       => true,
82
        'pconnect'      => true,
82
        'pconnect'      => true,
83
        'prepare'       => false,
83
        'prepare'       => false,
84
        'ssl'           => true,
84
        'ssl'           => true,
85
        'transactions'  => true,
85
        'transactions'  => true,
86
    );
86
    );
87
 
87
 
88
    /**
88
    /**
89
     * A mapping of native error codes to DB error codes
89
     * A mapping of native error codes to DB error codes
90
     * @var array
90
     * @var array
91
     */
91
     */
92
    var $errorcode_map = array(
92
    var $errorcode_map = array(
93
    );
93
    );
94
 
94
 
95
    /**
95
    /**
96
     * The raw database connection created by PHP
96
     * The raw database connection created by PHP
97
     * @var resource
97
     * @var resource
98
     */
98
     */
99
    var $connection;
99
    var $connection;
100
 
100
 
101
    /**
101
    /**
102
     * The DSN information for connecting to a database
102
     * The DSN information for connecting to a database
103
     * @var array
103
     * @var array
104
     */
104
     */
105
    var $dsn = array();
105
    var $dsn = array();
106
 
106
 
107
 
107
 
108
    /**
108
    /**
109
     * Should data manipulation queries be committed automatically?
109
     * Should data manipulation queries be committed automatically?
110
     * @var bool
110
     * @var bool
111
     * @access private
111
     * @access private
112
     */
112
     */
113
    var $autocommit = true;
113
    var $autocommit = true;
114
 
114
 
115
    /**
115
    /**
116
     * The quantity of transactions begun
116
     * The quantity of transactions begun
117
     *
117
     *
118
     * {@internal  While this is private, it can't actually be designated
118
     * {@internal  While this is private, it can't actually be designated
119
     * private in PHP 5 because it is directly accessed in the test suite.}}
119
     * private in PHP 5 because it is directly accessed in the test suite.}}
120
     *
120
     *
121
     * @var integer
121
     * @var integer
122
     * @access private
122
     * @access private
123
     */
123
     */
124
    var $transaction_opcount = 0;
124
    var $transaction_opcount = 0;
125
 
125
 
126
    /**
126
    /**
127
     * The number of rows affected by a data manipulation query
127
     * The number of rows affected by a data manipulation query
128
     * @var integer
128
     * @var integer
129
     */
129
     */
130
    var $affected = 0;
130
    var $affected = 0;
131
 
131
 
132
    /**
132
    /**
133
     * The current row being looked at in fetchInto()
133
     * The current row being looked at in fetchInto()
134
     * @var array
134
     * @var array
135
     * @access private
135
     * @access private
136
     */
136
     */
137
    var $row = array();
137
    var $row = array();
138
 
138
 
139
    /**
139
    /**
140
     * The number of rows in a given result set
140
     * The number of rows in a given result set
141
     * @var array
141
     * @var array
142
     * @access private
142
     * @access private
143
     */
143
     */
144
    var $_num_rows = array();
144
    var $_num_rows = array();
145
 
145
 
146
 
146
 
147
    // }}}
147
    // }}}
148
    // {{{ constructor
148
    // {{{ constructor
149
 
149
 
150
    /**
150
    /**
151
     * This constructor calls <kbd>$this->DB_common()</kbd>
151
     * This constructor calls <kbd>parent::__construct()</kbd>
152
     *
152
     *
153
     * @return void
153
     * @return void
154
     */
154
     */
155
    function DB_pgsql()
155
    function __construct()
156
    {
156
    {
157
        $this->DB_common();
157
        parent::__construct();
158
    }
158
    }
159
 
159
 
160
    // }}}
160
    // }}}
161
    // {{{ connect()
161
    // {{{ connect()
162
 
162
 
163
    /**
163
    /**
164
     * Connect to the database server, log in and open the database
164
     * Connect to the database server, log in and open the database
165
     *
165
     *
166
     * Don't call this method directly.  Use DB::connect() instead.
166
     * Don't call this method directly.  Use DB::connect() instead.
167
     *
167
     *
168
     * PEAR DB's pgsql driver supports the following extra DSN options:
168
     * PEAR DB's pgsql driver supports the following extra DSN options:
169
     *   + connect_timeout  How many seconds to wait for a connection to
169
     *   + connect_timeout  How many seconds to wait for a connection to
170
     *                       be established.  Available since PEAR DB 1.7.0.
170
     *                       be established.  Available since PEAR DB 1.7.0.
171
     *   + new_link         If set to true, causes subsequent calls to
171
     *   + new_link         If set to true, causes subsequent calls to
172
     *                       connect() to return a new connection link
172
     *                       connect() to return a new connection link
173
     *                       instead of the existing one.  WARNING: this is
173
     *                       instead of the existing one.  WARNING: this is
174
     *                       not portable to other DBMS's.  Available only
174
     *                       not portable to other DBMS's.  Available only
175
     *                       if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0.
175
     *                       if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0.
176
     *   + options          Command line options to be sent to the server.
176
     *   + options          Command line options to be sent to the server.
177
     *                       Available since PEAR DB 1.6.4.
177
     *                       Available since PEAR DB 1.6.4.
178
     *   + service          Specifies a service name in pg_service.conf that
178
     *   + service          Specifies a service name in pg_service.conf that
179
     *                       holds additional connection parameters.
179
     *                       holds additional connection parameters.
180
     *                       Available since PEAR DB 1.7.0.
180
     *                       Available since PEAR DB 1.7.0.
181
     *   + sslmode          How should SSL be used when connecting?  Values:
181
     *   + sslmode          How should SSL be used when connecting?  Values:
182
     *                       disable, allow, prefer or require.
182
     *                       disable, allow, prefer or require.
183
     *                       Available since PEAR DB 1.7.0.
183
     *                       Available since PEAR DB 1.7.0.
184
     *   + tty              This was used to specify where to send server
184
     *   + tty              This was used to specify where to send server
185
     *                       debug output.  Available since PEAR DB 1.6.4.
185
     *                       debug output.  Available since PEAR DB 1.6.4.
186
     *
186
     *
187
     * Example of connecting to a new link via a socket:
187
     * Example of connecting to a new link via a socket:
188
     * <code>
188
     * <code>
189
     * require_once 'DB.php';
189
     * require_once 'DB.php';
190
     * 
190
     * 
191
     * $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true';
191
     * $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true';
192
     * $options = array(
192
     * $options = array(
193
     *     'portability' => DB_PORTABILITY_ALL,
193
     *     'portability' => DB_PORTABILITY_ALL,
194
     * );
194
     * );
195
     * 
195
     * 
196
     * $db =& DB::connect($dsn, $options);
196
     * $db = DB::connect($dsn, $options);
197
     * if (PEAR::isError($db)) {
197
     * if (PEAR::isError($db)) {
198
     *     die($db->getMessage());
198
     *     die($db->getMessage());
199
     * }
199
     * }
200
     * </code>
200
     * </code>
201
     *
201
     *
202
     * @param array $dsn         the data source name
202
     * @param array $dsn         the data source name
203
     * @param bool  $persistent  should the connection be persistent?
203
     * @param bool  $persistent  should the connection be persistent?
204
     *
204
     *
205
     * @return int  DB_OK on success. A DB_Error object on failure.
205
     * @return int  DB_OK on success. A DB_Error object on failure.
206
     *
206
     *
207
     * @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT
207
     * @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT
208
     */
208
     */
209
    function connect($dsn, $persistent = false)
209
    function connect($dsn, $persistent = false)
210
    {
210
    {
211
        if (!PEAR::loadExtension('pgsql')) {
211
        if (!PEAR::loadExtension('pgsql')) {
212
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
212
            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
213
        }
213
        }
214
 
214
 
215
        $this->dsn = $dsn;
215
        $this->dsn = $dsn;
216
        if ($dsn['dbsyntax']) {
216
        if ($dsn['dbsyntax']) {
217
            $this->dbsyntax = $dsn['dbsyntax'];
217
            $this->dbsyntax = $dsn['dbsyntax'];
218
        }
218
        }
219
 
219
 
220
        $protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp';
220
        $protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp';
221
 
221
 
222
        $params = array('');
222
        $params = array('');
223
        if ($protocol == 'tcp') {
223
        if ($protocol == 'tcp') {
224
            if ($dsn['hostspec']) {
224
            if ($dsn['hostspec']) {
225
                $params[0] .= 'host=' . $dsn['hostspec'];
225
                $params[0] .= 'host=' . $dsn['hostspec'];
226
            }
226
            }
227
            if ($dsn['port']) {
227
            if ($dsn['port']) {
228
                $params[0] .= ' port=' . $dsn['port'];
228
                $params[0] .= ' port=' . $dsn['port'];
229
            }
229
            }
230
        } elseif ($protocol == 'unix') {
230
        } elseif ($protocol == 'unix') {
231
            // Allow for pg socket in non-standard locations.
231
            // Allow for pg socket in non-standard locations.
232
            if ($dsn['socket']) {
232
            if ($dsn['socket']) {
233
                $params[0] .= 'host=' . $dsn['socket'];
233
                $params[0] .= 'host=' . $dsn['socket'];
234
            }
234
            }
235
            if ($dsn['port']) {
235
            if ($dsn['port']) {
236
                $params[0] .= ' port=' . $dsn['port'];
236
                $params[0] .= ' port=' . $dsn['port'];
237
            }
237
            }
238
        }
238
        }
239
        if ($dsn['database']) {
239
        if ($dsn['database']) {
240
            $params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\'';
240
            $params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\'';
241
        }
241
        }
242
        if ($dsn['username']) {
242
        if ($dsn['username']) {
243
            $params[0] .= ' user=\'' . addslashes($dsn['username']) . '\'';
243
            $params[0] .= ' user=\'' . addslashes($dsn['username']) . '\'';
244
        }
244
        }
245
        if ($dsn['password']) {
245
        if ($dsn['password']) {
246
            $params[0] .= ' password=\'' . addslashes($dsn['password']) . '\'';
246
            $params[0] .= ' password=\'' . addslashes($dsn['password']) . '\'';
247
        }
247
        }
248
        if (!empty($dsn['options'])) {
248
        if (!empty($dsn['options'])) {
249
            $params[0] .= ' options=' . $dsn['options'];
249
            $params[0] .= ' options=' . $dsn['options'];
250
        }
250
        }
251
        if (!empty($dsn['tty'])) {
251
        if (!empty($dsn['tty'])) {
252
            $params[0] .= ' tty=' . $dsn['tty'];
252
            $params[0] .= ' tty=' . $dsn['tty'];
253
        }
253
        }
254
        if (!empty($dsn['connect_timeout'])) {
254
        if (!empty($dsn['connect_timeout'])) {
255
            $params[0] .= ' connect_timeout=' . $dsn['connect_timeout'];
255
            $params[0] .= ' connect_timeout=' . $dsn['connect_timeout'];
256
        }
256
        }
257
        if (!empty($dsn['sslmode'])) {
257
        if (!empty($dsn['sslmode'])) {
258
            $params[0] .= ' sslmode=' . $dsn['sslmode'];
258
            $params[0] .= ' sslmode=' . $dsn['sslmode'];
259
        }
259
        }
260
        if (!empty($dsn['service'])) {
260
        if (!empty($dsn['service'])) {
261
            $params[0] .= ' service=' . $dsn['service'];
261
            $params[0] .= ' service=' . $dsn['service'];
262
        }
262
        }
263
 
263
 
264
        if (isset($dsn['new_link'])
264
        if (isset($dsn['new_link'])
265
            && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true))
265
            && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true))
266
        {
266
        {
267
            if (version_compare(phpversion(), '4.3.0', '>=')) {
267
            if (version_compare(phpversion(), '4.3.0', '>=')) {
268
                $params[] = PGSQL_CONNECT_FORCE_NEW;
268
                $params[] = PGSQL_CONNECT_FORCE_NEW;
269
            }
269
            }
270
        }
270
        }
271
 
271
 
272
        $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
272
        $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
273
 
273
 
274
        $ini = ini_get('track_errors');
274
        $ini = ini_get('track_errors');
275
        $php_errormsg = '';
275
        $php_errormsg = '';
276
        if ($ini) {
276
        if ($ini) {
277
            $this->connection = @call_user_func_array($connect_function,
277
            $this->connection = @call_user_func_array($connect_function,
278
                                                      $params);
278
                                                      $params);
279
        } else {
279
        } else {
280
            ini_set('track_errors', 1);
280
            @ini_set('track_errors', 1);
281
            $this->connection = @call_user_func_array($connect_function,
281
            $this->connection = @call_user_func_array($connect_function,
282
                                                      $params);
282
                                                      $params);
283
            ini_set('track_errors', $ini);
283
            @ini_set('track_errors', $ini);
284
        }
284
        }
285
 
285
 
286
        if (!$this->connection) {
286
        if (!$this->connection) {
287
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
287
            return $this->raiseError(DB_ERROR_CONNECT_FAILED,
288
                                     null, null, null,
288
                                     null, null, null,
289
                                     $php_errormsg);
289
                                     $php_errormsg);
290
        }
290
        }
291
        return DB_OK;
291
        return DB_OK;
292
    }
292
    }
293
 
293
 
294
    // }}}
294
    // }}}
295
    // {{{ disconnect()
295
    // {{{ disconnect()
296
 
296
 
297
    /**
297
    /**
298
     * Disconnects from the database server
298
     * Disconnects from the database server
299
     *
299
     *
300
     * @return bool  TRUE on success, FALSE on failure
300
     * @return bool  TRUE on success, FALSE on failure
301
     */
301
     */
302
    function disconnect()
302
    function disconnect()
303
    {
303
    {
304
        $ret = @pg_close($this->connection);
304
        $ret = @pg_close($this->connection);
305
        $this->connection = null;
305
        $this->connection = null;
306
        return $ret;
306
        return $ret;
307
    }
307
    }
308
 
308
 
309
    // }}}
309
    // }}}
310
    // {{{ simpleQuery()
310
    // {{{ simpleQuery()
311
 
311
 
312
    /**
312
    /**
313
     * Sends a query to the database server
313
     * Sends a query to the database server
314
     *
314
     *
315
     * @param string  the SQL query string
315
     * @param string  the SQL query string
316
     *
316
     *
317
     * @return mixed  + a PHP result resrouce for successful SELECT queries
317
     * @return mixed  + a PHP result resrouce for successful SELECT queries
318
     *                + the DB_OK constant for other successful queries
318
     *                + the DB_OK constant for other successful queries
319
     *                + a DB_Error object on failure
319
     *                + a DB_Error object on failure
320
     */
320
     */
321
    function simpleQuery($query)
321
    function simpleQuery($query)
322
    {
322
    {
323
        $ismanip = DB::isManip($query);
323
        $ismanip = $this->_checkManip($query);
324
        $this->last_query = $query;
324
        $this->last_query = $query;
325
        $query = $this->modifyQuery($query);
325
        $query = $this->modifyQuery($query);
326
        if (!$this->autocommit && $ismanip) {
326
        if (!$this->autocommit && $ismanip) {
327
            if ($this->transaction_opcount == 0) {
327
            if ($this->transaction_opcount == 0) {
328
                $result = @pg_exec($this->connection, 'begin;');
328
                $result = @pg_exec($this->connection, 'begin;');
329
                if (!$result) {
329
                if (!$result) {
330
                    return $this->pgsqlRaiseError();
330
                    return $this->pgsqlRaiseError();
331
                }
331
                }
332
            }
332
            }
333
            $this->transaction_opcount++;
333
            $this->transaction_opcount++;
334
        }
334
        }
335
        $result = @pg_exec($this->connection, $query);
335
        $result = @pg_exec($this->connection, $query);
336
        if (!$result) {
336
        if (!$result) {
337
            return $this->pgsqlRaiseError();
337
            return $this->pgsqlRaiseError();
338
        }
338
        }
-
 
339
 
-
 
340
        /*
339
        // Determine which queries that should return data, and which
341
         * Determine whether queries produce affected rows, result or nothing.
-
 
342
         *
-
 
343
         * This logic was introduced in version 1.1 of the file by ssb,
-
 
344
         * though the regex has been modified slightly since then.
-
 
345
         *
340
        // should return an error code only.
346
         * PostgreSQL commands:
-
 
347
         * ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
-
 
348
         * CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
-
 
349
         * GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
-
 
350
         * REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
-
 
351
         * UNLISTEN, UPDATE, VACUUM, WITH
-
 
352
         */
341
        if ($ismanip) {
353
        if ($ismanip) {
342
            $this->affected = @pg_affected_rows($result);
354
            $this->affected = @pg_affected_rows($result);
343
            return DB_OK;
355
            return DB_OK;
344
        } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|SHOW)\s/si', $query)) {
356
        } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|FETCH|SHOW|WITH)\s/si',
345
            /* PostgreSQL commands:
-
 
346
               ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
-
 
347
               CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
-
 
348
               GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
-
 
349
               REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
-
 
350
               UNLISTEN, UPDATE, VACUUM
357
                             $query))
351
            */
358
        {
352
            $this->row[(int)$result] = 0; // reset the row counter.
359
            $this->row[(int)$result] = 0; // reset the row counter.
353
            $numrows = $this->numRows($result);
360
            $numrows = $this->numRows($result);
354
            if (is_object($numrows)) {
361
            if (is_object($numrows)) {
355
                return $numrows;
362
                return $numrows;
356
            }
363
            }
357
            $this->_num_rows[(int)$result] = $numrows;
364
            $this->_num_rows[(int)$result] = $numrows;
358
            $this->affected = 0;
365
            $this->affected = 0;
359
            return $result;
366
            return $result;
360
        } else {
367
        } else {
361
            $this->affected = 0;
368
            $this->affected = 0;
362
            return DB_OK;
369
            return DB_OK;
363
        }
370
        }
364
    }
371
    }
365
 
372
 
366
    // }}}
373
    // }}}
367
    // {{{ nextResult()
374
    // {{{ nextResult()
368
 
375
 
369
    /**
376
    /**
370
     * Move the internal pgsql result pointer to the next available result
377
     * Move the internal pgsql result pointer to the next available result
371
     *
378
     *
372
     * @param a valid fbsql result resource
379
     * @param a valid fbsql result resource
373
     *
380
     *
374
     * @access public
381
     * @access public
375
     *
382
     *
376
     * @return true if a result is available otherwise return false
383
     * @return true if a result is available otherwise return false
377
     */
384
     */
378
    function nextResult($result)
385
    function nextResult($result)
379
    {
386
    {
380
        return false;
387
        return false;
381
    }
388
    }
382
 
389
 
383
    // }}}
390
    // }}}
384
    // {{{ fetchInto()
391
    // {{{ fetchInto()
385
 
392
 
386
    /**
393
    /**
387
     * Places a row from the result set into the given array
394
     * Places a row from the result set into the given array
388
     *
395
     *
389
     * Formating of the array and the data therein are configurable.
396
     * Formating of the array and the data therein are configurable.
390
     * See DB_result::fetchInto() for more information.
397
     * See DB_result::fetchInto() for more information.
391
     *
398
     *
392
     * This method is not meant to be called directly.  Use
399
     * This method is not meant to be called directly.  Use
393
     * DB_result::fetchInto() instead.  It can't be declared "protected"
400
     * DB_result::fetchInto() instead.  It can't be declared "protected"
394
     * because DB_result is a separate object.
401
     * because DB_result is a separate object.
395
     *
402
     *
396
     * @param resource $result    the query result resource
403
     * @param resource $result    the query result resource
397
     * @param array    $arr       the referenced array to put the data in
404
     * @param array    $arr       the referenced array to put the data in
398
     * @param int      $fetchmode how the resulting array should be indexed
405
     * @param int      $fetchmode how the resulting array should be indexed
399
     * @param int      $rownum    the row number to fetch (0 = first row)
406
     * @param int      $rownum    the row number to fetch (0 = first row)
400
     *
407
     *
401
     * @return mixed  DB_OK on success, NULL when the end of a result set is
408
     * @return mixed  DB_OK on success, NULL when the end of a result set is
402
     *                 reached or on failure
409
     *                 reached or on failure
403
     *
410
     *
404
     * @see DB_result::fetchInto()
411
     * @see DB_result::fetchInto()
405
     */
412
     */
406
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
413
    function fetchInto($result, &$arr, $fetchmode, $rownum = null)
407
    {
414
    {
408
        $result_int = (int)$result;
415
        $result_int = (int)$result;
409
        $rownum = ($rownum !== null) ? $rownum : $this->row[$result_int];
416
        $rownum = ($rownum !== null) ? $rownum : $this->row[$result_int];
410
        if ($rownum >= $this->_num_rows[$result_int]) {
417
        if ($rownum >= $this->_num_rows[$result_int]) {
411
            return null;
418
            return null;
412
        }
419
        }
413
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
420
        if ($fetchmode & DB_FETCHMODE_ASSOC) {
414
            $arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC);
421
            $arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC);
415
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
422
            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
416
                $arr = array_change_key_case($arr, CASE_LOWER);
423
                $arr = array_change_key_case($arr, CASE_LOWER);
417
            }
424
            }
418
        } else {
425
        } else {
419
            $arr = @pg_fetch_row($result, $rownum);
426
            $arr = @pg_fetch_row($result, $rownum);
420
        }
427
        }
421
        if (!$arr) {
428
        if (!$arr) {
422
            return null;
429
            return null;
423
        }
430
        }
424
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
431
        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
425
            $this->_rtrimArrayValues($arr);
432
            $this->_rtrimArrayValues($arr);
426
        }
433
        }
427
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
434
        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
428
            $this->_convertNullArrayValuesToEmpty($arr);
435
            $this->_convertNullArrayValuesToEmpty($arr);
429
        }
436
        }
430
        $this->row[$result_int] = ++$rownum;
437
        $this->row[$result_int] = ++$rownum;
431
        return DB_OK;
438
        return DB_OK;
432
    }
439
    }
433
 
440
 
434
    // }}}
441
    // }}}
435
    // {{{ freeResult()
442
    // {{{ freeResult()
436
 
443
 
437
    /**
444
    /**
438
     * Deletes the result set and frees the memory occupied by the result set
445
     * Deletes the result set and frees the memory occupied by the result set
439
     *
446
     *
440
     * This method is not meant to be called directly.  Use
447
     * This method is not meant to be called directly.  Use
441
     * DB_result::free() instead.  It can't be declared "protected"
448
     * DB_result::free() instead.  It can't be declared "protected"
442
     * because DB_result is a separate object.
449
     * because DB_result is a separate object.
443
     *
450
     *
444
     * @param resource $result  PHP's query result resource
451
     * @param resource $result  PHP's query result resource
445
     *
452
     *
446
     * @return bool  TRUE on success, FALSE if $result is invalid
453
     * @return bool  TRUE on success, FALSE if $result is invalid
447
     *
454
     *
448
     * @see DB_result::free()
455
     * @see DB_result::free()
449
     */
456
     */
450
    function freeResult($result)
457
    function freeResult($result)
451
    {
458
    {
452
        if (is_resource($result)) {
459
        if (is_resource($result)) {
453
            unset($this->row[(int)$result]);
460
            unset($this->row[(int)$result]);
454
            unset($this->_num_rows[(int)$result]);
461
            unset($this->_num_rows[(int)$result]);
455
            $this->affected = 0;
462
            $this->affected = 0;
456
            return @pg_freeresult($result);
463
            return @pg_freeresult($result);
457
        }
464
        }
458
        return false;
465
        return false;
459
    }
466
    }
460
 
467
 
461
    // }}}
468
    // }}}
462
    // {{{ quote()
-
 
463
 
-
 
464
    /**
-
 
465
     * @deprecated  Deprecated in release 1.6.0
-
 
466
     * @internal
-
 
467
     */
-
 
468
    function quote($str)
-
 
469
    {
-
 
470
        return $this->quoteSmart($str);
-
 
471
    }
-
 
472
 
-
 
473
    // }}}
-
 
474
    // {{{ quoteSmart()
469
    // {{{ quoteBoolean()
475
 
470
 
476
    /**
471
    /**
477
     * Formats input so it can be safely used in a query
472
     * Formats a boolean value for use within a query in a locale-independent
478
     *
-
 
479
     * @param mixed $in  the data to be formatted
-
 
480
     *
-
 
481
     * @return mixed  the formatted data.  The format depends on the input's
-
 
482
     *                 PHP type:
-
 
483
     *                 + null = the string <samp>NULL</samp>
-
 
484
     *                 + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp>
-
 
485
     *                 + integer or double = the unquoted number
-
 
486
     *                 + other (including strings and numeric strings) =
-
 
487
     *                   the data escaped according to MySQL's settings
-
 
488
     *                   then encapsulated between single quotes
473
     * manner.
-
 
474
     *
-
 
475
     * @param boolean the boolean value to be quoted.
489
     *
476
     * @return string the quoted string.
490
     * @see DB_common::quoteSmart()
477
     * @see DB_common::quoteSmart()
491
     * @since Method available since Release 1.6.0
478
     * @since Method available since release 1.7.8.
492
     */
479
     */
493
    function quoteSmart($in)
-
 
494
    {
-
 
495
        if (is_int($in) || is_double($in)) {
-
 
496
            return $in;
-
 
497
        } elseif (is_bool($in)) {
480
    function quoteBoolean($boolean) {
498
            return $in ? 'TRUE' : 'FALSE';
-
 
499
        } elseif (is_null($in)) {
-
 
500
            return 'NULL';
-
 
501
        } else {
-
 
502
            return "'" . $this->escapeSimple($in) . "'";
-
 
503
        }
481
        return $boolean ? 'TRUE' : 'FALSE';
504
    }
482
    }
505
 
483
     
506
    // }}}
484
    // }}}
507
    // {{{ escapeSimple()
485
    // {{{ escapeSimple()
508
 
486
 
509
    /**
487
    /**
510
     * Escapes a string according to the current DBMS's standards
488
     * Escapes a string according to the current DBMS's standards
511
     *
489
     *
512
     * {@internal PostgreSQL treats a backslash as an escape character,
490
     * {@internal PostgreSQL treats a backslash as an escape character,
513
     * so they are escaped as well.
491
     * so they are escaped as well.
514
     *
492
     *
515
     * Not using pg_escape_string() yet because it requires PostgreSQL
-
 
516
     * to be at version 7.2 or greater.}}
-
 
517
     *
-
 
518
     * @param string $str  the string to be escaped
493
     * @param string $str  the string to be escaped
519
     *
494
     *
520
     * @return string  the escaped string
495
     * @return string  the escaped string
521
     *
496
     *
522
     * @see DB_common::quoteSmart()
497
     * @see DB_common::quoteSmart()
523
     * @since Method available since Release 1.6.0
498
     * @since Method available since Release 1.6.0
524
     */
499
     */
525
    function escapeSimple($str)
500
    function escapeSimple($str)
526
    {
501
    {
-
 
502
        if (function_exists('pg_escape_string')) {
-
 
503
            /* This fixes an undocumented BC break in PHP 5.2.0 which changed
-
 
504
             * the prototype of pg_escape_string. I'm not thrilled about having
-
 
505
             * to sniff the PHP version, quite frankly, but it's the only way
-
 
506
             * to deal with the problem. Revision 1.331.2.13.2.10 on
-
 
507
             * php-src/ext/pgsql/pgsql.c (PHP_5_2 branch) is to blame, for the
-
 
508
             * record. */
-
 
509
            if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
-
 
510
                return pg_escape_string($this->connection, $str);
-
 
511
            } else {
-
 
512
                return pg_escape_string($str);
-
 
513
            }
-
 
514
        } else {
527
        return str_replace("'", "''", str_replace('\\', '\\\\', $str));
515
            return str_replace("'", "''", str_replace('\\', '\\\\', $str));
-
 
516
        }
528
    }
517
    }
529
 
518
 
530
    // }}}
519
    // }}}
531
    // {{{ numCols()
520
    // {{{ numCols()
532
 
521
 
533
    /**
522
    /**
534
     * Gets the number of columns in a result set
523
     * Gets the number of columns in a result set
535
     *
524
     *
536
     * This method is not meant to be called directly.  Use
525
     * This method is not meant to be called directly.  Use
537
     * DB_result::numCols() instead.  It can't be declared "protected"
526
     * DB_result::numCols() instead.  It can't be declared "protected"
538
     * because DB_result is a separate object.
527
     * because DB_result is a separate object.
539
     *
528
     *
540
     * @param resource $result  PHP's query result resource
529
     * @param resource $result  PHP's query result resource
541
     *
530
     *
542
     * @return int  the number of columns.  A DB_Error object on failure.
531
     * @return int  the number of columns.  A DB_Error object on failure.
543
     *
532
     *
544
     * @see DB_result::numCols()
533
     * @see DB_result::numCols()
545
     */
534
     */
546
    function numCols($result)
535
    function numCols($result)
547
    {
536
    {
548
        $cols = @pg_numfields($result);
537
        $cols = @pg_numfields($result);
549
        if (!$cols) {
538
        if (!$cols) {
550
            return $this->pgsqlRaiseError();
539
            return $this->pgsqlRaiseError();
551
        }
540
        }
552
        return $cols;
541
        return $cols;
553
    }
542
    }
554
 
543
 
555
    // }}}
544
    // }}}
556
    // {{{ numRows()
545
    // {{{ numRows()
557
 
546
 
558
    /**
547
    /**
559
     * Gets the number of rows in a result set
548
     * Gets the number of rows in a result set
560
     *
549
     *
561
     * This method is not meant to be called directly.  Use
550
     * This method is not meant to be called directly.  Use
562
     * DB_result::numRows() instead.  It can't be declared "protected"
551
     * DB_result::numRows() instead.  It can't be declared "protected"
563
     * because DB_result is a separate object.
552
     * because DB_result is a separate object.
564
     *
553
     *
565
     * @param resource $result  PHP's query result resource
554
     * @param resource $result  PHP's query result resource
566
     *
555
     *
567
     * @return int  the number of rows.  A DB_Error object on failure.
556
     * @return int  the number of rows.  A DB_Error object on failure.
568
     *
557
     *
569
     * @see DB_result::numRows()
558
     * @see DB_result::numRows()
570
     */
559
     */
571
    function numRows($result)
560
    function numRows($result)
572
    {
561
    {
573
        $rows = @pg_numrows($result);
562
        $rows = @pg_numrows($result);
574
        if ($rows === null) {
563
        if ($rows === null) {
575
            return $this->pgsqlRaiseError();
564
            return $this->pgsqlRaiseError();
576
        }
565
        }
577
        return $rows;
566
        return $rows;
578
    }
567
    }
579
 
568
 
580
    // }}}
569
    // }}}
581
    // {{{ autoCommit()
570
    // {{{ autoCommit()
582
 
571
 
583
    /**
572
    /**
584
     * Enables or disables automatic commits
573
     * Enables or disables automatic commits
585
     *
574
     *
586
     * @param bool $onoff  true turns it on, false turns it off
575
     * @param bool $onoff  true turns it on, false turns it off
587
     *
576
     *
588
     * @return int  DB_OK on success.  A DB_Error object if the driver
577
     * @return int  DB_OK on success.  A DB_Error object if the driver
589
     *               doesn't support auto-committing transactions.
578
     *               doesn't support auto-committing transactions.
590
     */
579
     */
591
    function autoCommit($onoff = false)
580
    function autoCommit($onoff = false)
592
    {
581
    {
593
        // XXX if $this->transaction_opcount > 0, we should probably
582
        // XXX if $this->transaction_opcount > 0, we should probably
594
        // issue a warning here.
583
        // issue a warning here.
595
        $this->autocommit = $onoff ? true : false;
584
        $this->autocommit = $onoff ? true : false;
596
        return DB_OK;
585
        return DB_OK;
597
    }
586
    }
598
 
587
 
599
    // }}}
588
    // }}}
600
    // {{{ commit()
589
    // {{{ commit()
601
 
590
 
602
    /**
591
    /**
603
     * Commits the current transaction
592
     * Commits the current transaction
604
     *
593
     *
605
     * @return int  DB_OK on success.  A DB_Error object on failure.
594
     * @return int  DB_OK on success.  A DB_Error object on failure.
606
     */
595
     */
607
    function commit()
596
    function commit()
608
    {
597
    {
609
        if ($this->transaction_opcount > 0) {
598
        if ($this->transaction_opcount > 0) {
610
            // (disabled) hack to shut up error messages from libpq.a
599
            // (disabled) hack to shut up error messages from libpq.a
611
            //@fclose(@fopen("php://stderr", "w"));
600
            //@fclose(@fopen("php://stderr", "w"));
612
            $result = @pg_exec($this->connection, 'end;');
601
            $result = @pg_exec($this->connection, 'end;');
613
            $this->transaction_opcount = 0;
602
            $this->transaction_opcount = 0;
614
            if (!$result) {
603
            if (!$result) {
615
                return $this->pgsqlRaiseError();
604
                return $this->pgsqlRaiseError();
616
            }
605
            }
617
        }
606
        }
618
        return DB_OK;
607
        return DB_OK;
619
    }
608
    }
620
 
609
 
621
    // }}}
610
    // }}}
622
    // {{{ rollback()
611
    // {{{ rollback()
623
 
612
 
624
    /**
613
    /**
625
     * Reverts the current transaction
614
     * Reverts the current transaction
626
     *
615
     *
627
     * @return int  DB_OK on success.  A DB_Error object on failure.
616
     * @return int  DB_OK on success.  A DB_Error object on failure.
628
     */
617
     */
629
    function rollback()
618
    function rollback()
630
    {
619
    {
631
        if ($this->transaction_opcount > 0) {
620
        if ($this->transaction_opcount > 0) {
632
            $result = @pg_exec($this->connection, 'abort;');
621
            $result = @pg_exec($this->connection, 'abort;');
633
            $this->transaction_opcount = 0;
622
            $this->transaction_opcount = 0;
634
            if (!$result) {
623
            if (!$result) {
635
                return $this->pgsqlRaiseError();
624
                return $this->pgsqlRaiseError();
636
            }
625
            }
637
        }
626
        }
638
        return DB_OK;
627
        return DB_OK;
639
    }
628
    }
640
 
629
 
641
    // }}}
630
    // }}}
642
    // {{{ affectedRows()
631
    // {{{ affectedRows()
643
 
632
 
644
    /**
633
    /**
645
     * Determines the number of rows affected by a data maniuplation query
634
     * Determines the number of rows affected by a data maniuplation query
646
     *
635
     *
647
     * 0 is returned for queries that don't manipulate data.
636
     * 0 is returned for queries that don't manipulate data.
648
     *
637
     *
649
     * @return int  the number of rows.  A DB_Error object on failure.
638
     * @return int  the number of rows.  A DB_Error object on failure.
650
     */
639
     */
651
    function affectedRows()
640
    function affectedRows()
652
    {
641
    {
653
        return $this->affected;
642
        return $this->affected;
654
    }
643
    }
655
 
644
 
656
    // }}}
645
    // }}}
657
    // {{{ nextId()
646
    // {{{ nextId()
658
 
647
 
659
    /**
648
    /**
660
     * Returns the next free id in a sequence
649
     * Returns the next free id in a sequence
661
     *
650
     *
662
     * @param string  $seq_name  name of the sequence
651
     * @param string  $seq_name  name of the sequence
663
     * @param boolean $ondemand  when true, the seqence is automatically
652
     * @param boolean $ondemand  when true, the seqence is automatically
664
     *                            created if it does not exist
653
     *                            created if it does not exist
665
     *
654
     *
666
     * @return int  the next id number in the sequence.
655
     * @return int  the next id number in the sequence.
667
     *               A DB_Error object on failure.
656
     *               A DB_Error object on failure.
668
     *
657
     *
669
     * @see DB_common::nextID(), DB_common::getSequenceName(),
658
     * @see DB_common::nextID(), DB_common::getSequenceName(),
670
     *      DB_pgsql::createSequence(), DB_pgsql::dropSequence()
659
     *      DB_pgsql::createSequence(), DB_pgsql::dropSequence()
671
     */
660
     */
672
    function nextId($seq_name, $ondemand = true)
661
    function nextId($seq_name, $ondemand = true)
673
    {
662
    {
674
        $seqname = $this->getSequenceName($seq_name);
663
        $seqname = $this->getSequenceName($seq_name);
675
        $repeat = false;
664
        $repeat = false;
676
        do {
665
        do {
677
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
666
            $this->pushErrorHandling(PEAR_ERROR_RETURN);
678
            $result =& $this->query("SELECT NEXTVAL('${seqname}')");
667
            $result = $this->query("SELECT NEXTVAL('${seqname}')");
679
            $this->popErrorHandling();
668
            $this->popErrorHandling();
680
            if ($ondemand && DB::isError($result) &&
669
            if ($ondemand && DB::isError($result) &&
681
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
670
                $result->getCode() == DB_ERROR_NOSUCHTABLE) {
682
                $repeat = true;
671
                $repeat = true;
683
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
672
                $this->pushErrorHandling(PEAR_ERROR_RETURN);
684
                $result = $this->createSequence($seq_name);
673
                $result = $this->createSequence($seq_name);
685
                $this->popErrorHandling();
674
                $this->popErrorHandling();
686
                if (DB::isError($result)) {
675
                if (DB::isError($result)) {
687
                    return $this->raiseError($result);
676
                    return $this->raiseError($result);
688
                }
677
                }
689
            } else {
678
            } else {
690
                $repeat = false;
679
                $repeat = false;
691
            }
680
            }
692
        } while ($repeat);
681
        } while ($repeat);
693
        if (DB::isError($result)) {
682
        if (DB::isError($result)) {
694
            return $this->raiseError($result);
683
            return $this->raiseError($result);
695
        }
684
        }
696
        $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
685
        $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
697
        $result->free();
686
        $result->free();
698
        return $arr[0];
687
        return $arr[0];
699
    }
688
    }
700
 
689
 
701
    // }}}
690
    // }}}
702
    // {{{ createSequence()
691
    // {{{ createSequence()
703
 
692
 
704
    /**
693
    /**
705
     * Creates a new sequence
694
     * Creates a new sequence
706
     *
695
     *
707
     * @param string $seq_name  name of the new sequence
696
     * @param string $seq_name  name of the new sequence
708
     *
697
     *
709
     * @return int  DB_OK on success.  A DB_Error object on failure.
698
     * @return int  DB_OK on success.  A DB_Error object on failure.
710
     *
699
     *
711
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
700
     * @see DB_common::createSequence(), DB_common::getSequenceName(),
712
     *      DB_pgsql::nextID(), DB_pgsql::dropSequence()
701
     *      DB_pgsql::nextID(), DB_pgsql::dropSequence()
713
     */
702
     */
714
    function createSequence($seq_name)
703
    function createSequence($seq_name)
715
    {
704
    {
716
        $seqname = $this->getSequenceName($seq_name);
705
        $seqname = $this->getSequenceName($seq_name);
717
        $result = $this->query("CREATE SEQUENCE ${seqname}");
706
        $result = $this->query("CREATE SEQUENCE ${seqname}");
718
        return $result;
707
        return $result;
719
    }
708
    }
720
 
709
 
721
    // }}}
710
    // }}}
722
    // {{{ dropSequence()
711
    // {{{ dropSequence()
723
 
712
 
724
    /**
713
    /**
725
     * Deletes a sequence
714
     * Deletes a sequence
726
     *
715
     *
727
     * @param string $seq_name  name of the sequence to be deleted
716
     * @param string $seq_name  name of the sequence to be deleted
728
     *
717
     *
729
     * @return int  DB_OK on success.  A DB_Error object on failure.
718
     * @return int  DB_OK on success.  A DB_Error object on failure.
730
     *
719
     *
731
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
720
     * @see DB_common::dropSequence(), DB_common::getSequenceName(),
732
     *      DB_pgsql::nextID(), DB_pgsql::createSequence()
721
     *      DB_pgsql::nextID(), DB_pgsql::createSequence()
733
     */
722
     */
734
    function dropSequence($seq_name)
723
    function dropSequence($seq_name)
735
    {
724
    {
736
        return $this->query('DROP SEQUENCE '
725
        return $this->query('DROP SEQUENCE '
737
                            . $this->getSequenceName($seq_name));
726
                            . $this->getSequenceName($seq_name));
738
    }
727
    }
739
 
728
 
740
    // }}}
729
    // }}}
741
    // {{{ modifyLimitQuery()
730
    // {{{ modifyLimitQuery()
742
 
731
 
743
    /**
732
    /**
744
     * Adds LIMIT clauses to a query string according to current DBMS standards
733
     * Adds LIMIT clauses to a query string according to current DBMS standards
745
     *
734
     *
746
     * @param string $query   the query to modify
735
     * @param string $query   the query to modify
747
     * @param int    $from    the row to start to fetching (0 = the first row)
736
     * @param int    $from    the row to start to fetching (0 = the first row)
748
     * @param int    $count   the numbers of rows to fetch
737
     * @param int    $count   the numbers of rows to fetch
749
     * @param mixed  $params  array, string or numeric data to be used in
738
     * @param mixed  $params  array, string or numeric data to be used in
750
     *                         execution of the statement.  Quantity of items
739
     *                         execution of the statement.  Quantity of items
751
     *                         passed must match quantity of placeholders in
740
     *                         passed must match quantity of placeholders in
752
     *                         query:  meaning 1 placeholder for non-array
741
     *                         query:  meaning 1 placeholder for non-array
753
     *                         parameters or 1 placeholder per array element.
742
     *                         parameters or 1 placeholder per array element.
754
     *
743
     *
755
     * @return string  the query string with LIMIT clauses added
744
     * @return string  the query string with LIMIT clauses added
756
     *
745
     *
757
     * @access protected
746
     * @access protected
758
     */
747
     */
759
    function modifyLimitQuery($query, $from, $count, $params = array())
748
    function modifyLimitQuery($query, $from, $count, $params = array())
760
    {
749
    {
761
        return "$query LIMIT $count OFFSET $from";
750
        return "$query LIMIT $count OFFSET $from";
762
    }
751
    }
763
 
752
 
764
    // }}}
753
    // }}}
765
    // {{{ pgsqlRaiseError()
754
    // {{{ pgsqlRaiseError()
766
 
755
 
767
    /**
756
    /**
768
     * Produces a DB_Error object regarding the current problem
757
     * Produces a DB_Error object regarding the current problem
769
     *
758
     *
770
     * @param int $errno  if the error is being manually raised pass a
759
     * @param int $errno  if the error is being manually raised pass a
771
     *                     DB_ERROR* constant here.  If this isn't passed
760
     *                     DB_ERROR* constant here.  If this isn't passed
772
     *                     the error information gathered from the DBMS.
761
     *                     the error information gathered from the DBMS.
773
     *
762
     *
774
     * @return object  the DB_Error object
763
     * @return object  the DB_Error object
775
     *
764
     *
776
     * @see DB_common::raiseError(),
765
     * @see DB_common::raiseError(),
777
     *      DB_pgsql::errorNative(), DB_pgsql::errorCode()
766
     *      DB_pgsql::errorNative(), DB_pgsql::errorCode()
778
     */
767
     */
779
    function pgsqlRaiseError($errno = null)
768
    function pgsqlRaiseError($errno = null)
780
    {
769
    {
781
        $native = $this->errorNative();
770
        $native = $this->errorNative();
-
 
771
        if (!$native) {
-
 
772
            $native = 'Database connection has been lost.';
-
 
773
            $errno = DB_ERROR_CONNECT_FAILED;
-
 
774
        }
782
        if ($errno === null) {
775
        if ($errno === null) {
783
            $errno = $this->errorCode($native);
776
            $errno = $this->errorCode($native);
784
        }
777
        }
785
        return $this->raiseError($errno, null, null, null, $native);
778
        return $this->raiseError($errno, null, null, null, $native);
786
    }
779
    }
787
 
780
 
788
    // }}}
781
    // }}}
789
    // {{{ errorNative()
782
    // {{{ errorNative()
790
 
783
 
791
    /**
784
    /**
792
     * Gets the DBMS' native error message produced by the last query
785
     * Gets the DBMS' native error message produced by the last query
793
     *
786
     *
794
     * {@internal Error messages are used instead of error codes 
787
     * {@internal Error messages are used instead of error codes 
795
     * in order to support older versions of PostgreSQL.}}
788
     * in order to support older versions of PostgreSQL.}}
796
     *
789
     *
797
     * @return string  the DBMS' error message
790
     * @return string  the DBMS' error message
798
     */
791
     */
799
    function errorNative()
792
    function errorNative()
800
    {
793
    {
801
        return @pg_errormessage($this->connection);
794
        return @pg_errormessage($this->connection);
802
    }
795
    }
803
 
796
 
804
    // }}}
797
    // }}}
805
    // {{{ errorCode()
798
    // {{{ errorCode()
806
 
799
 
807
    /**
800
    /**
808
     * Determines PEAR::DB error code from the database's text error message.
801
     * Determines PEAR::DB error code from the database's text error message.
809
     *
802
     *
810
     * @param  string  $errormsg  error message returned from the database
803
     * @param  string  $errormsg  error message returned from the database
811
     * @return integer  an error number from a DB error constant
804
     * @return integer  an error number from a DB error constant
812
     */
805
     */
813
    function errorCode($errormsg)
806
    function errorCode($errormsg)
814
    {
807
    {
815
        static $error_regexps;
808
        static $error_regexps;
816
        if (!isset($error_regexps)) {
809
        if (!isset($error_regexps)) {
817
            $error_regexps = array(
810
            $error_regexps = array(
-
 
811
                '/column .* (of relation .*)?does not exist/i'
-
 
812
                    => DB_ERROR_NOSUCHFIELD,
818
                '/(relation|sequence|table).*does not exist|class .* not found/i'
813
                '/(relation|sequence|table).*does not exist|class .* not found/i'
819
                    => DB_ERROR_NOSUCHTABLE,
814
                    => DB_ERROR_NOSUCHTABLE,
820
                '/index .* does not exist/'
815
                '/index .* does not exist/'
821
                    => DB_ERROR_NOT_FOUND,
816
                    => DB_ERROR_NOT_FOUND,
822
                '/column .* does not exist/i'
-
 
823
                    => DB_ERROR_NOSUCHFIELD,
-
 
824
                '/relation .* already exists/i'
817
                '/relation .* already exists/i'
825
                    => DB_ERROR_ALREADY_EXISTS,
818
                    => DB_ERROR_ALREADY_EXISTS,
826
                '/(divide|division) by zero$/i'
819
                '/(divide|division) by zero$/i'
827
                    => DB_ERROR_DIVZERO,
820
                    => DB_ERROR_DIVZERO,
828
                '/pg_atoi: error in .*: can\'t parse /i'
821
                '/pg_atoi: error in .*: can\'t parse /i'
829
                    => DB_ERROR_INVALID_NUMBER,
822
                    => DB_ERROR_INVALID_NUMBER,
830
                '/invalid input syntax for( type)? (integer|numeric)/i'
823
                '/invalid input syntax for( type)? (integer|numeric)/i'
831
                    => DB_ERROR_INVALID_NUMBER,
824
                    => DB_ERROR_INVALID_NUMBER,
832
                '/value .* is out of range for type \w*int/i'
825
                '/value .* is out of range for type \w*int/i'
833
                    => DB_ERROR_INVALID_NUMBER,
826
                    => DB_ERROR_INVALID_NUMBER,
834
                '/integer out of range/i'
827
                '/integer out of range/i'
835
                    => DB_ERROR_INVALID_NUMBER,
828
                    => DB_ERROR_INVALID_NUMBER,
836
                '/value too long for type character/i'
829
                '/value too long for type character/i'
837
                    => DB_ERROR_INVALID,
830
                    => DB_ERROR_INVALID,
838
                '/attribute .* not found|relation .* does not have attribute/i'
831
                '/attribute .* not found|relation .* does not have attribute/i'
839
                    => DB_ERROR_NOSUCHFIELD,
832
                    => DB_ERROR_NOSUCHFIELD,
840
                '/column .* specified in USING clause does not exist in (left|right) table/i'
833
                '/column .* specified in USING clause does not exist in (left|right) table/i'
841
                    => DB_ERROR_NOSUCHFIELD,
834
                    => DB_ERROR_NOSUCHFIELD,
842
                '/parser: parse error at or near/i'
835
                '/parser: parse error at or near/i'
843
                    => DB_ERROR_SYNTAX,
836
                    => DB_ERROR_SYNTAX,
844
                '/syntax error at/'
837
                '/syntax error at/'
845
                    => DB_ERROR_SYNTAX,
838
                    => DB_ERROR_SYNTAX,
846
                '/column reference .* is ambiguous/i'
839
                '/column reference .* is ambiguous/i'
847
                    => DB_ERROR_SYNTAX,
840
                    => DB_ERROR_SYNTAX,
848
                '/permission denied/'
841
                '/permission denied/'
849
                    => DB_ERROR_ACCESS_VIOLATION,
842
                    => DB_ERROR_ACCESS_VIOLATION,
850
                '/violates not-null constraint/'
843
                '/violates not-null constraint/'
851
                    => DB_ERROR_CONSTRAINT_NOT_NULL,
844
                    => DB_ERROR_CONSTRAINT_NOT_NULL,
852
                '/violates [\w ]+ constraint/'
845
                '/violates [\w ]+ constraint/'
853
                    => DB_ERROR_CONSTRAINT,
846
                    => DB_ERROR_CONSTRAINT,
854
                '/referential integrity violation/'
847
                '/referential integrity violation/'
855
                    => DB_ERROR_CONSTRAINT,
848
                    => DB_ERROR_CONSTRAINT,
856
                '/more expressions than target columns/i'
849
                '/more expressions than target columns/i'
857
                    => DB_ERROR_VALUE_COUNT_ON_ROW,
850
                    => DB_ERROR_VALUE_COUNT_ON_ROW,
858
            );
851
            );
859
        }
852
        }
860
        foreach ($error_regexps as $regexp => $code) {
853
        foreach ($error_regexps as $regexp => $code) {
861
            if (preg_match($regexp, $errormsg)) {
854
            if (preg_match($regexp, $errormsg)) {
862
                return $code;
855
                return $code;
863
            }
856
            }
864
        }
857
        }
865
        // Fall back to DB_ERROR if there was no mapping.
858
        // Fall back to DB_ERROR if there was no mapping.
866
        return DB_ERROR;
859
        return DB_ERROR;
867
    }
860
    }
868
 
861
 
869
    // }}}
862
    // }}}
870
    // {{{ tableInfo()
863
    // {{{ tableInfo()
871
 
864
 
872
    /**
865
    /**
873
     * Returns information about a table or a result set
866
     * Returns information about a table or a result set
874
     *
867
     *
875
     * NOTE: only supports 'table' and 'flags' if <var>$result</var>
868
     * NOTE: only supports 'table' and 'flags' if <var>$result</var>
876
     * is a table name.
869
     * is a table name.
877
     *
870
     *
878
     * @param object|string  $result  DB_result object from a query or a
871
     * @param object|string  $result  DB_result object from a query or a
879
     *                                 string containing the name of a table.
872
     *                                 string containing the name of a table.
880
     *                                 While this also accepts a query result
873
     *                                 While this also accepts a query result
881
     *                                 resource identifier, this behavior is
874
     *                                 resource identifier, this behavior is
882
     *                                 deprecated.
875
     *                                 deprecated.
883
     * @param int            $mode    a valid tableInfo mode
876
     * @param int            $mode    a valid tableInfo mode
884
     *
877
     *
885
     * @return array  an associative array with the information requested.
878
     * @return array  an associative array with the information requested.
886
     *                 A DB_Error object on failure.
879
     *                 A DB_Error object on failure.
887
     *
880
     *
888
     * @see DB_common::tableInfo()
881
     * @see DB_common::tableInfo()
889
     */
882
     */
890
    function tableInfo($result, $mode = null)
883
    function tableInfo($result, $mode = null)
891
    {
884
    {
892
        if (is_string($result)) {
885
        if (is_string($result)) {
893
            /*
886
            /*
894
             * Probably received a table name.
887
             * Probably received a table name.
895
             * Create a result resource identifier.
888
             * Create a result resource identifier.
896
             */
889
             */
897
            $id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0");
890
            $id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0");
898
            $got_string = true;
891
            $got_string = true;
899
        } elseif (isset($result->result)) {
892
        } elseif (isset($result->result)) {
900
            /*
893
            /*
901
             * Probably received a result object.
894
             * Probably received a result object.
902
             * Extract the result resource identifier.
895
             * Extract the result resource identifier.
903
             */
896
             */
904
            $id = $result->result;
897
            $id = $result->result;
905
            $got_string = false;
898
            $got_string = false;
906
        } else {
899
        } else {
907
            /*
900
            /*
908
             * Probably received a result resource identifier.
901
             * Probably received a result resource identifier.
909
             * Copy it.
902
             * Copy it.
910
             * Deprecated.  Here for compatibility only.
903
             * Deprecated.  Here for compatibility only.
911
             */
904
             */
912
            $id = $result;
905
            $id = $result;
913
            $got_string = false;
906
            $got_string = false;
914
        }
907
        }
915
 
908
 
916
        if (!is_resource($id)) {
909
        if (!is_resource($id)) {
917
            return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
910
            return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
918
        }
911
        }
919
 
912
 
920
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
913
        if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
921
            $case_func = 'strtolower';
914
            $case_func = 'strtolower';
922
        } else {
915
        } else {
923
            $case_func = 'strval';
916
            $case_func = 'strval';
924
        }
917
        }
925
 
918
 
926
        $count = @pg_numfields($id);
919
        $count = @pg_numfields($id);
927
        $res   = array();
920
        $res   = array();
928
 
921
 
929
        if ($mode) {
922
        if ($mode) {
930
            $res['num_fields'] = $count;
923
            $res['num_fields'] = $count;
931
        }
924
        }
932
 
925
 
933
        for ($i = 0; $i < $count; $i++) {
926
        for ($i = 0; $i < $count; $i++) {
934
            $res[$i] = array(
927
            $res[$i] = array(
935
                'table' => $got_string ? $case_func($result) : '',
928
                'table' => $got_string ? $case_func($result) : '',
936
                'name'  => $case_func(@pg_fieldname($id, $i)),
929
                'name'  => $case_func(@pg_fieldname($id, $i)),
937
                'type'  => @pg_fieldtype($id, $i),
930
                'type'  => @pg_fieldtype($id, $i),
938
                'len'   => @pg_fieldsize($id, $i),
931
                'len'   => @pg_fieldsize($id, $i),
939
                'flags' => $got_string
932
                'flags' => $got_string
940
                           ? $this->_pgFieldFlags($id, $i, $result)
933
                           ? $this->_pgFieldFlags($id, $i, $result)
941
                           : '',
934
                           : '',
942
            );
935
            );
943
            if ($mode & DB_TABLEINFO_ORDER) {
936
            if ($mode & DB_TABLEINFO_ORDER) {
944
                $res['order'][$res[$i]['name']] = $i;
937
                $res['order'][$res[$i]['name']] = $i;
945
            }
938
            }
946
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
939
            if ($mode & DB_TABLEINFO_ORDERTABLE) {
947
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
940
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
948
            }
941
            }
949
        }
942
        }
950
 
943
 
951
        // free the result only if we were called on a table
944
        // free the result only if we were called on a table
952
        if ($got_string) {
945
        if ($got_string) {
953
            @pg_freeresult($id);
946
            @pg_freeresult($id);
954
        }
947
        }
955
        return $res;
948
        return $res;
956
    }
949
    }
957
 
950
 
958
    // }}}
951
    // }}}
959
    // {{{ _pgFieldFlags()
952
    // {{{ _pgFieldFlags()
960
 
953
 
961
    /**
954
    /**
962
     * Get a column's flags
955
     * Get a column's flags
963
     *
956
     *
964
     * Supports "not_null", "default_value", "primary_key", "unique_key"
957
     * Supports "not_null", "default_value", "primary_key", "unique_key"
965
     * and "multiple_key".  The default value is passed through
958
     * and "multiple_key".  The default value is passed through
966
     * rawurlencode() in case there are spaces in it.
959
     * rawurlencode() in case there are spaces in it.
967
     *
960
     *
968
     * @param int $resource   the PostgreSQL result identifier
961
     * @param int $resource   the PostgreSQL result identifier
969
     * @param int $num_field  the field number
962
     * @param int $num_field  the field number
970
     *
963
     *
971
     * @return string  the flags
964
     * @return string  the flags
972
     *
965
     *
973
     * @access private
966
     * @access private
974
     */
967
     */
975
    function _pgFieldFlags($resource, $num_field, $table_name)
968
    function _pgFieldFlags($resource, $num_field, $table_name)
976
    {
969
    {
977
        $field_name = @pg_fieldname($resource, $num_field);
970
        $field_name = @pg_fieldname($resource, $num_field);
-
 
971
 
-
 
972
        // Check if there's a schema in $table_name and update things
-
 
973
        // accordingly.
-
 
974
        $from = 'pg_attribute f, pg_class tab, pg_type typ';
-
 
975
        if (strpos($table_name, '.') !== false) {
-
 
976
            $from .= ', pg_namespace nsp';
-
 
977
            list($schema, $table) = explode('.', $table_name);
-
 
978
            $tableWhere = "tab.relname = '$table' AND tab.relnamespace = nsp.oid AND nsp.nspname = '$schema'";
-
 
979
        } else {
-
 
980
            $tableWhere = "tab.relname = '$table_name'";
-
 
981
        }
978
 
982
 
979
        $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef
983
        $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef
980
                                FROM pg_attribute f, pg_class tab, pg_type typ
984
                                FROM $from
981
                                WHERE tab.relname = typ.typname
985
                                WHERE tab.relname = typ.typname
982
                                AND typ.typrelid = f.attrelid
986
                                AND typ.typrelid = f.attrelid
983
                                AND f.attname = '$field_name'
987
                                AND f.attname = '$field_name'
984
                                AND tab.relname = '$table_name'");
988
                                AND $tableWhere");
985
        if (@pg_numrows($result) > 0) {
989
        if (@pg_numrows($result) > 0) {
986
            $row = @pg_fetch_row($result, 0);
990
            $row = @pg_fetch_row($result, 0);
987
            $flags  = ($row[0] == 't') ? 'not_null ' : '';
991
            $flags  = ($row[0] == 't') ? 'not_null ' : '';
988
 
992
 
989
            if ($row[1] == 't') {
993
            if ($row[1] == 't') {
990
                $result = @pg_exec($this->connection, "SELECT a.adsrc
994
                $result = @pg_exec($this->connection, "SELECT a.adsrc
991
                                    FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
995
                                    FROM $from, pg_attrdef a
992
                                    WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
996
                                    WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
993
                                    AND f.attrelid = a.adrelid AND f.attname = '$field_name'
997
                                    AND f.attrelid = a.adrelid AND f.attname = '$field_name'
994
                                    AND tab.relname = '$table_name' AND f.attnum = a.adnum");
998
                                    AND $tableWhere AND f.attnum = a.adnum");
995
                $row = @pg_fetch_row($result, 0);
999
                $row = @pg_fetch_row($result, 0);
996
                $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]);
1000
                $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]);
997
                $flags .= 'default_' . rawurlencode($num) . ' ';
1001
                $flags .= 'default_' . rawurlencode($num) . ' ';
998
            }
1002
            }
999
        } else {
1003
        } else {
1000
            $flags = '';
1004
            $flags = '';
1001
        }
1005
        }
1002
        $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey
1006
        $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey
1003
                                FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
1007
                                FROM $from, pg_index i
1004
                                WHERE tab.relname = typ.typname
1008
                                WHERE tab.relname = typ.typname
1005
                                AND typ.typrelid = f.attrelid
1009
                                AND typ.typrelid = f.attrelid
1006
                                AND f.attrelid = i.indrelid
1010
                                AND f.attrelid = i.indrelid
1007
                                AND f.attname = '$field_name'
1011
                                AND f.attname = '$field_name'
1008
                                AND tab.relname = '$table_name'");
1012
                                AND $tableWhere");
1009
        $count = @pg_numrows($result);
1013
        $count = @pg_numrows($result);
1010
 
1014
 
1011
        for ($i = 0; $i < $count ; $i++) {
1015
        for ($i = 0; $i < $count ; $i++) {
1012
            $row = @pg_fetch_row($result, $i);
1016
            $row = @pg_fetch_row($result, $i);
1013
            $keys = explode(' ', $row[2]);
1017
            $keys = explode(' ', $row[2]);
1014
 
1018
 
1015
            if (in_array($num_field + 1, $keys)) {
1019
            if (in_array($num_field + 1, $keys)) {
1016
                $flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : '';
1020
                $flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : '';
1017
                $flags .= ($row[1] == 't') ? 'primary_key ' : '';
1021
                $flags .= ($row[1] == 't') ? 'primary_key ' : '';
1018
                if (count($keys) > 1)
1022
                if (count($keys) > 1)
1019
                    $flags .= 'multiple_key ';
1023
                    $flags .= 'multiple_key ';
1020
            }
1024
            }
1021
        }
1025
        }
1022
 
1026
 
1023
        return trim($flags);
1027
        return trim($flags);
1024
    }
1028
    }
1025
 
1029
 
1026
    // }}}
1030
    // }}}
1027
    // {{{ getSpecialQuery()
1031
    // {{{ getSpecialQuery()
1028
 
1032
 
1029
    /**
1033
    /**
1030
     * Obtains the query string needed for listing a given type of objects
1034
     * Obtains the query string needed for listing a given type of objects
1031
     *
1035
     *
1032
     * @param string $type  the kind of objects you want to retrieve
1036
     * @param string $type  the kind of objects you want to retrieve
1033
     *
1037
     *
1034
     * @return string  the SQL query string or null if the driver doesn't
1038
     * @return string  the SQL query string or null if the driver doesn't
1035
     *                  support the object type requested
1039
     *                  support the object type requested
1036
     *
1040
     *
1037
     * @access protected
1041
     * @access protected
1038
     * @see DB_common::getListOf()
1042
     * @see DB_common::getListOf()
1039
     */
1043
     */
1040
    function getSpecialQuery($type)
1044
    function getSpecialQuery($type)
1041
    {
1045
    {
1042
        switch ($type) {
1046
        switch ($type) {
1043
            case 'tables':
1047
            case 'tables':
1044
                return 'SELECT c.relname AS "Name"'
1048
                return 'SELECT c.relname AS "Name"'
1045
                        . ' FROM pg_class c, pg_user u'
1049
                        . ' FROM pg_class c, pg_user u'
1046
                        . ' WHERE c.relowner = u.usesysid'
1050
                        . ' WHERE c.relowner = u.usesysid'
1047
                        . " AND c.relkind = 'r'"
1051
                        . " AND c.relkind = 'r'"
1048
                        . ' AND NOT EXISTS'
1052
                        . ' AND NOT EXISTS'
1049
                        . ' (SELECT 1 FROM pg_views'
1053
                        . ' (SELECT 1 FROM pg_views'
1050
                        . '  WHERE viewname = c.relname)'
1054
                        . '  WHERE viewname = c.relname)'
1051
                        . " AND c.relname !~ '^(pg_|sql_)'"
1055
                        . " AND c.relname !~ '^(pg_|sql_)'"
1052
                        . ' UNION'
1056
                        . ' UNION'
1053
                        . ' SELECT c.relname AS "Name"'
1057
                        . ' SELECT c.relname AS "Name"'
1054
                        . ' FROM pg_class c'
1058
                        . ' FROM pg_class c'
1055
                        . " WHERE c.relkind = 'r'"
1059
                        . " WHERE c.relkind = 'r'"
1056
                        . ' AND NOT EXISTS'
1060
                        . ' AND NOT EXISTS'
1057
                        . ' (SELECT 1 FROM pg_views'
1061
                        . ' (SELECT 1 FROM pg_views'
1058
                        . '  WHERE viewname = c.relname)'
1062
                        . '  WHERE viewname = c.relname)'
1059
                        . ' AND NOT EXISTS'
1063
                        . ' AND NOT EXISTS'
1060
                        . ' (SELECT 1 FROM pg_user'
1064
                        . ' (SELECT 1 FROM pg_user'
1061
                        . '  WHERE usesysid = c.relowner)'
1065
                        . '  WHERE usesysid = c.relowner)'
1062
                        . " AND c.relname !~ '^pg_'";
1066
                        . " AND c.relname !~ '^pg_'";
1063
            case 'schema.tables':
1067
            case 'schema.tables':
1064
                return "SELECT schemaname || '.' || tablename"
1068
                return "SELECT schemaname || '.' || tablename"
1065
                        . ' AS "Name"'
1069
                        . ' AS "Name"'
1066
                        . ' FROM pg_catalog.pg_tables'
1070
                        . ' FROM pg_catalog.pg_tables'
1067
                        . ' WHERE schemaname NOT IN'
1071
                        . ' WHERE schemaname NOT IN'
1068
                        . " ('pg_catalog', 'information_schema', 'pg_toast')";
1072
                        . " ('pg_catalog', 'information_schema', 'pg_toast')";
-
 
1073
            case 'schema.views':
-
 
1074
                return "SELECT schemaname || '.' || viewname from pg_views WHERE schemaname"
-
 
1075
                        . " NOT IN ('information_schema', 'pg_catalog')";
1069
            case 'views':
1076
            case 'views':
1070
                // Table cols: viewname | viewowner | definition
1077
                // Table cols: viewname | viewowner | definition
1071
                return 'SELECT viewname from pg_views WHERE schemaname'
1078
                return 'SELECT viewname from pg_views WHERE schemaname'
1072
                        . " NOT IN ('information_schema', 'pg_catalog')";
1079
                        . " NOT IN ('information_schema', 'pg_catalog')";
1073
            case 'users':
1080
            case 'users':
1074
                // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd  |valuntil
1081
                // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd  |valuntil
1075
                return 'SELECT usename FROM pg_user';
1082
                return 'SELECT usename FROM pg_user';
1076
            case 'databases':
1083
            case 'databases':
1077
                return 'SELECT datname FROM pg_database';
1084
                return 'SELECT datname FROM pg_database';
1078
            case 'functions':
1085
            case 'functions':
1079
            case 'procedures':
1086
            case 'procedures':
1080
                return 'SELECT proname FROM pg_proc WHERE proowner <> 1';
1087
                return 'SELECT proname FROM pg_proc WHERE proowner <> 1';
1081
            default:
1088
            default:
1082
                return null;
1089
                return null;
1083
        }
1090
        }
1084
    }
1091
    }
1085
 
1092
 
1086
    // }}}
1093
    // }}}
-
 
1094
    // {{{ _checkManip()
-
 
1095
 
-
 
1096
    /**
-
 
1097
     * Checks if the given query is a manipulation query. This also takes into
-
 
1098
     * account the _next_query_manip flag and sets the _last_query_manip flag
-
 
1099
     * (and resets _next_query_manip) according to the result.
-
 
1100
     *
-
 
1101
     * @param string The query to check.
-
 
1102
     *
-
 
1103
     * @return boolean true if the query is a manipulation query, false
-
 
1104
     * otherwise
-
 
1105
     *
-
 
1106
     * @access protected
-
 
1107
     */
-
 
1108
    function _checkManip($query)
-
 
1109
    {
-
 
1110
        return (preg_match('/^\s*(SAVEPOINT|RELEASE)\s+/i', $query)
-
 
1111
                || parent::_checkManip($query));
-
 
1112
    }
1087
 
1113
 
1088
}
1114
}
1089
 
1115
 
1090
/*
1116
/*
1091
 * Local variables:
1117
 * Local variables:
1092
 * tab-width: 4
1118
 * tab-width: 4
1093
 * c-basic-offset: 4
1119
 * c-basic-offset: 4
1094
 * End:
1120
 * End:
1095
 */
1121
 */
1096
 
1122
 
1097
?>
1123
?>