00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 include_once 'creole/SQLException.php';
00023 include_once 'creole/Connection.php';
00024
00025
00026
00027
00028
00029 @ini_set('track_errors', true);
00030
00046 class Creole {
00047
00051 const PERSISTENT = 1;
00052
00058 const NO_ASSOC_LOWER = 16;
00059
00064 const COMPAT_ASSOC_LOWER = 32;
00065
00070 const COMPAT_RTRIM_STRING = 64;
00071
00075 const COMPAT_ALL = 96;
00076
00083 private static $driverMap = array( 'mysql' => 'creole.drivers.mysql.MySQLConnection',
00084 'mysqli' => 'creole.drivers.mysqli.MySQLiConnection',
00085 'pgsql' => 'creole.drivers.pgsql.PgSQLConnection',
00086 'sqlite' => 'creole.drivers.sqlite.SQLiteConnection',
00087 'oracle' => 'creole.drivers.oracle.OCI8Connection',
00088 'mssql' => 'creole.drivers.mssql.MSSQLConnection',
00089 'odbc' => 'creole.drivers.odbc.ODBCConnection'
00090 );
00091
00097 private static $connectionMap = array();
00098
00126 public static function registerDriver($phptype, $dotpath)
00127 {
00128 self::$driverMap[$phptype] = $dotpath;
00129 }
00130
00137 public static function deregisterDriver($phptype)
00138 {
00139 unset(self::$driverMap[$phptype]);
00140 }
00141
00148 public static function getDriver($phptype)
00149 {
00150 if (isset(self::$driverMap[$phptype])) {
00151 return self::$driverMap[$phptype];
00152 } else {
00153 return null;
00154 }
00155 }
00156
00171 public static function getConnection($dsn, $flags = 0)
00172 {
00173 if (is_array($dsn)) {
00174 $dsninfo = $dsn;
00175 } else {
00176 $dsninfo = self::parseDSN($dsn);
00177 }
00178
00179
00180 if ( isset ( $dsninfo['persistent'] ) && ! empty ( $dsninfo['persistent'] ) )
00181 $flags |= Creole::PERSISTENT;
00182 if ( isset ( $dsninfo['compat_assoc_lower'] ) && ! empty ( $dsninfo['compat_assoc_lower'] ) )
00183 $flags |= Creole::COMPAT_ASSOC_LOWER;
00184 if ( isset ( $dsninfo['compat_rtrim_string'] ) && ! empty ( $dsninfo['compat_rtrim_string'] ) )
00185 $flags |= Creole::COMPAT_RTRIM_STRING;
00186 if ( isset ( $dsninfo['compat_all'] ) && ! empty ( $dsninfo['compat_all'] ) )
00187 $flags |= Creole::COMPAT_ALL;
00188
00189 if ($flags & Creole::NO_ASSOC_LOWER) {
00190 trigger_error("The Creole::NO_ASSOC_LOWER flag has been deprecated, and is now the default behavior. Use Creole::COMPAT_ASSOC_LOWER to lowercase resulset keys.", E_USER_WARNING);
00191 }
00192
00193
00194
00195 ksort($dsninfo);
00196 $connectionMapKey = crc32(serialize($dsninfo + array('compat_flags' => ($flags & Creole::COMPAT_ALL))));
00197
00198
00199 if(isset(self::$connectionMap[$connectionMapKey]))
00200 {
00201
00202
00203
00204
00205
00206
00207
00208 if( isset(self::$connectionMap[$connectionMapKey][1]) ) {
00209
00210
00211 $con = self::$connectionMap[$connectionMapKey][1];
00212 } else {
00213
00214
00215 $con = self::$connectionMap[$connectionMapKey][0];
00216 }
00217
00218
00219
00220
00221 if ($con->isConnected())
00222 return $con;
00223 }
00224
00225
00226
00227 if (isset(self::$driverMap['*'])) {
00228 $type = '*';
00229 } else {
00230 $type = $dsninfo['phptype'];
00231 if (!isset(self::$driverMap[$type])) {
00232 throw new SQLException("No driver has been registered to handle connection type: $type");
00233 }
00234 }
00235
00236
00237
00238 $clazz = self::import(self::$driverMap[$type]);
00239 $obj = new $clazz();
00240
00241 if (!($obj instanceof Connection)) {
00242 throw new SQLException("Class does not implement creole.Connection interface: $clazz");
00243 }
00244
00245 try {
00246 $obj->connect($dsninfo, $flags);
00247 } catch(SQLException $sqle) {
00248 $sqle->setUserInfo($dsninfo);
00249 throw $sqle;
00250 }
00251 $persistent = ($flags & Creole::PERSISTENT) === Creole::PERSISTENT;
00252 return self::$connectionMap[$connectionMapKey][(int)$persistent] = $obj;
00253 }
00254
00286 public static function parseDSN($dsn)
00287 {
00288 if (is_array($dsn)) {
00289 return $dsn;
00290 }
00291
00292 $parsed = array(
00293 'phptype' => null,
00294 'username' => null,
00295 'password' => null,
00296 'protocol' => null,
00297 'hostspec' => null,
00298 'port' => null,
00299 'socket' => null,
00300 'database' => null
00301 );
00302
00303 $preg_query = "!^(([a-z0-9]+)(\(([^()]+)\))?)(://((((([^@/:]+)(:([^@/]+))?)@)?((([a-z]+)\((([^?():]+)(:([^()?]+))?)\))|((([^/?:]+)(:([^/?]+))?))))/?)?([^?]+)?(\?(.+))?)?$!i";
00304
00305 $info = array();
00306
00307 if (preg_match($preg_query,$dsn,$info)) {
00308
00309 $parsed['phptype'] = @$info[2];
00310
00311
00312
00313 if (isset($info[5])) {
00314
00315 if (strlen($info[10]) > 0) {
00316 $parsed['username'] = @$info[10];
00317 }
00318
00319 if (strlen($info[12]) > 0) {
00320 $parsed['password'] = @$info[12];
00321 }
00322
00323 if (strlen($info[15]) > 0) {
00324 $parsed['protocol'] = @$info[15];
00325
00326 if ($parsed["protocol"] === "unix") {
00327 $parsed['socket'] = @$info[16];
00328 } else {
00329 $parsed["hostspec"] = @$info[17];
00330 if (strlen($info[19]) > 0) {
00331 $parsed["port"] = @$info[19];
00332 }
00333 }
00334 } elseif (strlen($info[20]) > 0) {
00335 $parsed["hostspec"] = @$info[22];
00336
00337 if ((isset($info[24]) && (strlen($info[24]) > 0))) {
00338 $parsed["port"] = @$info[24];
00339 }
00340 }
00341
00342 if ((isset($info[25])) && (strlen($info[25]) > 0)) {
00343 $parsed["database"] = @$info[25];
00344 }
00345
00346 if ((isset($info[27])) && (strlen($info[27]) >0)) {
00347 $opts = explode('&', $info[27]);
00348 foreach ($opts as $opt) {
00349 list($key, $value) = explode('=', $opt);
00350 if (!isset($parsed[$key])) {
00351 $parsed[$key] = urldecode($value);
00352 }
00353 }
00354 }
00355
00356 }
00357 }
00358
00359 return $parsed;
00360 }
00361
00371 public static function import($class) {
00372 if (!class_exists($class, false)) {
00373 $path = strtr($class, '.', DIRECTORY_SEPARATOR) . '.php';
00374 $ret = include_once($path);
00375 if ($ret === false) {
00376 throw new SQLException("Unable to load driver class: " . $class);
00377 }
00378
00379 $pos = strrpos($class, '.');
00380 if ($pos !== false) {
00381 $class = substr($class, $pos + 1);
00382 }
00383 if (!class_exists($class)) {
00384 throw new SQLException("Unable to find loaded class: $class (Hint: make sure classname matches filename)");
00385 }
00386 }
00387 return $class;
00388 }
00389
00390 }