]> granicus.if.org Git - php/commitdiff
Improved error handling
authorArd Biesheuvel <abies@php.net>
Sat, 12 Jun 2004 16:58:20 +0000 (16:58 +0000)
committerArd Biesheuvel <abies@php.net>
Sat, 12 Jun 2004 16:58:20 +0000 (16:58 +0000)
Added some comments

ext/pdo_firebird/firebird_driver.c
ext/pdo_firebird/firebird_statement.c
ext/pdo_firebird/package.xml
ext/pdo_firebird/php_pdo_firebird_int.h

index 4cf7b6c87026b8b49c57697badec0ca5eed218e5..8b8ad371d3b7274d24f16b01cea05851bbf350f8 100644 (file)
 #include "php_pdo_firebird.h"
 #include "php_pdo_firebird_int.h"
 
-static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
-{
-       pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
-       ISC_STATUS *s = H->isc_status;
-       char buf[400];
-       long i = 0, l;
-
-       add_next_index_long(info, isc_sqlcode(s));
-
-       while (l = isc_interprete(&buf[i],&s)) {
-               i += l;
-               strcpy(&buf[i++], " ");
-       }
-
-       add_next_index_string(info, buf, 1);
-
-       return 1;
-}
-
 /* map driver specific error message to PDO error */
 void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long line TSRMLS_DC)
 {
@@ -100,7 +81,8 @@ void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long li
 
 #define RECORD_ERROR(dbh) _firebird_error(dbh, NULL, __FILE__, __LINE__ TSRMLS_CC)
 
-static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+/* called by PDO to close a db handle */
+static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
        
@@ -124,8 +106,8 @@ static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
 
        return 0;
 }
-/* }}} */
 
+/* called by PDO to prepare an SQL query */
 static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt,
        long options, zval *driver_options TSRMLS_DC)
 {
@@ -141,18 +123,18 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le
                num_sqlda.version = PDO_FB_SQLDA_VERSION;
                num_sqlda.sqln = 1;
 
-               /* allocate */
+               /* allocate a statement handle */
                if (isc_dsql_allocate_statement(H->isc_status, &H->db, &s)) {
                        break;
                }
 
-               /* prepare the statement */
+               /* prepare the SQL statement */
                if (isc_dsql_prepare(H->isc_status, &H->tr, &s, (short)sql_len, const_cast(sql),
                                PDO_FB_DIALECT, &num_sqlda)) {
                        break;
                }
                
-               /* allocate a statement handle of the right size */
+               /* allocate a statement handle struct of the right size (struct out_sqlda is inlined) */
                S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
                S->H = H;
                S->stmt = s;
@@ -166,6 +148,7 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le
                }
                S->statement_type = result[3];  
                
+               /* fill the output sqlda with information about the prepared query */
                if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
                        RECORD_ERROR(dbh);
                        break;
@@ -205,6 +188,7 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le
        return 0;
 }
 
+/* called by PDO to execute a statement that doesn't produce a result */
 static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -214,10 +198,11 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
        int ret = 0;
        XSQLDA in_sqlda, out_sqlda;
                
-       /* no placeholder in exec() for now */
+       /* TODO no placeholders in exec() for now */
        in_sqlda.version = out_sqlda.version = PDO_FB_SQLDA_VERSION;
        in_sqlda.sqld = out_sqlda.sqld = 0;
        
+       /* start a new transaction implicitly if auto_commit is enabled and no transaction is open */
        if (dbh->auto_commit && !dbh->in_txn) {
                if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, 0, NULL)) {
                        RECORD_ERROR(dbh);
@@ -226,32 +211,32 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
                dbh->in_txn = 1;
        }
        
-       /* allocate */
+       /* allocate the statement */
        if (isc_dsql_allocate_statement(H->isc_status, &H->db, &stmt)) {
                RECORD_ERROR(dbh);
                return -1;
        }
        
-       /* Firebird allows SQL statements up to 64k */
+       /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
        if (sql_len > SHORT_MAX) {
                dbh->error_code = PDO_ERR_TRUNCATED;
                return -1;
        }
        
-       /* prepare */
+       /* prepare the statement */
        if (isc_dsql_prepare(H->isc_status, &H->tr, &stmt, (short) sql_len, const_cast(sql),
                        PDO_FB_DIALECT, &out_sqlda)) {
                RECORD_ERROR(dbh);
                return -1;
        }
 
-       /* execute */
+       /* execute the statement */
        if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) {
                RECORD_ERROR(dbh);
                return -1;
        }
        
-       /* return the number of affected rows */
+       /* find out how many rows were affected */
        if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), info_count, sizeof(result),
                        result)) {
                RECORD_ERROR(dbh);
@@ -270,7 +255,7 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
                }
        }
        
-       /* commit? */
+       /* commit if we're in auto_commit mode */
        if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
                RECORD_ERROR(dbh);
        }
@@ -278,6 +263,7 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
        return ret;
 }
 
+/* called by the PDO SQL parser to add quotes to values that are copied into SQL */
 static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen,
        char **quoted, int *quotedlen TSRMLS_DC)
 {
@@ -317,6 +303,7 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unqu
        }                       
 }
 
+/* called by PDO to start a transaction */
 static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -328,6 +315,7 @@ static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
        return 1;
 }
 
+/* called by PDO to commit a transaction */
 static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -339,6 +327,7 @@ static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
        return 1;
 }
 
+/* called by PDO to rollback a transaction */
 static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -350,6 +339,7 @@ static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
        return 1;
 }
 
+/* called by PDO to set a driver-specific dbh attribute */
 static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -358,25 +348,58 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TS
 
                case PDO_ATTR_AUTOCOMMIT:
 
-                       if (dbh->in_txn) {
-                               /* Assume they want to commit whatever is outstanding */
-                               if (isc_commit_transaction(H->isc_status, &H->tr)) {
-                                       RECORD_ERROR(dbh);
-                                       return 0;
-                               }
-                               dbh->in_txn = 0;
-                       }
-                       
                        convert_to_long(val);
        
-                       dbh->auto_commit = Z_LVAL_P(val);
-
+                       /* if (the value is really being changed and a transaction is open) */                  
+                       if ((Z_LVAL_P(val)?1:0) ^ dbh->auto_commit && dbh->in_txn) {
+                               
+                               if (dbh->auto_commit = Z_BVAL_P(val)) {
+                                       /* just keep the running transaction but commit it */
+                                       if (isc_commit_retaining(H->isc_status, &H->tr)) {
+                                               RECORD_ERROR(dbh);
+                                               break;
+                                       }
+                               } else {
+                                       /* close the transaction */
+                                       if (isc_commit_transaction(H->isc_status, &H->tr)) {
+                                               RECORD_ERROR(dbh);
+                                               break;
+                                       }
+                                       dbh->in_txn = 0;
+                               }
+                       }
                        return 1;
+       }
+       return 0;
+}
 
-               default:
+/* called by PDO to get a driver-specific dbh attribute */
+static int firebird_handle_get_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
+{
+       return 0;
+}
+
+/* called by PDO to retrieve driver-specific information about an error that has occurred */
+static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
+{
+       pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+       ISC_STATUS *s = H->isc_status;
+       char buf[400];
+       long i = 0, l, sqlcode = isc_sqlcode(s);
 
-                       return 0;
+       if (sqlcode) {
+               add_next_index_long(info, sqlcode);
+
+               while (l = isc_interprete(&buf[i],&s)) {
+                       i += l;
+                       strcpy(&buf[i++], " ");
+               }
+               add_next_index_string(info, buf, 1);
+       } else {
+               add_next_index_long(info, -999);
+               add_next_index_string(info, H->last_app_error,1);
        }
+       return 1;
 }
 
 static struct pdo_dbh_methods firebird_methods = {
@@ -388,10 +411,12 @@ static struct pdo_dbh_methods firebird_methods = {
        firebird_handle_commit,
        firebird_handle_rollback,
        firebird_handle_set_attribute,
-       NULL,
+       NULL, /* last_id not supported */
        pdo_firebird_fetch_error_func,
+       firebird_handle_get_attribute,
 };
 
+/* the driver-specific PDO handle constructor */
 static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
 {
        struct pdo_data_src_parser vars[] = {
index ca636791ae3f647744cc09c5beba67ce3ffe4747..eca73de00bc7ced76408d844b39b3f3bcd2570a2 100644 (file)
@@ -34,6 +34,7 @@
        
 #define RECORD_ERROR(stmt) _firebird_error(NULL, stmt,  __FILE__, __LINE__ TSRMLS_CC)
 
+/* free the allocated space for passing field values to the db and back */
 static void free_sqlda(XSQLDA const *sqlda)
 {
        int i;
@@ -47,11 +48,13 @@ static void free_sqlda(XSQLDA const *sqlda)
        }
 }
        
+/* called by PDO to clean up a statement handle */
 static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
 {
        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        int i;
        
+       /* clean up the fetch buffers if they have been used */
        for (i = 0; i < S->out_sqlda.sqld; ++i) {
                if (S->fetch_buf[i]) {
                        efree(S->fetch_buf[i]);
@@ -59,6 +62,7 @@ static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
        }
        efree(S->fetch_buf);
        
+       /* clean up the input descriptor */
        if (S->in_sqlda) {
                free_sqlda(S->in_sqlda);
                efree(S->in_sqlda);
@@ -70,6 +74,7 @@ static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
        return 1;
 }
 
+/* called by PDO to execute a prepared query */
 static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
 {
        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
@@ -96,6 +101,7 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
                        break;
                }
        
+               *S->name = 0;
                S->exhausted = 0;
                
                return 1;
@@ -106,12 +112,16 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
        return 0;
 }
 
+/* called by PDO to fetch the next row from a statement */
 static int firebird_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC)
 {
        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        pdo_firebird_db_handle *H = S->H;
 
-       if (!S->exhausted) {
+       if (!stmt->executed) {
+               stmt->error_code = PDO_ERR_CANT_MAP;
+               H->last_app_error = "Cannot fetch from a closed cursor";
+       } else if (!S->exhausted) {
 
                /* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because
                 * the result was returned in the execute call */
@@ -131,6 +141,7 @@ static int firebird_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC)
        return 0;
 }
 
+/* called by PDO to retrieve information about the fields being returned */
 static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
 {
        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
@@ -149,6 +160,7 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
        return 1;
 }
 
+/* internal function to override return types of parameters */
 static void set_param_type(enum pdo_param_type *param_type, XSQLVAR const *var)
 {
        /* set the param type after the field type */
@@ -306,6 +318,7 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
 
        if (!sqlda || param->paramno >= sqlda->sqld) {
                stmt->error_code = PDO_ERR_NOT_FOUND;
+               S->H->last_app_error = "Invalid parameter index";
                return 0;
        }
 
index ca429e5a153a1a46add19fac18ca974c93c3227b..7659da742bf897093c7c72e58eafd47928f36a1b 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>\r
 <!DOCTYPE package SYSTEM "../pear/package.dtd">\r
-<package version="1.0"><!-- $Id: package.xml,v 1.2 2004-06-12 03:09:47 abies Exp $ -->\r
+<package version="1.0"><!-- $Id: package.xml,v 1.3 2004-06-12 16:58:20 abies Exp $ -->\r
  <name>PDO_Firebird</name>\r
  <summary>Firebird/InterBase support for PDO</summary>\r
  <maintainers>\r
  </description>\r
  <license>PHP</license>\r
  <release>\r
-  <state>pre-alpha</state>\r
+  <state>alpha</state>\r
   <version>0.1</version>\r
-  <date>2004-06-11</date>\r
+  <date>2004-06-12</date>\r
 \r
   <notes>\r
    To compile and run this module, you will need to have the main PDO module and Firebird's\r
-   client library installed on your system.\r
+   client library installed on your system. (InterBase 6 or higher should work as well)\r
   </notes>\r
 \r
   <filelist>\r
+   <file role="doc" name="CREDITS"/>\r
+\r
    <file role="src" name="config.m4"/>\r
    <file role="src" name="config.w32"/>\r
    <file role="src" name="firebird_driver.c"/>\r
    <file role="src" name="php_pdo_firebird.h"/>\r
    <file role="src" name="php_pdo_firebird_int.h"/>\r
 \r
-   <file role="doc" name="CREDITS"/>\r
+   <dir name="tests">\r
+     <file role="test">connect.phpt</file>\r
+     <file role="test">ddl.phpt</file>\r
+     <file role="test">execute.phpt</file>\r
+   </dir>\r
+\r
   </filelist>\r
   <deps>\r
    <dep type="php" rel="ge" version="5.0.0RC3"/>\r
index 70bf160147b55ce6e9f84db99801cce133f049c4..b4f2260a224b4ac924ba7e59ec268c770d60b9f4 100644 (file)
@@ -60,6 +60,9 @@ typedef struct {
        /* the transaction handle */
        isc_tr_handle tr;
 
+       /* the last error that didn't come from the API */
+       char const *last_app_error;
+       
 } pdo_firebird_db_handle;