home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Magazine / HomeAutomation / Apache / lib / php / DB / common.php next >
Encoding:
PHP Script  |  2000-07-11  |  10.1 KB  |  374 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: Stig Bakken <ssb@fast.no>                                   |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // Base class for DB implementations.
  21. //
  22.  
  23. //
  24. // XXX legend:
  25. //
  26. // XXX ERRORMSG: Needs a better way of dealing with errors.
  27. // XXX ADDREF:     As soon as Zend/PHP gets support for returning
  28. //                 references, this return value should be made into
  29. //                 a reference.
  30. //
  31.  
  32. if (!empty($GLOBALS['USED_PACKAGES']['DB/common'])) return;
  33. $GLOBALS['USED_PACKAGES']['DB/common'] = true;
  34.  
  35. /**
  36.  * DB_common is a base class for DB implementations, and should be
  37.  * inherited by all such.
  38.  */
  39. class DB_common {
  40.     // {{{ properties
  41.  
  42.     var $features;        // assoc of capabilities for this DB implementation
  43.     var $errorcode_map;    // assoc mapping native error codes to DB ones
  44.     var $type;            // DB type (mysql, oci8, odbc etc.)
  45.  
  46.     // }}}
  47.     // {{{ constructor
  48.  
  49.     function DB_common() {
  50.         $this->features = array();
  51.         $this->errorcode_map = array();
  52.     }
  53.  
  54.     // }}}
  55.     // {{{ quoteString()
  56.  
  57.     /**
  58.      * Quotes a string so it can be safely used within string delimiters
  59.      * in a query.
  60.      *
  61.      * @param $string the input string to quote
  62.      *
  63.      * @return string the quoted string
  64.      */
  65.     function quoteString($string) {
  66.         return str_replace("'", "\'", $string);
  67.     }
  68.  
  69.     // }}}
  70.     // {{{ provides()
  71.  
  72.     /**
  73.      * Tell whether a DB implementation or its backend extension
  74.      * supports a given feature.
  75.      *
  76.      * @param $feature name of the feature (see the DB class doc)
  77.      *
  78.      * @return bool whether this DB implementation supports $feature
  79.      */
  80.     function provides($feature) {
  81.         return $this->features[$feature];
  82.     }
  83.  
  84.     // }}}
  85.     // {{{ errorCode()
  86.  
  87.     /**
  88.      * Map native error codes to DB's portable ones.  Requires that
  89.      * the DB implementation's constructor fills in the $errorcode_map
  90.      * property.
  91.      *
  92.      * @param $nativecode the native error code, as returned by the backend
  93.      * database extension (string or integer)
  94.      *
  95.      * @return int a portable DB error code, or FALSE if this DB
  96.      * implementation has no mapping for the given error code.
  97.      */
  98.     function errorCode($nativecode) {
  99.         if ($this->errorcode_map[$nativecode]) {
  100.             return $this->errorcode_map[$nativecode];
  101.         }
  102.         //php_error(E_WARNING, get_class($this)."::errorCode: no mapping for $nativecode");
  103.         // Fall back to DB_ERROR if there was no mapping.  Ideally,
  104.         // this should never happen.
  105.         return DB_ERROR;
  106.     }
  107.  
  108.     // }}}
  109.     // {{{ errorMessage()
  110.  
  111.     /**
  112.      * Map a DB error code to a textual message.  This is actually
  113.      * just a wrapper for DB::errorMessage().
  114.      *
  115.      * @param $dbcode the DB error code
  116.      *
  117.      * @return string the corresponding error message, of FALSE
  118.      * if the error code was unknown
  119.      */
  120.     function errorMessage($dbcode) {
  121.         return DB::errorMessage($this->errorcode_map[$dbcode]);
  122.     }
  123.  
  124.     // }}}
  125.  
  126.     // {{{ prepare()
  127.  
  128.     /**
  129.      * Prepares a query for multiple execution with execute().  With
  130.      * PostgreSQL, this is emulated.
  131.      */
  132.     function prepare($query) {
  133.         $tokens = split('[\&\?]', $query);
  134.         $token = 0;
  135.         $types = array();
  136.         for ($i = 0; $i < strlen($query); $i++) {
  137.             switch ($query[$i]) {
  138.                 case '?':
  139.                     $types[$token++] = DB_PARAM_SCALAR;
  140.                     break;
  141.                 case '&':
  142.                     $types[$token++] = DB_PARAM_OPAQUE;
  143.                     break;
  144.             }
  145.         }
  146.         $this->prepare_tokens[] = &$tokens;
  147.         end($this->prepare_tokens);
  148.         $k = key($this->prepare_tokens);
  149.         $this->prepare_types[$k] = $types;
  150.         return $k;
  151.     }
  152.  
  153.     // }}}
  154.     // {{{ execute_emulate_query()
  155.  
  156.     /**
  157.      * @return a string containing the real query run when emulating
  158.      * prepare/execute.  A DB error code is returned on failure.
  159.      */
  160.     function execute_emulate_query($stmt, $data = false) {
  161.         $p = &$this->prepare_tokens;
  162.         $stmt = 0; // XXX HORRIBLE HACK
  163.         if (!isset($this->prepare_tokens[$stmt]) ||
  164.             !is_array($this->prepare_tokens[$stmt]) ||
  165.             !sizeof($this->prepare_tokens[$stmt])) {
  166.             return DB_ERROR_INVALID;
  167.         }
  168.         $qq = &$this->prepare_tokens[$stmt];
  169.         $qp = sizeof($qq) - 1;
  170.         if ((!$data && $qp > 0) ||
  171.             (!is_array($data) && $qp > 1) ||
  172.             (is_array($data) && $qp > sizeof($data))) {
  173.             return DB_ERROR_NEED_MORE_DATA;
  174.         }
  175.         $realquery = $qq[0];
  176.         for ($i = 0; $i < $qp; $i++) {
  177.             if ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) {
  178.                 if (is_array($data)) {
  179.                     $fp = fopen($data[$i], "r");
  180.                 } else {
  181.                     $fp = fopen($data, "r");
  182.                 }
  183.                 $pdata = '';
  184.                 if ($fp) {
  185.                     while (($buf = fread($fp, 4096)) != false) {
  186.                         $pdata .= $buf;
  187.                     }
  188.                 }
  189.             } else {
  190.                 if (is_array($data)) {
  191.                     $pdata = &$data[$i];
  192.                 } else {
  193.                     $pdata = &$data;
  194.                 }
  195.             }
  196.             $realquery .= "'" . $this->quoteString($pdata) . "'";
  197.             $realquery .= $qq[$i + 1];
  198.         }
  199.         return $realquery;
  200.     }
  201.  
  202.     // }}}
  203.  
  204.     // {{{ executeMultiple()
  205.  
  206.     /**
  207.      * This function does several execute() calls on the same
  208.      * statement handle.  $data must be an array indexed numerically
  209.      * from 0, one execute call is done for every "row" in the array.
  210.      *
  211.      * If an error occurs during execute(), executeMultiple() does not
  212.      * execute the unfinished rows, but rather returns that error.
  213.      */
  214.     function executeMultiple($stmt, &$data) {
  215.         for ($i = 0; $i < sizeof($data); $i++) {
  216.             $res = $this->execute($stmt, &$data[$i]);
  217.             if (DB::isError($res)) {
  218.                 return $res;
  219.             }
  220.         }
  221.         return DB_OK;
  222.     }
  223.  
  224.     // }}}
  225.     // {{{ getOne()
  226.  
  227.     /**
  228.      * Fetch the first column of the first row of data returned from
  229.      * a query.  Takes care of doing the query and freeing the results
  230.      * when finished.
  231.      *
  232.      * @param $query the SQL query
  233.      * @param $params is supplies, prepare/execute will be used
  234.      *        with this array as execute parameters
  235.      */
  236.     function &getOne($query, $params = array()) {
  237.         if (sizeof($params) > 0) {
  238.             $sth = $this->prepare($query);
  239.             if (DB::isError($sth)) {
  240.                 return $sth;
  241.             }
  242.             $res = $this->execute($sth, &$params);
  243.         } else {
  244.             $res = $this->simpleQuery($query);
  245.         }
  246.         if (DB::isError($res)) {
  247.             return $res;
  248.         }
  249.         $row = $this->fetchRow($res, DB_GETMODE_ORDERED);
  250.         if (DB::isError($row)) {
  251.             return $row;
  252.         }
  253.         $ret = &$row[0];
  254.         $this->freeResult($res);
  255.         return $ret;
  256.     }
  257.  
  258.     // }}}
  259.     // {{{ getRow()
  260.  
  261.     /**
  262.      * Fetch the first row of data returned from a query.  Takes care
  263.      * of doing the query and freeing the results when finished.
  264.      *
  265.      * @param $query the SQL query
  266.      * @return array the first row of results as an array indexed from
  267.      * 0, or a DB error code.
  268.      */
  269.     function &getRow($query, $getmode = DB_GETMODE_DEFAULT, $params = array()) {
  270.         $res = $this->simpleQuery($query);
  271.         if (DB::isError($res)) {
  272.             return $res;
  273.         }
  274.         $row = $this->fetchRow($res, $getmode);
  275.         if (DB::isError($row)) {
  276.             return $row;
  277.         }
  278.         $this->freeResult($res);
  279.         return $row;
  280.     }
  281.  
  282.     // }}}
  283.     // {{{ getAssoc()
  284.  
  285.     /**
  286.      * Fetch the entire result set of a query and return it as an
  287.      * associative array using the first column as the key.
  288.      *
  289.      * @param $query the SQL query
  290.      *
  291.      * @param $force_array (optional) used only when the query returns
  292.      * exactly two columns.  If true, the values of the returned array
  293.      * will be one-element arrays instead of scalars.
  294.      *
  295.      * @return array associative array with results from the query.
  296.      * If the result set contains more than two columns, the value
  297.      * will be an array of the values from column 2-n.  If the result
  298.      * set contains only two columns, the returned value will be a
  299.      * scalar with the value of the second column (unless forced to an
  300.      * array with the $force_array parameter).  A DB error code is
  301.      * returned on errors.  If the result set contains fewer than two
  302.      * columns, DB_ERROR_TRUNCATED is returned.
  303.      *
  304.      * For example, if the table "mytable" contains:
  305.      *
  306.      *  ID      TEXT       DATE
  307.      * --------------------------------
  308.      *  1       'one'      944679408
  309.      *  2       'two'      944679408
  310.      *  3       'three'    944679408
  311.      *
  312.      * Then the call getAssoc('SELECT id,text FROM mytable') returns:
  313.      *   array(
  314.      *     '1' => 'one',
  315.      *     '2' => 'two',
  316.      *     '3' => 'three',
  317.      *   )
  318.      *
  319.      * ...while the call getAssoc('SELECT id,text,date FROM mydate') returns:
  320.      *   array(
  321.      *     '1' => array('one', '944679408'),
  322.      *     '2' => array('two', '944679408'),
  323.      *     '3' => array('three', '944679408')
  324.      *   )
  325.      *
  326.      * Keep in mind that database functions in PHP usually return string
  327.      * values for results regardless of the database's internal type.
  328.      */
  329.     function &getAssoc($query, $force_array = false, $params = array()) {
  330.         $res = $this->simpleQuery($query);
  331.         if (DB::isError($res)) {
  332.             return $res;
  333.         }
  334.         $cols = $this->numCols($res);
  335.         if ($cols < 2) {
  336.             return DB_ERROR_TRUNCATED;
  337.         }
  338.         $results = array();
  339.         if ($cols > 2 || $force_array) {
  340.             // return array values
  341.             // XXX this part can be optimized
  342.             while (!DB::isError($row = $this->fetchRow($res))) {
  343.                 reset($row);
  344.                 // we copy the row of data into a new array
  345.                 // to get indices running from 0 again
  346.                 for ($i = 1; $i < $cols; $i++) {
  347.                     $results[$row[0]][$i-1] = $row[$i];
  348.                 }
  349.             }
  350.         } else {
  351.             // return scalar values
  352.             while (!DB::isError($row = $this->fetchRow($res))) {
  353.                 $results[$row[0]] = $row[1];
  354.             }
  355.         }
  356.         return $results; // XXX ADDREF
  357.     }
  358.  
  359.     // }}}
  360.     // {{{ getAll()
  361.  
  362.     function &getAll($query, $getmode = DB_GETMODE_DEFAULT, $params = array()) {
  363.                 
  364.     }
  365.  
  366.     // }}}
  367. }
  368.  
  369. // Local variables:
  370. // tab-width: 4
  371. // c-basic-offset: 4
  372. // End:
  373. ?>
  374.