@@ -143,6 +143,14 @@ class DB_pgsql extends DB_common
143
143
var $ _num_rows = array ();
144
144
145
145
146
+ /**
147
+ * PostgreSQL server version, required for accomodating changes
148
+ * related to metadata column deprecations (i.e. pg_attrdef.adsrc)
149
+ * @var integer
150
+ * @access private
151
+ */
152
+ var $ pg_major_server_version = 0 ;
153
+
146
154
// }}}
147
155
// {{{ constructor
148
156
@@ -186,12 +194,12 @@ function __construct()
186
194
* Example of connecting to a new link via a socket:
187
195
* <code>
188
196
* require_once 'DB.php';
189
- *
197
+ *
190
198
* $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true';
191
199
* $options = array(
192
200
* 'portability' => DB_PORTABILITY_ALL,
193
201
* );
194
- *
202
+ *
195
203
* $db = DB::connect($dsn, $options);
196
204
* if (PEAR::isError($db)) {
197
205
* die($db->getMessage());
@@ -286,7 +294,13 @@ function connect($dsn, $persistent = false)
286
294
return $ this ->raiseError (DB_ERROR_CONNECT_FAILED ,
287
295
null , null , null ,
288
296
$ php_errormsg );
297
+ }
298
+
299
+ if (function_exists ('pg_version ' )) {
300
+ $ pg_ver = pg_version ($ this ->connection );
301
+ $ this ->pg_major_server_version = intval (array_key_exists ('server ' , $ pg_ver ) ? $ pg_ver ['server ' ] : 0 );
289
302
}
303
+
290
304
return DB_OK ;
291
305
}
292
306
@@ -355,12 +369,12 @@ function simpleQuery($query)
355
369
} elseif (preg_match ('/^\s*\(*\s*(SELECT|EXPLAIN|FETCH|SHOW|WITH)\s/si ' ,
356
370
$ query ))
357
371
{
358
- $ this ->row [( int ) $ result ] = 0 ; // reset the row counter.
372
+ $ this ->row [$ this -> _resultId ( $ result) ] = 0 ; // reset the row counter.
359
373
$ numrows = $ this ->numRows ($ result );
360
374
if (is_object ($ numrows )) {
361
375
return $ numrows ;
362
376
}
363
- $ this ->_num_rows [( int ) $ result ] = $ numrows ;
377
+ $ this ->_num_rows [$ this -> _resultId ( $ result) ] = $ numrows ;
364
378
$ this ->affected = 0 ;
365
379
return $ result ;
366
380
} else {
@@ -399,7 +413,7 @@ function nextResult($result)
399
413
* DB_result::fetchInto() instead. It can't be declared "protected"
400
414
* because DB_result is a separate object.
401
415
*
402
- * @param resource $result the query result resource
416
+ * @param mixed $result the query result resource or PgSql\Result
403
417
* @param array $arr the referenced array to put the data in
404
418
* @param int $fetchmode how the resulting array should be indexed
405
419
* @param int $rownum the row number to fetch (0 = first row)
@@ -411,7 +425,7 @@ function nextResult($result)
411
425
*/
412
426
function fetchInto ($ result , &$ arr , $ fetchmode , $ rownum = null )
413
427
{
414
- $ result_int = ( int ) $ result ;
428
+ $ result_int = $ this -> _resultId ( $ result) ;
415
429
$ rownum = ($ rownum !== null ) ? $ rownum : $ this ->row [$ result_int ];
416
430
if ($ rownum >= $ this ->_num_rows [$ result_int ]) {
417
431
return null ;
@@ -447,17 +461,17 @@ function fetchInto($result, &$arr, $fetchmode, $rownum = null)
447
461
* DB_result::free() instead. It can't be declared "protected"
448
462
* because DB_result is a separate object.
449
463
*
450
- * @param resource $result PHP's query result resource
464
+ * @param mixed $result PHP's query result resource or PgSql\Result
451
465
*
452
466
* @return bool TRUE on success, FALSE if $result is invalid
453
467
*
454
468
* @see DB_result::free()
455
469
*/
456
470
function freeResult ($ result )
457
471
{
458
- if (is_resource ($ result )) {
459
- unset($ this ->row [( int ) $ result ]);
460
- unset($ this ->_num_rows [( int ) $ result ]);
472
+ if (is_resource ($ result ) || is_a ( $ result , ' PgSql\Result ' ) ) {
473
+ unset($ this ->row [$ this -> _resultId ( $ result) ]);
474
+ unset($ this ->_num_rows [$ this -> _resultId ( $ result) ]);
461
475
$ this ->affected = 0 ;
462
476
return @pg_free_result ($ result );
463
477
}
@@ -479,7 +493,7 @@ function freeResult($result)
479
493
function quoteBoolean ($ boolean ) {
480
494
return $ boolean ? 'TRUE ' : 'FALSE ' ;
481
495
}
482
-
496
+
483
497
// }}}
484
498
// {{{ escapeSimple()
485
499
@@ -525,7 +539,7 @@ function escapeSimple($str)
525
539
* DB_result::numCols() instead. It can't be declared "protected"
526
540
* because DB_result is a separate object.
527
541
*
528
- * @param resource $result PHP's query result resource
542
+ * @param mixed $result PHP's query result resource or PgSql\Result
529
543
*
530
544
* @return int the number of columns. A DB_Error object on failure.
531
545
*
@@ -550,7 +564,7 @@ function numCols($result)
550
564
* DB_result::numRows() instead. It can't be declared "protected"
551
565
* because DB_result is a separate object.
552
566
*
553
- * @param resource $result PHP's query result resource
567
+ * @param mixed $result PHP's query result resource or PgSql\Result
554
568
*
555
569
* @return int the number of rows. A DB_Error object on failure.
556
570
*
@@ -783,7 +797,7 @@ function pgsqlRaiseError($errno = null)
783
797
/**
784
798
* Gets the DBMS' native error message produced by the last query
785
799
*
786
- * {@internal Error messages are used instead of error codes
800
+ * {@internal Error messages are used instead of error codes
787
801
* in order to support older versions of PostgreSQL.}}
788
802
*
789
803
* @return string the DBMS' error message
@@ -905,7 +919,7 @@ function tableInfo($result, $mode = null)
905
919
$ got_string = false ;
906
920
}
907
921
908
- if (!is_resource ($ id )) {
922
+ if (!is_resource ($ id ) && ! is_a ( $ id , ' PgSql\Result ' )) {
909
923
return $ this ->pgsqlRaiseError (DB_ERROR_NEED_MORE_DATA );
910
924
}
911
925
@@ -957,16 +971,16 @@ function tableInfo($result, $mode = null)
957
971
* and "multiple_key". The default value is passed through
958
972
* rawurlencode() in case there are spaces in it.
959
973
*
960
- * @param int $resource the PostgreSQL result identifier
974
+ * @param int $id the PostgreSQL result identifier
961
975
* @param int $num_field the field number
962
976
*
963
977
* @return string the flags
964
978
*
965
979
* @access private
966
980
*/
967
- function _pgFieldFlags ($ resource , $ num_field , $ table_name )
981
+ function _pgFieldFlags ($ id , $ num_field , $ table_name )
968
982
{
969
- $ field_name = @pg_field_name ($ resource , $ num_field );
983
+ $ field_name = @pg_field_name ($ id , $ num_field );
970
984
971
985
// Check if there's a schema in $table_name and update things
972
986
// accordingly.
@@ -990,7 +1004,10 @@ function _pgFieldFlags($resource, $num_field, $table_name)
990
1004
$ flags = ($ row [0 ] == 't ' ) ? 'not_null ' : '' ;
991
1005
992
1006
if ($ row [1 ] == 't ' ) {
993
- $ result = @pg_query ($ this ->connection , "SELECT a.adsrc
1007
+ $ select_field = $ this ->pg_major_server_version >= 12
1008
+ ? 'pg_get_expr(a.adbin, a.adrelid) '
1009
+ : 'a.adsrc ' ;
1010
+ $ result = @pg_query ($ this ->connection , "SELECT $ select_field
994
1011
FROM $ from, pg_attrdef a
995
1012
WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
996
1013
AND f.attrelid = a.adrelid AND f.attname = ' $ field_name'
@@ -1110,6 +1127,33 @@ function _checkManip($query)
1110
1127
|| parent ::_checkManip ($ query ));
1111
1128
}
1112
1129
1130
+ // }}}
1131
+ // {{{ _resultId()
1132
+
1133
+ /**
1134
+ * Returns a numeric value identifying the result, used for maintaining
1135
+ * indexes. Required by migration from resources to 'PgSql\Result'
1136
+ * types with PHP 8.1.
1137
+ *
1138
+ * @param mixed $result the query result resource or PgSql\Result
1139
+ *
1140
+ * @return int
1141
+ *
1142
+ * @access protected
1143
+ */
1144
+ function _resultId ($ result )
1145
+ {
1146
+ return
1147
+ is_resource ($ result )
1148
+ ? ( function_exists ('get_resource_id ' )
1149
+ ? get_resource_id ($ result )
1150
+ : (int )$ result
1151
+ ) : ( function_exists ('spl_object_id ' )
1152
+ ? spl_object_id ($ result )
1153
+ // catch-all statement
1154
+ : (int )$ result
1155
+ );
1156
+ }
1113
1157
}
1114
1158
1115
1159
/*
0 commit comments