+----------------------------------------------------------------------+
| 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 |
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);
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;
}
SQLFreeHandle(SQL_HANDLE_STMT, S->stmt);
return 0;
}
-
+
stmt->driver_data = S;
stmt->methods = &odbc_stmt_methods;
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
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 */
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;
}
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 */
dbh->alloc_own_columns = 1;
return 1;
+
+fail:
+ dbh->methods = &odbc_methods;
+ return 0;
}
/* }}} */
+----------------------------------------------------------------------+
| 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 |
SQLNumResultCols(S->stmt, &colcount);
stmt->column_count = (int)colcount;
-
S->cols = ecalloc(colcount, sizeof(pdo_odbc_column));
}
{
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 */
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 {
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;
} 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;
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
);
}
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;
}
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;
}
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);
/* 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;
}
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) {