DB
[ class tree: DB ] [ index: DB ] [ all elements ]

Source for file pgsql.php

Documentation is available at pgsql.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 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 <hirokawa@php.net>                             |
  17. // |          Stig Bakken <ssb@php.net>                                   |
  18. // | Maintainer: Daniel Convissor <danielc@php.net>                       |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: pgsql.php,v 1.75 2004/04/07 05:12:28 danielc Exp $
  22.  
  23. require_once 'DB/common.php';
  24.  
  25. /**
  26.  * Database independent query interface definition for PHP's PostgreSQL
  27.  * extension.
  28.  *
  29.  * @package  DB
  30.  * @version  $Id: pgsql.php,v 1.75 2004/04/07 05:12:28 danielc Exp $
  31.  * @category Database
  32.  * @author   Rui Hirokawa <hirokawa@php.net>
  33.  * @author   Stig Bakken <ssb@php.net>
  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.  
  87.         $this->dsn = $dsninfo;
  88.         $protocol $dsninfo['protocol'$dsninfo['protocol''tcp';
  89.         $connstr '';
  90.  
  91.         if ($protocol == 'tcp'{
  92.             if ($dsninfo['hostspec']{
  93.                 $connstr .= 'host=' $dsninfo['hostspec'];
  94.             }
  95.             if ($dsninfo['port']{
  96.                 $connstr .= ' port=' $dsninfo['port'];
  97.             }
  98.         elseif ($protocol == 'unix'{
  99.             // Allow for pg socket in non-standard locations.
  100.             if ($dsninfo['socket']{
  101.                 $connstr .= 'host=' $dsninfo['socket'];
  102.             }
  103.         }
  104.  
  105.         if ($dsninfo['database']{
  106.             $connstr .= ' dbname=\'' addslashes($dsninfo['database']'\'';
  107.         }
  108.         if ($dsninfo['username']{
  109.             $connstr .= ' user=\'' addslashes($dsninfo['username']'\'';
  110.         }
  111.         if ($dsninfo['password']{
  112.             $connstr .= ' password=\'' addslashes($dsninfo['password']'\'';
  113.         }
  114.         if (!empty($dsninfo['options'])) {
  115.             $connstr .= ' options=' $dsninfo['options'];
  116.         }
  117.         if (!empty($dsninfo['tty'])) {
  118.             $connstr .= ' tty=' $dsninfo['tty'];
  119.         }
  120.  
  121.         $connect_function $persistent 'pg_pconnect' 'pg_connect';
  122.         // catch error
  123.         ob_start();
  124.         $conn $connect_function($connstr);
  125.         $error ob_get_contents();
  126.         ob_end_clean();
  127.         if ($conn == false{
  128.             return $this->raiseError(DB_ERROR_CONNECT_FAILEDnull,
  129.                                      nullnullstrip_tags($error));
  130.         }
  131.         $this->connection = $conn;
  132.         return DB_OK;
  133.     }
  134.  
  135.     // }}}
  136.     // {{{ disconnect()
  137.  
  138.     /**
  139.      * Log out and disconnect from the database.
  140.      *
  141.      * @return bool true on success, false if not connected.
  142.      */
  143.     function disconnect()
  144.     {
  145.         $ret @pg_close($this->connection);
  146.         $this->connection = null;
  147.         return $ret;
  148.     }
  149.  
  150.     // }}}
  151.     // {{{ simpleQuery()
  152.  
  153.     /**
  154.      * Send a query to PostgreSQL and return the results as a
  155.      * PostgreSQL resource identifier.
  156.      *
  157.      * @param $query the SQL query
  158.      *
  159.      * @return int returns a valid PostgreSQL result for successful SELECT
  160.      *  queries, DB_OK for other successful queries.  A DB error code
  161.      *  is returned on failure.
  162.      */
  163.     function simpleQuery($query)
  164.     {
  165.         $ismanip DB::isManip($query);
  166.         $this->last_query = $query;
  167.         $query $this->modifyQuery($query);
  168.         if (!$this->autocommit && $ismanip{
  169.             if ($this->transaction_opcount == 0{
  170.                 $result @pg_exec($this->connection'begin;');
  171.                 if (!$result{
  172.                     return $this->pgsqlRaiseError();
  173.                 }
  174.             }
  175.             $this->transaction_opcount++;
  176.         }
  177.         $result @pg_exec($this->connection$query);
  178.         if (!$result{
  179.             return $this->pgsqlRaiseError();
  180.         }
  181.         // Determine which queries that should return data, and which
  182.         // should return an error code only.
  183.         if ($ismanip{
  184.             $this->affected = @pg_cmdtuples($result);
  185.             return DB_OK;
  186.         elseif (preg_match('/^\s*\(?\s*(SELECT(?!\s+INTO)|EXPLAIN|SHOW)\s/si'$query)) {
  187.             /* PostgreSQL commands:
  188.                ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
  189.                CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
  190.                GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
  191.                REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
  192.                UNLISTEN, UPDATE, VACUUM
  193.             */
  194.             $this->row[(int)$result= 0; // reset the row counter.
  195.             $numrows $this->numrows($result);
  196.             if (is_object($numrows)) {
  197.                 return $numrows;
  198.             }
  199.             $this->num_rows[(int)$result$numrows;
  200.             $this->affected = 0;
  201.             return $result;
  202.         else {
  203.             $this->affected = 0;
  204.             return DB_OK;
  205.         }
  206.     }
  207.  
  208.     // }}}
  209.     // {{{ nextResult()
  210.  
  211.     /**
  212.      * Move the internal pgsql result pointer to the next available result
  213.      *
  214.      * @param valid fbsql result resource
  215.      *
  216.      * @access public
  217.      *
  218.      * @return true if a result is available otherwise return false
  219.      */
  220.     function nextResult($result)
  221.     {
  222.         return false;
  223.     }
  224.  
  225.     // }}}
  226.     // {{{ errorCode()
  227.  
  228.     /**
  229.      * Determine PEAR::DB error code from the database's text error message.
  230.      *
  231.      * @param  string  $errormsg  error message returned from the database
  232.      * @return integer  an error number from a DB error constant
  233.      */
  234.     function errorCode($errormsg)
  235.     {
  236.         static $error_regexps;
  237.         if (!isset($error_regexps)) {
  238.             $error_regexps = array(
  239.                 '/(([Rr]elation|[Ss]equence|[Tt]able)( [\"\'].*[\"\'])? does not exist|[Cc]lass ".+" not found)$/' => DB_ERROR_NOSUCHTABLE,
  240.                 '/[Cc]olumn [\"\'].*[\"\'] does not exist/' => DB_ERROR_NOSUCHFIELD,
  241.                 '/[Rr]elation [\"\'].*[\"\'] already exists|[Cc]annot insert a duplicate key into (a )?unique index.*/' => DB_ERROR_ALREADY_EXISTS,
  242.                 '/(divide|division) by zero$/'          => DB_ERROR_DIVZERO,
  243.                 '/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,
  244.                 '/invalid input syntax for integer/'    => DB_ERROR_INVALID_NUMBER,
  245.                 '/ttribute [\"\'].*[\"\'] not found$|[Rr]elation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,
  246.                 '/parser: parse error at or near \"/'   => DB_ERROR_SYNTAX,
  247.                 '/syntax error at/'                     => DB_ERROR_SYNTAX,
  248.                 '/violates not-null constraint/'        => DB_ERROR_CONSTRAINT_NOT_NULL,
  249.                 '/violates [\w ]+ constraint/'          => DB_ERROR_CONSTRAINT,
  250.                 '/referential integrity violation/'     => DB_ERROR_CONSTRAINT
  251.             );
  252.         }
  253.         foreach ($error_regexps as $regexp => $code{
  254.             if (preg_match($regexp$errormsg)) {
  255.                 return $code;
  256.             }
  257.         }
  258.         // Fall back to DB_ERROR if there was no mapping.
  259.         return DB_ERROR;
  260.     }
  261.  
  262.     // }}}
  263.     // {{{ fetchInto()
  264.  
  265.     /**
  266.      * Fetch a row and insert the data into an existing array.
  267.      *
  268.      * Formating of the array and the data therein are configurable.
  269.      * See DB_result::fetchInto() for more information.
  270.      *
  271.      * @param resource $result    query result identifier
  272.      * @param array    $arr       (reference) array where data from the row
  273.      *                             should be placed
  274.      * @param int      $fetchmode how the resulting array should be indexed
  275.      * @param int      $rownum    the row number to fetch
  276.      *
  277.      * @return mixed DB_OK on success, null when end of result set is
  278.      *                reached or on failure
  279.      *
  280.      * @see DB_result::fetchInto()
  281.      * @access private
  282.      */
  283.     function fetchInto($result&$arr$fetchmode$rownum=null)
  284.     {
  285.         $rownum ($rownum !== null$rownum $this->row[$result];
  286.         if ($rownum >= $this->num_rows[$result]{
  287.             return null;
  288.         }
  289.         if ($fetchmode DB_FETCHMODE_ASSOC{
  290.             $arr @pg_fetch_array($result$rownumPGSQL_ASSOC);
  291.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE && $arr{
  292.                 $arr array_change_key_case($arrCASE_LOWER);
  293.             }
  294.         else {
  295.             $arr @pg_fetch_row($result$rownum);
  296.         }
  297.         if (!$arr{
  298.             $err = pg_errormessage($this->connection);
  299.             if (!$err{
  300.                 return null;
  301.             }
  302.             return $this->pgsqlRaiseError();
  303.         }
  304.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  305.             $this->_rtrimArrayValues($arr);
  306.         }
  307.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  308.             $this->_convertNullArrayValuesToEmpty($arr);
  309.         }
  310.         $this->row[$result= ++$rownum;
  311.         return DB_OK;
  312.     }
  313.  
  314.     // }}}
  315.     // {{{ freeResult()
  316.  
  317.     /**
  318.      * Free the internal resources associated with $result.
  319.      *
  320.      * @param $result int PostgreSQL result identifier
  321.      *
  322.      * @return bool true on success, false if $result is invalid
  323.      */
  324.     function freeResult($result)
  325.     {
  326.         if (is_resource($result)) {
  327.             unset($this->row[(int)$result]);
  328.             unset($this->num_rows[(int)$result]);
  329.             $this->affected = 0;
  330.             return @pg_freeresult($result);
  331.         }
  332.         return false;
  333.     }
  334.  
  335.     // }}}
  336.     // {{{ quote()
  337.  
  338.     /**
  339.      * @deprecated  Deprecated in release 1.6.0
  340.      * @internal
  341.      */
  342.     function quote($str{
  343.         return $this->quoteSmart($str);
  344.     }
  345.  
  346.     // }}}
  347.     // {{{ quoteSmart()
  348.  
  349.     /**
  350.      * Format input so it can be safely used in a query
  351.      *
  352.      * @param mixed $in  data to be quoted
  353.      *
  354.      * @return mixed Submitted variable's type = returned value:
  355.      *                + null = the string <samp>NULL</samp>
  356.      *                + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp>
  357.      *                + integer or double = the unquoted number
  358.      *                + other (including strings and numeric strings) =
  359.      *                  the data escaped according to MySQL's settings
  360.      *                  then encapsulated between single quotes
  361.      *
  362.      * @internal
  363.      */
  364.     function quoteSmart($in)
  365.     {
  366.         if (is_int($in|| is_double($in)) {
  367.             return $in;
  368.         elseif (is_bool($in)) {
  369.             return $in 'TRUE' 'FALSE';
  370.         elseif (is_null($in)) {
  371.             return 'NULL';
  372.         else {
  373.             return "'" $this->escapeSimple($in"'";
  374.         }
  375.     }
  376.  
  377.     // }}}
  378.     // {{{ escapeSimple()
  379.  
  380.     /**
  381.      * Escape a string according to the current DBMS's standards
  382.      *
  383.      * PostgreSQL treats a backslash as an escape character, so they are
  384.      * removed.
  385.      *
  386.      * Not using pg_escape_string() yet because it requires PostgreSQL
  387.      * to be at version 7.2 or greater.
  388.      *
  389.      * @param string $str  the string to be escaped
  390.      *
  391.      * @return string  the escaped string
  392.      *
  393.      * @internal
  394.      */
  395.     function escapeSimple($str{
  396.         return str_replace("'""''"str_replace('\\''\\\\'$str));
  397.     }
  398.  
  399.     // }}}
  400.     // {{{ numCols()
  401.  
  402.     /**
  403.      * Get the number of columns in a result set.
  404.      *
  405.      * @param $result resource PostgreSQL result identifier
  406.      *
  407.      * @return int the number of columns per row in $result
  408.      */
  409.     function numCols($result)
  410.     {
  411.         $cols @pg_numfields($result);
  412.         if (!$cols{
  413.             return $this->pgsqlRaiseError();
  414.         }
  415.         return $cols;
  416.     }
  417.  
  418.     // }}}
  419.     // {{{ numRows()
  420.  
  421.     /**
  422.      * Get the number of rows in a result set.
  423.      *
  424.      * @param $result resource PostgreSQL result identifier
  425.      *
  426.      * @return int the number of rows in $result
  427.      */
  428.     function numRows($result)
  429.     {
  430.         $rows @pg_numrows($result);
  431.         if ($rows === null{
  432.             return $this->pgsqlRaiseError();
  433.         }
  434.         return $rows;
  435.     }
  436.  
  437.     // }}}
  438.     // {{{ errorNative()
  439.  
  440.     /**
  441.      * Get the native error code of the last error (if any) that
  442.      * occured on the current connection.
  443.      *
  444.      * @return int native PostgreSQL error code
  445.      */
  446.     function errorNative()
  447.     {
  448.         return pg_errormessage($this->connection);
  449.     }
  450.  
  451.     // }}}
  452.     // {{{ autoCommit()
  453.  
  454.     /**
  455.      * Enable/disable automatic commits
  456.      */
  457.     function autoCommit($onoff = false)
  458.     {
  459.         // XXX if $this->transaction_opcount > 0, we should probably
  460.         // issue a warning here.
  461.         $this->autocommit = $onoff ? true : false;
  462.         return DB_OK;
  463.     }
  464.  
  465.     // }}}
  466.     // {{{ commit()
  467.  
  468.     /**
  469.      * Commit the current transaction.
  470.      */
  471.     function commit()
  472.     {
  473.         if ($this->transaction_opcount > 0{
  474.             // (disabled) hack to shut up error messages from libpq.a
  475.             //@fclose(@fopen("php://stderr", "w"));
  476.             $result @pg_exec($this->connection'end;');
  477.             $this->transaction_opcount = 0;
  478.             if (!$result{
  479.                 return $this->pgsqlRaiseError();
  480.             }
  481.         }
  482.         return DB_OK;
  483.     }
  484.  
  485.     // }}}
  486.     // {{{ rollback()
  487.  
  488.     /**
  489.      * Roll back (undo) the current transaction.
  490.      */
  491.     function rollback()
  492.     {
  493.         if ($this->transaction_opcount > 0{
  494.             $result @pg_exec($this->connection'abort;');
  495.             $this->transaction_opcount = 0;
  496.             if (!$result{
  497.                 return $this->pgsqlRaiseError();
  498.             }
  499.         }
  500.         return DB_OK;
  501.     }
  502.  
  503.     // }}}
  504.     // {{{ affectedRows()
  505.  
  506.     /**
  507.      * Gets the number of rows affected by the last query.
  508.      * if the last query was a select, returns 0.
  509.      *
  510.      * @return int number of rows affected by the last query or DB_ERROR
  511.      */
  512.     function affectedRows()
  513.     {
  514.         return $this->affected;
  515.     }
  516.  
  517.     // }}}
  518.     // {{{ nextId()
  519.  
  520.     /**
  521.      * Returns the next free id in a sequence
  522.      *
  523.      * @param string  $seq_name  name of the sequence
  524.      * @param boolean $ondemand  when true, the seqence is automatically
  525.      *                            created if it does not exist
  526.      *
  527.      * @return int  the next id number in the sequence.  DB_Error if problem.
  528.      *
  529.      * @internal
  530.      * @see DB_common::nextID()
  531.      * @access public
  532.      */
  533.     function nextId($seq_name$ondemand = true)
  534.     {
  535.         $seqname $this->getSequenceName($seq_name);
  536.         $repeat = false;
  537.         do {
  538.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  539.             $result =$this->query("SELECT NEXTVAL('${seqname}')");
  540.             $this->popErrorHandling();
  541.             if ($ondemand && DB::isError($result&&
  542.                 $result->getCode(== DB_ERROR_NOSUCHTABLE{
  543.                 $repeat = true;
  544.                 $this->pushErrorHandling(PEAR_ERROR_RETURN);
  545.                 $result $this->createSequence($seq_name);
  546.                 $this->popErrorHandling();
  547.                 if (DB::isError($result)) {
  548.                     return $this->raiseError($result);
  549.                 }
  550.             else {
  551.                 $repeat = false;
  552.             }
  553.         while ($repeat);
  554.         if (DB::isError($result)) {
  555.             return $this->raiseError($result);
  556.         }
  557.         $arr $result->fetchRow(DB_FETCHMODE_ORDERED);
  558.         $result->free();
  559.         return $arr[0];
  560.     }
  561.  
  562.     // }}}
  563.     // {{{ createSequence()
  564.  
  565.     /**
  566.      * Create the sequence
  567.      *
  568.      * @param string $seq_name the name of the sequence
  569.      * @return mixed DB_OK on success or DB error on error
  570.      * @access public
  571.      */
  572.     function createSequence($seq_name)
  573.     {
  574.         $seqname $this->getSequenceName($seq_name);
  575.         $result $this->query("CREATE SEQUENCE ${seqname}");
  576.         return $result;
  577.     }
  578.  
  579.     // }}}
  580.     // {{{ dropSequence()
  581.  
  582.     /**
  583.      * Drop a sequence
  584.      *
  585.      * @param string $seq_name the name of the sequence
  586.      * @return mixed DB_OK on success or DB error on error
  587.      * @access public
  588.      */
  589.     function dropSequence($seq_name)
  590.     {
  591.         $seqname $this->getSequenceName($seq_name);
  592.         return $this->query("DROP SEQUENCE ${seqname}");
  593.     }
  594.  
  595.     // }}}
  596.     // {{{ modifyLimitQuery()
  597.  
  598.     function modifyLimitQuery($query$from$count$params = array())
  599.     {
  600.         $query $query . " LIMIT $count OFFSET $from";
  601.         return $query;
  602.     }
  603.  
  604.     // }}}
  605.     // {{{ pgsqlRaiseError()
  606.  
  607.     /**
  608.      * Gather information about an error, then use that info to create a
  609.      * DB error object and finally return that object.
  610.      *
  611.      * @param  integer  $errno  PEAR error number (usually a DB constant) if
  612.      *                           manually raising an error
  613.      * @return object  DB error object
  614.      * @see errorNative()
  615.      * @see errorCode()
  616.      * @see DB_common::raiseError()
  617.      */
  618.     function pgsqlRaiseError($errno = null)
  619.     {
  620.         $native $this->errorNative();
  621.         if ($errno === null{
  622.             $err $this->errorCode($native);
  623.         else {
  624.             $err $errno;
  625.         }
  626.         return $this->raiseError($errnullnullnull$native);
  627.     }
  628.  
  629.     // }}}
  630.     // {{{ _pgFieldFlags()
  631.  
  632.     /**
  633.      * Flags of a Field
  634.      *
  635.      * @param int $resource PostgreSQL result identifier
  636.      * @param int $num_field the field number
  637.      *
  638.      * @return string The flags of the field ("not_null", "default_value",
  639.      *                 "primary_key", "unique_key" and "multiple_key"
  640.      *                 are supported).  The default value is passed
  641.      *                 through rawurlencode() in case there are spaces in it.
  642.      * @access private
  643.      */
  644.     function _pgFieldFlags($resource$num_field$table_name)
  645.     {
  646.         $field_name @pg_fieldname($resource$num_field);
  647.  
  648.         $result @pg_exec($this->connection"SELECT f.attnotnull, f.atthasdef
  649.                                 FROM pg_attribute f, pg_class tab, pg_type typ
  650.                                 WHERE tab.relname = typ.typname
  651.                                 AND typ.typrelid = f.attrelid
  652.                                 AND f.attname = '$field_name'
  653.                                 AND tab.relname = '$table_name'");
  654.         if (@pg_numrows($result> 0{
  655.             $row @pg_fetch_row($result0);
  656.             $flags  ($row[0== 't''not_null ' '';
  657.  
  658.             if ($row[1== 't'{
  659.                 $result @pg_exec($this->connection"SELECT a.adsrc
  660.                                     FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
  661.                                     WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
  662.                                     AND f.attrelid = a.adrelid AND f.attname = '$field_name'
  663.                                     AND tab.relname = '$table_name' AND f.attnum = a.adnum");
  664.                 $row @pg_fetch_row($result0);
  665.                 $num preg_replace("/'(.*)'::\w+/""\\1"$row[0]);
  666.                 $flags .= 'default_' rawurlencode($num' ';
  667.             }
  668.         else {
  669.             $flags '';
  670.         }
  671.         $result @pg_exec($this->connection"SELECT i.indisunique, i.indisprimary, i.indkey
  672.                                 FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
  673.                                 WHERE tab.relname = typ.typname
  674.                                 AND typ.typrelid = f.attrelid
  675.                                 AND f.attrelid = i.indrelid
  676.                                 AND f.attname = '$field_name'
  677.                                 AND tab.relname = '$table_name'");
  678.         $count @pg_numrows($result);
  679.  
  680.         for ($i = 0; $i $count $i++{
  681.             $row @pg_fetch_row($result$i);
  682.             $keys explode(' '$row[2]);
  683.  
  684.             if (in_array($num_field + 1$keys)) {
  685.                 $flags .= ($row[0== 't' && $row[1== 'f''unique_key ' '';
  686.                 $flags .= ($row[1== 't''primary_key ' '';
  687.                 if (count($keys> 1)
  688.                     $flags .= 'multiple_key ';
  689.             }
  690.         }
  691.  
  692.         return trim($flags);
  693.     }
  694.  
  695.     // }}}
  696.     // {{{ tableInfo()
  697.  
  698.     /**
  699.      * Returns information about a table or a result set.
  700.      *
  701.      * NOTE: only supports 'table' and 'flags' if <var>$result</var>
  702.      * is a table name.
  703.      *
  704.      * @param object|string $result  DB_result object from a query or a
  705.      *                                 string containing the name of a table
  706.      * @param int            $mode    a valid tableInfo mode
  707.      * @return array  an associative array with the information requested
  708.      *                 or an error object if something is wrong
  709.      * @access public
  710.      * @internal
  711.      * @see DB_common::tableInfo()
  712.      */
  713.     function tableInfo($result$mode = null)
  714.     {
  715.         if (isset($result->result)) {
  716.             /*
  717.              * Probably received a result object.
  718.              * Extract the result resource identifier.
  719.              */
  720.             $id $result->result;
  721.             $got_string = false;
  722.         elseif (is_string($result)) {
  723.             /*
  724.              * Probably received a table name.
  725.              * Create a result resource identifier.
  726.              */
  727.             $id @pg_exec($this->connection"SELECT * FROM $result LIMIT 0");
  728.             $got_string = true;
  729.         else {
  730.             /*
  731.              * Probably received a result resource identifier.
  732.              * Copy it.
  733.              * Deprecated.  Here for compatibility only.
  734.              */
  735.             $id $result;
  736.             $got_string = false;
  737.         }
  738.  
  739.         if (!is_resource($id)) {
  740.             return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  741.         }
  742.  
  743.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  744.             $case_func 'strtolower';
  745.         else {
  746.             $case_func 'strval';
  747.         }
  748.  
  749.         $count @pg_numfields($id);
  750.  
  751.         // made this IF due to performance (one if is faster than $count if's)
  752.         if (!$mode{
  753.  
  754.             for ($i=0; $i<$count$i++{
  755.                 $res[$i]['table'$got_string $case_func($result'';
  756.                 $res[$i]['name']  $case_func(@pg_fieldname($id$i));
  757.                 $res[$i]['type']  @pg_fieldtype($id$i);
  758.                 $res[$i]['len']   @pg_fieldsize($id$i);
  759.                 $res[$i]['flags'$got_string $this->_pgFieldflags($id$i$result'';
  760.             }
  761.  
  762.         else // full
  763.             $res['num_fields']$count;
  764.  
  765.             for ($i=0; $i<$count$i++{
  766.                 $res[$i]['table'$got_string $case_func($result'';
  767.                 $res[$i]['name']  $case_func(@pg_fieldname($id$i));
  768.                 $res[$i]['type']  @pg_fieldtype($id$i);
  769.                 $res[$i]['len']   @pg_fieldsize($id$i);
  770.                 $res[$i]['flags'$got_string $this->_pgFieldFlags($id$i$result'';
  771.  
  772.                 if ($mode DB_TABLEINFO_ORDER{
  773.                     $res['order'][$res[$i]['name']] $i;
  774.                 }
  775.                 if ($mode DB_TABLEINFO_ORDERTABLE{
  776.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  777.                 }
  778.             }
  779.         }
  780.  
  781.         // free the result only if we were called on a table
  782.         if ($got_string{
  783.             @pg_freeresult($id);
  784.         }
  785.         return $res;
  786.     }
  787.  
  788.     // }}}
  789.     // {{{ getTablesQuery()
  790.  
  791.     /**
  792.      * Returns the query needed to get some backend info
  793.      * @param string $type What kind of info you want to retrieve
  794.      * @return string The SQL query string
  795.      */
  796.     function getSpecialQuery($type)
  797.     {
  798.         switch ($type{
  799.             case 'tables':
  800.                 return "SELECT c.relname as \"Name\"
  801.                         FROM pg_class c, pg_user u
  802.                         WHERE c.relowner = u.usesysid AND c.relkind = 'r'
  803.                         AND not exists (select 1 from pg_views where viewname = c.relname)
  804.                         AND c.relname !~ '^pg_'
  805.                         UNION
  806.                         SELECT c.relname as \"Name\"
  807.                         FROM pg_class c
  808.                         WHERE c.relkind = 'r'
  809.                         AND not exists (select 1 from pg_views where viewname = c.relname)
  810.                         AND not exists (select 1 from pg_user where usesysid = c.relowner)
  811.                         AND c.relname !~ '^pg_'";
  812.             case 'views':
  813.                 // Table cols: viewname | viewowner | definition
  814.                 return 'SELECT viewname FROM pg_views';
  815.             case 'users':
  816.                 // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd  |valuntil
  817.                 return 'SELECT usename FROM pg_user';
  818.             case 'databases':
  819.                 return 'SELECT datname FROM pg_database';
  820.             case 'functions':
  821.                 return 'SELECT proname FROM pg_proc';
  822.             default:
  823.                 return null;
  824.         }
  825.     }
  826.  
  827.     // }}}
  828.  
  829. }
  830.  
  831. /*
  832.  * Local variables:
  833.  * tab-width: 4
  834.  * c-basic-offset: 4
  835.  * End:
  836.  */
  837.  
  838. ?>

Documentation generated on Mon, 11 Mar 2019 10:14:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.