home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Magazine / HomeAutomation / Apache / lib / php / DB / pgsql.php < prev    next >
Encoding:
PHP Script  |  2000-07-11  |  11.2 KB  |  443 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 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_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Rui Hirokawa <louis@cityfujisawa.ne.jp>                     |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // Database independent query interface definition for PHP's PostgreSQL
  21. // extension.
  22. //
  23. // [SSB] Problems in this code:
  24. //
  25. // 1. $this->row is used as a row counter
  26. // for the fetchRow() implementation.  There are two problems with this:
  27. // First of all, $this->row is not reset when the result is freed.  Also,
  28. // If the user creates two DB_result objects on the same DB connection,
  29. // it will break completely because both result sets will be using the
  30. // same row counter.  Solution: change $this->row into an array indexed
  31. // by resource id.
  32. // --> $this->row is changed to an indexed array. (R.Hirokawa)
  33. //
  34. // 2. The pgsql extension currently does not have error codes.  This
  35. // should be fixed so DB_pgsql can do portable error codes.
  36. // --> The error codes are not supported in the current pgsql API (libpq).
  37. //
  38. // 3. The transaction is supported by PostgreSQL, 
  39. //    but the current implementation is not useful to use the transaction.
  40.  
  41.  
  42. //
  43. // XXX legend:
  44. //
  45. // XXX ERRORMSG: The error message from the pgsql function should
  46. //                 be registered here.
  47. //
  48.  
  49. include_once 'DB/common.php';
  50.  
  51. class DB_pgsql extends DB_common {
  52.     // {{{ properties
  53.  
  54.     var $connection;
  55.     var $phptype, $dbsyntax;
  56.     var $prepare_tokens = array();
  57.     var $prepare_types = array();
  58.     var $numrows;
  59.     var $row;
  60.  
  61.     // }}}
  62.  
  63.     // {{{ constructor
  64.  
  65.     function DB_pgsql() {
  66.         $this->phptype = 'pgsql';
  67.         $this->dbsyntax = 'pgsql';
  68.         $this->features = array(
  69.             'prepare' => false,
  70.             'pconnect' => true,
  71.             'transactions' => true
  72.         );
  73.         $this->errorcode_map = array();
  74.         $this->numrows = array();
  75.         $this->row = array();
  76.     }
  77.  
  78.     // }}}
  79.  
  80.     // {{{ connect()
  81.  
  82.     /**
  83.      * Connect to a database and log in as the specified user.
  84.      *
  85.      * @param $dsn the data source name (see DB::parseDSN for syntax)
  86.      * @param $persistent (optional) whether the connection should
  87.      *        be persistent
  88.      *
  89.      * @return int DB_OK on success, a DB error code on failure
  90.      */
  91.     function connect($dsn, $persistent = false) {
  92.         if (is_array($dsn)) {
  93.             $dsninfo = &$dsn;
  94.         } else {
  95.             $dsninfo = DB::parseDSN($dsn);
  96.         }
  97.         if (!$dsninfo || !$dsninfo['phptype']) {
  98.             return DB_ERROR; // XXX ERRORMSG
  99.         }
  100.         $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
  101.         $user = $dsninfo['username'];
  102.         $pw = $dsninfo['password'];
  103.         $dbname = $dsninfo['database'];
  104.         $options = $dsninfo['options'];
  105.         $tty = $dsninfo['tty'];
  106.         $port = $dsninfo['port'] ? $dsninfo['port'] : '5432';
  107.  
  108.         $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
  109.         if ($dbhost && $user && $pw && $dbname) {
  110.             $conn = $connect_function(
  111.                 "host=$dbhost port=$port dbname=$dbname user=$user password=$pw");
  112.         } elseif ($dbhost && $dbname && $options && $tty) {
  113.             $conn = $connect_function($dbhost, $port, $options, $tty, $dbname);
  114.         } elseif ($dbhost && $dbname) {
  115.             $conn = $connect_function($dbhost, $port, $dbname);
  116.         } else {
  117.             $conn = false;
  118.         }
  119.         if ($conn == false) {
  120.             return DB_ERROR; // XXX ERRORMSG
  121.         }
  122.         $this->connection = $conn;
  123.         return DB_OK;
  124.     }
  125.  
  126.     // }}}
  127.     // {{{ disconnect()
  128.  
  129.     /**
  130.      * Log out and disconnect from the database.
  131.      *
  132.      * @return bool TRUE on success, FALSE if not connected.
  133.      */
  134.     function disconnect() {
  135.         return pg_close($this->connection); // XXX ERRORMSG
  136.     }
  137.  
  138.     // }}}
  139.     // {{{ query()
  140.  
  141.  
  142.     /**
  143.      * Send a query to PostgreSQL and return the results as a DB_result object.
  144.      *
  145.      * @param $query the SQL query
  146.      *
  147.      * @return object a DB_result object on success, a DB error code
  148.      * on failure
  149.      */
  150.     function &query($query) {
  151.         $result = pg_exec($this->connection, $query);
  152.         if (!$result) {
  153.             return pg_errormessage($this->connection);
  154.         }
  155.         // Determine which queries that should return data, and which
  156.         // should return an error code only.
  157.         if (preg_match('/(SELECT|SHOW)/i', $query)) {
  158.             $resultObj = new DB_result($this, $result);
  159.             $this->row[$result] = 0; // reset the row counter. 
  160.             $this->numrows[$result] = pg_numrows($result); 
  161.             return $resultObj;
  162.         } else {
  163.             return DB_OK;
  164.         }
  165.     }
  166.  
  167.     // }}}
  168.     // {{{ simpleQuery()
  169.  
  170.     /**
  171.      * Send a query to PostgreSQL and return the results as a PostgreSQL resource
  172.      * identifier.
  173.      *
  174.      * @param $query the SQL query
  175.      *
  176.      * @return int returns a valid PostgreSQL result for successful SELECT
  177.      * queries, DB_OK for other successful queries.  A DB error code
  178.      * is returned on failure.
  179.      */
  180.     function simpleQuery($query) {
  181.         $result = pg_exec($this->connection, $query);
  182.         if (!$result) {
  183.             return pg_errormessage($this->connection);
  184.         }
  185.         // Determine which queries that should return data, and which
  186.         // should return an error code only.
  187.         if (preg_match('/(SELECT|SHOW)/i', $query)) {
  188.             $this->row[$result] = 0; // reset the row counter.
  189.             $this->numrows[$result] = pg_numrows($result);  
  190.             return $result;
  191.         } else {
  192.             return DB_OK;
  193.         }
  194.     }
  195.  
  196.     // }}}
  197.     // {{{ fetchRow()
  198.  
  199.     /**
  200.      * Fetch a row and return as array.
  201.      *
  202.      * @param $result PostgreSQL result identifier
  203.      * @param $getmode how the resulting array should be indexed
  204.      *
  205.      * @return int an array on success, a DB error code on failure, NULL
  206.      *             if there is no more data
  207.      */
  208.     function &fetchRow($result, $getmode = DB_GETMODE_DEFAULT) {
  209.         if ($this->row[$result]>=$this->numrows[$result]){
  210.             return NULL;
  211.         }
  212.         if ($getmode & DB_GETMODE_ASSOC) {
  213.             $row = pg_fetch_array($result, $this->row[$result]);
  214.         } else {
  215.             $row = pg_fetch_row($result, $this->row[$result]);
  216.         }
  217.         if (!$row) {
  218.             $err = pg_errormessage($this->connection);
  219.             if (!$err) {
  220.                 return NULL;
  221.             }
  222.             return $err;
  223.         }
  224.         $this->row[$result]++;
  225.         return $row;
  226.     }
  227.  
  228.     // }}}
  229.     // {{{ fetchInto()
  230.  
  231.     /**
  232.      * Fetch a row and insert the data into an existing array.
  233.      *
  234.      * @param $result PostgreSQL result identifier
  235.      * @param $arr (reference) array where data from the row is stored
  236.      * @param $getmode how the array data should be indexed
  237.      *
  238.      * @return int DB_OK on success, a DB error code on failure
  239.      */
  240.     function fetchInto($result, &$arr, $getmode = DB_GETMODE_DEFAULT) {
  241.         if ($this->row[$result]>=$this->numrows[$result]){
  242.             return NULL;
  243.         }
  244.         if ($getmode & DB_GETMODE_ASSOC) {
  245.             $arr = pg_fetch_array($result, $this->row[$result]);
  246.         } else {
  247.             $arr = pg_fetch_row($result, $this->row[$result]);
  248.         }
  249.         if (!$arr) {
  250.             /* 
  251.              $errno = pg_errormessage($this->connection);
  252.              if (!$errno) {
  253.                 return NULL;
  254.              }
  255.              return $errno;
  256.             */
  257.             // the error codes are not supported in pgsql. 
  258.             return DB_ERROR_NOT_CAPABLE; 
  259.         }
  260.         $this->row[$result]++;
  261.         return DB_OK;
  262.     }
  263.  
  264.     // }}}
  265.     // {{{ freeResult()
  266.  
  267.     /**
  268.      * Free the internal resources associated with $result.
  269.      *
  270.      * @param $result PostgreSQL result identifier or DB statement identifier
  271.      *
  272.      * @return bool TRUE on success, FALSE if $result is invalid
  273.      */
  274.     function freeResult($result) {
  275.         if (is_resource($result)) {
  276.             return pg_freeresult($result);
  277.         }
  278.         if (!isset($this->prepare_tokens[$result])) {
  279.             return false;
  280.         }
  281.         unset($this->prepare_tokens[$result]);
  282.         unset($this->prepare_types[$result]);
  283.         unset($this->row[$result]);
  284.         unset($this->numrows[$result]);
  285.         return true; 
  286.     }
  287.  
  288.     // }}}
  289.     // {{{ numCols()
  290.  
  291.     /**
  292.      * Get the number of columns in a result set.
  293.      *
  294.      * @param $result PostgreSQL result identifier
  295.      *
  296.      * @return int the number of columns per row in $result
  297.      */
  298.     function numCols($result) {
  299.         $cols = pg_numfields($result);
  300.         if (!$cols) {
  301.             return pg_errormessage($this->connection);
  302.         }
  303.         return $cols;
  304.     }
  305.  
  306.     // }}}
  307.     // {{{ numRows()
  308.  
  309.     /**
  310.      * Get the number of rows in a result set.
  311.      *
  312.      * @param $result PostgreSQL result identifier
  313.      *
  314.      * @return int the number of rows in $result
  315.      */
  316.     function numRows($result) {
  317.         $rows = pg_numrows($result);
  318.         if (!$rows) {
  319.             return pg_errormessage($this->connection);
  320.         }
  321.         return $rows;
  322.     }
  323.  
  324.     // }}}
  325.     // {{{ errorNative()
  326.  
  327.     /**
  328.      * Get the native error code of the last error (if any) that
  329.      * occured on the current connection.
  330.      *
  331.      * @return int native PostgreSQL error code
  332.      */
  333.     function errorNative() {
  334.     /*    return pg_errormessage($this->connection); */
  335.         // the error codes are not supported in pgsql. 
  336.         return DB_ERROR_NOT_CAPABLE; 
  337.     }
  338.  
  339.     // }}}
  340.     // {{{ prepare()
  341.  
  342.     /**
  343.      * Prepares a query for multiple execution with execute().  With
  344.      * PostgreSQL, this is emulated.
  345.      */
  346.     function prepare($query) {
  347.         $tokens = split('[\&\?]', $query);
  348.         $token = 0;
  349.         $types = array();
  350.         for ($i = 0; $i < strlen($query); $i++) {
  351.             switch ($query[$i]) {
  352.                 case '?':
  353.                     $types[$token++] = DB_PARAM_SCALAR;
  354.                     break;
  355.                 case '&':
  356.                     $types[$token++] = DB_PARAM_OPAQUE;
  357.                     break;
  358.             }
  359.         }
  360.         $this->prepare_tokens[] = &$tokens;
  361.         end($this->prepare_tokens);
  362.         $k = key($this->prepare_tokens);
  363.         $this->prepare_types[$k] = $types;
  364.         return $k;
  365.     }
  366.  
  367.     // }}}
  368.     // {{{ execute()
  369.  
  370.     /**
  371.      * @return int returns a PostgreSQL result resource for successful
  372.      * SELECT queries, DB_OK for other successful queries.  A DB error
  373.      * code is returned on failure.
  374.      */
  375.     function execute($stmt, $data = false) {
  376.         $realquery = $this->execute_emulate_query($stmt, $data);
  377.         $result = pg_exec($this->connection, $realquery);
  378.         if (!$result) {
  379.             return pg_errormessage($this->connection);
  380.         }
  381.         if (preg_match('/(SELECT|SHOW)/i', $realquery)) {
  382.             $this->row[$result] = 0; // reset the row counter.
  383.             $this->numrows[$result] = pg_numrows($result);
  384.             return $result;
  385.         } else {
  386.             return DB_OK;
  387.         }
  388.     }
  389.  
  390.     // }}}
  391.     // {{{ autoCommit()
  392.  
  393.     /**
  394.      * Enable/disable automatic commits [not supported by PostgreSQL]
  395.      */
  396.     function autoCommit($onoff = false) {
  397.         return DB_ERROR_NOT_CAPABLE;
  398.     }
  399.  
  400.     // }}}
  401.     // {{{ commit()
  402.  
  403.     /**
  404.      * Commit transactions on the current connection
  405.      */
  406.     function commit() {
  407.         $result = pg_exec($this->connection, "end;");
  408.         if (!$result) {
  409.             return pg_errormessage($this->connection);
  410.         }
  411.         return DB_OK;
  412.     }
  413.  
  414.     // }}}
  415.     // {{{ rollback()
  416.  
  417.     /**
  418.      * Roll back all uncommitted transactions on the current connection.
  419.      */
  420.     function rollback() {
  421.         $result = pg_exec($this->connection, "abort;");
  422.         if (!$result) {
  423.             return pg_errormessage($this->connection);
  424.         }
  425.         return DB_OK;
  426.     }
  427.  
  428.     // }}}
  429.  
  430.     // TODO/wishlist:
  431.     // simpleFetch
  432.     // simpleGet
  433.     // affectedRows
  434.     // longReadlen
  435.     // binmode
  436. }
  437.  
  438. // Local variables:
  439. // tab-width: 4
  440. // c-basic-offset: 4
  441. // End:
  442. ?>
  443.