home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 March / PCWorld_2003-03_cd.bin / Software / Vyzkuste / phptriad / phptriad2-2-1.exe / php / pear / DB / pgsql.php < prev    next >
Encoding:
PHP Script  |  2001-11-13  |  26.3 KB  |  811 lines

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