| [ Index ] |
|
Code source de Dolibarr 2.0.1 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2003 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp> | 17 // | Stig Bakken <ssb@php.net> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: pgsql.php,v 1.1 2004/06/30 16:28:15 rodolphe Exp $ 21 // 22 // Database independent query interface definition for PHP's PostgreSQL 23 // extension. 24 // 25 26 require_once 'DB/common.php'; 27 28 class DB_pgsql extends DB_common 29 { 30 // {{{ properties 31 32 var $connection; 33 var $phptype, $dbsyntax; 34 var $prepare_tokens = array(); 35 var $prepare_types = array(); 36 var $transaction_opcount = 0; 37 var $dsn = array(); 38 var $row = array(); 39 var $num_rows = array(); 40 var $affected = 0; 41 var $autocommit = true; 42 var $fetchmode = DB_FETCHMODE_ORDERED; 43 44 // }}} 45 // {{{ constructor 46 47 function DB_pgsql() 48 { 49 $this->DB_common(); 50 $this->phptype = 'pgsql'; 51 $this->dbsyntax = 'pgsql'; 52 $this->features = array( 53 'prepare' => false, 54 'pconnect' => true, 55 'transactions' => true, 56 'limit' => 'alter' 57 ); 58 $this->errorcode_map = array( 59 ); 60 } 61 62 // }}} 63 // {{{ connect() 64 65 /** 66 * Connect to a database and log in as the specified user. 67 * 68 * @param $dsn the data source name (see DB::parseDSN for syntax) 69 * @param $persistent (optional) whether the connection should 70 * be persistent 71 * 72 * @return int DB_OK on success, a DB error code on failure 73 */ 74 function connect($dsninfo, $persistent = false) 75 { 76 if (!DB::assertExtension('pgsql')) 77 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 78 79 $this->dsn = $dsninfo; 80 $protocol = (isset($dsninfo['protocol'])) ? $dsninfo['protocol'] : 'tcp'; 81 $connstr = ''; 82 83 if ($protocol == 'tcp') { 84 if (!empty($dsninfo['hostspec'])) { 85 $connstr = 'host=' . $dsninfo['hostspec']; 86 } 87 if (!empty($dsninfo['port'])) { 88 $connstr .= ' port=' . $dsninfo['port']; 89 } 90 } 91 92 if (isset($dsninfo['database'])) { 93 $connstr .= ' dbname=\'' . addslashes($dsninfo['database']) . '\''; 94 } 95 if (!empty($dsninfo['username'])) { 96 $connstr .= ' user=\'' . addslashes($dsninfo['username']) . '\''; 97 } 98 if (!empty($dsninfo['password'])) { 99 $connstr .= ' password=\'' . addslashes($dsninfo['password']) . '\''; 100 } 101 if (!empty($dsninfo['options'])) { 102 $connstr .= ' options=' . $dsninfo['options']; 103 } 104 if (!empty($dsninfo['tty'])) { 105 $connstr .= ' tty=' . $dsninfo['tty']; 106 } 107 108 $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; 109 // catch error 110 ob_start(); 111 $conn = $connect_function($connstr); 112 $error = ob_get_contents(); 113 ob_end_clean(); 114 if ($conn == false) { 115 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, 116 null, null, strip_tags($error)); 117 } 118 $this->connection = $conn; 119 return DB_OK; 120 } 121 122 // }}} 123 // {{{ disconnect() 124 125 /** 126 * Log out and disconnect from the database. 127 * 128 * @return bool TRUE on success, FALSE if not connected. 129 */ 130 function disconnect() 131 { 132 $ret = @pg_close($this->connection); 133 $this->connection = null; 134 return $ret; 135 } 136 137 // }}} 138 // {{{ simpleQuery() 139 140 /** 141 * Send a query to PostgreSQL and return the results as a 142 * PostgreSQL resource identifier. 143 * 144 * @param $query the SQL query 145 * 146 * @return int returns a valid PostgreSQL result for successful SELECT 147 * queries, DB_OK for other successful queries. A DB error code 148 * is returned on failure. 149 */ 150 function simpleQuery($query) 151 { 152 $ismanip = DB::isManip($query); 153 $this->last_query = $query; 154 $query = $this->modifyQuery($query); 155 if (!$this->autocommit && $ismanip) { 156 if ($this->transaction_opcount == 0) { 157 $result = @pg_exec($this->connection, "begin;"); 158 if (!$result) { 159 return $this->pgsqlRaiseError(); 160 } 161 } 162 $this->transaction_opcount++; 163 } 164 $result = @pg_exec($this->connection, $query); 165 if (!$result) { 166 return $this->pgsqlRaiseError(); 167 } 168 // Determine which queries that should return data, and which 169 // should return an error code only. 170 if ($ismanip) { 171 $this->affected = @pg_cmdtuples($result); 172 return DB_OK; 173 } elseif (preg_match('/^\s*\(?\s*SELECT\s+/si', $query) && 174 !preg_match('/^\s*\(?\s*SELECT\s+INTO\s/si', $query)) { 175 /* PostgreSQL commands: 176 ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, 177 CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, 178 GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, 179 REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, 180 UNLISTEN, UPDATE, VACUUM 181 */ 182 $this->row[$result] = 0; // reset the row counter. 183 $numrows = $this->numrows($result); 184 if (is_object($numrows)) { 185 return $numrows; 186 } 187 $this->num_rows[$result] = $numrows; 188 $this->affected = 0; 189 return $result; 190 } else { 191 $this->affected = 0; 192 return DB_OK; 193 } 194 } 195 196 // }}} 197 // {{{ nextResult() 198 199 /** 200 * Move the internal pgsql result pointer to the next available result 201 * 202 * @param a valid fbsql result resource 203 * 204 * @access public 205 * 206 * @return true if a result is available otherwise return false 207 */ 208 function nextResult($result) 209 { 210 return false; 211 } 212 213 // }}} 214 // {{{ errorCode() 215 216 /** 217 * Map native error codes to DB's portable ones. Requires that 218 * the DB implementation's constructor fills in the $errorcode_map 219 * property. 220 * 221 * @param $nativecode the native error code, as returned by the backend 222 * database extension (string or integer) 223 * 224 * @return int a portable DB error code, or FALSE if this DB 225 * implementation has no mapping for the given error code. 226 */ 227 228 function errorCode($errormsg) 229 { 230 static $error_regexps; 231 if (empty($error_regexps)) { 232 $error_regexps = array( 233 '/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => DB_ERROR_NOSUCHTABLE, 234 '/table [\"\'].*[\"\'] does not exist/' => DB_ERROR_NOSUCHTABLE, 235 '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => DB_ERROR_ALREADY_EXISTS, 236 '/divide by zero$/' => DB_ERROR_DIVZERO, 237 '/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER, 238 '/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD, 239 '/parser: parse error at or near \"/' => DB_ERROR_SYNTAX, 240 '/referential integrity violation/' => DB_ERROR_CONSTRAINT 241 ); 242 } 243 foreach ($error_regexps as $regexp => $code) { 244 if (preg_match($regexp, $errormsg)) { 245 return $code; 246 } 247 } 248 // Fall back to DB_ERROR if there was no mapping. 249 return DB_ERROR; 250 } 251 252 // }}} 253 // {{{ fetchInto() 254 255 /** 256 * Fetch a row and insert the data into an existing array. 257 * 258 * @param $result PostgreSQL result identifier 259 * @param $row (reference) array where data from the row is stored 260 * @param $fetchmode how the array data should be indexed 261 * @param $rownum the row number to fetch 262 * 263 * @return int DB_OK on success, a DB error code on failure 264 */ 265 function fetchInto($result, &$row, $fetchmode, $rownum=null) 266 { 267 $rownum = ($rownum !== null) ? $rownum : $this->row[$result]; 268 if ($rownum >= $this->num_rows[$result]) { 269 return null; 270 } 271 if ($fetchmode & DB_FETCHMODE_ASSOC) { 272 $row = @pg_fetch_array($result, $rownum, PGSQL_ASSOC); 273 } else { 274 $row = @pg_fetch_row($result, $rownum); 275 } 276 if (!$row) { 277 $err = pg_errormessage($this->connection); 278 if (!$err) { 279 return null; 280 } 281 return $this->pgsqlRaiseError(); 282 } 283 $this->row[$result] = ++$rownum; 284 return DB_OK; 285 } 286 287 // }}} 288 // {{{ freeResult() 289 290 /** 291 * Free the internal resources associated with $result. 292 * 293 * @param $result int PostgreSQL result identifier or DB statement identifier 294 * 295 * @return bool TRUE on success, FALSE if $result is invalid 296 */ 297 function freeResult($result) 298 { 299 if (is_resource($result)) { 300 return @pg_freeresult($result); 301 } 302 if (!isset($this->prepare_tokens[(int)$result])) { 303 return false; 304 } 305 unset($this->prepare_tokens[(int)$result]); 306 unset($this->prepare_types[(int)$result]); 307 unset($this->row[(int)$result]); 308 unset($this->num_rows[(int)$result]); 309 $this->affected = 0; 310 return true; 311 } 312 313 // }}} 314 // {{{ quote() 315 /** 316 * Quote the given string so it can be safely used within string delimiters 317 * in a query. 318 * @param $string mixed Data to be quoted 319 * @return mixed "NULL" string, quoted string or original data 320 */ 321 function quote($str = null) 322 { 323 switch (strtolower(gettype($str))) { 324 case 'null': 325 return 'NULL'; 326 case 'integer': 327 case 'double' : 328 return $str; 329 case 'boolean': 330 return $str ? 'TRUE' : 'FALSE'; 331 case 'string': 332 default: 333 $str = str_replace("'", "''", $str); 334 //PostgreSQL treats a backslash as an escape character. 335 $str = str_replace('\\', '\\\\', $str); 336 return "'$str'"; 337 } 338 } 339 // }}} 340 // {{{ numCols() 341 342 /** 343 * Get the number of columns in a result set. 344 * 345 * @param $result resource PostgreSQL result identifier 346 * 347 * @return int the number of columns per row in $result 348 */ 349 function numCols($result) 350 { 351 $cols = @pg_numfields($result); 352 if (!$cols) { 353 return $this->pgsqlRaiseError(); 354 } 355 return $cols; 356 } 357 358 // }}} 359 // {{{ numRows() 360 361 /** 362 * Get the number of rows in a result set. 363 * 364 * @param $result resource PostgreSQL result identifier 365 * 366 * @return int the number of rows in $result 367 */ 368 function numRows($result) 369 { 370 $rows = @pg_numrows($result); 371 if ($rows === null) { 372 return $this->pgsqlRaiseError(); 373 } 374 return $rows; 375 } 376 377 // }}} 378 // {{{ errorNative() 379 380 /** 381 * Get the native error code of the last error (if any) that 382 * occured on the current connection. 383 * 384 * @return int native PostgreSQL error code 385 */ 386 function errorNative() 387 { 388 return pg_errormessage($this->connection); 389 } 390 391 // }}} 392 // {{{ autoCommit() 393 394 /** 395 * Enable/disable automatic commits 396 */ 397 function autoCommit($onoff = false) 398 { 399 // XXX if $this->transaction_opcount > 0, we should probably 400 // issue a warning here. 401 $this->autocommit = $onoff ? true : false; 402 return DB_OK; 403 } 404 405 // }}} 406 // {{{ commit() 407 408 /** 409 * Commit the current transaction. 410 */ 411 function commit() 412 { 413 if ($this->transaction_opcount > 0) { 414 // (disabled) hack to shut up error messages from libpq.a 415 //@fclose(@fopen("php://stderr", "w")); 416 $result = @pg_exec($this->connection, "end;"); 417 $this->transaction_opcount = 0; 418 if (!$result) { 419 return $this->pgsqlRaiseError(); 420 } 421 } 422 return DB_OK; 423 } 424 425 // }}} 426 // {{{ rollback() 427 428 /** 429 * Roll back (undo) the current transaction. 430 */ 431 function rollback() 432 { 433 if ($this->transaction_opcount > 0) { 434 $result = @pg_exec($this->connection, "abort;"); 435 $this->transaction_opcount = 0; 436 if (!$result) { 437 return $this->pgsqlRaiseError(); 438 } 439 } 440 return DB_OK; 441 } 442 443 // }}} 444 // {{{ affectedRows() 445 446 /** 447 * Gets the number of rows affected by the last query. 448 * if the last query was a select, returns 0. 449 * 450 * @return int number of rows affected by the last query or DB_ERROR 451 */ 452 function affectedRows() 453 { 454 return $this->affected; 455 } 456 // }}} 457 // {{{ nextId() 458 459 /** 460 * Get the next value in a sequence. 461 * 462 * We are using native PostgreSQL sequences. If a sequence does 463 * not exist, it will be created, unless $ondemand is false. 464 * 465 * @access public 466 * @param string $seq_name the name of the sequence 467 * @param bool $ondemand whether to create the sequence on demand 468 * @return a sequence integer, or a DB error 469 */ 470 function nextId($seq_name, $ondemand = true) 471 { 472 $seqname = $this->getSequenceName($seq_name); 473 $repeat = false; 474 do { 475 $this->pushErrorHandling(PEAR_ERROR_RETURN); 476 $result = $this->query("SELECT NEXTVAL('$seqname}')"); 477 $this->popErrorHandling(); 478 if ($ondemand && DB::isError($result) && 479 $result->getCode() == DB_ERROR_NOSUCHTABLE) { 480 $repeat = true; 481 $this->pushErrorHandling(PEAR_ERROR_RETURN); 482 $result = $this->createSequence($seq_name); 483 $this->popErrorHandling(); 484 if (DB::isError($result)) { 485 return $this->raiseError($result); 486 } 487 } else { 488 $repeat = false; 489 } 490 } while ($repeat); 491 if (DB::isError($result)) { 492 return $this->raiseError($result); 493 } 494 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); 495 $result->free(); 496 return $arr[0]; 497 } 498 499 // }}} 500 // {{{ createSequence() 501 502 /** 503 * Create the sequence 504 * 505 * @param string $seq_name the name of the sequence 506 * @return mixed DB_OK on success or DB error on error 507 * @access public 508 */ 509 function createSequence($seq_name) 510 { 511 $seqname = $this->getSequenceName($seq_name); 512 $result = $this->query("CREATE SEQUENCE $seqname}"); 513 return $result; 514 } 515 516 // }}} 517 // {{{ dropSequence() 518 519 /** 520 * Drop a sequence 521 * 522 * @param string $seq_name the name of the sequence 523 * @return mixed DB_OK on success or DB error on error 524 * @access public 525 */ 526 function dropSequence($seq_name) 527 { 528 $seqname = $this->getSequenceName($seq_name); 529 return $this->query("DROP SEQUENCE $seqname}"); 530 } 531 532 // }}} 533 // {{{ modifyLimitQuery() 534 535 function modifyLimitQuery($query, $from, $count) 536 { 537 $query = $query . " LIMIT $count OFFSET $from"; 538 return $query; 539 } 540 541 // }}} 542 // {{{ pgsqlRaiseError() 543 544 function pgsqlRaiseError($errno = null) 545 { 546 $native = $this->errorNative(); 547 if ($errno === null) { 548 $err = $this->errorCode($native); 549 } else { 550 $err = $errno; 551 } 552 return $this->raiseError($err, null, null, null, $native); 553 } 554 555 // }}} 556 // {{{ _pgFieldFlags() 557 558 /** 559 * Flags of a Field 560 * 561 * @param int $resource PostgreSQL result identifier 562 * @param int $num_field the field number 563 * 564 * @return string The flags of the field ("not_null", "default_xx", "primary_key", 565 * "unique" and "multiple_key" are supported) 566 * @access private 567 */ 568 function _pgFieldFlags($resource, $num_field, $table_name) 569 { 570 $field_name = @pg_fieldname($resource, $num_field); 571 572 $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef 573 FROM pg_attribute f, pg_class tab, pg_type typ 574 WHERE tab.relname = typ.typname 575 AND typ.typrelid = f.attrelid 576 AND f.attname = '$field_name' 577 AND tab.relname = '$table_name'"); 578 if (@pg_numrows($result) > 0) { 579 $row = @pg_fetch_row($result, 0); 580 $flags = ($row[0] == 't') ? 'not_null ' : ''; 581 582 if ($row[1] == 't') { 583 $result = @pg_exec($this->connection, "SELECT a.adsrc 584 FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a 585 WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid 586 AND f.attrelid = a.adrelid AND f.attname = '$field_name' 587 AND tab.relname = '$table_name' AND f.attnum = a.adnum"); 588 $row = @pg_fetch_row($result, 0); 589 $num = str_replace('\'', '', $row[0]); 590 591 $flags .= "default_$num "; 592 } 593 } 594 $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey 595 FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i 596 WHERE tab.relname = typ.typname 597 AND typ.typrelid = f.attrelid 598 AND f.attrelid = i.indrelid 599 AND f.attname = '$field_name' 600 AND tab.relname = '$table_name'"); 601 $count = @pg_numrows($result); 602 603 for ($i = 0; $i < $count ; $i++) { 604 $row = @pg_fetch_row($result, $i); 605 $keys = explode(" ", $row[2]); 606 607 if (in_array($num_field + 1, $keys)) { 608 $flags .= ($row[0] == 't') ? 'unique ' : ''; 609 $flags .= ($row[1] == 't') ? 'primary ' : ''; 610 if (count($keys) > 1) 611 $flags .= 'multiple_key '; 612 } 613 } 614 615 return trim($flags); 616 } 617 618 // }}} 619 // {{{ tableInfo() 620 621 /** 622 * Returns information about a table or a result set 623 * 624 * NOTE: doesn't support table name and flags if called from a db_result 625 * 626 * @param mixed $resource PostgreSQL result identifier or table name 627 * @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or 628 * DB_TABLEINFO_ORDER) 629 * 630 * @return array An array with all the information 631 */ 632 function tableInfo($result, $mode = null) 633 { 634 $count = 0; 635 $id = 0; 636 $res = array(); 637 638 /* 639 * depending on $mode, metadata returns the following values: 640 * 641 * - mode is false (default): 642 * $result[]: 643 * [0]["table"] table name 644 * [0]["name"] field name 645 * [0]["type"] field type 646 * [0]["len"] field length 647 * [0]["flags"] field flags 648 * 649 * - mode is DB_TABLEINFO_ORDER 650 * $result[]: 651 * ["num_fields"] number of metadata records 652 * [0]["table"] table name 653 * [0]["name"] field name 654 * [0]["type"] field type 655 * [0]["len"] field length 656 * [0]["flags"] field flags 657 * ["order"][field name] index of field named "field name" 658 * The last one is used, if you have a field name, but no index. 659 * Test: if (isset($result['meta']['myfield'])) { ... 660 * 661 * - mode is DB_TABLEINFO_ORDERTABLE 662 * the same as above. but additionally 663 * ["ordertable"][table name][field name] index of field 664 * named "field name" 665 * 666 * this is, because if you have fields from different 667 * tables with the same field name * they override each 668 * other with DB_TABLEINFO_ORDER 669 * 670 * you can combine DB_TABLEINFO_ORDER and 671 * DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER | 672 * DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL 673 */ 674 675 // if $result is a string, then we want information about a 676 // table without a resultset 677 678 if (is_string($result)) { 679 $id = @pg_exec($this->connection,"SELECT * FROM $result LIMIT 0"); 680 if (empty($id)) { 681 return $this->pgsqlRaiseError(); 682 } 683 } else { // else we want information about a resultset 684 $id = $result; 685 if (empty($id)) { 686 return $this->pgsqlRaiseError(); 687 } 688 } 689 690 $count = @pg_numfields($id); 691 692 // made this IF due to performance (one if is faster than $count if's) 693 if (empty($mode)) { 694 695 for ($i=0; $i<$count; $i++) { 696 $res[$i]['table'] = (is_string($result)) ? $result : ''; 697 $res[$i]['name'] = @pg_fieldname ($id, $i); 698 $res[$i]['type'] = @pg_fieldtype ($id, $i); 699 $res[$i]['len'] = @pg_fieldsize ($id, $i); 700 $res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldflags($id, $i, $result) : ''; 701 } 702 703 } else { // full 704 $res["num_fields"]= $count; 705 706 for ($i=0; $i<$count; $i++) { 707 $res[$i]['table'] = (is_string($result)) ? $result : ''; 708 $res[$i]['name'] = @pg_fieldname ($id, $i); 709 $res[$i]['type'] = @pg_fieldtype ($id, $i); 710 $res[$i]['len'] = @pg_fieldsize ($id, $i); 711 $res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldFlags($id, $i, $result) : ''; 712 if ($mode & DB_TABLEINFO_ORDER) { 713 $res['order'][$res[$i]['name']] = $i; 714 } 715 if ($mode & DB_TABLEINFO_ORDERTABLE) { 716 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 717 } 718 } 719 } 720 721 // free the result only if we were called on a table 722 if (is_string($result) && is_resource($id)) { 723 @pg_freeresult($id); 724 } 725 return $res; 726 } 727 728 // }}} 729 // {{{ getTablesQuery() 730 731 /** 732 * Returns the query needed to get some backend info 733 * @param string $type What kind of info you want to retrieve 734 * @return string The SQL query string 735 */ 736 function getSpecialQuery($type) 737 { 738 switch ($type) { 739 case 'tables': { 740 $sql = "SELECT c.relname as \"Name\" 741 FROM pg_class c, pg_user u 742 WHERE c.relowner = u.usesysid AND c.relkind = 'r' 743 AND not exists (select 1 from pg_views where viewname = c.relname) 744 AND c.relname !~ '^pg_' 745 UNION 746 SELECT c.relname as \"Name\" 747 FROM pg_class c 748 WHERE c.relkind = 'r' 749 AND not exists (select 1 from pg_views where viewname = c.relname) 750 AND not exists (select 1 from pg_user where usesysid = c.relowner) 751 AND c.relname !~ '^pg_'"; 752 break; 753 } 754 case 'views': { 755 // Table cols: viewname | viewowner | definition 756 $sql = "SELECT viewname FROM pg_views"; 757 break; 758 } 759 case 'users': { 760 // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil 761 $sql = 'SELECT usename FROM pg_user'; 762 break; 763 } 764 case 'databases': { 765 $sql = 'SELECT datname FROM pg_database'; 766 break; 767 } 768 case 'functions': { 769 $sql = 'SELECT proname FROM pg_proc'; 770 break; 771 } 772 default: 773 return null; 774 } 775 return $sql; 776 } 777 778 // }}} 779 780 } 781 782 // Local variables: 783 // tab-width: 4 784 // c-basic-offset: 4 785 // End: 786 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 12:29:37 2007 | par Balluche grâce à PHPXref 0.7 |
|