home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Magazine / HomeAutomation / Apache / lib / php / DB.php next >
Encoding:
PHP Script  |  2000-07-11  |  13.4 KB  |  481 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. // $Id: DB.php,v 1.19 2000/06/21 02:22:04 chagenbu Exp $
  21. //
  22. // Database independent query interface.
  23. //
  24.  
  25. // {{{ Database independent error codes.
  26.  
  27. /*
  28.  * The method mapErrorCode in each DB_dbtype implementation maps
  29.  * native error codes to one of these.
  30.  *
  31.  * If you add an error code here, make sure you also add a textual
  32.  * version of it in DB::errorMessage().
  33.  */
  34. define("DB_OK",                         0);
  35. define("DB_ERROR",                     -1);
  36. define("DB_ERROR_SYNTAX",              -2);
  37. define("DB_ERROR_CONSTRAINT",          -3);
  38. define("DB_ERROR_NOT_FOUND",           -4);
  39. define("DB_ERROR_ALREADY_EXISTS",      -5);
  40. define("DB_ERROR_UNSUPPORTED",         -6);
  41. define("DB_ERROR_MISMATCH",            -7);
  42. define("DB_ERROR_INVALID",             -8);
  43. define("DB_ERROR_NOT_CAPABLE",         -9);
  44. define("DB_ERROR_TRUNCATED",       -10);
  45. define("DB_ERROR_INVALID_NUMBER",  -11);
  46. define("DB_ERROR_INVALID_DATE",    -12);
  47. define("DB_ERROR_DIVZERO",         -13);
  48. define("DB_ERROR_NODBSELECTED",    -14);
  49. define("DB_ERROR_CANNOT_CREATE",   -15);
  50. define("DB_ERROR_CANNOT_DELETE",   -16);
  51. define("DB_ERROR_CANNOT_DROP",     -17);
  52. define("DB_ERROR_NOSUCHTABLE",     -18);
  53. define("DB_ERROR_NOSUCHFIELD",     -19);
  54. define("DB_ERROR_NEED_MORE_DATA",  -20);
  55.  
  56. /*
  57.  * Warnings are not detected as errors by DB::isError(), and are not
  58.  * fatal.  You can detect whether an error is in fact a warning with
  59.  * DB::isWarning().
  60.  */
  61. define("DB_WARNING_READ_ONLY",   -1000);
  62.  
  63. // }}}
  64. // {{{ Prepare/execute parameter types
  65.  
  66. /*
  67.  * These constants are used when storing information about prepared
  68.  * statements (using the "prepare" method in DB_dbtype).
  69.  *
  70.  * The prepare/execute model in DB is mostly borrowed from the ODBC
  71.  * extension, in a query the "?" character means a scalar parameter.
  72.  * There is one extension though, a "*" character means an opaque
  73.  * parameter.  An opaque parameter is simply a file name, the real
  74.  * data are in that file (useful for stuff like putting uploaded files
  75.  * into your database).
  76.  */
  77. define("DB_PARAM_SCALAR",           1);
  78. define("DB_PARAM_OPAQUE",           2);
  79.  
  80. // }}}
  81. // {{{ Binary data modes
  82.  
  83. /*
  84.  * These constants define different ways of returning binary data
  85.  * from queries.  Again, this model has been borrowed from the ODBC
  86.  * extension.
  87.  *
  88.  * DB_BINMODE_PASSTHRU sends the data directly through to the browser
  89.  * when data is fetched from the database.
  90.  * DB_BINMODE_RETURN lets you return data as usual.
  91.  * DB_BINMODE_CONVERT returns data as well, only it is converted to
  92.  * hex format, for example the string "123" would become "313233".
  93.  */
  94. define("DB_BINMODE_PASSTHRU",       1);
  95. define("DB_BINMODE_RETURN",         2);
  96. define("DB_BINMODE_CONVERT",        3);
  97.  
  98. // }}}
  99. // {{{ Get modes: flags that control the layout of query result structures
  100.  
  101. /**
  102.  * Column data indexed by numbers, ordered from 0 and up
  103.  */
  104. define('DB_GETMODE_ORDERED', 1);
  105. /**
  106.  * Column data indexed by column names
  107.  */
  108. define('DB_GETMODE_ASSOC',   2);
  109. /**
  110.  * For multi-dimensional results: normally the first level of arrays
  111.  * is the row number, and the second level indexed by column number or name.
  112.  * DB_GETMODE_FLIPPED switches this order, so the first level of arrays
  113.  * is the column name, and the second level the row number.
  114.  */
  115. define('DB_GETMODE_FLIPPED', 4);
  116.  
  117. /**
  118.  * This constant DB's default get mode.  It is possible to override by
  119.  * defining in your scripts before including DB.
  120.  */
  121. if (!defined('DB_GETMODE_DEFAULT')) {
  122.     define('DB_GETMODE_DEFAULT', DB_GETMODE_ORDERED);
  123. }
  124.  
  125. // }}}
  126.  
  127. /**
  128.  * The main "DB" class is simply a container class with some static
  129.  * methods for creating DB objects as well as some utility functions
  130.  * common to all parts of DB.
  131.  *
  132.  * The object model of DB is as follows (indentation means inheritance):
  133.  *
  134.  * DB           The main DB class.  This is simply a utility class
  135.  *              with some "static" methods for creating DB objects as
  136.  *              well as common utility functions for other DB classes.
  137.  * 
  138.  * DB_common    The base for each DB implementation.  Provides default
  139.  * |            implementations (in OO lingo virtual methods) for
  140.  * |            the actual DB implementations as well as a bunch of
  141.  * |            query utility functions.
  142.  * |
  143.  * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
  144.  *              When calling DB::factory or DB::connect for MySQL
  145.  *              connections, the object returned is an instance of this
  146.  *              class.
  147.  *
  148.  * @version  1.00
  149.  * @author   Stig Bakken <ssb@fast.no>
  150.  * @since    PHP 4.0
  151.  */
  152. class DB {
  153.     // {{{ factory()
  154.  
  155.     /**
  156.      * Create a new DB object for the specified database type
  157.      *
  158.      * @param $type string database type, for example "mysql"
  159.      *
  160.      * @return object a newly created DB object, or a DB error code on
  161.      * error
  162.      */
  163.     function &factory($type) {
  164.         if (!@include_once("DB/${type}.php")) {
  165.             return DB_ERROR_NOT_FOUND;
  166.         }
  167.         $classname = 'DB_' . $type;
  168.         $obj = new $classname;
  169.         return $obj;
  170.     }
  171.  
  172.     // }}}
  173.     // {{{ connect()
  174.  
  175.     /**
  176.      * Create a new DB object and connect to the specified database
  177.      *
  178.      * @param $dsn string "data source name", see the DB::parseDSN
  179.      * method for a description of the dsn format.
  180.      *
  181.      * @param $persistent bool whether this connection should be
  182.      * persistent.  Ignored if the backend extension does not support
  183.      * persistent connections.
  184.      *
  185.      * @return object a newly created DB object, or a DB error code on
  186.      * error
  187.      */
  188.     function &connect($dsn, $persistent = false) {
  189.         global $USED_PACKAGES;
  190.  
  191.         $dsninfo = DB::parseDSN($dsn);
  192.         $type = $dsninfo['phptype'];
  193.         if (!@include_once("DB/${type}.php")) {
  194.             return DB_ERROR_NOT_FOUND;
  195.         }
  196.         $classname = 'DB_' . $type;
  197.         $obj = new $classname;
  198.         $err = $obj->connect(&$dsninfo, $persistent);
  199.         if (DB::isError($err)) {
  200.             return $err;
  201.         }
  202.         return $obj;
  203.     }
  204.  
  205.     // }}}
  206.     // {{{ apiVersion()
  207.  
  208.     /**
  209.      * Return the DB API version
  210.      *
  211.      * @return int the DB API version number
  212.      */
  213.     function apiVersion() {
  214.         return 1;
  215.     }
  216.  
  217.     // }}}
  218.     // {{{ isError()
  219.  
  220.     /**
  221.      * Tell whether a result code from a DB method is an error
  222.      *
  223.      * @param $code int result code
  224.      *
  225.      * @return bool whether $code is an error
  226.      */
  227.     function isError($code) {
  228.         return is_int($code) && ($code < 0) && ($code > -1000);
  229.     }
  230.  
  231.     // }}}
  232.     // {{{ isWarning()
  233.  
  234.     /**
  235.      * Tell whether a result code from a DB method is a warning.
  236.      * Warnings differ from errors in that they are generated by DB,
  237.      * and are not fatal.
  238.      *
  239.      * @param $code int result code
  240.      *
  241.      * @return bool whether $code is a warning
  242.      */
  243.     function isWarning($code) {
  244.         return is_int($code) && ($code <= -1000);
  245.     }
  246.  
  247.     // }}}
  248.     // {{{ errorMessage()
  249.  
  250.     /**
  251.      * Return a textual error message for a DB error code
  252.      *
  253.      * @param $code int error code
  254.      *
  255.      * @return string error message, or false if the error code was
  256.      * not recognized
  257.      */
  258.     function errorMessage($code) {
  259.         if (!isset($errorMessages)) {
  260.             $errorMessages = array(
  261.                 DB_OK                   => "no error",
  262.                 DB_ERROR                => "unknown error",
  263.                 DB_ERROR_SYNTAX         => "syntax error",
  264.                 DB_ERROR_CONSTRAINT     => "constraint violation",
  265.                 DB_ERROR_NOT_FOUND      => "not found",
  266.                 DB_ERROR_ALREADY_EXISTS => "already exists",
  267.                 DB_ERROR_UNSUPPORTED    => "not supported",
  268.                 DB_ERROR_MISMATCH       => "mismatch",
  269.                 DB_ERROR_INVALID        => "invalid",
  270.                 DB_ERROR_NOT_CAPABLE    => "DB implementation not capable",
  271.                 DB_ERROR_INVALID_NUMBER => "invalid number",
  272.                 DB_ERROR_INVALID_DATE   => "invalid date or time",
  273.                 DB_ERROR_DIVZERO        => "division by zero",
  274.                 DB_ERROR_NODBSELECTED   => "no database selected",
  275.                 DB_ERROR_CANNOT_CREATE  => "can not create",
  276.                 DB_ERROR_CANNOT_DELETE  => "can not delete",
  277.                 DB_ERROR_CANNOT_DROP    => "can not drop",
  278.                 DB_ERROR_NOSUCHTABLE    => "no such table",
  279.                 DB_ERROR_NOSUCHFIELD    => "no such field",
  280.                 DB_WARNING_READ_ONLY    => "warning: read only"
  281.             );
  282.         }
  283.         return $errorMessages[$code];
  284.     }
  285.  
  286.     // }}}
  287.     // {{{ parseDSN()
  288.  
  289.     /**
  290.      * Parse a data source name
  291.      *
  292.      * @param $dsn string Data Source Name to be parsed
  293.      *
  294.      * @return array an associative array with the following keys:
  295.      * <dl>
  296.      *  <dt>phptype</dt>
  297.      *  <dd>Database backend used in PHP (mysql, odbc etc.)</dd>
  298.      *  <dt>dbsyntax</dt>
  299.      *  <dd>Database used with regards to SQL syntax etc.</dd>
  300.      *  <dt>protocol</dt>
  301.      *  <dd>Communication protocol to use (tcp, unix etc.)</dd>
  302.      *  <dt>hostspec</dt>
  303.      *  <dd>Host specification (hostname[:port])</dd>
  304.      *  <dt>database</dt>
  305.      *  <dd>Database to use on the DBMS server</dd>
  306.      *  <dt>username</dt>
  307.      *  <dd>User name for login</dd>
  308.      *  <dt>password</dt>
  309.      *  <dd>Password for login</dd>
  310.      * </dl>
  311.      * </p>
  312.      *
  313.      * <p>
  314.      * The format of the supplied DSN is in its fullest form:
  315.      * <ul>
  316.      *  <li>phptype(dbsyntax)://username:password@protocol+hostspec/database</li>
  317.      * </ul>
  318.      * Most variations are allowed:
  319.      * <ul>
  320.      *  <li>phptype://username:password@protocol+hostspec/database</li>
  321.      *  <li>phptype://username:password@hostspec/database</li>
  322.      *  <li>phptype://username:password@hostspec</li>
  323.      *  <li>phptype://hostspec/database</li>
  324.      *  <li>phptype://hostspec</li>
  325.      *  <li>phptype(dbsyntax)</li>
  326.      *  <li>phptype</li>
  327.      * </ul>
  328.      * </p>
  329.      *
  330.      * @return bool FALSE is returned on error
  331.      */
  332.     function parseDSN($dsn) {
  333.         $parsed = array(
  334.             'phptype'  => false,
  335.             'dbsyntax' => false,
  336.             'protocol' => false,
  337.             'hostspec' => false,
  338.             'database' => false,
  339.             'username' => false,
  340.             'password' => false
  341.         );
  342.         if (preg_match('|^([^:]+)://|', $dsn, &$arr)) {
  343.             $dbtype = $arr[1];
  344.             $dsn = preg_replace('|^[^:]+://|', '', $dsn);
  345.             // match "phptype(dbsyntax)"
  346.             if (preg_match('|^([^\(]+)\((.+)\)$|', $dbtype, &$arr)) {
  347.                 $parsed['phptype'] = $arr[1];
  348.                 $parsed['dbsyntax'] = $arr[2];
  349.             } else {
  350.                 $parsed['phptype'] = $dbtype;
  351.             }
  352.         } else {
  353.             // match "phptype(dbsyntax)"
  354.             if (preg_match('|^([^\(]+)\((.+)\)$|', $dsn, &$arr)) {
  355.                 $parsed['phptype'] = $arr[1];
  356.                 $parsed['dbsyntax'] = $arr[2];
  357.             } else {
  358.                 $parsed['phptype'] = $dsn;
  359.             }
  360.             return $parsed;
  361.         }
  362.  
  363.         if (preg_match('|^(.*)/([^/]+)/?$|', $dsn, &$arr)) {
  364.             $parsed['database'] = $arr[2];
  365.             $dsn = $arr[1];
  366.         }
  367.  
  368.         if (preg_match('|^([^:]+):([^@]+)@?(.*)$|', $dsn, &$arr)) {
  369.             $parsed['username'] = $arr[1];
  370.             $parsed['password'] = $arr[2];
  371.             $dsn = $arr[3];
  372.         } elseif (preg_match('|^([^:]+)@(.*)$|', $dsn, &$arr)) {
  373.             $parsed['username'] = $arr[1];
  374.             $dsn = $arr[3];
  375.         }
  376.  
  377.         if (preg_match('|^([^\+]+)\+(.*)$|', $dsn, &$arr)) {
  378.             $parsed['protocol'] = $arr[1];
  379.             $dsn = $arr[2];
  380.         }
  381.  
  382.         if (!$parsed['database'])
  383.             $dsn = preg_replace('|/+$|', '', $dsn);
  384.  
  385.         $parsed['hostspec'] = $dsn;
  386.  
  387.         if (!$parsed['dbsyntax']) {
  388.             $parsed['dbsyntax'] = $parsed['phptype'];
  389.         }
  390.  
  391.         return $parsed;
  392.     }
  393.  
  394.     // }}}
  395. }
  396.  
  397. /**
  398.  * This class implements a wrapper for a DB result set.
  399.  * A new instance of this class will be returned by the DB implementation
  400.  * after processing a query that returns data.
  401.  */
  402. class DB_result {
  403.     // {{{ properties
  404.  
  405.     var $dbh;
  406.     var $result;
  407.  
  408.     // }}}
  409.     // {{{ DB_result()
  410.  
  411.     /**
  412.      * DB_result constructor.
  413.      * @param   $dbh    DB object reference
  414.      * @param   $result result resource id
  415.      */
  416.     function DB_result(&$dbh, $result) {
  417.         $this->dbh = &$dbh;
  418.         $this->result = $result;
  419.     }
  420.  
  421.     // }}}
  422.     // {{{ fetchRow()
  423.  
  424.     /**
  425.      * Fetch and return a row of data.
  426.      * @return  array   a row of data, or false on error
  427.      */
  428.     function fetchRow($getmode = DB_GETMODE_DEFAULT) {
  429.         return $this->dbh->fetchRow($this->result, $getmode);
  430.     }
  431.  
  432.     // }}}
  433.     // {{{ fetchInto()
  434.  
  435.     /**
  436.      * Fetch a row of data into an existing array.
  437.      *
  438.      * @param   $arr    reference to data array
  439.      * @return  int     error code
  440.      */
  441.     function fetchInto(&$arr, $getmode = DB_GETMODE_DEFAULT) {
  442.         return $this->dbh->fetchInto($this->result, &$arr, $getmode);
  443.     }
  444.  
  445.     // }}}
  446.     // {{{ numCols()
  447.  
  448.     /**
  449.      * Get the the number of columns in a result set.
  450.      *
  451.      * @return int the number of columns, or a DB error code
  452.      */
  453.     function numCols() {
  454.         return $this->dbh->numCols($this->result);
  455.     }
  456.  
  457.     // }}}
  458.     // {{{ free()
  459.  
  460.     /**
  461.      * Frees the resources allocated for this result set.
  462.      * @return  int     error code
  463.      */
  464.     function free() {
  465.         $err = $this->dbh->freeResult($this->result);
  466.         if (DB::isError($err)) {
  467.             return $err;
  468.         }
  469.         $this->dbh = $this->result = false;
  470.         return true;
  471.     }
  472.  
  473.     // }}}
  474. }
  475.  
  476. // Local variables:
  477. // tab-width: 4
  478. // c-basic-offset: 4
  479. // End:
  480. ?>
  481.