Index: trunk/phase3/includes/DatabasePostgres.php |
— | — | @@ -505,12 +505,18 @@ |
506 | 506 | } |
507 | 507 | |
508 | 508 | function freeResult( $res ) { |
| 509 | + if ( $res instanceof ResultWrapper ) { |
| 510 | + $res = $res->result; |
| 511 | + } |
509 | 512 | if ( !@pg_free_result( $res ) ) { |
510 | 513 | throw new DBUnexpectedError($this, "Unable to free Postgres result\n" ); |
511 | 514 | } |
512 | 515 | } |
513 | 516 | |
514 | 517 | function fetchObject( $res ) { |
| 518 | + if ( $res instanceof ResultWrapper ) { |
| 519 | + $res = $res->result; |
| 520 | + } |
515 | 521 | @$row = pg_fetch_object( $res ); |
516 | 522 | # FIXME: HACK HACK HACK HACK debug |
517 | 523 | |
— | — | @@ -524,6 +530,9 @@ |
525 | 531 | } |
526 | 532 | |
527 | 533 | function fetchRow( $res ) { |
| 534 | + if ( $res instanceof ResultWrapper ) { |
| 535 | + $res = $res->result; |
| 536 | + } |
528 | 537 | @$row = pg_fetch_array( $res ); |
529 | 538 | if( pg_last_error($this->mConn) ) { |
530 | 539 | throw new DBUnexpectedError($this, 'SQL error: ' . htmlspecialchars( pg_last_error($this->mConn) ) ); |
— | — | @@ -532,14 +541,27 @@ |
533 | 542 | } |
534 | 543 | |
535 | 544 | function numRows( $res ) { |
| 545 | + if ( $res instanceof ResultWrapper ) { |
| 546 | + $res = $res->result; |
| 547 | + } |
536 | 548 | @$n = pg_num_rows( $res ); |
537 | 549 | if( pg_last_error($this->mConn) ) { |
538 | 550 | throw new DBUnexpectedError($this, 'SQL error: ' . htmlspecialchars( pg_last_error($this->mConn) ) ); |
539 | 551 | } |
540 | 552 | return $n; |
541 | 553 | } |
542 | | - function numFields( $res ) { return pg_num_fields( $res ); } |
543 | | - function fieldName( $res, $n ) { return pg_field_name( $res, $n ); } |
| 554 | + function numFields( $res ) { |
| 555 | + if ( $res instanceof ResultWrapper ) { |
| 556 | + $res = $res->result; |
| 557 | + } |
| 558 | + return pg_num_fields( $res ); |
| 559 | + } |
| 560 | + function fieldName( $res, $n ) { |
| 561 | + if ( $res instanceof ResultWrapper ) { |
| 562 | + $res = $res->result; |
| 563 | + } |
| 564 | + return pg_field_name( $res, $n ); |
| 565 | + } |
544 | 566 | |
545 | 567 | /** |
546 | 568 | * This must be called after nextSequenceVal |
— | — | @@ -548,7 +570,13 @@ |
549 | 571 | return $this->mInsertId; |
550 | 572 | } |
551 | 573 | |
552 | | - function dataSeek( $res, $row ) { return pg_result_seek( $res, $row ); } |
| 574 | + function dataSeek( $res, $row ) { |
| 575 | + if ( $res instanceof ResultWrapper ) { |
| 576 | + $res = $res->result; |
| 577 | + } |
| 578 | + return pg_result_seek( $res, $row ); |
| 579 | + } |
| 580 | + |
553 | 581 | function lastError() { |
554 | 582 | if ( $this->mConn ) { |
555 | 583 | return pg_last_error(); |
— | — | @@ -917,7 +945,7 @@ |
918 | 946 | . "WHERE c.relnamespace = n.oid AND c.relname = $etable AND n.nspname = $eschema " |
919 | 947 | . "AND c.relkind IN ('" . implode("','", $types) . "')"; |
920 | 948 | $res = $this->query( $SQL ); |
921 | | - $count = $res ? pg_num_rows($res) : 0; |
| 949 | + $count = $res ? $res->numRows() : 0; |
922 | 950 | if ($res) |
923 | 951 | $this->freeResult( $res ); |
924 | 952 | return $count ? true : false; |
— | — | @@ -950,7 +978,7 @@ |
951 | 979 | $this->addQuotes($trigger))); |
952 | 980 | if (!$res) |
953 | 981 | return NULL; |
954 | | - $rows = pg_num_rows($res); |
| 982 | + $rows = $res->numRows(); |
955 | 983 | $this->freeResult($res); |
956 | 984 | return $rows; |
957 | 985 | } |
— | — | @@ -974,7 +1002,7 @@ |
975 | 1003 | $res = $this->query($SQL); |
976 | 1004 | if (!$res) |
977 | 1005 | return NULL; |
978 | | - $rows = pg_num_rows($res); |
| 1006 | + $rows = $res->numRows(); |
979 | 1007 | $this->freeResult($res); |
980 | 1008 | return $rows; |
981 | 1009 | } |
— | — | @@ -987,7 +1015,12 @@ |
988 | 1016 | $SQL = "SELECT rolname FROM pg_catalog.pg_namespace n, pg_catalog.pg_roles r " |
989 | 1017 | ."WHERE n.nspowner=r.oid AND n.nspname = '$eschema'"; |
990 | 1018 | $res = $this->query( $SQL ); |
991 | | - $owner = $res ? pg_num_rows($res) ? pg_fetch_result($res, 0, 0) : false : false; |
| 1019 | + if ( $res && $res->numRows() ) { |
| 1020 | + $row = $res->fetchRow(); |
| 1021 | + $owner = $row->rolname; |
| 1022 | + } else { |
| 1023 | + $owner = false; |
| 1024 | + } |
992 | 1025 | if ($res) |
993 | 1026 | $this->freeResult($res); |
994 | 1027 | return $owner; |
— | — | @@ -1005,7 +1038,7 @@ |
1006 | 1039 | . "WHERE c.relnamespace = n.oid AND c.relname = '$etable' AND n.nspname = '$eschema' " |
1007 | 1040 | . "AND a.attrelid = c.oid AND a.attname = '$ecol'"; |
1008 | 1041 | $res = $this->query( $SQL, $fname ); |
1009 | | - $count = $res ? pg_num_rows($res) : 0; |
| 1042 | + $count = $res ? $res->numRows() : 0; |
1010 | 1043 | if ($res) |
1011 | 1044 | $this->freeResult( $res ); |
1012 | 1045 | return $count; |
— | — | @@ -1071,7 +1104,8 @@ |
1072 | 1105 | $tss = $this->addQuotes($wgDBts2schema); |
1073 | 1106 | $pgp = $this->addQuotes($wgDBport); |
1074 | 1107 | $dbn = $this->addQuotes($this->mDBname); |
1075 | | - $ctype = pg_fetch_result($this->doQuery("SHOW lc_ctype"),0,0); |
| 1108 | + $ctypeRow = $this->doQuery("SHOW lc_ctype")->fetchArray(); |
| 1109 | + $ctype = $ctypeRow[0]; |
1076 | 1110 | |
1077 | 1111 | $SQL = "UPDATE mediawiki_version SET mw_version=$mwv, pg_version=$pgv, pg_user=$pgu, ". |
1078 | 1112 | "mw_schema = $mws, ts2_schema = $tss, pg_port=$pgp, pg_dbname=$dbn, ". |
Index: trunk/phase3/includes/Database.php |
— | — | @@ -678,9 +678,12 @@ |
679 | 679 | * Usually aborts on failure. If errors are explicitly ignored, returns success. |
680 | 680 | * |
681 | 681 | * @param $sql String: SQL query |
682 | | - * @param $fname String: Name of the calling function, for profiling/SHOW PROCESSLIST comment (you can use __METHOD__ or add some extra info) |
683 | | - * @param $tempIgnore Bool: Whether to avoid throwing an exception on errors... maybe best to catch the exception instead? |
684 | | - * @return Result object to feed to fetchObject, fetchRow, ...; or false on failure if $tempIgnore set |
| 682 | + * @param $fname String: Name of the calling function, for profiling/SHOW PROCESSLIST |
| 683 | + * comment (you can use __METHOD__ or add some extra info) |
| 684 | + * @param $tempIgnore Bool: Whether to avoid throwing an exception on errors... |
| 685 | + * maybe best to catch the exception instead? |
| 686 | + * @return true for a successful write query, ResultWrapper object for a successful read query, |
| 687 | + * or false on failure if $tempIgnore set |
685 | 688 | * @throws DBQueryError Thrown when the database returns an error of any kind |
686 | 689 | */ |
687 | 690 | public function query( $sql, $fname = '', $tempIgnore = false ) { |
— | — | @@ -765,7 +768,7 @@ |
766 | 769 | wfProfileOut( $queryProf ); |
767 | 770 | wfProfileOut( $totalProf ); |
768 | 771 | } |
769 | | - return $ret; |
| 772 | + return $this->resultObject( $ret ); |
770 | 773 | } |
771 | 774 | |
772 | 775 | /** |
— | — | @@ -909,6 +912,9 @@ |
910 | 913 | * Free a result object |
911 | 914 | */ |
912 | 915 | function freeResult( $res ) { |
| 916 | + if ( $res instanceof ResultWrapper ) { |
| 917 | + $res = $res->result; |
| 918 | + } |
913 | 919 | if ( !@/**/mysql_free_result( $res ) ) { |
914 | 920 | throw new DBUnexpectedError( $this, "Unable to free MySQL result" ); |
915 | 921 | } |
— | — | @@ -924,6 +930,9 @@ |
925 | 931 | * @throws DBUnexpectedError Thrown if the database returns an error |
926 | 932 | */ |
927 | 933 | function fetchObject( $res ) { |
| 934 | + if ( $res instanceof ResultWrapper ) { |
| 935 | + $res = $res->result; |
| 936 | + } |
928 | 937 | @/**/$row = mysql_fetch_object( $res ); |
929 | 938 | if( $this->lastErrno() ) { |
930 | 939 | throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) ); |
— | — | @@ -940,6 +949,9 @@ |
941 | 950 | * @throws DBUnexpectedError Thrown if the database returns an error |
942 | 951 | */ |
943 | 952 | function fetchRow( $res ) { |
| 953 | + if ( $res instanceof ResultWrapper ) { |
| 954 | + $res = $res->result; |
| 955 | + } |
944 | 956 | @/**/$row = mysql_fetch_array( $res ); |
945 | 957 | if ( $this->lastErrno() ) { |
946 | 958 | throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) ); |
— | — | @@ -951,6 +963,9 @@ |
952 | 964 | * Get the number of rows in a result object |
953 | 965 | */ |
954 | 966 | function numRows( $res ) { |
| 967 | + if ( $res instanceof ResultWrapper ) { |
| 968 | + $res = $res->result; |
| 969 | + } |
955 | 970 | @/**/$n = mysql_num_rows( $res ); |
956 | 971 | if( $this->lastErrno() ) { |
957 | 972 | throw new DBUnexpectedError( $this, 'Error in numRows(): ' . htmlspecialchars( $this->lastError() ) ); |
— | — | @@ -962,14 +977,24 @@ |
963 | 978 | * Get the number of fields in a result object |
964 | 979 | * See documentation for mysql_num_fields() |
965 | 980 | */ |
966 | | - function numFields( $res ) { return mysql_num_fields( $res ); } |
| 981 | + function numFields( $res ) { |
| 982 | + if ( $res instanceof ResultWrapper ) { |
| 983 | + $res = $res->result; |
| 984 | + } |
| 985 | + return mysql_num_fields( $res ); |
| 986 | + } |
967 | 987 | |
968 | 988 | /** |
969 | 989 | * Get a field name in a result object |
970 | 990 | * See documentation for mysql_field_name(): |
971 | 991 | * http://www.php.net/mysql_field_name |
972 | 992 | */ |
973 | | - function fieldName( $res, $n ) { return mysql_field_name( $res, $n ); } |
| 993 | + function fieldName( $res, $n ) { |
| 994 | + if ( $res instanceof ResultWrapper ) { |
| 995 | + $res = $res->result; |
| 996 | + } |
| 997 | + return mysql_field_name( $res, $n ); |
| 998 | + } |
974 | 999 | |
975 | 1000 | /** |
976 | 1001 | * Get the inserted value of an auto-increment row |
— | — | @@ -987,7 +1012,12 @@ |
988 | 1013 | * Change the position of the cursor in a result object |
989 | 1014 | * See mysql_data_seek() |
990 | 1015 | */ |
991 | | - function dataSeek( $res, $row ) { return mysql_data_seek( $res, $row ); } |
| 1016 | + function dataSeek( $res, $row ) { |
| 1017 | + if ( $res instanceof ResultWrapper ) { |
| 1018 | + $res = $res->result; |
| 1019 | + } |
| 1020 | + return mysql_data_seek( $res, $row ); |
| 1021 | + } |
992 | 1022 | |
993 | 1023 | /** |
994 | 1024 | * Get the last error number |
— | — | @@ -1352,9 +1382,9 @@ |
1353 | 1383 | function fieldInfo( $table, $field ) { |
1354 | 1384 | $table = $this->tableName( $table ); |
1355 | 1385 | $res = $this->query( "SELECT * FROM $table LIMIT 1" ); |
1356 | | - $n = mysql_num_fields( $res ); |
| 1386 | + $n = mysql_num_fields( $res->result ); |
1357 | 1387 | for( $i = 0; $i < $n; $i++ ) { |
1358 | | - $meta = mysql_fetch_field( $res, $i ); |
| 1388 | + $meta = mysql_fetch_field( $res->result, $i ); |
1359 | 1389 | if( $field == $meta->name ) { |
1360 | 1390 | return new MySQLField($meta); |
1361 | 1391 | } |
— | — | @@ -1366,6 +1396,9 @@ |
1367 | 1397 | * mysql_field_type() wrapper |
1368 | 1398 | */ |
1369 | 1399 | function fieldType( $res, $index ) { |
| 1400 | + if ( $res instanceof ResultWrapper ) { |
| 1401 | + $res = $res->result; |
| 1402 | + } |
1370 | 1403 | return mysql_field_type( $res, $index ); |
1371 | 1404 | } |
1372 | 1405 | |
— | — | @@ -2001,7 +2034,12 @@ |
2002 | 2035 | */ |
2003 | 2036 | function resultObject( $result ) { |
2004 | 2037 | if( empty( $result ) ) { |
2005 | | - return NULL; |
| 2038 | + return false; |
| 2039 | + } elseif ( $result instanceof ResultWrapper ) { |
| 2040 | + return $result; |
| 2041 | + } elseif ( $result === true ) { |
| 2042 | + // Successful write query |
| 2043 | + return $result; |
2006 | 2044 | } else { |
2007 | 2045 | return new ResultWrapper( $this, $result ); |
2008 | 2046 | } |
— | — | @@ -2176,7 +2214,7 @@ |
2177 | 2215 | $cmd = $this->replaceVars( $cmd ); |
2178 | 2216 | $res = $this->query( $cmd, __METHOD__, true ); |
2179 | 2217 | if ( $resultCallback ) { |
2180 | | - call_user_func( $resultCallback, $this->resultObject( $res ) ); |
| 2218 | + call_user_func( $resultCallback, $res ); |
2181 | 2219 | } |
2182 | 2220 | |
2183 | 2221 | if ( false === $res ) { |
— | — | @@ -2248,36 +2286,51 @@ |
2249 | 2287 | var $db, $result; |
2250 | 2288 | |
2251 | 2289 | /** |
2252 | | - * @todo document |
| 2290 | + * Create a new result object from a result resource and a Database object |
2253 | 2291 | */ |
2254 | | - function ResultWrapper( &$database, $result ) { |
2255 | | - $this->db =& $database; |
2256 | | - $this->result =& $result; |
| 2292 | + function ResultWrapper( $database, $result ) { |
| 2293 | + $this->db = $database; |
| 2294 | + if ( $result instanceof ResultWrapper ) { |
| 2295 | + $this->result = $result->result; |
| 2296 | + } else { |
| 2297 | + $this->result = $result; |
| 2298 | + } |
2257 | 2299 | } |
2258 | 2300 | |
2259 | 2301 | /** |
2260 | | - * @todo document |
| 2302 | + * Get the number of rows in a result object |
2261 | 2303 | */ |
2262 | 2304 | function numRows() { |
2263 | 2305 | return $this->db->numRows( $this->result ); |
2264 | 2306 | } |
2265 | 2307 | |
2266 | 2308 | /** |
2267 | | - * @todo document |
| 2309 | + * Fetch the next row from the given result object, in object form. |
| 2310 | + * Fields can be retrieved with $row->fieldname, with fields acting like |
| 2311 | + * member variables. |
| 2312 | + * |
| 2313 | + * @param $res SQL result object as returned from Database::query(), etc. |
| 2314 | + * @return MySQL row object |
| 2315 | + * @throws DBUnexpectedError Thrown if the database returns an error |
2268 | 2316 | */ |
2269 | 2317 | function fetchObject() { |
2270 | 2318 | return $this->db->fetchObject( $this->result ); |
2271 | 2319 | } |
2272 | 2320 | |
2273 | 2321 | /** |
2274 | | - * @todo document |
| 2322 | + * Fetch the next row from the given result object, in associative array |
| 2323 | + * form. Fields are retrieved with $row['fieldname']. |
| 2324 | + * |
| 2325 | + * @param $res SQL result object as returned from Database::query(), etc. |
| 2326 | + * @return MySQL row object |
| 2327 | + * @throws DBUnexpectedError Thrown if the database returns an error |
2275 | 2328 | */ |
2276 | 2329 | function fetchRow() { |
2277 | 2330 | return $this->db->fetchRow( $this->result ); |
2278 | 2331 | } |
2279 | 2332 | |
2280 | 2333 | /** |
2281 | | - * @todo document |
| 2334 | + * Free a result object |
2282 | 2335 | */ |
2283 | 2336 | function free() { |
2284 | 2337 | $this->db->freeResult( $this->result ); |
— | — | @@ -2285,10 +2338,17 @@ |
2286 | 2339 | unset( $this->db ); |
2287 | 2340 | } |
2288 | 2341 | |
| 2342 | + /** |
| 2343 | + * Change the position of the cursor in a result object |
| 2344 | + * See mysql_data_seek() |
| 2345 | + */ |
2289 | 2346 | function seek( $row ) { |
2290 | 2347 | $this->db->dataSeek( $this->result, $row ); |
2291 | 2348 | } |
2292 | 2349 | |
| 2350 | + /** |
| 2351 | + * Reset the cursor to the start of the result set |
| 2352 | + */ |
2293 | 2353 | function rewind() { |
2294 | 2354 | if ($this->numRows()) { |
2295 | 2355 | $this->db->dataSeek($this->result, 0); |