]> granicus.if.org Git - php/commitdiff
Nearly complete implementation
authorArd Biesheuvel <abies@php.net>
Sat, 12 Jun 2004 03:09:48 +0000 (03:09 +0000)
committerArd Biesheuvel <abies@php.net>
Sat, 12 Jun 2004 03:09:48 +0000 (03:09 +0000)
No date/time fields yet ...

ext/pdo_firebird/CREDITS
ext/pdo_firebird/config.w32
ext/pdo_firebird/firebird_driver.c
ext/pdo_firebird/firebird_statement.c
ext/pdo_firebird/package.xml
ext/pdo_firebird/php_pdo_firebird.h
ext/pdo_firebird/php_pdo_firebird_int.h
ext/pdo_firebird/tests/ddl.phpt [new file with mode: 0644]

index 7757c96ee0347b70c784e63701bb7c808b0b737c..a33294b69c0e6455ae1cce79b33bd7bd1f7ad72a 100644 (file)
@@ -1,2 +1,2 @@
-Firebird/InterBase PDO module
+Firebird/InterBase driver for PDO
 Ard Biesheuvel
index 160689d2df48f630af84ce26861b1afe40a22fc9..c04c55c65a9a9edb5258b311692eea9a39b797e7 100644 (file)
@@ -4,7 +4,9 @@
 ARG_WITH("pdo-firebird", "Firebird support for PDO", "no");
 
 if (PHP_PDO_FIREBIRD != "no") {
-       if (CHECK_LIB("fbclient_ms.lib", "pdo_firebird", PHP_PDO_FIREBIRD) &&
+
+       if ((CHECK_LIB("fbclient_ms.lib", "pdo_firebird", PHP_PDO_FIREBIRD) ||
+                       CHECK_LIB("gds32_ms.lib", "pdo_firebird", PHP_PDO_FIREBIRD)) &&
                        CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_PDO_FIREBIRD", PHP_PHP_BUILD + "\\include\\firebird;" + PHP_PDO_FIREBIRD)) {
                EXTENSION("pdo_firebird", "pdo_firebird.c firebird_driver.c firebird_statement.c");
                ADD_FLAG('CFLAGS_PDO_FIREBIRD', "/I ..\\pecl");
index 4215b34a4ce1983e3fcf69205931ac8ff2d5812d..beecaccedc25ece682648b0cdcc791c4b9b5a8ef 100644 (file)
@@ -34,17 +34,72 @@ static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
        ISC_STATUS *s = H->isc_status;
-       char buf[128];
+       char buf[400];
+       long i = 0, l;
 
        add_next_index_long(info, isc_sqlcode(s));
 
-       while (isc_interprete(buf,&s)) {
-               add_next_index_string(info, buf, 1);
+       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)
+{
+       pdo_firebird_db_handle *H = stmt ? ((pdo_firebird_stmt *)stmt->driver_data)->H 
+               : (pdo_firebird_db_handle *)dbh->driver_data;
+       long *error_code = stmt ? &stmt->error_code : &dbh->error_code;
+       
+       switch (isc_sqlcode(H->isc_status)) {
+
+               case 0:
+                       *error_code = PDO_ERR_NONE;
+                       break;
+               default:
+                       *error_code = PDO_ERR_CANT_MAP;
+                       break;
+               case -104:
+                       *error_code = PDO_ERR_SYNTAX;
+                       break;
+               case -530:
+               case -803:
+                       *error_code = PDO_ERR_CONSTRAINT;
+                       break;
+               case -204:
+               case -205:
+               case -206:
+               case -829:
+                       *error_code = PDO_ERR_NOT_FOUND;
+                       break;
+               case -607:              
+                       *error_code = PDO_ERR_ALREADY_EXISTS;
+                       break;
+               
+                       *error_code = PDO_ERR_NOT_IMPLEMENTED;
+                       break;
+               case -313:
+               case -804:
+                       *error_code = PDO_ERR_MISMATCH;
+                       break;
+               case -303:
+               case -314:      
+               case -413:
+                       *error_code = PDO_ERR_TRUNCATED;
+                       break;
+                       
+                       *error_code = PDO_ERR_DISCONNECTED;
+                       break;
+       }
+}
+
+#define RECORD_ERROR(dbh) _firebird_error(dbh, NULL, __FILE__, __LINE__ TSRMLS_CC)
+
 static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@@ -52,17 +107,17 @@ static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
        if (dbh->in_txn) {
                if (dbh->auto_commit) {
                        if (isc_commit_transaction(H->isc_status, &H->tr)) {
-                               /* error */
+                               RECORD_ERROR(dbh);
                        }
                } else {
                        if (isc_rollback_transaction(H->isc_status, &H->tr)) {
-                               /* error */
+                               RECORD_ERROR(dbh);
                        }
                }
        }
        
        if (isc_detach_database(H->isc_status, &H->db)) {
-               /* error */
+               RECORD_ERROR(dbh);
        }
 
        pefree(H, dbh->is_persistent);
@@ -84,10 +139,16 @@ 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 */
+               if (isc_dsql_allocate_statement(H->isc_status, &H->db, &s)) {
+                       RECORD_ERROR(dbh);
+                       return -1;
+               }
+
                /* prepare the statement */
-               if (isc_dsql_prepare(H->isc_status, &H->tr, &s, (short)sql_len, /* sigh */ (char*) sql,
+               if (isc_dsql_prepare(H->isc_status, &H->tr, &s, (short)sql_len, const_cast(sql),
                                PDO_FB_DIALECT, &num_sqlda)) {
-                       /* error */
+                       RECORD_ERROR(dbh);
                        break;
                }
                
@@ -95,14 +156,31 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le
                S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
                S->H = H;
                S->stmt = s;
+               S->out_sqlda.version = PDO_FB_SQLDA_VERSION;
+               S->out_sqlda.sqln = stmt->column_count = num_sqlda.sqld;
+
+               if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
+                       RECORD_ERROR(dbh);
+                       break;
+               }
                
-               if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->out_sqlda)) {
-                       /* error */
+               /* allocate the input descriptors */
+               if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &num_sqlda)) {
+                       RECORD_ERROR(dbh);
                        break;
                }
                
-               /* TODO what about input params */              
+               if (num_sqlda.sqld) {
+                       S->in_sqlda = ecalloc(1,XSQLDA_LENGTH(num_sqlda.sqld));
+                       S->in_sqlda->version = PDO_FB_SQLDA_VERSION;
+                       S->in_sqlda->sqln = num_sqlda.sqld;
                
+                       if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
+                               RECORD_ERROR(dbh);
+                               break;
+                       }
+               }
+       
                stmt->driver_data = S;
                stmt->methods = &firebird_stmt_methods;
        
@@ -111,6 +189,9 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le
        } while (0);
        
        if (S) {
+               if (S->in_sqlda) {
+                       efree(S->in_sqlda);
+               }
                efree(S);
        }
        
@@ -124,31 +205,49 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
        static char info_count[] = { isc_info_sql_records };
        char result[64];
        int ret = 0;
+       XSQLDA in_sqlda, out_sqlda;
                
+       /* no placeholder in exec() for now */
+       in_sqlda.version = out_sqlda.version = PDO_FB_SQLDA_VERSION;
+       in_sqlda.sqld = out_sqlda.sqld = 0;
+       
        if (dbh->auto_commit && !dbh->in_txn) {
                if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, 0, NULL)) {
-                       /* error */
+                       RECORD_ERROR(dbh);
                        return -1;
                }
                dbh->in_txn = 1;
        }
        
+       /* allocate */
+       if (isc_dsql_allocate_statement(H->isc_status, &H->db, &stmt)) {
+               RECORD_ERROR(dbh);
+               return -1;
+       }
+       
+       /* Firebird allows SQL statements up to 64k */
+       if (sql_len > SHORT_MAX) {
+               dbh->error_code = PDO_ERR_TRUNCATED;
+               return -1;
+       }
+       
        /* prepare */
-       if (isc_dsql_prepare(H->isc_status, &H->tr, &stmt, 0, (char*) sql, PDO_FB_DIALECT, NULL)) {
-               /* error */
+       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 */
-       if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, NULL, NULL)) {
-               /* error */
+       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 */
        if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), info_count, sizeof(result),
                        result)) {
-               /* error */
+               RECORD_ERROR(dbh);
                return -1;
        }
 
@@ -166,18 +265,68 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T
        
        /* commit? */
        if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
-               /* error */
+               RECORD_ERROR(dbh);
        }
 
        return ret;
 }
 
+static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen,
+       char **quoted, int *quotedlen TSRMLS_DC)
+{
+       pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+       int qcount = 0;
+       char const *c;
+       
+       /* Firebird only requires single quotes to be doubled if string lengths are used */
+       
+       /* count the number of ' characters */
+       for (c = unquoted; c = strchr(c,'\''); qcount++, c++);
+       
+       if (!qcount) {
+               return 0;
+       } else {
+               char const *l, *r;
+               char *c;
+               
+               *quotedlen = unquotedlen + qcount;
+               *quoted = c = emalloc(*quotedlen+1);
+               
+               /* foreach (chunk that ends in a quote) */
+               for (l = unquoted; r = strchr(l,'\''); l = r+1) {
+                       
+                       /* copy the chunk */
+                       strncpy(c, l, r-l);
+                       c += (r-l);
+                       
+                       /* add the second quote */
+                       *c++ = '\'';
+               }
+               
+               /* copy the remainder */
+               strncpy(c, l, *quotedlen-(c-*quoted));
+               
+               return 1;
+       }                       
+}
+
+static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
+{
+       pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+
+       if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, 0, NULL)) {
+               RECORD_ERROR(dbh);
+               return 0;
+       }
+       return 1;
+}
+
 static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
 {
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
 
        if (isc_commit_transaction(H->isc_status, &H->tr)) {
-               /* error */
+               RECORD_ERROR(dbh);
                return 0;
        }
        return 1;
@@ -188,7 +337,7 @@ static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
        pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
 
        if (isc_rollback_transaction(H->isc_status, &H->tr)) {
-               /* error */
+               RECORD_ERROR(dbh);
                return 0;
        }
        return 1;
@@ -204,8 +353,8 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TS
 
                        if (dbh->in_txn) {
                                /* Assume they want to commit whatever is outstanding */
-                               if (isc_commit_retaining(H->isc_status, &H->tr)) {
-                                       /* error */
+                               if (isc_commit_transaction(H->isc_status, &H->tr)) {
+                                       RECORD_ERROR(dbh);
                                        return 0;
                                }
                                dbh->in_txn = 0;
@@ -227,8 +376,8 @@ static struct pdo_dbh_methods firebird_methods = {
        firebird_handle_closer,
        firebird_handle_preparer,
        firebird_handle_doer,
-       NULL,
-       NULL,
+       firebird_handle_quoter,
+       firebird_handle_begin,
        firebird_handle_commit,
        firebird_handle_rollback,
        firebird_handle_set_attribute,
@@ -275,6 +424,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRM
                dbh->alloc_own_columns = 0;
                dbh->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
                dbh->native_case = PDO_CASE_UPPER;
+               dbh->alloc_own_columns = 1;
 
                ret = 1;
                
index dc1f648799ca5af548a69e753ae19942007bd394..c03b4b5ac0c21ad464f8b5236a9e0e0997bdacc8 100644 (file)
 #include "ext/standard/info.h"
 #include "pdo/php_pdo.h"
 #include "pdo/php_pdo_driver.h"
+#include "php_pdo_firebird.h"
+#include "php_pdo_firebird_int.h"
 
-struct pdo_stmt_methods firebird_stmt_methods = {0,0,0,0,0,0};
-/*
+#define RECORD_ERROR(stmt) _firebird_error(NULL, stmt,  __FILE__, __LINE__ TSRMLS_CC)
+
+static void free_sqlda(XSQLDA const *sqlda)
+{
+       int i;
+       
+       for (i = 0; i < sqlda->sqld; ++i) {
+               XSQLVAR const *var = &sqlda->sqlvar[i];
+               
+               if (var->sqlind) {
+                       efree(var->sqlind);
+               }
+       }
+}
+       
+static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       
+       if (S->in_sqlda) {
+               free_sqlda(S->in_sqlda);
+               efree(S->in_sqlda);
+       }
+
+       free_sqlda(&S->out_sqlda);
+       efree(S);
+       
+       return 1;
+}
+
+static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       pdo_firebird_db_handle *H = S->H;
+
+       /* named cursors should be closed first */
+       if (*S->name && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) {
+               RECORD_ERROR(stmt);
+               return 0;
+       }
+       
+       /* assume all params have been bound */
+       if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
+               RECORD_ERROR(stmt);
+               return 0;
+       }
+       
+       S->exhausted = 0;
+       
+       return 1;
+}
+
+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;
+
+       switch (S->exhausted) {
+               default:
+                       if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
+                               if (H->isc_status[0] && H->isc_status[1]) {
+                                       RECORD_ERROR(stmt);
+                               }
+                               S->exhausted = 1;
+               case 1:
+                               return 0;
+                       }
+       }
+       return 1;
+}
+
+static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       struct pdo_column_data *col = &stmt->columns[colno];
+       XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
+       
+       /* allocate storage for the column */
+       var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
+       var->sqldata = &((char*)var->sqlind)[sizeof(short)];
+
+       col->precision = -var->sqlscale;
+       col->maxlen = var->sqllen;
+       col->namelen = var->aliasname_length;
+       col->name = estrndup(var->aliasname,var->aliasname_length);
+       
+       return 1;
+}
+
+static void set_param_type(enum pdo_param_type *param_type, XSQLVAR const *var)
+{
+       /* set the param type after the field type */
+       switch (var->sqltype & ~1) {
+               case SQL_SHORT:
+               case SQL_LONG:
+               case SQL_INT64:
+                       if (var->sqlscale < 0) {
+               case SQL_TEXT:
+               case SQL_VARYING:
+                               *param_type = PDO_PARAM_STR;
+                       } else {
+                               *param_type = PDO_PARAM_INT;
+                       }
+                       break;
+               case SQL_FLOAT:
+               case SQL_DOUBLE:
+                       *param_type = PDO_PARAM_DBL;
+                       break;
+       }
+}
+
+static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
+       enum pdo_param_event event_type TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda;
+       XSQLVAR *var = &sqlda->sqlvar[param->paramno];
+
+       if (event_type == PDO_PARAM_EVT_FREE) { /* not used */
+               return 1;
+       }
+
+       if (!sqlda || param->paramno >= sqlda->sqld) {
+               stmt->error_code = PDO_ERR_NOT_FOUND;
+               return 0;
+       }
+
+       switch (event_type) {
+               zval *zparam;
+                       
+               case PDO_PARAM_EVT_ALLOC:
+                               
+                       if (param->is_param) {
+                               /* allocate the parameter */
+                               var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
+                               var->sqldata = &((char*)var->sqlind)[sizeof(short)];
+                       }
+                       break;
+                       
+               case PDO_PARAM_EVT_EXEC_PRE:
+
+                       if (!param->is_param) {
+                               break;
+                       }
+
+                       zparam = param->parameter;
+
+                       /* check if a NULL should be inserted */
+                       switch (Z_TYPE_P(zparam)) {
+                               int force_null;
+       
+                               case IS_STRING:
+                                       force_null = 0;
+       
+                                       /* for these types, an empty string can be handled like a NULL value */
+                                       switch (var->sqltype & ~1) {
+                                               case SQL_SHORT:
+                                               case SQL_LONG:
+                                               case SQL_INT64:
+                                               case SQL_FLOAT:
+                                               case SQL_DOUBLE:
+                                               case SQL_TIMESTAMP:
+                                               case SQL_TYPE_DATE:
+                                               case SQL_TYPE_TIME:
+                                                       force_null = (Z_STRLEN_P(zparam) == 0);
+                                       }
+                                       if (! force_null) break;
+       
+                               case IS_NULL:
+                                       /* complain if this field doesn't allow NULL values */
+                                       if (! (var->sqltype & 1)) {
+                                               stmt->error_code = PDO_ERR_CONSTRAINT;
+                                               return 0;
+                                       }
+                                       *var->sqlind = -1;
+                                       return 1;
+                       }
+
+                       *var->sqlind = 0;
+       
+                       SEPARATE_ZVAL(&zparam);
+
+                       convert_to_string(zparam);
+
+                       var->sqltype = SQL_TEXT;
+                       var->sqldata = Z_STRVAL_P(zparam);
+                       var->sqllen      = Z_STRLEN_P(zparam);
+
+                       break;
+
+               case PDO_PARAM_EVT_FETCH_POST:
+                       /* set the param value according to the fetched row */
+                       return SUCCESS == _php_ibase_var_zval(param->parameter, var->sqldata, var->sqltype,
+                               var->sqllen, var->sqlscale, 0 TSRMLS_CC);
+
+       }               
+
+       return 1;
+}
+
+static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
+
+       if (*var->sqlind == -1) {
+               /* A NULL value */
+               *ptr = NULL;
+               *len = 0;
+       } else {
+               /* override the column param type */
+               set_param_type(&stmt->columns[colno].param_type,var);
+               
+               switch (var->sqltype & ~1) {
+                       ISC_INT64 bint;
+                       
+                       case SQL_VARYING:
+                               *ptr = &var->sqldata[2];
+                               *len = *(short*)var->sqldata;
+                               break;
+                       case SQL_TEXT:
+                               *ptr = var->sqldata;
+                               *len = var->sqllen;
+                               break;
+                       case SQL_SHORT:
+                               *(long*)*ptr = *(short*)var->sqldata;
+                               *len = sizeof(short);
+                               break;
+                       case SQL_LONG:
+                               *(long*)*ptr = *(ISC_LONG*)var->sqldata;
+                               *len = sizeof(ISC_LONG);
+                               break;
+                       case SQL_INT64:
+                               *len = sizeof(long);
+#if SIZEOF_LONG == 8
+                               *ptr = var->sqldata;
+#else                          
+                               bint = *(ISC_INT64*)var->sqldata;
+
+                               if (bint >= LONG_MIN && bint <= LONG_MAX) {
+                                       *(long*)*ptr = (long)bint;
+                               }
+#endif
+                               break;
+               
+                       case SQL_DOUBLE:
+                               *ptr = var->sqldata;
+                               *len = sizeof(double);
+                               break;
+                               
+                       case SQL_TYPE_DATE:
+                       case SQL_TYPE_TIME:
+                       case SQL_TIMESTAMP:
+                               ;                       
+               }
+       }
+       return 1;
+}
+
+static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC)
+{
+       pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
+       
+       switch (attr) {
+               case PDO_ATTR_CURSOR_NAME:
+                       convert_to_string(val);
+                       
+                       if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
+                               RECORD_ERROR(stmt);
+                               return 0;
+                       }
+                       strncpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
+                       S->name[sizeof(S->name)] = 0;
+                       break;
+       }
+       return 1;
+}
+
+struct pdo_stmt_methods firebird_stmt_methods = {
        firebird_stmt_dtor,
        firebird_stmt_execute,
        firebird_stmt_fetch,
        firebird_stmt_describe,
        firebird_stmt_get_col,
-       firebird_stmt_param_hook
+       firebird_stmt_param_hook,
+       firebird_stmt_set_attribute
 };
-*/
+
 /*
  * Local variables:
  * tab-width: 4
index 99b689db247d841d092ee0647a8132138f1fee29..ca429e5a153a1a46add19fac18ca974c93c3227b 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">\r
+<package version="1.0"><!-- $Id: package.xml,v 1.2 2004-06-12 03:09:47 abies Exp $ -->\r
  <name>PDO_Firebird</name>\r
  <summary>Firebird/InterBase support for PDO</summary>\r
  <maintainers>\r
index 9eb913dd597c9ae3e162e01c9b6c59839356b556..83b2e9304a26dc55afe5e0c3827389731ea593d5 100644 (file)
@@ -25,9 +25,15 @@ extern zend_module_entry pdo_firebird_module_entry;
 #define phpext_pdo_firebird_ptr &pdo_firebird_module_entry
 
 #ifdef PHP_WIN32
-#define PHP_PDO_FB_API __declspec(dllexport)
+# ifdef PDO_FIREBIRD_EXPORTS
+#  define PDO_FB_API __declspec(dllexport)
+# elif defined(COMPILE_DL_PDO_FIREBIRD)
+#  define PDO_FB_API __declspec(dllimport)
+# else
+#  define PDO_FB_API
+# endif
 #else
-#define PHP_PDO_FB_API
+# define PDO_FB_API
 #endif
 
 #ifdef ZTS
index da602e49f1c5837c0b75f30a0197fa20c00037da..4e339b71b75f8de801898b819030438cc13aea77 100644 (file)
 
 #define PDO_FB_DIALECT 3
 
+#define SHORT_MAX (1 << 8*sizeof(short)-1)
 
-typedef struct {
-       const char *file;
-       int line;
-       long errcode;
-       char *errmsg;
-} pdo_firebird_error_info;
-
+/* Firebird API has a couple of missing const decls in its API */
+#define const_cast(s) ((char*)(s))
 
 typedef struct {
 
@@ -62,8 +58,19 @@ typedef struct {
        /* the statement handle */
        isc_stmt_handle stmt;
        
+       /* the name of the cursor (if it has one) */
+       char name[32];
+       
+       /* whether EOF was reached for this statement */
+       unsigned exhausted:1;
+
+       unsigned _reserved:31;
+       
+       /* the input SQLDA */
+       XSQLDA *in_sqlda;
+       
        /* the output SQLDA */
-       XSQLDA out_sqlda[1]; /* last member */
+       XSQLDA out_sqlda; /* last member */
        
 } pdo_firebird_stmt;
 
@@ -71,6 +78,8 @@ extern pdo_driver_t pdo_firebird_driver;
 
 extern struct pdo_stmt_methods firebird_stmt_methods;
 
+void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long line TSRMLS_DC);
+
 #endif /* PHP_PDO_FIREBIRD_INT_H */
 
 /*
diff --git a/ext/pdo_firebird/tests/ddl.phpt b/ext/pdo_firebird/tests/ddl.phpt
new file mode 100644 (file)
index 0000000..7709bb3
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+PDO_Firebird: DDL/transactions
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php /* $Id$ */
+
+       require("testdb.inc");
+    
+       $db = new PDO("firebird:dbname=$test_base",$user,$password) or die;
+       $db->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_WARNING);
+       
+       $db->exec("CREATE TABLE ddl (id INT NOT NULL PRIMARY KEY, text BLOB SUB_TYPE 1)");
+       $db->exec("CREATE GENERATOR gen_ddl_id");
+       $db->exec("CREATE TRIGGER ddl_bi FOR ddl BEFORE INSERT AS
+               BEGIN IF (NEW.id IS NULL) THEN NEW.id=GEN_ID(gen_ddl_id,1); END");
+       
+       $db->setAttribute(PDO_ATTR_AUTOCOMMIT,0);
+       
+       $db->beginTransaction();
+       var_dump($db->exec("INSERT INTO ddl (text) VALUES ('bla')"));
+       var_dump($db->exec("UPDATE ddl SET text='blabla'"));
+       $db->rollback();
+       
+       $db->beginTransaction();
+       var_dump($db->exec("DELETE FROM ddl"));
+       $db->commit();
+       
+       unset($db);
+       echo "done\n";
+       
+?>
+--EXPECT--
+int(1)
+int(1)
+int(0)
+done