diff options
Diffstat (limited to 'ext/pdo_odbc')
-rwxr-xr-x | ext/pdo_odbc/odbc_driver.c | 153 | ||||
-rwxr-xr-x | ext/pdo_odbc/odbc_stmt.c | 6 | ||||
-rwxr-xr-x | ext/pdo_odbc/pdo_odbc.c | 2 | ||||
-rwxr-xr-x | ext/pdo_odbc/php_pdo_odbc_int.h | 21 |
4 files changed, 151 insertions, 31 deletions
diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c index 8ab670ac7c..6107e33170 100755 --- a/ext/pdo_odbc/odbc_driver.c +++ b/ext/pdo_odbc/odbc_driver.c @@ -30,19 +30,113 @@ #include "php_pdo_odbc.h" #include "php_pdo_odbc_int.h" -void _odbc_error(pdo_dbh_t *dbh, char *what, PDO_ODBC_HSTMT stmt, const char *file, int line TSRMLS_DC) /* {{{ */ +static struct { + char state[6]; + enum pdo_error err; +} odbc_to_pdo_err_map[] = { + /* this table maps ODBC V3 SQLSTATE codes to PDO_ERR codes */ + { "42S01", PDO_ERR_ALREADY_EXISTS }, + { "42S11", PDO_ERR_ALREADY_EXISTS }, + { "42S21", PDO_ERR_ALREADY_EXISTS }, + { "IM001", PDO_ERR_NOT_IMPLEMENTED }, + { "42S22", PDO_ERR_NOT_FOUND }, + { "42S12", PDO_ERR_NOT_FOUND }, + { "42S02", PDO_ERR_NOT_FOUND }, + { "42000", PDO_ERR_SYNTAX }, + { "23000", PDO_ERR_CONSTRAINT }, + { "22025", PDO_ERR_SYNTAX }, + { "22019", PDO_ERR_SYNTAX }, + { "22018", PDO_ERR_SYNTAX }, + { "08S01", PDO_ERR_DISCONNECTED }, + { "01S07", PDO_ERR_TRUNCATED }, + +}; + +static HashTable err_hash; + +void pdo_odbc_fini_error_table(void) +{ + zend_hash_destroy(&err_hash); +} + +void pdo_odbc_init_error_table(void) +{ + int i; + + zend_hash_init(&err_hash, 0, NULL, NULL, 1); + + for (i = 0; i < sizeof(odbc_to_pdo_err_map)/sizeof(odbc_to_pdo_err_map[0]); i++) { + zend_hash_add(&err_hash, odbc_to_pdo_err_map[i].state, sizeof(odbc_to_pdo_err_map[i].state), + &odbc_to_pdo_err_map[i].err, sizeof(odbc_to_pdo_err_map[i].err), NULL); + } +} + +static enum pdo_error pdo_odbc_map_error(char *state) +{ + enum pdo_error *p_err; + if (SUCCESS == zend_hash_find(&err_hash, state, sizeof(odbc_to_pdo_err_map[0].state), (void**)&p_err)) { + return *p_err; + } + return PDO_ERR_CANT_MAP; +} + +static int pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) +{ + pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; + pdo_odbc_errinfo *einfo = &H->einfo; + pdo_odbc_stmt *S = NULL; + char *message = NULL; + + if (stmt) { + S = (pdo_odbc_stmt*)stmt->driver_data; + einfo = &S->einfo; + } + + spprintf(&message, 0, "%s: %d %s [SQL State %s] (%s:%d)", + einfo->what, einfo->last_error, einfo->last_err_msg, einfo->last_state, einfo->file, einfo->line); + + add_next_index_long(info, einfo->last_error); + add_next_index_string(info, message, 0); + add_next_index_string(info, einfo->last_state, 1); + + return 1; +} + + +void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line TSRMLS_DC) /* {{{ */ { RETCODE rc; SWORD errmsgsize; pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data; + pdo_odbc_errinfo *einfo = &H->einfo; + pdo_odbc_stmt *S = NULL; + enum pdo_error *pdo_err = &dbh->error_code; + + if (stmt) { + S = (pdo_odbc_stmt*)stmt->driver_data; - rc = SQLError(H->env, H->dbc, stmt, H->last_state, &H->last_error, - H->last_err_msg, sizeof(H->last_err_msg)-1, &errmsgsize); + einfo = &S->einfo; + pdo_err = &stmt->error_code; + } - H->last_err_msg[errmsgsize] = '\0'; + if (statement == SQL_NULL_HSTMT && S) { + statement = S->stmt; + } - php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: %d %s [SQL State %s]", - file, line, what, H->last_error, H->last_err_msg, H->last_state); + rc = SQLError(H->env, H->dbc, statement, einfo->last_state, &einfo->last_error, + einfo->last_err_msg, sizeof(einfo->last_err_msg)-1, &errmsgsize); + + einfo->last_err_msg[errmsgsize] = '\0'; + einfo->file = file; + einfo->line = line; + einfo->what = what; + + *pdo_err = pdo_odbc_map_error(einfo->last_state); + + if (!dbh->methods) { + zend_throw_exception_ex(php_pdo_get_exception(), *pdo_err TSRMLS_CC, "%s: %d %s [SQL State %s]", + what, einfo->last_error, einfo->last_err_msg, einfo->last_state); + } } /* }}} */ @@ -54,7 +148,7 @@ static int odbc_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK); } - SQLFreeHandle(SQL_HANDLE_STMT, H->dbc); + SQLFreeHandle(SQL_HANDLE_DBC, H->dbc); SQLFreeHandle(SQL_HANDLE_ENV, H->env); pefree(H, dbh->is_persistent); @@ -73,14 +167,14 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, p if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) { efree(S); - odbc_error(dbh, "SQLAllocStmt", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLAllocStmt"); return 0; } rc = SQLPrepare(S->stmt, (char*)sql, SQL_NTS); if (rc != SQL_SUCCESS) { - odbc_error(dbh, "SQLPrepare", S->stmt); + pdo_odbc_stmt_error("SQLPrepare"); } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { @@ -98,20 +192,29 @@ static long odbc_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRML { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; RETCODE rc; - long row_count; + long row_count = -1; + PDO_ODBC_HSTMT stmt; + + rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &stmt); + if (rc != SQL_SUCCESS) { + pdo_odbc_drv_error("SQLAllocHandle: STMT"); + return -1; + } + + rc = SQLExecDirect(stmt, (char *)sql, sql_len); - rc = SQLExecDirect(H->dbc, (char *)sql, sql_len); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - /* XXX error reporting needed */ - return 0; + pdo_odbc_doer_error("SQLExecDirect"); + goto out; } - rc = SQLRowCount(H->dbc, &row_count); + rc = SQLRowCount(stmt, &row_count); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - /* XXX error reporting needed */ - return 0; + pdo_odbc_doer_error("SQLRowCount"); + goto out; } - +out: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); return row_count; } @@ -136,7 +239,7 @@ static int odbc_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_COMMIT); if (rc != SQL_SUCCESS) { - odbc_error(dbh, "SQLEndTran: Commit", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLEndTran: Commit"); if (rc != SQL_SUCCESS_WITH_INFO) { return 0; @@ -153,7 +256,7 @@ static int odbc_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK); if (rc != SQL_SUCCESS) { - odbc_error(dbh, "SQLEndTran: Rollback", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLEndTran: Rollback"); if (rc != SQL_SUCCESS_WITH_INFO) { return 0; @@ -173,6 +276,10 @@ static struct pdo_dbh_methods odbc_methods = { odbc_handle_begin, odbc_handle_commit, odbc_handle_rollback, + NULL, /* set attr */ + NULL, /* last id */ + pdo_odbc_fetch_error_func, + NULL, /* get attr */ }; static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ @@ -189,14 +296,14 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_D rc = SQLSetEnvAttr(H->env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - odbc_error(dbh, "SQLSetEnvAttr: ODBC3", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLSetEnvAttr: ODBC3"); odbc_handle_closer(dbh TSRMLS_CC); return 0; } rc = SQLAllocHandle(SQL_HANDLE_DBC, H->env, &H->dbc); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - odbc_error(dbh, "SQLAllocHandle (DBC)", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLAllocHandle (DBC)"); odbc_handle_closer(dbh TSRMLS_CC); return 0; } @@ -204,7 +311,7 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_D if (!dbh->auto_commit) { rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER); if (rc != SQL_SUCCESS) { - odbc_error(dbh, "SQLSetConnectAttr AUTOCOMMIT = OFF", SQL_NULL_HSTMT); + pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = OFF"); odbc_handle_closer(dbh TSRMLS_CC); return 0; } @@ -232,7 +339,7 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_D } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - odbc_error(dbh, use_direct ? "SQLDriverConnect" : "SQLConnect", SQL_NULL_HSTMT); + pdo_odbc_drv_error(use_direct ? "SQLDriverConnect" : "SQLConnect"); odbc_handle_closer(dbh TSRMLS_CC); return 0; } diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index 9878be2ad4..40d2245a84 100755 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -73,11 +73,11 @@ static int odbc_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) break; case SQL_NO_DATA_FOUND: case SQL_SUCCESS_WITH_INFO: - odbc_error(stmt->dbh, "SQLExecute", S->stmt); + pdo_odbc_stmt_error("SQLExecute"); break; default: - odbc_error(stmt->dbh, "SQLExecute", S->stmt); + pdo_odbc_stmt_error("SQLExecute"); return 0; } @@ -156,7 +156,7 @@ static int odbc_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) return 0; } - odbc_error(stmt->dbh, "SQLFetch", S->stmt); + pdo_odbc_stmt_error("SQLFetch"); return 0; } diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c index 4564ac67e0..546c45ed04 100755 --- a/ext/pdo_odbc/pdo_odbc.c +++ b/ext/pdo_odbc/pdo_odbc.c @@ -68,6 +68,7 @@ ZEND_GET_MODULE(pdo_odbc) PHP_MINIT_FUNCTION(pdo_odbc) { php_pdo_register_driver(&pdo_odbc_driver); + pdo_odbc_init_error_table(); return SUCCESS; } /* }}} */ @@ -77,6 +78,7 @@ PHP_MINIT_FUNCTION(pdo_odbc) PHP_MSHUTDOWN_FUNCTION(pdo_odbc) { php_pdo_unregister_driver(&pdo_odbc_driver); + pdo_odbc_fini_error_table(); return SUCCESS; } /* }}} */ diff --git a/ext/pdo_odbc/php_pdo_odbc_int.h b/ext/pdo_odbc/php_pdo_odbc_int.h index dbf7c6c1d2..ff7798c9aa 100755 --- a/ext/pdo_odbc/php_pdo_odbc_int.h +++ b/ext/pdo_odbc/php_pdo_odbc_int.h @@ -105,12 +105,17 @@ /* }}} */ typedef struct { - PDO_ODBC_HENV env; - PDO_ODBC_HDBC dbc; - char last_state[6]; char last_err_msg[SQL_MAX_MESSAGE_LENGTH]; SDWORD last_error; + const char *file, *what; + int line; +} pdo_odbc_errinfo; + +typedef struct { + PDO_ODBC_HENV env; + PDO_ODBC_HDBC dbc; + pdo_odbc_errinfo einfo; } pdo_odbc_db_handle; typedef struct { @@ -125,13 +130,19 @@ typedef struct { PDO_ODBC_HSTMT stmt; pdo_odbc_column *cols; pdo_odbc_db_handle *H; + pdo_odbc_errinfo einfo; } pdo_odbc_stmt; extern pdo_driver_t pdo_odbc_driver; extern struct pdo_stmt_methods odbc_stmt_methods; -void _odbc_error(pdo_dbh_t *dbh, char *what, PDO_ODBC_HSTMT stmt, const char *file, int line TSRMLS_DC); -#define odbc_error(dbh, what, stmt) _odbc_error(dbh, what, stmt, __FILE__, __LINE__ TSRMLS_CC) +void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line TSRMLS_DC); +#define pdo_odbc_drv_error(what) pdo_odbc_error(dbh, NULL, SQL_NULL_HSTMT, what, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_odbc_stmt_error(what) pdo_odbc_error(stmt->dbh, stmt, SQL_NULL_HSTMT, what, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_odbc_doer_error(what) pdo_odbc_error(dbh, NULL, stmt, what, __FILE__, __LINE__ TSRMLS_CC) + +void pdo_odbc_init_error_table(void); +void pdo_odbc_fini_error_table(void); /* * Local variables: |