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

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