diff options
Diffstat (limited to 'ext/pdo_odbc')
-rw-r--r-- | ext/pdo_odbc/odbc_driver.c | 78 | ||||
-rw-r--r-- | ext/pdo_odbc/odbc_stmt.c | 103 |
2 files changed, 77 insertions, 104 deletions
diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c index 76b981e2c2..790ee87851 100644 --- a/ext/pdo_odbc/odbc_driver.c +++ b/ext/pdo_odbc/odbc_driver.c @@ -27,7 +27,7 @@ #include "php_pdo_odbc_int.h" #include "zend_exceptions.h" -static int pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info) +static void pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; pdo_odbc_errinfo *einfo = &H->einfo; @@ -47,8 +47,6 @@ static int pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *inf add_next_index_long(info, einfo->last_error); add_next_index_str(info, message); add_next_index_string(info, einfo->last_state); - - return 1; } @@ -120,7 +118,7 @@ void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, } /* }}} */ -static int odbc_handle_closer(pdo_dbh_t *dbh) +static void odbc_handle_closer(pdo_dbh_t *dbh) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data; @@ -134,19 +132,16 @@ static int odbc_handle_closer(pdo_dbh_t *dbh) H->env = NULL; pefree(H, dbh->is_persistent); dbh->driver_data = NULL; - - return 0; } -static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) +static bool odbc_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options) { RETCODE rc; pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; pdo_odbc_stmt *S = ecalloc(1, sizeof(*S)); enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY; int ret; - char *nsql = NULL; - size_t nsql_len = 0; + zend_string *nsql = NULL; S->H = H; S->assume_utf8 = H->assume_utf8; @@ -154,7 +149,7 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, /* before we prepare, we need to peek at the query; if it uses named parameters, * we want PDO to rewrite them for us */ stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; - ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); + ret = pdo_parse_params(stmt, sql, &nsql); if (ret == 1) { /* query was re-written */ @@ -163,7 +158,7 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, /* couldn't grok it */ strcpy(dbh->error_code, stmt->error_code); efree(S); - return 0; + return false; } rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &S->stmt); @@ -171,10 +166,10 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) { efree(S); if (nsql) { - efree(nsql); + zend_string_release(nsql); } pdo_odbc_drv_error("SQLAllocStmt"); - return 0; + return false; } stmt->driver_data = S; @@ -186,15 +181,15 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_odbc_stmt_error("SQLSetStmtAttr: SQL_ATTR_CURSOR_SCROLLABLE"); SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); if (nsql) { - efree(nsql); + zend_string_release(nsql); } - return 0; + return false; } } - rc = SQLPrepare(S->stmt, (SQLCHAR *) sql, SQL_NTS); + rc = SQLPrepare(S->stmt, (SQLCHAR *) ZSTR_VAL(sql), SQL_NTS); if (nsql) { - efree(nsql); + zend_string_release(nsql); } stmt->methods = &odbc_stmt_methods; @@ -212,12 +207,12 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - return 0; + return false; } - return 1; + return true; } -static zend_long odbc_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len) +static zend_long odbc_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; RETCODE rc; @@ -230,7 +225,7 @@ static zend_long odbc_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_le return -1; } - rc = SQLExecDirect(stmt, (SQLCHAR *) sql, sql_len); + rc = SQLExecDirect(stmt, (SQLCHAR *) ZSTR_VAL(sql), ZSTR_LEN(sql)); if (rc == SQL_NO_DATA) { /* If SQLExecDirect executes a searched update or delete statement that @@ -267,7 +262,7 @@ static int odbc_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquo } */ -static int odbc_handle_begin(pdo_dbh_t *dbh) +static bool odbc_handle_begin(pdo_dbh_t *dbh) { if (dbh->auto_commit) { /* we need to disable auto-commit now, to be able to initiate a transaction */ @@ -277,13 +272,13 @@ static int odbc_handle_begin(pdo_dbh_t *dbh) rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER); if (rc != SQL_SUCCESS) { pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = OFF"); - return 0; + return false; } } - return 1; + return true; } -static int odbc_handle_commit(pdo_dbh_t *dbh) +static bool odbc_handle_commit(pdo_dbh_t *dbh) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; RETCODE rc; @@ -294,7 +289,7 @@ static int odbc_handle_commit(pdo_dbh_t *dbh) pdo_odbc_drv_error("SQLEndTran: Commit"); if (rc != SQL_SUCCESS_WITH_INFO) { - return 0; + return false; } } @@ -303,13 +298,13 @@ static int odbc_handle_commit(pdo_dbh_t *dbh) rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER); if (rc != SQL_SUCCESS) { pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON"); - return 0; + return false; } } - return 1; + return true; } -static int odbc_handle_rollback(pdo_dbh_t *dbh) +static bool odbc_handle_rollback(pdo_dbh_t *dbh) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; RETCODE rc; @@ -320,7 +315,7 @@ static int odbc_handle_rollback(pdo_dbh_t *dbh) pdo_odbc_drv_error("SQLEndTran: Rollback"); if (rc != SQL_SUCCESS_WITH_INFO) { - return 0; + return false; } } if (dbh->auto_commit && H->dbc) { @@ -328,25 +323,30 @@ static int odbc_handle_rollback(pdo_dbh_t *dbh) rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER); if (rc != SQL_SUCCESS) { pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON"); - return 0; + return false; } } - return 1; + return true; } -static int odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) +static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; + bool bval; + switch (attr) { case PDO_ODBC_ATTR_ASSUME_UTF8: - H->assume_utf8 = zval_is_true(val); - return 1; + if (!pdo_get_bool_param(&bval, val)) { + return false; + } + H->assume_utf8 = bval; + return true; default: strcpy(H->einfo.last_err_msg, "Unknown Attribute"); H->einfo.what = "setAttribute"; strcpy(H->einfo.last_state, "IM001"); - return 0; + return false; } } @@ -384,7 +384,11 @@ static const struct pdo_dbh_methods odbc_methods = { NULL, /* last id */ pdo_odbc_fetch_error_func, odbc_handle_get_attr, /* get attr */ - NULL, /* check_liveness */ + NULL, /* check_liveness */ + NULL, /* get_driver_methods */ + NULL, /* request_shutdown */ + NULL, /* in transaction, use PDO's internal tracking mechanism */ + NULL /* get_gc */ }; static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */ diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index 5e882fbcc9..c1f4b5f497 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -88,31 +88,28 @@ static int pdo_odbc_utf82ucs2(pdo_stmt_t *stmt, int is_unicode, const char *buf, return PDO_ODBC_CONV_NOT_REQUIRED; } -static int pdo_odbc_ucs22utf8(pdo_stmt_t *stmt, int is_unicode, const char *buf, - zend_ulong buflen, zend_ulong *outlen) +static int pdo_odbc_ucs22utf8(pdo_stmt_t *stmt, int is_unicode, zval *result) { #ifdef PHP_WIN32 - if (is_unicode && buflen) { + ZEND_ASSERT(Z_TYPE_P(result) == IS_STRING); + if (is_unicode && Z_STRLEN_P(result) != 0) { pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; DWORD ret; - ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), NULL, 0, NULL, NULL); + ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) Z_STRVAL_P(result), Z_STRLEN_P(result)/sizeof(WCHAR), NULL, 0, NULL, NULL); if (ret == 0) { return PDO_ODBC_CONV_FAIL; } - if (S->convbufsize <= ret) { - S->convbufsize = ret + 1; - S->convbuf = erealloc(S->convbuf, S->convbufsize); - } - - ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), S->convbuf, S->convbufsize, NULL, NULL); + zend_string *str = zend_string_alloc(ret, 0); + ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) Z_STRVAL_P(result), Z_STRLEN_P(result)/sizeof(WCHAR), ZSTR_VAL(str), ZSTR_LEN(str), NULL, NULL); if (ret == 0) { return PDO_ODBC_CONV_FAIL; } - *outlen = ret; - S->convbuf[*outlen] = '\0'; + ZSTR_VAL(str)[ret] = '\0'; + zval_ptr_dtor_str(result); + ZVAL_STR(result, str); return PDO_ODBC_CONV_OK; } #endif @@ -480,38 +477,27 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p P = param->driver_data; if (P->outbuf) { - zend_ulong ulen; - char *srcbuf; - zend_ulong srclen = 0; - if (Z_ISREF(param->parameter)) { parameter = Z_REFVAL(param->parameter); } else { parameter = ¶m->parameter; } zval_ptr_dtor(parameter); - ZVAL_NULL(parameter); switch (P->len) { case SQL_NULL_DATA: + ZVAL_NULL(parameter); break; default: - switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, P->outbuf, P->len, &ulen)) { + ZVAL_STRINGL(parameter, P->outbuf, P->len); + switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, parameter)) { case PDO_ODBC_CONV_FAIL: /* something fishy, but allow it to come back as binary */ case PDO_ODBC_CONV_NOT_REQUIRED: - srcbuf = P->outbuf; - srclen = P->len; break; case PDO_ODBC_CONV_OK: - srcbuf = S->convbuf; - srclen = ulen; break; } - - ZVAL_NEW_STR(parameter, zend_string_alloc(srclen, 0)); - memcpy(Z_STRVAL_P(parameter), srcbuf, srclen); - Z_STRVAL_P(parameter)[Z_STRLEN_P(parameter)] = '\0'; } } return 1; @@ -612,9 +598,6 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno) col->name = zend_string_init(S->cols[colno].colname, colnamelen, 0); S->cols[colno].is_unicode = pdo_odbc_sqltype_is_unicode(S, S->cols[colno].coltype); - /* returning data as a string */ - col->param_type = PDO_PARAM_STR; - /* tell ODBC to put it straight into our buffer, but only if it * isn't "long" data, and only if we haven't already bound a long * column. */ @@ -642,17 +625,21 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno) return 1; } -static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees) +static int odbc_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value) +{ + array_init(return_value); + add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR); + return 1; +} + +static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type) { pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; pdo_odbc_column *C = &S->cols[colno]; - zend_ulong ulen; /* if it is a column containing "long" data, perform late binding now */ if (C->is_long) { SQLLEN orig_fetched_len = SQL_NULL_DATA; - zend_ulong used = 0; - char *buf; RETCODE rc; /* fetch it into C->data, which is allocated with a length @@ -679,11 +666,9 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong this loop has to work whether or not SQLGetData() provides the total column length. calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read for that size would be slower except maybe for extremely long columns.*/ - char *buf2; - - buf2 = emalloc(256); - buf = estrndup(C->data, 256); - used = 255; /* not 256; the driver NUL terminated the buffer */ + char *buf2 = emalloc(256); + zend_string *str = zend_string_init(C->data, 256, 0); + size_t used = 255; /* not 256; the driver NUL terminated the buffer */ do { C->fetched_len = 0; @@ -702,12 +687,12 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong /* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size) (if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */ - buf = erealloc(buf, used + 255+1); - memcpy(buf + used, buf2, 255); + str = zend_string_realloc(str, used + 256, 0); + memcpy(ZSTR_VAL(str) + used, buf2, 256); used = used + 255; } else if (rc==SQL_SUCCESS) { - buf = erealloc(buf, used + C->fetched_len+1); - memcpy(buf + used, buf2, C->fetched_len); + str = zend_string_realloc(str, used + C->fetched_len, 0); + memcpy(ZSTR_VAL(str) + used, buf2, C->fetched_len); used = used + C->fetched_len; } else { /* includes SQL_NO_DATA */ @@ -719,11 +704,8 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong efree(buf2); /* NULL terminate the buffer once, when finished, for use with the rest of PHP */ - buf[used] = '\0'; - - *ptr = buf; - *caller_frees = 1; - *len = used; + ZSTR_VAL(str)[used] = '\0'; + ZVAL_STR(result, str); if (C->is_unicode) { goto unicode_conv; } @@ -731,8 +713,6 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong } /* something went caca */ - *ptr = NULL; - *len = 0; return 1; } @@ -740,40 +720,29 @@ in_data: /* check the indicator to ensure that the data is intact */ if (C->fetched_len == SQL_NULL_DATA) { /* A NULL value */ - *ptr = NULL; - *len = 0; + ZVAL_NULL(result); return 1; } else if (C->fetched_len >= 0) { /* it was stored perfectly */ - *ptr = C->data; - *len = C->fetched_len; + ZVAL_STRINGL_FAST(result, C->data, C->fetched_len); if (C->is_unicode) { goto unicode_conv; } return 1; } else { /* no data? */ - *ptr = NULL; - *len = 0; + ZVAL_NULL(result); return 1; } - unicode_conv: - switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, *ptr, *len, &ulen)) { +unicode_conv: + switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, result)) { case PDO_ODBC_CONV_FAIL: /* oh well. They can have the binary version of it */ case PDO_ODBC_CONV_NOT_REQUIRED: /* shouldn't happen... */ return 1; - case PDO_ODBC_CONV_OK: - if (*caller_frees) { - efree(*ptr); - } - *ptr = emalloc(ulen + 1); - *len = ulen; - memcpy(*ptr, S->convbuf, ulen+1); - *caller_frees = 1; return 1; } return 1; @@ -883,8 +852,8 @@ const struct pdo_stmt_methods odbc_stmt_methods = { odbc_stmt_get_col, odbc_stmt_param_hook, odbc_stmt_set_param, - odbc_stmt_get_attr, /* get attr */ - NULL, /* get column meta */ + odbc_stmt_get_attr, + odbc_stmt_get_column_meta, odbc_stmt_next_rowset, odbc_stmt_close_cursor }; |