summaryrefslogtreecommitdiff
path: root/ext/pdo_dblib/dblib_driver.c
diff options
context:
space:
mode:
authorStanley Sufficool <ssufficool@php.net>2013-06-03 20:02:08 -0700
committerStanley Sufficool <ssufficool@php.net>2013-06-03 20:02:08 -0700
commit5a04ab9a54f529f4197bed6f17599604266cdb35 (patch)
treef8ecd80c92159255e84616b56d0399b0da4dd6c7 /ext/pdo_dblib/dblib_driver.c
parent7360f0f1e6c4b49e89bd3c2cf1f524e9cf7f9dcc (diff)
downloadphp-git-5a04ab9a54f529f4197bed6f17599604266cdb35.tar.gz
Fix PDO_DBLIB bugs: #64338, #64808, #63638
Synchronize with master
Diffstat (limited to 'ext/pdo_dblib/dblib_driver.c')
-rw-r--r--ext/pdo_dblib/dblib_driver.c103
1 files changed, 82 insertions, 21 deletions
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index ffc910177f..9ed5087369 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -32,6 +32,9 @@
#include "php_pdo_dblib_int.h"
#include "zend_exceptions.h"
+/* Cache of the server supported datatypes, initialized in handle_factory */
+zval* pdo_dblib_datatypes;
+
static int dblib_fetch_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
@@ -262,17 +265,37 @@ static struct pdo_dbh_methods dblib_methods = {
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
{
pdo_dblib_db_handle *H;
- int i, ret = 0;
+ int i, nvars, nvers, ret = 0;
+ int *val;
+
+ const pdo_dblib_keyval tdsver[] = {
+ {"4.2",DBVERSION_42}
+ ,{"4.6",DBVERSION_46}
+ ,{"5.0",DBVERSION_70} /* FIXME: This does not work with Sybase, but environ will */
+ ,{"6.0",DBVERSION_70}
+ ,{"7.0",DBVERSION_70}
+ ,{"7.1",DBVERSION_71}
+ ,{"7.2",DBVERSION_72}
+ ,{"8.0",DBVERSION_72}
+ ,{"10.0",DBVERSION_100}
+ ,{"auto",0} /* Only works with FreeTDS. Other drivers will bork */
+
+ };
+
+ nvers = sizeof(tdsver)/sizeof(tdsver[0]);
+
struct pdo_data_src_parser vars[] = {
- { "charset", NULL, 0 },
- { "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 },
- { "host", "127.0.0.1", 0 },
- { "dbname", NULL, 0 },
- { "secure", NULL, 0 }, /* DBSETLSECURE */
- /* TODO: DBSETLVERSION ? */
+ { "charset", NULL, 0 }
+ ,{ "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 }
+ ,{ "host", "127.0.0.1", 0 }
+ ,{ "dbname", NULL, 0 }
+ ,{ "secure", NULL, 0 } /* DBSETLSECURE */
+ ,{ "version", NULL, 0 } /* DBSETLVERSION */
};
-
- php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
+
+ nvars = sizeof(vars)/sizeof(vars[0]);
+
+ php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, nvars);
H = pecalloc(1, sizeof(*H), dbh->is_persistent);
H->login = dblogin();
@@ -282,11 +305,37 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
goto cleanup;
}
+ DBERRHANDLE(H->login, (EHANDLEFUNC) error_handler);
+ DBMSGHANDLE(H->login, (MHANDLEFUNC) msg_handler);
+
+ if(vars[5].optval) {
+ for(i=0;i<nvers;i++) {
+ if(strcmp(vars[5].optval,tdsver[i].key) == 0) {
+ if(FAIL==dbsetlversion(H->login, tdsver[i].value)) {
+ pdo_raise_impl_error(dbh, NULL, "HY000", "PDO_DBLIB: Failed to set version specified in connection string." TSRMLS_CC);
+ goto cleanup;
+ }
+ break;
+ }
+ }
+
+ if (i==nvers) {
+ printf("Invalid version '%s'\n", vars[5].optval);
+ pdo_raise_impl_error(dbh, NULL, "HY000", "PDO_DBLIB: Invalid version specified in connection string." TSRMLS_CC);
+ goto cleanup; /* unknown version specified */
+ }
+ }
+
if (dbh->username) {
- DBSETLUSER(H->login, dbh->username);
+ if(FAIL == DBSETLUSER(H->login, dbh->username)) {
+ goto cleanup;
+ }
}
+
if (dbh->password) {
- DBSETLPWD(H->login, dbh->password);
+ if(FAIL == DBSETLPWD(H->login, dbh->password)) {
+ goto cleanup;
+ }
}
#if !PHP_DBLIB_IS_MSSQL
@@ -297,14 +346,9 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
DBSETLAPP(H->login, vars[1].optval);
-#if PHP_DBLIB_IS_MSSQL
- dbprocerrhandle(H->login, (EHANDLEFUNC) error_handler);
- dbprocmsghandle(H->login, (MHANDLEFUNC) msg_handler);
-#endif
-
H->link = dbopen(H->login, vars[2].optval);
- if (H->link == NULL) {
+ if (!H->link) {
goto cleanup;
}
@@ -315,18 +359,35 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
DBSETOPT(H->link, DBTEXTSIZE, "2147483647");
/* allow double quoted indentifiers */
- DBSETOPT(H->link, DBQUOTEDIDENT, NULL);
+ DBSETOPT(H->link, DBQUOTEDIDENT, "1");
- if (vars[3].optval && FAIL == dbuse(H->link, vars[3].optval)) {
- goto cleanup;
+ if (vars[3].optval) {
+ DBSETLDBNAME(H->login, vars[3].optval);
}
ret = 1;
dbh->max_escaped_char_length = 2;
dbh->alloc_own_columns = 1;
+#if 0
+ /* Cache the supported data types from the servers systypes table */
+ if(dbcmd(H->link, "select usertype, name from systypes order by usertype") != FAIL) {
+ if(dbsqlexec(H->link) != FAIL) {
+ dbresults(H->link);
+ while (dbnextrow(H->link) == SUCCESS) {
+ val = dbdata(H->link, 1);
+ add_index_string(pdo_dblib_datatypes, *val, dbdata(H->link, 2), 1);
+ }
+ }
+ /* Throw out any remaining resultsets */
+ dbcancel(H-link);
+ }
+#endif
+
+
+
cleanup:
- for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
+ for (i = 0; i < nvars; i++) {
if (vars[i].freeme) {
efree(vars[i].optval);
}