cvs: php-src /ext/pdo_odbc odbc_driver.c odbc_stmt.c pdo_odbc.c php_pdo_odbc.h php_pdo_odbc_int.h

From: Date: Thu, 07 Jul 2005 12:49:23 +0000
Subject: cvs: php-src /ext/pdo_odbc odbc_driver.c odbc_stmt.c pdo_odbc.c php_pdo_odbc.h php_pdo_odbc_int.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-32743@lists.php.net to get a copy of this message
wez Thu Jul 7 08:49:23 2005 EDT Modified files: /php-src/ext/pdo_odbc odbc_driver.c odbc_stmt.c pdo_odbc.c php_pdo_odbc.h php_pdo_odbc_int.h Log: Fix handling of parameter binding. We need to guess at parameter sizing in some cases (eg: MS Access) as the SQLDescribeParam() API is an optional feature. Tidy up error handling. Add workaround for a shutdown bug that I see with MS ODBC implementation. (working to determine the precise cause of this). PDO core test suite now passes all tests.

http://cvs.php.net/diff.php/php-src/ext/pdo_odbc/odbc_driver.c?r1=1.23&r2=1.24&ty=u Index: php-src/ext/pdo_odbc/odbc_driver.c diff -u php-src/ext/pdo_odbc/odbc_driver.c:1.23 php-src/ext/pdo_odbc/odbc_driver.c:1.24 --- php-src/ext/pdo_odbc/odbc_driver.c:1.23 Sat Jun 11 10:48:06 2005 +++ php-src/ext/pdo_odbc/odbc_driver.c Thu Jul 7 08:49:21 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: odbc_driver.c,v 1.23 2005/06/11 14:48:06 wez Exp $ */ +/* $Id: odbc_driver.c,v 1.24 2005/07/07 12:49:21 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -85,7 +85,7 @@ einfo->what = what; strcpy(*pdo_err, einfo->last_state); - +/* printf("@@ SQLSTATE[%s] %s\n", *pdo_err, einfo->last_err_msg); */ if (!dbh->methods) { zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] %s: %d %s", *pdo_err, what, einfo->last_error, einfo->last_err_msg); @@ -96,16 +96,18 @@ static int odbc_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data; - if (H->dbc != SQL_NULL_HANDLE) { SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK); +#ifndef PHP_WIN32 /* avoiding a bug I've found on my XP box */ SQLDisconnect(H->dbc); +#endif SQLFreeHandle(SQL_HANDLE_DBC, H->dbc); H->dbc = NULL; } SQLFreeHandle(SQL_HANDLE_ENV, H->env); H->env = NULL; pefree(H, dbh->is_persistent); + dbh->driver_data = NULL; return 0; } @@ -174,7 +176,7 @@ SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); return 0; } - + stmt->driver_data = S; stmt->methods = &odbc_stmt_methods; @@ -335,17 +337,15 @@ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { pdo_odbc_drv_error("SQLSetEnvAttr: ODBC3"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } -#ifdef SQL_ATTR_CONNECTION_POOLING +#if 0 /*&& def SQL_ATTR_CONNECTION_POOLING */ if (pdo_odbc_pool_on != SQL_CP_OFF) { rc = SQLSetEnvAttr(H->env, SQL_ATTR_CP_MATCH, (void*)pdo_odbc_pool_mode, 0); if (rc != SQL_SUCCESS) { pdo_odbc_drv_error("SQLSetEnvAttr: SQL_ATTR_CP_MATCH"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } } #endif @@ -353,16 +353,14 @@ rc = SQLAllocHandle(SQL_HANDLE_DBC, H->env, &H->dbc); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { pdo_odbc_drv_error("SQLAllocHandle (DBC)"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)(dbh->auto_commit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF), SQL_NTS); if (rc != SQL_SUCCESS) { pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } /* set up the cursor library, if needed, or if configured explicitly */ @@ -370,8 +368,7 @@ rc = SQLSetConnectAttr(H->dbc, SQL_ODBC_CURSORS, (void*)cursor_lib, 0); if (rc != SQL_SUCCESS && cursor_lib != SQL_CUR_USE_IF_NEEDED) { pdo_odbc_drv_error("SQLSetConnectAttr SQL_ODBC_CURSORS"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } @@ -399,8 +396,7 @@ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { pdo_odbc_drv_error(use_direct ? "SQLDriverConnect" : "SQLConnect"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; + goto fail; } /* TODO: if we want to play nicely, we should check to see if the driver really supports ODBC v3 or not */ @@ -409,6 +405,10 @@ dbh->alloc_own_columns = 1; return 1; + +fail: + dbh->methods = &odbc_methods; + return 0; } /* }}} */ http://cvs.php.net/diff.php/php-src/ext/pdo_odbc/odbc_stmt.c?r1=1.20&r2=1.21&ty=u Index: php-src/ext/pdo_odbc/odbc_stmt.c diff -u php-src/ext/pdo_odbc/odbc_stmt.c:1.20 php-src/ext/pdo_odbc/odbc_stmt.c:1.21 --- php-src/ext/pdo_odbc/odbc_stmt.c:1.20 Tue Apr 19 16:55:02 2005 +++ php-src/ext/pdo_odbc/odbc_stmt.c Thu Jul 7 08:49:21 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: odbc_stmt.c,v 1.20 2005/04/19 20:55:02 iliaa Exp $ */ +/* $Id: odbc_stmt.c,v 1.21 2005/07/07 12:49:21 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -140,7 +140,6 @@ SQLNumResultCols(S->stmt, &colcount); stmt->column_count = (int)colcount; - S->cols = ecalloc(colcount, sizeof(pdo_odbc_column)); } @@ -152,8 +151,8 @@ { pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; RETCODE rc; - SWORD sqltype, ctype, scale, nullable; - UDWORD precision; + SWORD sqltype = 0, ctype = 0, scale = 0, nullable = 0; + UDWORD precision = 0; pdo_odbc_param *P; /* we're only interested in parameters for prepared SQL right now */ @@ -176,13 +175,26 @@ case PDO_PARAM_STMT: return 0; - - case PDO_PARAM_STR: + default: - convert_to_string(param->parameter); + break; } - SQLDescribeParam(S->stmt, param->paramno+1, &sqltype, &precision, &scale, &nullable); + rc = SQLDescribeParam(S->stmt, param->paramno+1, &sqltype, &precision, &scale, &nullable); + if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { + /* MS Access, for instance, doesn't support SQLDescribeParam, + * so we need to guess */ + sqltype = PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB ? + SQL_LONGVARBINARY : + SQL_LONGVARCHAR; + precision = 4000; + scale = 5; + nullable = 1; + + if (param->max_value_len > 0) { + precision = param->max_value_len; + } + } if (sqltype == SQL_BINARY || sqltype == SQL_VARBINARY || sqltype == SQL_LONGVARBINARY) { ctype = SQL_C_BINARY; } else { @@ -193,6 +205,7 @@ param->driver_data = P; P->len = 0; /* is re-populated each EXEC_PRE */ + P->outbuf = NULL; if ((param->param_type & PDO_PARAM_INPUT_OUTPUT) == PDO_PARAM_INPUT_OUTPUT) { P->paramtype = SQL_PARAM_INPUT_OUTPUT; @@ -201,10 +214,15 @@ } else { P->paramtype = SQL_PARAM_OUTPUT; } - if (P->paramtype != SQL_PARAM_INPUT && PDO_PARAM_TYPE(param->param_type) != PDO_PARAM_LOB && param->max_value_len > Z_STRLEN_P(param->parameter)) { - Z_STRVAL_P(param->parameter) = erealloc(Z_STRVAL_P(param->parameter), param->max_value_len + 1); + + if (P->paramtype != SQL_PARAM_INPUT) { + if (PDO_PARAM_TYPE(param->param_type) != PDO_PARAM_NULL) { + /* need an explicit buffer to hold result */ + P->len = param->max_value_len > 0 ? param->max_value_len : precision; + P->outbuf = emalloc(P->len + 1); + } } - + if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB && P->paramtype != SQL_PARAM_INPUT) { pdo_odbc_stmt_error("Can't bind a lob for output"); return 0; @@ -212,11 +230,10 @@ rc = SQLBindParameter(S->stmt, param->paramno+1, P->paramtype, ctype, sqltype, precision, scale, - P->paramtype == SQL_PARAM_INPUT && - PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB ? - (SQLPOINTER)param : - Z_STRVAL_P(param->parameter), - param->max_value_len <= 0 ? 0 : param->max_value_len, + P->paramtype == SQL_PARAM_INPUT ? + (SQLPOINTER)param : + P->outbuf, + P->len, &P->len ); @@ -241,24 +258,74 @@ } if (0 == php_stream_stat(stm, &sb)) { - P->len = SQL_LEN_DATA_AT_EXEC(sb.sb.st_size); + if (P->outbuf) { + int len, amount; + char *ptr = P->outbuf; + char *end = P->outbuf + P->len; + + P->len = 0; + do { + amount = end - ptr; + if (amount == 0) { + break; + } + if (amount > 8192) + amount = 8192; + len = php_stream_read(stm, ptr, amount); + if (len == 0) { + break; + } + ptr += len; + P->len += len; + } while (1); + + } else { + P->len = SQL_LEN_DATA_AT_EXEC(sb.sb.st_size); + } } else { - P->len = SQL_LEN_DATA_AT_EXEC(0); + if (P->outbuf) { + P->len = 0; + } else { + P->len = SQL_LEN_DATA_AT_EXEC(0); + } } } else { convert_to_string(param->parameter); - P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(param->parameter)); + if (P->outbuf) { + P->len = Z_STRLEN_P(param->parameter); + memcpy(P->outbuf, Z_STRVAL_P(param->parameter), P->len); + } else { + P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(param->parameter)); + } } + } else if (Z_TYPE_P(param->parameter) == IS_NULL || PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL) { + P->len = SQL_NULL_DATA; } else { - P->len = Z_STRLEN_P(param->parameter); + convert_to_string(param->parameter); + if (P->outbuf) { + P->len = Z_STRLEN_P(param->parameter); + memcpy(P->outbuf, Z_STRVAL_P(param->parameter), P->len); + } else { + P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(param->parameter)); + } } return 1; case PDO_PARAM_EVT_EXEC_POST: - if (Z_TYPE_P(param->parameter) == IS_STRING) { - P = param->driver_data; - Z_STRLEN_P(param->parameter) = P->len; - Z_STRVAL_P(param->parameter)[P->len] = '\0'; + P = param->driver_data; + if (P->outbuf) { + switch (P->len) { + case SQL_NULL_DATA: + zval_dtor(param->parameter); + ZVAL_NULL(param->parameter); + break; + default: + convert_to_string(param->parameter); + Z_STRVAL_P(param->parameter) = erealloc(Z_STRVAL_P(param->parameter), P->len+1); + memcpy(Z_STRVAL_P(param->parameter), P->outbuf, P->len); + Z_STRLEN_P(param->parameter) = P->len; + Z_STRVAL_P(param->parameter)[P->len] = '\0'; + } } return 1; } @@ -287,10 +354,12 @@ rc = SQLFetchScroll(S->stmt, odbcori, offset); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { + pdo_odbc_stmt_error("SQLFetchScroll"); return 1; } if (rc == SQL_NO_DATA) { + pdo_odbc_stmt_error("SQLFetchScroll"); return 0; } @@ -312,6 +381,11 @@ sizeof(S->cols[colno].colname)-1, &colnamelen, &S->cols[colno].coltype, &colsize, NULL, NULL); + if (rc != SQL_SUCCESS) { + pdo_odbc_stmt_error("SQLBindCol"); + return 0; + } + col->maxlen = S->cols[colno].datalen = colsize; col->namelen = colnamelen; col->name = estrdup(S->cols[colno].colname); @@ -324,7 +398,12 @@ /* tell ODBC to put it straight into our buffer */ rc = SQLBindCol(S->stmt, colno+1, SQL_C_CHAR, S->cols[colno].data, S->cols[colno].datalen+1, &S->cols[colno].fetched_len); - + + if (rc != SQL_SUCCESS) { + pdo_odbc_stmt_error("SQLBindCol"); + return 0; + } + return 1; } @@ -412,6 +491,9 @@ free_cols(stmt, S TSRMLS_CC); + /* NOTE: can't guarantee that output or input/output parameters + * are set until this fella returns SQL_NO_DATA, according to + * MSDN ODBC docs */ rc = SQLMoreResults(S->stmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { http://cvs.php.net/diff.php/php-src/ext/pdo_odbc/pdo_odbc.c?r1=1.12&r2=1.13&ty=u Index: php-src/ext/pdo_odbc/pdo_odbc.c diff -u php-src/ext/pdo_odbc/pdo_odbc.c:1.12 php-src/ext/pdo_odbc/pdo_odbc.c:1.13 --- php-src/ext/pdo_odbc/pdo_odbc.c:1.12 Wed Jun 22 04:45:22 2005 +++ php-src/ext/pdo_odbc/pdo_odbc.c Thu Jul 7 08:49:21 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pdo_odbc.c,v 1.12 2005/06/22 08:45:22 wez Exp $ */ +/* $Id: pdo_odbc.c,v 1.13 2005/07/07 12:49:21 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -80,7 +80,7 @@ } #ifdef SQL_ATTR_CONNECTION_POOLING - /* ugh, we don't really .ini stuff in PDO, but since ODBC connection + /* ugh, we don't really like .ini stuff in PDO, but since ODBC connection * pooling is process wide, we can't set it from within the scope of a * request without affecting others, which goes against our isolated request * policy. So, we use cfg_get_string here to check it this once. http://cvs.php.net/diff.php/php-src/ext/pdo_odbc/php_pdo_odbc.h?r1=1.1&r2=1.2&ty=u Index: php-src/ext/pdo_odbc/php_pdo_odbc.h diff -u php-src/ext/pdo_odbc/php_pdo_odbc.h:1.1 php-src/ext/pdo_odbc/php_pdo_odbc.h:1.2 --- php-src/ext/pdo_odbc/php_pdo_odbc.h:1.1 Mon May 17 11:43:01 2004 +++ php-src/ext/pdo_odbc/php_pdo_odbc.h Thu Jul 7 08:49:21 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -12,11 +12,11 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: | + | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_odbc.h,v 1.1 2004/05/17 15:43:01 wez Exp $ */ +/* $Id: php_pdo_odbc.h,v 1.2 2005/07/07 12:49:21 wez Exp $ */ #ifndef PHP_PDO_ODBC_H #define PHP_PDO_ODBC_H http://cvs.php.net/diff.php/php-src/ext/pdo_odbc/php_pdo_odbc_int.h?r1=1.8&r2=1.9&ty=u Index: php-src/ext/pdo_odbc/php_pdo_odbc_int.h diff -u php-src/ext/pdo_odbc/php_pdo_odbc_int.h:1.8 php-src/ext/pdo_odbc/php_pdo_odbc_int.h:1.9 --- php-src/ext/pdo_odbc/php_pdo_odbc_int.h:1.8 Sun Feb 6 22:27:54 2005 +++ php-src/ext/pdo_odbc/php_pdo_odbc_int.h Thu Jul 7 08:49:21 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_odbc_int.h,v 1.8 2005/02/07 03:27:54 wez Exp $ */ +/* $Id: php_pdo_odbc_int.h,v 1.9 2005/07/07 12:49:21 wez Exp $ */ #ifdef PHP_WIN32 # define PDO_ODBC_TYPE "Win32" @@ -149,6 +149,7 @@ typedef struct { SQLINTEGER len; SQLSMALLINT paramtype; + char *outbuf; } pdo_odbc_param; extern pdo_driver_t pdo_odbc_driver;
« previous php.cvs (#32743) next »