diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index aa0edbbb472fd..d2c1ca26456e5 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -396,6 +396,84 @@ static PHP_METHOD(PDO, dbh_constructor) } /* }}} */ +/* {{{ proto PDO::connect(string dsn[, string username[, string passwd [, array options]]]) + */ +// Needs a jolly good refactor, as it starts as an almost exact copy of `static PHP_METHOD(PDO, dbh_constructor)` +static PHP_METHOD(PDO, connect) +{ + char *data_source; + size_t data_source_len; + char *colon; + char *username=NULL, *password=NULL; + size_t usernamelen, passwordlen; + pdo_driver_t *driver = NULL; + zval *options = NULL; + char alt_dsn[512]; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 4) + Z_PARAM_STRING(data_source, data_source_len) + Z_PARAM_OPTIONAL + Z_PARAM_STRING_EX(username, usernamelen, 1, 0) + Z_PARAM_STRING_EX(password, passwordlen, 1, 0) + Z_PARAM_ARRAY_EX(options, 1, 0) + ZEND_PARSE_PARAMETERS_END(); + + /* parse the data source name */ + colon = strchr(data_source, ':'); + + if (!colon) { + /* let's see if this string has a matching dsn in the php.ini */ + char *ini_dsn = NULL; + + snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source); + if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name"); + return; + } + + data_source = ini_dsn; + colon = strchr(data_source, ':'); + + if (!colon) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name (via INI: %s)", alt_dsn); + return; + } + } + + if (!strncmp(data_source, "uri:", sizeof("uri:")-1)) { + /* the specified URI holds connection details */ + data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn)); + if (!data_source) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source URI"); + return; + } + colon = strchr(data_source, ':'); + if (!colon) { + zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name (via URI)"); + return; + } + } + + driver = pdo_find_driver(data_source, colon - data_source); + + if (!driver) { + /* NB: don't want to include the data_source in the error message as + * it might contain a password */ + zend_throw_exception_ex(php_pdo_get_exception(), 0, "could not find driver"); + return; + } + + // Now the driver has been identified, this is where we should be doing `new PDOSQLite()` for sqlite datasources + if (driver->driver_name == 'sqlite') { + thingtoreturn = new PDOSQLite(data_source, username, password, options) + } + // @TODO Add a catch-all for drivers without this implemented + + // Somehow return the new object... + ZVAL_OBJ(return_value, thingtoreturn); // Or pointer to *thingtoreturn? +} +/* }}} */ + static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */ { if (!Z_ISUNDEF_P(ctor_args)) { @@ -1214,6 +1292,7 @@ ZEND_END_ARG_INFO() const zend_function_entry pdo_dbh_functions[] = /* {{{ */ { ZEND_MALIAS(PDO, __construct, dbh_constructor, arginfo_pdo___construct, ZEND_ACC_PUBLIC) + PHP_ME(PDO, connect, arginfo_pdo___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(PDO, prepare, arginfo_pdo_prepare, ZEND_ACC_PUBLIC) PHP_ME(PDO, beginTransaction, arginfo_pdo__void, ZEND_ACC_PUBLIC) PHP_ME(PDO, commit, arginfo_pdo__void, ZEND_ACC_PUBLIC) diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index 5c2fd63cdbd78..4e14c6ae343fc 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -28,6 +28,11 @@ #include "php_pdo_sqlite.h" #include "php_pdo_sqlite_int.h" #include "zend_exceptions.h" +#include "zend_interfaces.h" + +/* Class entry pointers */ +PHPAPI zend_class_entry *pdo_dbh_sqlite_ptr; +PHPAPI zend_class_entry *ce_pdo; /* {{{ pdo_sqlite_functions[] */ static const zend_function_entry pdo_sqlite_functions[] = { @@ -78,6 +83,23 @@ PHP_MINIT_FUNCTION(pdo_sqlite) REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_READONLY_STATEMENT", (zend_long)PDO_SQLITE_ATTR_READONLY_STATEMENT); REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_EXTENDED_RESULT_CODES", (zend_long)PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); + zend_class_entry *pce; + zend_class_entry ce_sqlite; + + if ((pce = zend_hash_str_find_ptr(CG(class_table), "pdo", sizeof("PDO") - 1)) == NULL) { + return SUCCESS; /* SimpleXML must be initialized before */ + } + + ce_pdo = pce; + INIT_CLASS_ENTRY(ce_sqlite, "PDOSQLite", pdo_sqlite_functions); + // The Reflection extension manges to set serialize and unserialize *before* calling + // zend_register_internal_class(). I couldn't make that work (something to do with + // pointers/references?) so have had to put them after. + pdo_dbh_sqlite_ptr = zend_register_internal_class_ex(&ce_sqlite, ce_pdo); // @TODO Second parameter doesn't resolve + pdo_dbh_sqlite_ptr->serialize = zend_class_serialize_deny; + pdo_dbh_sqlite_ptr->unserialize = zend_class_unserialize_deny; + zend_declare_property_string(pdo_dbh_sqlite_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC); + return php_pdo_register_driver(&pdo_sqlite_driver); } /* }}} */ @@ -99,4 +121,4 @@ PHP_MINFO_FUNCTION(pdo_sqlite) php_info_print_table_row(2, "SQLite Library", sqlite3_libversion()); php_info_print_table_end(); } -/* }}} */ +/* }}} */ \ No newline at end of file diff --git a/ext/pdo_sqlite/php_pdo_sqlite.h b/ext/pdo_sqlite/php_pdo_sqlite.h index 73d8a98675b2f..a4e2b951b333e 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite.h +++ b/ext/pdo_sqlite/php_pdo_sqlite.h @@ -35,4 +35,4 @@ PHP_RINIT_FUNCTION(pdo_sqlite); PHP_RSHUTDOWN_FUNCTION(pdo_sqlite); PHP_MINFO_FUNCTION(pdo_sqlite); -#endif /* PHP_PDO_SQLITE_H */ +#endif /* PHP_PDO_SQLITE_H */ \ No newline at end of file