MDB
[ class tree: MDB ] [ index: MDB ] [ all elements ]

Source for file MDB.php

Documentation is available at MDB.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: MDB.php,v 1.59.4.12 2004/02/28 10:37:54 quipo Exp $
  46. //
  47. require_once('PEAR.php');
  48.  
  49. /**
  50.  * The method mapErrorCode in each MDB_dbtype implementation maps
  51.  * native error codes to one of these.
  52.  *
  53.  * If you add an error code here, make sure you also add a textual
  54.  * version of it in MDB::errorMessage().
  55.  */
  56.  
  57. define('MDB_OK',                         1);
  58. define('MDB_ERROR',                     -1);
  59. define('MDB_ERROR_SYNTAX',              -2);
  60. define('MDB_ERROR_CONSTRAINT',          -3);
  61. define('MDB_ERROR_NOT_FOUND',           -4);
  62. define('MDB_ERROR_ALREADY_EXISTS',      -5);
  63. define('MDB_ERROR_UNSUPPORTED',         -6);
  64. define('MDB_ERROR_MISMATCH',            -7);
  65. define('MDB_ERROR_INVALID',             -8);
  66. define('MDB_ERROR_NOT_CAPABLE',         -9);
  67. define('MDB_ERROR_TRUNCATED',          -10);
  68. define('MDB_ERROR_INVALID_NUMBER',     -11);
  69. define('MDB_ERROR_INVALID_DATE',       -12);
  70. define('MDB_ERROR_DIVZERO',            -13);
  71. define('MDB_ERROR_NODBSELECTED',       -14);
  72. define('MDB_ERROR_CANNOT_CREATE',      -15);
  73. define('MDB_ERROR_CANNOT_DELETE',      -16);
  74. define('MDB_ERROR_CANNOT_DROP',        -17);
  75. define('MDB_ERROR_NOSUCHTABLE',        -18);
  76. define('MDB_ERROR_NOSUCHFIELD',        -19);
  77. define('MDB_ERROR_NEED_MORE_DATA',     -20);
  78. define('MDB_ERROR_NOT_LOCKED',         -21);
  79. define('MDB_ERROR_VALUE_COUNT_ON_ROW'-22);
  80. define('MDB_ERROR_INVALID_DSN',        -23);
  81. define('MDB_ERROR_CONNECT_FAILED',     -24);
  82. define('MDB_ERROR_EXTENSION_NOT_FOUND',-25);
  83. define('MDB_ERROR_NOSUCHDB',           -26);
  84. define('MDB_ERROR_ACCESS_VIOLATION',   -27);
  85. define('MDB_ERROR_CANNOT_REPLACE',     -28);
  86. define('MDB_ERROR_CONSTRAINT_NOT_NULL',-29);
  87. define('MDB_ERROR_DEADLOCK',           -30);
  88. define('MDB_ERROR_CANNOT_ALTER',       -31);
  89. define('MDB_ERROR_MANAGER',            -32);
  90. define('MDB_ERROR_MANAGER_PARSE',      -33);
  91. define('MDB_ERROR_LOADMODULE',         -34);
  92. define('MDB_ERROR_INSUFFICIENT_DATA',  -35);
  93. /**
  94.  * This is a special constant that tells DB the user hasn't specified
  95.  * any particular get mode, so the default should be used.
  96.  */
  97.  
  98. define('MDB_FETCHMODE_DEFAULT'0);
  99.  
  100. /**
  101.  * Column data indexed by numbers, ordered from 0 and up
  102.  */
  103.  
  104. define('MDB_FETCHMODE_ORDERED',  1);
  105.  
  106. /**
  107.  * Column data indexed by column names
  108.  */
  109.  
  110. define('MDB_FETCHMODE_ASSOC',    2);
  111.  
  112. /**
  113.  * For multi-dimensional results: normally the first level of arrays
  114.  * is the row number, and the second level indexed by column number or name.
  115.  * MDB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
  116.  * is the column name, and the second level the row number.
  117.  */
  118.  
  119. define('MDB_FETCHMODE_FLIPPED',  4);
  120.  
  121. /**
  122.  * These are constants for the tableInfo-function
  123.  * they are bitwised or'ed. so if there are more constants to be defined
  124.  * in the future, adjust MDB_TABLEINFO_FULL accordingly
  125.  */
  126.  
  127. define('MDB_TABLEINFO_ORDER',      1);
  128. define('MDB_TABLEINFO_ORDERTABLE'2);
  129. define('MDB_TABLEINFO_FULL',       3);
  130.  
  131. /**
  132.  * These are constants for each of the supported datatypes
  133.  */
  134.  
  135. define('MDB_TYPE_TEXT'      0);
  136. define('MDB_TYPE_BOOLEAN'   1);
  137. define('MDB_TYPE_INTEGER'   2);
  138. define('MDB_TYPE_DECIMAL'   3);
  139. define('MDB_TYPE_FLOAT'     4);
  140. define('MDB_TYPE_DATE'      5);
  141. define('MDB_TYPE_TIME'      6);
  142. define('MDB_TYPE_TIMESTAMP' 7);
  143. define('MDB_TYPE_CLOB'      8);
  144. define('MDB_TYPE_BLOB'      9);
  145.  
  146. /**
  147.  * These are global variables that are used to track the various class instances
  148.  */
  149.  
  150. $GLOBALS['_MDB_lobs'= array();
  151. $GLOBALS['_MDB_databases'= array();
  152.  
  153. /**
  154.  * The main 'MDB' class is simply a container class with some static
  155.  * methods for creating DB objects as well as some utility functions
  156.  * common to all parts of DB.
  157.  *
  158.  * The object model of DB is as follows (indentation means inheritance):
  159.  *
  160.  * MDB          The main DB class.  This is simply a utility class
  161.  *              with some 'static' methods for creating MDB objects as
  162.  *              well as common utility functions for other MDB classes.
  163.  *
  164.  * MDB_common   The base for each DB implementation.  Provides default
  165.  * |            implementations (in OO lingo virtual methods) for
  166.  * |            the actual DB implementations as well as a bunch of
  167.  * |            query utility functions.
  168.  * |
  169.  * +-MDB_mysql  The DB implementation for MySQL. Inherits MDB_Common.
  170.  *              When calling MDB::factory or MDB::connect for MySQL
  171.  *              connections, the object returned is an instance of this
  172.  *              class.
  173.  * +-MDB_pgsql  The DB implementation for PostGreSQL. Inherits MDB_Common.
  174.  *              When calling MDB::factory or MDB::connect for PostGreSQL
  175.  *              connections, the object returned is an instance of this
  176.  *              class.
  177.  *
  178.  * MDB_Date     This class provides several method to convert from and to
  179.  *              MDB timestamps.
  180.  *
  181.  * MDB_Manager  This class handles the xml schema management.
  182.  *
  183.  * @package  MDB
  184.  * @version  $Id: MDB.php,v 1.59.4.12 2004/02/28 10:37:54 quipo Exp $
  185.  * @category Database
  186.  * @author   Lukas Smith <smith@backendmedia.com>
  187.  */
  188. class MDB
  189. {
  190.     // }}}
  191.     // {{{ setOptions()
  192.  
  193.     /**
  194.      * set option array in an exiting database object
  195.      *
  196.      * @param   object  $db       MDB object
  197.      * @param   mixed   $options  An associative array of option names and
  198.      *                             their values.
  199.      * @access  public
  200.      */
  201.     function setOptions(&$db$options)
  202.     {
  203.         if(is_array($options)) {
  204.             foreach($options as $option => $value{
  205.                 $test $db->setOption($option$value);
  206.                 if(MDB::isError($test)) {
  207.                     return $test;
  208.                 }
  209.             }
  210.         else {
  211.             $db->setOption('persistent'$options);
  212.         }
  213.         $include_lob $db->getOption('includelob');
  214.         if(!MDB::isError($include_lob&& $include_lob{
  215.             $db->loadLob('load at start');
  216.         }
  217.         $includemanager $db->getOption('includemanager');
  218.         if(!MDB::isError($includemanager&& $includemanager{
  219.             $db->loadManager('load at start');
  220.         }
  221.         $debug $db->getOption('debug');
  222.         if(!MDB::isError($debug&& $debug{
  223.             $db->captureDebugOutput(TRUE);
  224.         }
  225.     }
  226.  
  227.     // }}}
  228.     // {{{ factory()
  229.  
  230.     /**
  231.      * Create a new DB connection object for the specified database
  232.      * type
  233.      * IMPORTANT: In order for MDB to work properly it is necessary that
  234.      * you make sure that you work with a reference of the original
  235.      * object instead of a copy (this is a PHP4 quirk).
  236.      *
  237.      * For example:
  238.      *     $mdb =& MDB::factory($dsn);
  239.      *          ^^
  240.      * And not:
  241.      *     $mdb = MDB::factory($dsn);
  242.      *          ^^
  243.      *
  244.      * @param   string  $type   database type, for example 'mysql'
  245.      * @return  mixed   a newly created MDB connection object, or a MDB
  246.      *                   error object on error
  247.      * @access  public
  248.      */
  249.     function &factory($type)
  250.     {
  251.         $class_name = "MDB_$type";
  252.  
  253.         @include_once("MDB/${type}.php");
  254.  
  255.         @$db =new $class_name;
  256.  
  257.         return($db);
  258.     }
  259.  
  260.     // }}}
  261.     // {{{ connect()
  262.  
  263.     /**
  264.      * Create a new MDB connection object and connect to the specified
  265.      * database
  266.      *
  267.      * IMPORTANT: In order for MDB to work properly it is necessary that
  268.      * you make sure that you work with a reference of the original
  269.      * object instead of a copy (this is a PHP4 quirk).
  270.      *
  271.      * For example:
  272.      *     $mdb =& MDB::connect($dsn);
  273.      *          ^^
  274.      * And not:
  275.      *     $mdb = MDB::connect($dsn);
  276.      *          ^^
  277.      *
  278.      * @param   mixed   $dsn      'data source name', see the MDB::parseDSN
  279.      *                             method for a description of the dsn format.
  280.      *                             Can also be specified as an array of the
  281.      *                             format returned by MDB::parseDSN.
  282.      * @param   mixed   $options  An associative array of option names and
  283.      *                             their values.
  284.      * @return  mixed   a newly created MDB connection object, or a MDB
  285.      *                   error object on error
  286.      * @access  public
  287.      * @see     MDB::parseDSN
  288.      */
  289.     function &connect($dsn$options = FALSE)
  290.     {
  291.         $dsninfo MDB::parseDSN($dsn);
  292.         if(isset($dsninfo['phptype'])) {
  293.             $type          $dsninfo['phptype'];
  294.             $class_name    'MDB_'.$type;
  295.             $include       'MDB/'.$type.'.php';
  296.         else {
  297.             return(PEAR::raiseError(NULLMDB_ERROR_NOT_FOUND,
  298.                 NULLNULL'no RDBMS driver specified',
  299.                 'MDB_Error'TRUE));
  300.         }
  301.  
  302.         if(is_array($options)
  303.             && isset($options['debug'])
  304.             && $options['debug'>= 2
  305.         {
  306.             // expose php errors with sufficient debug level
  307.             @include_once($include);
  308.         else {
  309.             include_once($include);
  310.         }
  311.  
  312.         if(!class_exists($class_name)) {
  313.             $error = PEAR::raiseError(NULLMDB_ERROR_NOT_FOUNDNULLNULL,
  314.                 'Unable to include the '.$include.' file''MDB_Error'TRUE);
  315.             return($error);
  316.         }
  317.  
  318.         @$db =new $class_name();
  319.  
  320.         $db->setDSN($dsninfo);
  321.  
  322.         MDB::setOptions($db$options);
  323.  
  324.         if(isset($dsninfo['database'])) {
  325.             $err $db->connect();
  326.             if (MDB::isError($err)) {
  327.                 $dsn $db->getDSN();
  328.                 $err->addUserInfo($dsn);
  329.                 return($err);
  330.             }
  331.         }
  332.         return($db);
  333.     }
  334.  
  335.     // }}}
  336.     // {{{ connect()
  337.  
  338.     /**
  339.      * Returns a MDB connection with the requested DSN.
  340.      * A newnew MDB connection object is only created if no object with the
  341.      * reuested DSN exists yet.
  342.      *
  343.      * IMPORTANT: In order for MDB to work properly it is necessary that
  344.      * you make sure that you work with a reference of the original
  345.      * object instead of a copy (this is a PHP4 quirk).
  346.      *
  347.      * For example:
  348.      *     $mdb =& MDB::sngleton($dsn);
  349.      *          ^^
  350.      * And not:
  351.      *     $mdb = MDB::singleton($dsn);
  352.      *          ^^
  353.      *
  354.      * @param   mixed   $dsn      'data source name', see the MDB::parseDSN
  355.      *                             method for a description of the dsn format.
  356.      *                             Can also be specified as an array of the
  357.      *                             format returned by MDB::parseDSN.
  358.      * @param   mixed   $options  An associative array of option names and
  359.      *                             their values.
  360.      * @return  mixed   a newly created MDB connection object, or a MDB
  361.      *                   error object on error
  362.      * @access  public
  363.      * @see     MDB::parseDSN
  364.      */
  365.     function &singleton($dsn = NULL$options = FALSE)
  366.     {
  367.         if ($dsn{
  368.             $dsninfo MDB::parseDSN($dsn);
  369.             $dsninfo_default = array(
  370.                 'phptype' => NULL,
  371.                 'username' => NULL,
  372.                 'password' => NULL,
  373.                 'hostspec' => NULL,
  374.                 'database' => NULL,
  375.             );
  376.             $dsninfo array_merge($dsninfo_default$dsninfo);
  377.             $keys array_keys($GLOBALS['_MDB_databases']);
  378.             for ($i=0$j=count($keys)$i<$j; ++$i{
  379.                 $tmp_dsn $GLOBALS['_MDB_databases'][$keys[$i]]->getDSN('array');
  380.                 if ($dsninfo['phptype'== $tmp_dsn['phptype']
  381.                     && $dsninfo['username'== $tmp_dsn['username']
  382.                     && $dsninfo['password'== $tmp_dsn['password']
  383.                     && $dsninfo['hostspec'== $tmp_dsn['hostspec']
  384.                     && $dsninfo['database'== $tmp_dsn['database'])
  385.                 {
  386.                     MDB::setOptions($GLOBALS['_MDB_databases'][$keys[$i]]$options);
  387.                     return $GLOBALS['_MDB_databases'][$keys[$i]];
  388.                 }
  389.             }
  390.         else {
  391.             if (is_array($GLOBALS['_MDB_databases'])
  392.                 && reset($GLOBALS['_MDB_databases'])
  393.             {
  394.                 $db =$GLOBALS['_MDB_databases'][key($GLOBALS['_MDB_databases'])];
  395.                 return $db;
  396.             }
  397.         }
  398.         $db =MDB::connect($dsn$options);
  399.         return $db;
  400.     }
  401.  
  402.     // }}}
  403.     // {{{ loadFile()
  404.  
  405.     /**
  406.      * load a file (like 'Date.php' or 'Manager.php')
  407.      *
  408.      * @return $file    name of the file to be included from the MDB dir without
  409.      *                   the '.php' extension (like 'Date' or 'Manager')
  410.      * @access public
  411.      */
  412.     function loadFile($file)
  413.     {
  414.         @include_once('MDB/'.$file.'.php');
  415.     }
  416.  
  417.     // }}}
  418.     // {{{ apiVersion()
  419.  
  420.     /**
  421.      * Return the MDB API version
  422.      *
  423.      * @return int     the MDB API version number
  424.      * @access public
  425.      */
  426.     function apiVersion()
  427.     {
  428.         return(1);
  429.     }
  430.  
  431.     // }}}
  432.     // {{{ isError()
  433.  
  434.     /**
  435.      * Tell whether a result code from a MDB method is an error
  436.      *
  437.      * @param   int       $value  result code
  438.      * @return  boolean   whether $value is an MDB_Error
  439.      * @access public
  440.      */
  441.     function isError($value)
  442.     {
  443.         return is_a($value'MDB_Error');
  444.     }
  445.  
  446.     // }}}
  447.     // {{{ isConnection()
  448.     /**
  449.      * Tell whether a value is a MDB connection
  450.      *
  451.      * @param mixed $value value to test
  452.      *
  453.      * @return bool whether $value is a MDB connection
  454.      *
  455.      * @access public
  456.      */
  457.     function isConnection($value)
  458.     {
  459.         return is_a($value'MDB_Common');
  460.     }
  461.  
  462.     // }}}
  463.     // {{{ isManip()
  464.  
  465.     /**
  466.      * Tell whether a query is a data manipulation query (insert,
  467.      * update or delete) or a data definition query (create, drop,
  468.      * alter, grant, revoke).
  469.      *
  470.      * @param   string   $query the query
  471.      * @return  boolean  whether $query is a data manipulation query
  472.      * @access public
  473.      */
  474.     function isManip($query)
  475.     {
  476.         $manips 'INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|
  477.                   ALTER|GRANT|REVOKE|LOCK|UNLOCK|ROLLBACK|COMMIT';
  478.         if (preg_match('/^\s*"?('.$manips.')\s+/i'$query)) {
  479.             return(TRUE);
  480.         }
  481.         return(FALSE);
  482.     }
  483.  
  484.     // }}}
  485.     // {{{ errorMessage()
  486.  
  487.     /**
  488.      * Return a textual error message for a MDB error code
  489.      *
  490.      * @param   int     $value error code
  491.      * @return  string  error message, or false if the error code was
  492.      *                   not recognized
  493.      * @access public
  494.      */
  495.     function errorMessage($value)
  496.     {
  497.         static $errorMessages;
  498.         if (!isset($errorMessages)) {
  499.             $errorMessages = array(
  500.                 MDB_ERROR                    => 'unknown error',
  501.                 MDB_ERROR_ALREADY_EXISTS     => 'already exists',
  502.                 MDB_ERROR_CANNOT_CREATE      => 'can not create',
  503.                 MDB_ERROR_CANNOT_ALTER       => 'can not alter',
  504.                 MDB_ERROR_CANNOT_REPLACE     => 'can not replace',
  505.                 MDB_ERROR_CANNOT_DELETE      => 'can not delete',
  506.                 MDB_ERROR_CANNOT_DROP        => 'can not drop',
  507.                 MDB_ERROR_CONSTRAINT         => 'constraint violation',
  508.                 MDB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
  509.                 MDB_ERROR_DIVZERO            => 'division by zero',
  510.                 MDB_ERROR_INVALID            => 'invalid',
  511.                 MDB_ERROR_INVALID_DATE       => 'invalid date or time',
  512.                 MDB_ERROR_INVALID_NUMBER     => 'invalid number',
  513.                 MDB_ERROR_MISMATCH           => 'mismatch',
  514.                 MDB_ERROR_NODBSELECTED       => 'no database selected',
  515.                 MDB_ERROR_NOSUCHFIELD        => 'no such field',
  516.                 MDB_ERROR_NOSUCHTABLE        => 'no such table',
  517.                 MDB_ERROR_NOT_CAPABLE        => 'MDB backend not capable',
  518.                 MDB_ERROR_NOT_FOUND          => 'not found',
  519.                 MDB_ERROR_NOT_LOCKED         => 'not locked',
  520.                 MDB_ERROR_SYNTAX             => 'syntax error',
  521.                 MDB_ERROR_UNSUPPORTED        => 'not supported',
  522.                 MDB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
  523.                 MDB_ERROR_INVALID_DSN        => 'invalid DSN',
  524.                 MDB_ERROR_CONNECT_FAILED     => 'connect failed',
  525.                 MDB_OK                       => 'no error',
  526.                 MDB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
  527.                 MDB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
  528.                 MDB_ERROR_NOSUCHDB           => 'no such database',
  529.                 MDB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
  530.                 MDB_ERROR_MANAGER            => 'MDB_manager error',
  531.                 MDB_ERROR_MANAGER_PARSE      => 'MDB_manager schema parse error',
  532.                 MDB_ERROR_LOADMODULE         => 'Error while including on demand module',
  533.                 MDB_ERROR_TRUNCATED          => 'truncated',
  534.                 MDB_ERROR_DEADLOCK           => 'deadlock detected',
  535.             );
  536.         }
  537.  
  538.         if (MDB::isError($value)) {
  539.             $value $value->getCode();
  540.         }
  541.  
  542.         return(isset($errorMessages[$value]?
  543.            $errorMessages[$value$errorMessages[MDB_ERROR]);
  544.     }
  545.  
  546.     // }}}
  547.     // {{{ parseDSN()
  548.  
  549.     /**
  550.      * Parse a data source name
  551.      *
  552.      * A array with the following keys will be returned:
  553.      *  phptype: Database backend used in PHP (mysql, odbc etc.)
  554.      *  dbsyntax: Database used with regards to SQL syntax etc.
  555.      *  protocol: Communication protocol to use (tcp, unix etc.)
  556.      *  hostspec: Host specification (hostname[:port])
  557.      *  database: Database to use on the DBMS server
  558.      *  username: User name for login
  559.      *  password: Password for login
  560.      *
  561.      * The format of the supplied DSN is in its fullest form:
  562.      *
  563.      *  phptype(dbsyntax)://username:password@protocol+hostspec/database
  564.      *
  565.      * Most variations are allowed:
  566.      *
  567.      *  phptype://username:password@protocol+hostspec:110//usr/db_file.db
  568.      *  phptype://username:password@hostspec/database_name
  569.      *  phptype://username:password@hostspec
  570.      *  phptype://username@hostspec
  571.      *  phptype://hostspec/database
  572.      *  phptype://hostspec
  573.      *  phptype(dbsyntax)
  574.      *  phptype
  575.      *
  576.      * @param   string  $dsn Data Source Name to be parsed
  577.      * @return  array   an associative array
  578.      * @access public
  579.      * @author Tomas V.V.Cox <cox@idecnet.com>
  580.      */
  581.     function parseDSN($dsn)
  582.     {
  583.         if (is_array($dsn)) {
  584.             return($dsn);
  585.         }
  586.  
  587.         $parsed = array(
  588.             'phptype'  => FALSE,
  589.             'dbsyntax' => FALSE,
  590.             'username' => FALSE,
  591.             'password' => FALSE,
  592.             'protocol' => FALSE,
  593.             'hostspec' => FALSE,
  594.             'port'     => FALSE,
  595.             'socket'   => FALSE,
  596.             'database' => FALSE
  597.         );
  598.  
  599.         // Find phptype and dbsyntax
  600.         if (($pos strpos($dsn'://')) !== FALSE{
  601.             $str substr($dsn0$pos);
  602.             $dsn substr($dsn$pos + 3);
  603.         else {
  604.             $str $dsn;
  605.             $dsn = NULL;
  606.         }
  607.  
  608.         // Get phptype and dbsyntax
  609.         // $str => phptype(dbsyntax)
  610.         if (preg_match('|^(.+?)\((.*?)\)$|'$str$arr)) {
  611.             $parsed['phptype']  $arr[1];
  612.             $parsed['dbsyntax'(empty($arr[2])) $arr[1$arr[2];
  613.         else {
  614.             $parsed['phptype']  $str;
  615.             $parsed['dbsyntax'$str;
  616.         }
  617.  
  618.         if (empty($dsn)) {
  619.             return($parsed);
  620.         }
  621.  
  622.         // Get (if found): username and password
  623.         // $dsn => username:password@protocol+hostspec/database
  624.         if (($at strrpos($dsn,'@')) !== FALSE{
  625.             $str substr($dsn0$at);
  626.             $dsn substr($dsn$at + 1);
  627.             if (($pos strpos($str':')) !== FALSE{
  628.                 $parsed['username'rawurldecode(substr($str0$pos));
  629.                 $parsed['password'rawurldecode(substr($str$pos + 1));
  630.             else {
  631.                 $parsed['username'rawurldecode($str);
  632.             }
  633.         }
  634.  
  635.         // Find protocol and hostspec
  636.  
  637.         // $dsn => proto(proto_opts)/database
  638.         if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|'$dsn$match)) {
  639.             $proto       $match[1];
  640.             $proto_opts  (!empty($match[2])) $match[2: FALSE;
  641.             $dsn         $match[3];
  642.  
  643.         // $dsn => protocol+hostspec/database (old format)
  644.         else {
  645.             if (strpos($dsn'+'!== FALSE{
  646.                 list($proto$dsnexplode('+'$dsn2);
  647.             }
  648.             if (strpos($dsn'/'!== FALSE{
  649.                 list($proto_opts$dsnexplode('/'$dsn2);
  650.             else {
  651.                 $proto_opts $dsn;
  652.                 $dsn = NULL;
  653.             }
  654.         }
  655.  
  656.         // process the different protocol options
  657.         $parsed['protocol'(!empty($proto)) $proto 'tcp';
  658.         $proto_opts rawurldecode($proto_opts);
  659.         if ($parsed['protocol'== 'tcp'{
  660.             if (strpos($proto_opts':'!== FALSE{
  661.                 list($parsed['hostspec']$parsed['port']=
  662.                                                      explode(':'$proto_opts);
  663.             else {
  664.                 $parsed['hostspec'$proto_opts;
  665.             }
  666.         elseif ($parsed['protocol'== 'unix'{
  667.             $parsed['socket'$proto_opts;
  668.         }
  669.  
  670.         // Get dabase if any
  671.         // $dsn => database
  672.         if (!empty($dsn)) {
  673.             // /database
  674.             if (($pos strpos($dsn'?')) === FALSE{
  675.                 $parsed['database'$dsn;
  676.             // /database?param1=value1&param2=value2
  677.             else {
  678.                 $parsed['database'substr($dsn0$pos);
  679.                 $dsn substr($dsn$pos + 1);
  680.                 if (strpos($dsn'&'!== FALSE{
  681.                     $opts explode('&'$dsn);
  682.                 else // database?param1=value1
  683.                     $opts = array($dsn);
  684.                 }
  685.                 foreach ($opts as $opt{
  686.                     list($key$valueexplode('='$opt);
  687.                     if (!isset($parsed[$key])) // don't allow params overwrite
  688.                         $parsed[$keyrawurldecode($value);
  689.                     }
  690.                 }
  691.             }
  692.         }
  693.  
  694.         return($parsed);
  695.     }
  696. }
  697.  
  698. /**
  699.  * MDB_Error implements a class for reporting portable database error
  700.  * messages.
  701.  *
  702.  * @package MDB
  703.  * @category Database
  704.  * @author  Stig Bakken <ssb@fast.no>
  705.  */
  706. class MDB_Error extends PEAR_Error
  707. {
  708.  
  709.     // }}}
  710.     // {{{ constructor
  711.  
  712.     /**
  713.      * MDB_Error constructor.
  714.      *
  715.      * @param mixed   $code      MDB error code, or string with error message.
  716.      * @param integer $mode      what 'error mode' to operate in
  717.      * @param integer $level     what error level to use for
  718.      *                            $mode & PEAR_ERROR_TRIGGER
  719.      * @param smixed  $debuginfo additional debug info, such as the last query
  720.      */
  721.     function MDB_Error($code = MDB_ERROR$mode = PEAR_ERROR_RETURN,
  722.               $level = E_USER_NOTICE$debuginfo = NULL)
  723.     {
  724.         if (is_int($code)) {
  725.             $this->PEAR_Error('MDB Error: '.MDB::errorMessage($code)$code,
  726.                 $mode$level$debuginfo);
  727.         else {
  728.             $this->PEAR_Error("MDB Error: $code"MDB_ERROR$mode$level,
  729.                 $debuginfo);
  730.         }
  731.     }
  732. }
  733. ?>

Documentation generated on Mon, 11 Mar 2019 10:15:26 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.