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.77 2004/06/25 18:51:43 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.77 2004/06/25 18:51:43 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.         $result_int = (int)$result;
  286.         $rownum ($rownum !== null$rownum $this->row[$result_int];
  287.         if ($rownum >= $this->num_rows[$result_int]{
  288.             return null;
  289.         }
  290.         if ($fetchmode DB_FETCHMODE_ASSOC{
  291.             $arr @pg_fetch_array($result$rownumPGSQL_ASSOC);
  292.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE && $arr{
  293.                 $arr array_change_key_case($arrCASE_LOWER);
  294.             }
  295.         else {
  296.             $arr @pg_fetch_row($result$rownum);
  297.         }
  298.         if (!$arr{
  299.             $err = pg_errormessage($this->connection);
  300.             if (!$err{
  301.                 return null;
  302.             }
  303.             return $this->pgsqlRaiseError();
  304.         }
  305.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  306.             $this->_rtrimArrayValues($arr);
  307.         }
  308.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  309.             $this->_convertNullArrayValuesToEmpty($arr);
  310.         }
  311.         $this->row[$result_int= ++$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
  322.      *
  323.      * @return bool true on success, false if $result is invalid
  324.      */
  325.     function freeResult($result)
  326.     {
  327.         if (is_resource($result)) {
  328.             unset($this->row[(int)$result]);
  329.             unset($this->num_rows[(int)$result]);
  330.             $this->affected = 0;
  331.             return @pg_freeresult($result);
  332.         }
  333.         return false;
  334.     }
  335.  
  336.     // }}}
  337.     // {{{ quote()
  338.  
  339.     /**
  340.      * @deprecated  Deprecated in release 1.6.0
  341.      * @internal
  342.      */
  343.     function quote($str{
  344.         return $this->quoteSmart($str);
  345.     }
  346.  
  347.     // }}}
  348.     // {{{ quoteSmart()
  349.  
  350.     /**
  351.      * Format input so it can be safely used in a query
  352.      *
  353.      * @param mixed $in  data to be quoted
  354.      *
  355.      * @return mixed Submitted variable's type = returned value:
  356.      *                + null = the string <samp>NULL</samp>
  357.      *                + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp>
  358.      *                + integer or double = the unquoted number
  359.      *                + other (including strings and numeric strings) =
  360.      *                  the data escaped according to MySQL's settings
  361.      *                  then encapsulated between single quotes
  362.      *
  363.      * @internal
  364.      */
  365.     function quoteSmart($in)
  366.     {
  367.         if (is_int($in|| is_double($in)) {
  368.             return $in;
  369.         elseif (is_bool($in)) {
  370.             return $in 'TRUE' 'FALSE';
  371.         elseif (is_null($in)) {
  372.             return 'NULL';
  373.         else {
  374.             return "'" $this->escapeSimple($in"'";
  375.         }
  376.     }
  377.  
  378.     // }}}
  379.     // {{{ escapeSimple()
  380.  
  381.     /**
  382.      * Escape a string according to the current DBMS's standards
  383.      *
  384.      * PostgreSQL treats a backslash as an escape character, so they are
  385.      * removed.
  386.      *
  387.      * Not using pg_escape_string() yet because it requires PostgreSQL
  388.      * to be at version 7.2 or greater.
  389.      *
  390.      * @param string $str  the string to be escaped
  391.      *
  392.      * @return string  the escaped string
  393.      *
  394.      * @internal
  395.      */
  396.     function escapeSimple($str{
  397.         return str_replace("'""''"str_replace('\\''\\\\'$str));
  398.     }
  399.  
  400.     // }}}
  401.     // {{{ numCols()
  402.  
  403.     /**
  404.      * Get the number of columns in a result set.
  405.      *
  406.      * @param $result resource PostgreSQL result identifier
  407.      *
  408.      * @return int the number of columns per row in $result
  409.      */
  410.     function numCols($result)
  411.     {
  412.         $cols @pg_numfields($result);
  413.         if (!$cols{
  414.             return $this->pgsqlRaiseError();
  415.         }
  416.         return $cols;
  417.     }
  418.  
  419.     // }}}
  420.     // {{{ numRows()
  421.  
  422.     /**
  423.      * Get the number of rows in a result set.
  424.      *
  425.      * @param $result resource PostgreSQL result identifier
  426.      *
  427.      * @return int the number of rows in $result
  428.      */
  429.     function numRows($result)
  430.     {
  431.         $rows @pg_numrows($result);
  432.         if ($rows === null{
  433.             return $this->pgsqlRaiseError();
  434.         }
  435.         return $rows;
  436.     }
  437.  
  438.     // }}}
  439.     // {{{ errorNative()
  440.  
  441.     /**
  442.      * Get the native error code of the last error (if any) that
  443.      * occured on the current connection.
  444.      *
  445.      * @return int native PostgreSQL error code
  446.      */
  447.     function errorNative()
  448.     {
  449.         return pg_errormessage($this->connection);
  450.     }
  451.  
  452.     // }}}
  453.     // {{{ autoCommit()
  454.  
  455.     /**
  456.      * Enable/disable automatic commits
  457.      */
  458.     function autoCommit($onoff = false)
  459.     {
  460.         // XXX if $this->transaction_opcount > 0, we should probably
  461.         // issue a warning here.
  462.         $this->autocommit = $onoff ? true : false;
  463.         return DB_OK;
  464.     }
  465.  
  466.     // }}}
  467.     // {{{ commit()
  468.  
  469.     /**
  470.      * Commit the current transaction.
  471.      */
  472.     function commit()
  473.     {
  474.         if ($this->transaction_opcount > 0{
  475.             // (disabled) hack to shut up error messages from libpq.a
  476.             //@fclose(@fopen("php://stderr", "w"));
  477.             $result @pg_exec($this->connection'end;');
  478.             $this->transaction_opcount = 0;
  479.             if (!$result{
  480.                 return $this->pgsqlRaiseError();
  481.             }
  482.         }
  483.         return DB_OK;
  484.     }
  485.  
  486.     // }}}
  487.     // {{{ rollback()
  488.  
  489.     /**
  490.      * Roll back (undo) the current transaction.
  491.      */
  492.     function rollback()
  493.     {
  494.         if ($this->transaction_opcount > 0{
  495.             $result @pg_exec($this->connection'abort;');
  496.             $this->transaction_opcount = 0;
  497.             if (!$result{
  498.                 return $this->pgsqlRaiseError();
  499.             }
  500.         }
  501.         return DB_OK;
  502.     }
  503.  
  504.     // }}}
  505.     // {{{ affectedRows()
  506.  
  507.     /**
  508.      * Gets the number of rows affected by the last query.
  509.      * if the last query was a select, returns 0.
  510.      *
  511.      * @return int number of rows affected by the last query or DB_ERROR
  512.      */
  513.     function affectedRows()
  514.     {
  515.         return $this->affected;
  516.     }
  517.  
  518.     // }}}
  519.     // {{{ nextId()
  520.  
  521.     /**
  522.      * Returns the next free id in a sequence
  523.      *
  524.      * @param string  $seq_name  name of the sequence
  525.      * @param boolean $ondemand  when true, the seqence is automatically
  526.      *                            created if it does not exist
  527.      *
  528.      * @return int  the next id number in the sequence.  DB_Error if problem.
  529.      *
  530.      * @internal
  531.      * @see DB_common::nextID()
  532.      * @access public
  533.      */
  534.     function nextId($seq_name$ondemand = true)
  535.     {
  536.         $seqname $this->getSequenceName($seq_name);
  537.         $repeat = false;
  538.         do {
  539.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  540.             $result =$this->query("SELECT NEXTVAL('${seqname}')");
  541.             $this->popErrorHandling();
  542.             if ($ondemand && DB::isError($result&&
  543.                 $result->getCode(== DB_ERROR_NOSUCHTABLE{
  544.                 $repeat = true;
  545.                 $this->pushErrorHandling(PEAR_ERROR_RETURN);
  546.                 $result $this->createSequence($seq_name);
  547.                 $this->popErrorHandling();
  548.                 if (DB::isError($result)) {
  549.                     return $this->raiseError($result);
  550.                 }
  551.             else {
  552.                 $repeat = false;
  553.             }
  554.         while ($repeat);
  555.         if (DB::isError($result)) {
  556.             return $this->raiseError($result);
  557.         }
  558.         $arr $result->fetchRow(DB_FETCHMODE_ORDERED);
  559.         $result->free();
  560.         return $arr[0];
  561.     }
  562.  
  563.     // }}}
  564.     // {{{ createSequence()
  565.  
  566.     /**
  567.      * Create the sequence
  568.      *
  569.      * @param string $seq_name the name of the sequence
  570.      * @return mixed DB_OK on success or DB error on error
  571.      * @access public
  572.      */
  573.     function createSequence($seq_name)
  574.     {
  575.         $seqname $this->getSequenceName($seq_name);
  576.         $result $this->query("CREATE SEQUENCE ${seqname}");
  577.         return $result;
  578.     }
  579.  
  580.     // }}}
  581.     // {{{ dropSequence()
  582.  
  583.     /**
  584.      * Drop a sequence
  585.      *
  586.      * @param string $seq_name the name of the sequence
  587.      * @return mixed DB_OK on success or DB error on error
  588.      * @access public
  589.      */
  590.     function dropSequence($seq_name)
  591.     {
  592.         $seqname $this->getSequenceName($seq_name);
  593.         return $this->query("DROP SEQUENCE ${seqname}");
  594.     }
  595.  
  596.     // }}}
  597.     // {{{ modifyLimitQuery()
  598.  
  599.     function modifyLimitQuery($query$from$count$params = array())
  600.     {
  601.         $query $query . " LIMIT $count OFFSET $from";
  602.         return $query;
  603.     }
  604.  
  605.     // }}}
  606.     // {{{ pgsqlRaiseError()
  607.  
  608.     /**
  609.      * Gather information about an error, then use that info to create a
  610.      * DB error object and finally return that object.
  611.      *
  612.      * @param  integer  $errno  PEAR error number (usually a DB constant) if
  613.      *                           manually raising an error
  614.      * @return object  DB error object
  615.      * @see errorNative()
  616.      * @see errorCode()
  617.      * @see DB_common::raiseError()
  618.      */
  619.     function pgsqlRaiseError($errno = null)
  620.     {
  621.         $native $this->errorNative();
  622.         if ($errno === null{
  623.             $err $this->errorCode($native);
  624.         else {
  625.             $err $errno;
  626.         }
  627.         return $this->raiseError($errnullnullnull$native);
  628.     }
  629.  
  630.     // }}}
  631.     // {{{ _pgFieldFlags()
  632.  
  633.     /**
  634.      * Flags of a Field
  635.      *
  636.      * @param int $resource PostgreSQL result identifier
  637.      * @param int $num_field the field number
  638.      *
  639.      * @return string The flags of the field ("not_null", "default_value",
  640.      *                 "primary_key", "unique_key" and "multiple_key"
  641.      *                 are supported).  The default value is passed
  642.      *                 through rawurlencode() in case there are spaces in it.
  643.      * @access private
  644.      */
  645.     function _pgFieldFlags($resource$num_field$table_name)
  646.     {
  647.         $field_name @pg_fieldname($resource$num_field);
  648.  
  649.         $result @pg_exec($this->connection"SELECT f.attnotnull, f.atthasdef
  650.                                 FROM pg_attribute f, pg_class tab, pg_type typ
  651.                                 WHERE tab.relname = typ.typname
  652.                                 AND typ.typrelid = f.attrelid
  653.                                 AND f.attname = '$field_name'
  654.                                 AND tab.relname = '$table_name'");
  655.         if (@pg_numrows($result> 0{
  656.             $row @pg_fetch_row($result0);
  657.             $flags  ($row[0== 't''not_null ' '';
  658.  
  659.             if ($row[1== 't'{
  660.                 $result @pg_exec($this->connection"SELECT a.adsrc
  661.                                     FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
  662.                                     WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
  663.                                     AND f.attrelid = a.adrelid AND f.attname = '$field_name'
  664.                                     AND tab.relname = '$table_name' AND f.attnum = a.adnum");
  665.                 $row @pg_fetch_row($result0);
  666.                 $num preg_replace("/'(.*)'::\w+/""\\1"$row[0]);
  667.                 $flags .= 'default_' rawurlencode($num' ';
  668.             }
  669.         else {
  670.             $flags '';
  671.         }
  672.         $result @pg_exec($this->connection"SELECT i.indisunique, i.indisprimary, i.indkey
  673.                                 FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
  674.                                 WHERE tab.relname = typ.typname
  675.                                 AND typ.typrelid = f.attrelid
  676.                                 AND f.attrelid = i.indrelid
  677.                                 AND f.attname = '$field_name'
  678.                                 AND tab.relname = '$table_name'");
  679.         $count @pg_numrows($result);
  680.  
  681.         for ($i = 0; $i $count $i++{
  682.             $row @pg_fetch_row($result$i);
  683.             $keys explode(' '$row[2]);
  684.  
  685.             if (in_array($num_field + 1$keys)) {
  686.                 $flags .= ($row[0== 't' && $row[1== 'f''unique_key ' '';
  687.                 $flags .= ($row[1== 't''primary_key ' '';
  688.                 if (count($keys> 1)
  689.                     $flags .= 'multiple_key ';
  690.             }
  691.         }
  692.  
  693.         return trim($flags);
  694.     }
  695.  
  696.     // }}}
  697.     // {{{ tableInfo()
  698.  
  699.     /**
  700.      * Returns information about a table or a result set.
  701.      *
  702.      * NOTE: only supports 'table' and 'flags' if <var>$result</var>
  703.      * is a table name.
  704.      *
  705.      * @param object|string $result  DB_result object from a query or a
  706.      *                                 string containing the name of a table
  707.      * @param int            $mode    a valid tableInfo mode
  708.      * @return array  an associative array with the information requested
  709.      *                 or an error object if something is wrong
  710.      * @access public
  711.      * @internal
  712.      * @see DB_common::tableInfo()
  713.      */
  714.     function tableInfo($result$mode = null)
  715.     {
  716.         if (isset($result->result)) {
  717.             /*
  718.              * Probably received a result object.
  719.              * Extract the result resource identifier.
  720.              */
  721.             $id $result->result;
  722.             $got_string = false;
  723.         elseif (is_string($result)) {
  724.             /*
  725.              * Probably received a table name.
  726.              * Create a result resource identifier.
  727.              */
  728.             $id @pg_exec($this->connection"SELECT * FROM $result LIMIT 0");
  729.             $got_string = true;
  730.         else {
  731.             /*
  732.              * Probably received a result resource identifier.
  733.              * Copy it.
  734.              * Deprecated.  Here for compatibility only.
  735.              */
  736.             $id $result;
  737.             $got_string = false;
  738.         }
  739.  
  740.         if (!is_resource($id)) {
  741.             return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  742.         }
  743.  
  744.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  745.             $case_func 'strtolower';
  746.         else {
  747.             $case_func 'strval';
  748.         }
  749.  
  750.         $count @pg_numfields($id);
  751.  
  752.         // made this IF due to performance (one if is faster than $count if's)
  753.         if (!$mode{
  754.  
  755.             for ($i=0; $i<$count$i++{
  756.                 $res[$i]['table'$got_string $case_func($result'';
  757.                 $res[$i]['name']  $case_func(@pg_fieldname($id$i));
  758.                 $res[$i]['type']  @pg_fieldtype($id$i);
  759.                 $res[$i]['len']   @pg_fieldsize($id$i);
  760.                 $res[$i]['flags'$got_string $this->_pgFieldflags($id$i$result'';
  761.             }
  762.  
  763.         else // full
  764.             $res['num_fields']$count;
  765.  
  766.             for ($i=0; $i<$count$i++{
  767.                 $res[$i]['table'$got_string $case_func($result'';
  768.                 $res[$i]['name']  $case_func(@pg_fieldname($id$i));
  769.                 $res[$i]['type']  @pg_fieldtype($id$i);
  770.                 $res[$i]['len']   @pg_fieldsize($id$i);
  771.                 $res[$i]['flags'$got_string $this->_pgFieldFlags($id$i$result'';
  772.  
  773.                 if ($mode DB_TABLEINFO_ORDER{
  774.                     $res['order'][$res[$i]['name']] $i;
  775.                 }
  776.                 if ($mode DB_TABLEINFO_ORDERTABLE{
  777.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  778.                 }
  779.             }
  780.         }
  781.  
  782.         // free the result only if we were called on a table
  783.         if ($got_string{
  784.             @pg_freeresult($id);
  785.         }
  786.         return $res;
  787.     }
  788.  
  789.     // }}}
  790.     // {{{ getTablesQuery()
  791.  
  792.     /**
  793.      * Returns the query needed to get some backend info
  794.      * @param string $type What kind of info you want to retrieve
  795.      * @return string The SQL query string
  796.      */
  797.     function getSpecialQuery($type)
  798.     {
  799.         switch ($type{
  800.             case 'tables':
  801.                 return "SELECT c.relname as \"Name\"
  802.                         FROM pg_class c, pg_user u
  803.                         WHERE c.relowner = u.usesysid AND c.relkind = 'r'
  804.                         AND not exists (select 1 from pg_views where viewname = c.relname)
  805.                         AND c.relname !~ '^(pg_|sql_)'
  806.                         UNION
  807.                         SELECT c.relname as \"Name\"
  808.                         FROM pg_class c
  809.                         WHERE c.relkind = 'r'
  810.                         AND not exists (select 1 from pg_views where viewname = c.relname)
  811.                         AND not exists (select 1 from pg_user where usesysid = c.relowner)
  812.                         AND c.relname !~ '^pg_'";
  813.             case 'views':
  814.                 // Table cols: viewname | viewowner | definition
  815.                 return 'SELECT viewname FROM pg_views';
  816.             case 'users':
  817.                 // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd  |valuntil
  818.                 return 'SELECT usename FROM pg_user';
  819.             case 'databases':
  820.                 return 'SELECT datname FROM pg_database';
  821.             case 'functions':
  822.                 return 'SELECT proname FROM pg_proc';
  823.             default:
  824.                 return null;
  825.         }
  826.     }
  827.  
  828.     // }}}
  829.  
  830. }
  831.  
  832. /*
  833.  * Local variables:
  834.  * tab-width: 4
  835.  * c-basic-offset: 4
  836.  * End:
  837.  */
  838.  
  839. ?>

Documentation generated on Mon, 11 Mar 2019 13:53:01 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.