PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo_firebird - firebird_driver.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 189 270 70.0 %
Date: 2014-04-19 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2014 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Ard Biesheuvel <abies@php.net>                               |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include "config.h"
      21             : #endif
      22             : 
      23             : #define _GNU_SOURCE
      24             : 
      25             : #include "php.h"
      26             : #ifdef ZEND_ENGINE_2
      27             : # include "zend_exceptions.h"
      28             : #endif
      29             : #include "php_ini.h"
      30             : #include "ext/standard/info.h"
      31             : #include "pdo/php_pdo.h"
      32             : #include "pdo/php_pdo_driver.h"
      33             : #include "php_pdo_firebird.h"
      34             : #include "php_pdo_firebird_int.h"
      35             : 
      36             : static int firebird_alloc_prepare_stmt(pdo_dbh_t*, const char*, long, XSQLDA*, isc_stmt_handle*,
      37             :         HashTable* TSRMLS_DC);
      38             : 
      39             : /* map driver specific error message to PDO error */
      40         300 : void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long line TSRMLS_DC) /* {{{ */
      41             : {
      42             : #if 0
      43             :         pdo_firebird_db_handle *H = stmt ? ((pdo_firebird_stmt *)stmt->driver_data)->H 
      44             :                 : (pdo_firebird_db_handle *)dbh->driver_data;
      45             : #endif
      46         300 :         pdo_error_type *const error_code = stmt ? &stmt->error_code : &dbh->error_code;
      47             :         
      48             : #if 0
      49             :         switch (isc_sqlcode(H->isc_status)) {
      50             : 
      51             :                 case 0:
      52             :                         *error_code = PDO_ERR_NONE;
      53             :                         break;
      54             :                 default:
      55             :                         *error_code = PDO_ERR_CANT_MAP;
      56             :                         break;
      57             :                 case -104:
      58             :                         *error_code = PDO_ERR_SYNTAX;
      59             :                         break;
      60             :                 case -530:
      61             :                 case -803:
      62             :                         *error_code = PDO_ERR_CONSTRAINT;
      63             :                         break;
      64             :                 case -204:
      65             :                 case -205:
      66             :                 case -206:
      67             :                 case -829:
      68             :                         *error_code = PDO_ERR_NOT_FOUND;
      69             :                         break;
      70             : 
      71             :                         *error_code = PDO_ERR_ALREADY_EXISTS;
      72             :                         break;
      73             :                 
      74             :                         *error_code = PDO_ERR_NOT_IMPLEMENTED;
      75             :                         break;
      76             :                 case -313:
      77             :                 case -804:
      78             :                         *error_code = PDO_ERR_MISMATCH;
      79             :                         break;
      80             :                 case -303:
      81             :                 case -314:      
      82             :                 case -413:
      83             :                         *error_code = PDO_ERR_TRUNCATED;
      84             :                         break;
      85             :                         
      86             :                         *error_code = PDO_ERR_DISCONNECTED;
      87             :                         break;
      88             :         }
      89             : #else
      90         300 :         strcpy(*error_code, "HY000");
      91             : #endif
      92         300 : }
      93             : /* }}} */
      94             : 
      95             : #define RECORD_ERROR(dbh) _firebird_error(dbh, NULL, __FILE__, __LINE__ TSRMLS_CC)
      96             : 
      97             : /* called by PDO to close a db handle */
      98         118 : static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
      99             : {
     100         118 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     101             :         
     102         118 :         if (dbh->in_txn) {
     103           0 :                 if (dbh->auto_commit) {
     104           0 :                         if (isc_commit_transaction(H->isc_status, &H->tr)) {
     105           0 :                                 RECORD_ERROR(dbh);
     106             :                         }
     107             :                 } else {
     108           0 :                         if (isc_rollback_transaction(H->isc_status, &H->tr)) {
     109           0 :                                 RECORD_ERROR(dbh);
     110             :                         }
     111             :                 }
     112             :         }
     113             :         
     114         118 :         if (isc_detach_database(H->isc_status, &H->db)) {
     115           0 :                 RECORD_ERROR(dbh);
     116             :         }
     117             : 
     118         118 :         if (H->date_format) {
     119           0 :                 efree(H->date_format);
     120             :         }
     121         118 :         if (H->time_format) {
     122           0 :                 efree(H->time_format);
     123             :         }
     124         118 :         if (H->timestamp_format) {
     125           0 :                 efree(H->timestamp_format);
     126             :         }
     127             :         
     128         118 :         pefree(H, dbh->is_persistent);
     129             : 
     130         118 :         return 0;
     131             : }
     132             : /* }}} */
     133             : 
     134             : /* called by PDO to prepare an SQL query */
     135         116 : static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, /* {{{ */
     136             :         pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
     137             : {
     138         116 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     139         116 :         pdo_firebird_stmt *S = NULL;
     140             :         HashTable *np;
     141             : 
     142             :         do {
     143         116 :                 isc_stmt_handle s = NULL;
     144             :                 XSQLDA num_sqlda;
     145             :                 static char const info[] = { isc_info_sql_stmt_type };
     146             :                 char result[8];
     147             : 
     148         116 :                 num_sqlda.version = PDO_FB_SQLDA_VERSION;
     149         116 :                 num_sqlda.sqln = 1;
     150             : 
     151         116 :                 ALLOC_HASHTABLE(np);
     152         116 :                 zend_hash_init(np, 8, NULL, NULL, 0);
     153             :                 
     154             :                 /* allocate and prepare statement */
     155         116 :                 if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &num_sqlda, &s, np TSRMLS_CC)) {
     156           3 :                         break;
     157             :                 }
     158             :         
     159             :                 /* allocate a statement handle struct of the right size (struct out_sqlda is inlined) */
     160         113 :                 S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
     161         113 :                 S->H = H;
     162         113 :                 S->stmt = s;
     163         113 :                 S->fetch_buf = ecalloc(1,sizeof(char*) * num_sqlda.sqld);
     164         113 :                 S->out_sqlda.version = PDO_FB_SQLDA_VERSION;
     165         113 :                 S->out_sqlda.sqln = stmt->column_count = num_sqlda.sqld;
     166         113 :                 S->named_params = np;
     167             : 
     168             :                 /* determine the statement type */
     169         113 :                 if (isc_dsql_sql_info(H->isc_status, &s, sizeof(info), const_cast(info), sizeof(result),
     170             :                                 result)) {
     171           0 :                         break;
     172             :                 }
     173         113 :                 S->statement_type = result[3];       
     174             :                 
     175             :                 /* fill the output sqlda with information about the prepared query */
     176         113 :                 if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
     177           0 :                         RECORD_ERROR(dbh);
     178           0 :                         break;
     179             :                 }
     180             :                 
     181             :                 /* allocate the input descriptors */
     182         113 :                 if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &num_sqlda)) {
     183           0 :                         break;
     184             :                 }
     185             :                 
     186         113 :                 if (num_sqlda.sqld) {
     187          29 :                         S->in_sqlda = ecalloc(1,XSQLDA_LENGTH(num_sqlda.sqld));
     188          29 :                         S->in_sqlda->version = PDO_FB_SQLDA_VERSION;
     189          29 :                         S->in_sqlda->sqln = num_sqlda.sqld;
     190             :                 
     191          29 :                         if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
     192           0 :                                 break;
     193             :                         }
     194             :                 }
     195             :         
     196         113 :                 stmt->driver_data = S;
     197         113 :                 stmt->methods = &firebird_stmt_methods;
     198         113 :                 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
     199             :         
     200         113 :                 return 1;
     201             : 
     202             :         } while (0);
     203             : 
     204           3 :         RECORD_ERROR(dbh);
     205             :         
     206           3 :         zend_hash_destroy(np);
     207           3 :         FREE_HASHTABLE(np);
     208             :         
     209           3 :         if (S) {
     210           0 :                 if (S->in_sqlda) {
     211           0 :                         efree(S->in_sqlda);
     212             :                 }
     213           0 :                 efree(S);
     214             :         }
     215             :         
     216           3 :         return 0;
     217             : }
     218             : /* }}} */
     219             : 
     220             : /* called by PDO to execute a statement that doesn't produce a result set */
     221         513 : static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */
     222             : {
     223         513 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     224         513 :         isc_stmt_handle stmt = NULL;
     225             :         static char const info_count[] = { isc_info_sql_records };
     226             :         char result[64];
     227         513 :         int ret = 0;
     228             :         XSQLDA in_sqlda, out_sqlda;
     229             :                 
     230             :         /* TODO no placeholders in exec() for now */
     231         513 :         in_sqlda.version = out_sqlda.version = PDO_FB_SQLDA_VERSION;
     232         513 :         in_sqlda.sqld = out_sqlda.sqld = 0;
     233         513 :         out_sqlda.sqln = 1;
     234             :         
     235             :         /* allocate and prepare statement */
     236         513 :         if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &out_sqlda, &stmt, 0 TSRMLS_CC)) {
     237         285 :                 return -1;
     238             :         }
     239             : 
     240             :         /* execute the statement */
     241         228 :         if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) {
     242           0 :                 RECORD_ERROR(dbh);
     243           0 :                 return -1;
     244             :         }
     245             :         
     246             :         /* find out how many rows were affected */
     247         228 :         if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), const_cast(info_count),
     248             :                         sizeof(result), result)) {
     249           0 :                 RECORD_ERROR(dbh);
     250           0 :                 return -1;
     251             :         }
     252             : 
     253         228 :         if (result[0] == isc_info_sql_records) {
     254         107 :                 unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
     255             : 
     256         642 :                 while (result[i] != isc_info_end && i < result_size) {
     257         428 :                         short len = (short)isc_vax_integer(&result[i+1],2);
     258         428 :                         if (result[i] != isc_info_req_select_count) {
     259         321 :                                 ret += isc_vax_integer(&result[i+3],len);
     260             :                         }
     261         428 :                         i += len+3;
     262             :                 }
     263             :         }
     264             :         
     265             :         /* commit if we're in auto_commit mode */
     266         228 :         if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
     267           9 :                 RECORD_ERROR(dbh);
     268             :         }
     269             : 
     270         228 :         return ret;
     271             : }
     272             : /* }}} */
     273             : 
     274             : /* called by the PDO SQL parser to add quotes to values that are copied into SQL */
     275           1 : static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, /* {{{ */
     276             :         char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
     277             : {
     278           1 :         int qcount = 0;
     279             :         char const *co, *l, *r;
     280             :         char *c;
     281             :         
     282           1 :         if (!unquotedlen) {
     283           0 :                 *quotedlen = 2;
     284           0 :                 *quoted = emalloc(*quotedlen+1);
     285           0 :                 strcpy(*quoted, "''");
     286           0 :                 return 1;
     287             :         }
     288             :                         
     289             :         /* Firebird only requires single quotes to be doubled if string lengths are used */
     290             :         /* count the number of ' characters */
     291           1 :         for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++);
     292             :         
     293           1 :         *quotedlen = unquotedlen + qcount + 2;
     294           1 :         *quoted = c = emalloc(*quotedlen+1);            
     295           1 :         *c++ = '\'';
     296             :         
     297             :         /* foreach (chunk that ends in a quote) */
     298           2 :         for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {                     
     299           1 :                 strncpy(c, l, r-l+1);
     300           1 :                 c += (r-l+1);                   
     301             :                 /* add the second quote */
     302           1 :                 *c++ = '\'';
     303             :         }
     304             :                 
     305             :         /* copy the remainder */
     306           1 :         strncpy(c, l, *quotedlen-(c-*quoted)-1);
     307           1 :         (*quoted)[*quotedlen-1] = '\''; 
     308           1 :         (*quoted)[*quotedlen]   = '\0';
     309             :         
     310           1 :         return 1;
     311             : }
     312             : /* }}} */
     313             : 
     314             : /* called by PDO to start a transaction */
     315         133 : static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     316             : {
     317         133 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     318         133 :         char tpb[8] = { isc_tpb_version3 }, *ptpb = tpb+1;
     319             : #if abies_0     
     320             :         if (dbh->transaction_flags & PDO_TRANS_ISOLATION_LEVEL) {
     321             :                 if (dbh->transaction_flags & PDO_TRANS_READ_UNCOMMITTED) {
     322             :                         /* this is a poor fit, but it's all we have */
     323             :                         *ptpb++ = isc_tpb_read_committed;
     324             :                         *ptpb++ = isc_tpb_rec_version;
     325             :                         dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_UNCOMMITTED);
     326             :                 } else if (dbh->transaction_flags & PDO_TRANS_READ_COMMITTED) {
     327             :                         *ptpb++ = isc_tpb_read_committed;
     328             :                         *ptpb++ = isc_tpb_no_rec_version;
     329             :                         dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_COMMITTED);
     330             :                 } else if (dbh->transaction_flags & PDO_TRANS_REPEATABLE_READ) {
     331             :                         *ptpb++ = isc_tpb_concurrency;
     332             :                         dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_REPEATABLE_READ);
     333             :                 } else {
     334             :                         *ptpb++ = isc_tpb_consistency;
     335             :                         dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_SERIALIZABLE);
     336             :                 }
     337             :         }
     338             :                 
     339             :         if (dbh->transaction_flags & PDO_TRANS_ACCESS_MODE) {
     340             :                 if (dbh->transaction_flags & PDO_TRANS_READONLY) {
     341             :                         *ptpb++ = isc_tpb_read;
     342             :                         dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);
     343             :                 } else {
     344             :                         *ptpb++ = isc_tpb_write;
     345             :                         dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READWRITE);
     346             :                 }
     347             :         }
     348             : 
     349             :         if (dbh->transaction_flags & PDO_TRANS_CONFLICT_RESOLUTION) {
     350             :                 if (dbh->transaction_flags & PDO_TRANS_RETRY) {
     351             :                         *ptpb++ = isc_tpb_wait;
     352             :                         dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_RETRY);
     353             :                 } else {
     354             :                         *ptpb++ = isc_tpb_nowait;
     355             :                         dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_ABORT);
     356             :                 }
     357             :         }
     358             : #endif
     359         133 :         if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb-tpb), tpb)) {
     360           0 :                 RECORD_ERROR(dbh);
     361           0 :                 return 0;
     362             :         }
     363         133 :         return 1;
     364             : }
     365             : /* }}} */
     366             : 
     367             : /* called by PDO to commit a transaction */
     368          16 : static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     369             : {
     370          16 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     371             : 
     372          16 :         if (isc_commit_transaction(H->isc_status, &H->tr)) {
     373           0 :                 RECORD_ERROR(dbh);
     374           0 :                 return 0;
     375             :         }
     376          16 :         return 1;
     377             : }
     378             : /* }}} */
     379             : 
     380             : /* called by PDO to rollback a transaction */
     381         117 : static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     382             : {
     383         117 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     384             : 
     385         117 :         if (isc_rollback_transaction(H->isc_status, &H->tr)) {
     386           0 :                 RECORD_ERROR(dbh);
     387           0 :                 return 0;
     388             :         }
     389         117 :         return 1;
     390             : }
     391             : /* }}} */
     392             : 
     393             : /* used by prepare and exec to allocate a statement handle and prepare the SQL */
     394         629 : static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const char *sql, long sql_len, /* {{{ */
     395             :         XSQLDA *out_sqlda, isc_stmt_handle *s, HashTable *named_params TSRMLS_DC)
     396             : {
     397         629 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     398             :         char *c, *new_sql, in_quote, in_param, pname[64], *ppname;
     399         629 :         long l, pindex = -1;
     400             :                 
     401             :         /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
     402         629 :         if (sql_len > 65536) {
     403           0 :                 strcpy(dbh->error_code, "01004");
     404           0 :                 return 0;
     405             :         }
     406             :         
     407             :         /* start a new transaction implicitly if auto_commit is enabled and no transaction is open */
     408         629 :         if (dbh->auto_commit && !dbh->in_txn) {
     409             :                 /* dbh->transaction_flags = PDO_TRANS_READ_UNCOMMITTED; */
     410             : 
     411         131 :                 if (!firebird_handle_begin(dbh TSRMLS_CC)) {
     412           0 :                         return 0;
     413             :                 }
     414         131 :                 dbh->in_txn = 1;
     415             :         }
     416             :         
     417             :         /* allocate the statement */
     418         629 :         if (isc_dsql_allocate_statement(H->isc_status, &H->db, s)) {
     419           0 :                 RECORD_ERROR(dbh);
     420           0 :                 return 0;
     421             :         }
     422             :         
     423             :         /* in order to support named params, which Firebird itself doesn't, 
     424             :            we need to replace :foo by ?, and store the name we just replaced */
     425         629 :         new_sql = c = emalloc(sql_len+1);
     426             :         
     427       19229 :         for (l = in_quote = in_param = 0; l <= sql_len; ++l) {
     428       18600 :                 if ( !(in_quote ^= (sql[l] == '\''))) {
     429       17876 :                         if (!in_param) {
     430       17756 :                                 switch (sql[l]) {
     431             :                                         case ':':
     432          23 :                                                 in_param = 1;
     433          23 :                                                 ppname = pname;
     434          23 :                                                 *ppname++ = sql[l];
     435             :                                         case '?':
     436          55 :                                                 *c++ = '?';
     437          55 :                                                 ++pindex;
     438          55 :                                         continue;
     439             :                                 }
     440             :                         } else {
     441         195 :                                 if ((in_param &= ((sql[l] >= 'A' && sql[l] <= 'Z') || (sql[l] >= 'a' && sql[l] <= 'z')
     442          75 :                                         || (sql[l] >= '0' && sql[l] <= '9') || sql[l] == '_' || sql[l] == '-'))) { 
     443             : 
     444             :                                         
     445          97 :                                         *ppname++ = sql[l];
     446          97 :                                         continue;
     447             :                                 } else {
     448          23 :                                         *ppname++ = 0;
     449          23 :                                         if (named_params) {
     450          23 :                                                 zend_hash_update(named_params, pname, (unsigned int)(ppname-pname),
     451             :                                                         (void*)&pindex, sizeof(long)+1,NULL);
     452             :                                         }
     453             :                                 }
     454             :                         }
     455             :                 }
     456       18448 :                 *c++ = sql[l];
     457             :         }
     458             : 
     459             :         /* prepare the statement */
     460         629 :         if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, PDO_FB_DIALECT, out_sqlda)) {
     461         288 :                 RECORD_ERROR(dbh);
     462         288 :                 efree(new_sql);
     463         288 :                 return 0;
     464             :         }
     465             :         
     466         341 :         efree(new_sql);
     467         341 :         return 1;
     468             : }
     469             : /* }}} */
     470             :         
     471             : /* called by PDO to set a driver-specific dbh attribute */
     472           4 : static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */
     473             : {
     474           4 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     475             : 
     476           4 :         switch (attr) {
     477             :                 case PDO_ATTR_AUTOCOMMIT:
     478             : 
     479           1 :                         convert_to_boolean(val);
     480             :         
     481             :                         /* ignore if the new value equals the old one */                        
     482           1 :                         if (dbh->auto_commit ^ Z_BVAL_P(val)) {
     483           1 :                                 if (dbh->in_txn) {
     484           1 :                                         if (Z_BVAL_P(val)) {
     485             :                                                 /* turning on auto_commit with an open transaction is illegal, because
     486             :                                                    we won't know what to do with it */
     487           0 :                                                 H->last_app_error = "Cannot enable auto-commit while a transaction is already open";
     488           0 :                                                 return 0;
     489             :                                         } else {
     490             :                                                 /* close the transaction */
     491           1 :                                                 if (!firebird_handle_commit(dbh TSRMLS_CC)) {
     492           0 :                                                         break;
     493             :                                                 }
     494           1 :                                                 dbh->in_txn = 0;
     495             :                                         }
     496             :                                 }
     497           1 :                                 dbh->auto_commit = Z_BVAL_P(val);
     498             :                         }
     499           1 :                         return 1;
     500             : 
     501             :                 case PDO_ATTR_FETCH_TABLE_NAMES:
     502           0 :                         convert_to_boolean(val);
     503           0 :                         H->fetch_table_names = Z_BVAL_P(val);
     504           0 :                         return 1;
     505             : 
     506             :                 case PDO_FB_ATTR_DATE_FORMAT:
     507           0 :                         convert_to_string(val);
     508           0 :                         if (H->date_format) {
     509           0 :                                 efree(H->date_format);
     510             :                         }
     511           0 :                         spprintf(&H->date_format, 0, "%s", Z_STRVAL_P(val)); 
     512           0 :                         return 1;
     513             : 
     514             :                 case PDO_FB_ATTR_TIME_FORMAT:
     515           0 :                         convert_to_string(val);
     516           0 :                         if (H->time_format) {
     517           0 :                                 efree(H->time_format);
     518             :                         }
     519           0 :                         spprintf(&H->time_format, 0, "%s", Z_STRVAL_P(val)); 
     520           0 :                         return 1;
     521             : 
     522             :                 case PDO_FB_ATTR_TIMESTAMP_FORMAT:
     523           0 :                         convert_to_string(val);
     524           0 :                         if (H->timestamp_format) {
     525           0 :                                 efree(H->timestamp_format);
     526             :                         }
     527           0 :                         spprintf(&H->timestamp_format, 0, "%s", Z_STRVAL_P(val)); 
     528           0 :                         return 1;
     529             :         }
     530           3 :         return 0;
     531             : }
     532             : /* }}} */
     533             : 
     534             : /* callback to used to report database server info */
     535           4 : static void firebird_info_cb(void *arg, char const *s) /* {{{ */
     536             : {
     537           4 :         if (arg) {
     538           0 :                 if (*(char*)arg) { /* second call */
     539           0 :                         strcat(arg, " ");
     540             :                 }
     541           0 :                 strcat(arg, s);
     542             :         }
     543           4 : }
     544             : /* }}} */
     545             : 
     546             : /* called by PDO to get a driver-specific dbh attribute */
     547           1 : static int firebird_handle_get_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */
     548             : {
     549           1 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     550             : 
     551           1 :         switch (attr) {
     552             :                 char tmp[512];
     553             :                 
     554             :                 case PDO_ATTR_AUTOCOMMIT:
     555           0 :                         ZVAL_LONG(val,dbh->auto_commit);
     556           0 :                         return 1;
     557             : 
     558             :                 case PDO_ATTR_CONNECTION_STATUS:
     559           1 :                         ZVAL_BOOL(val, !isc_version(&H->db, firebird_info_cb, NULL));
     560           1 :                         return 1;
     561             : 
     562             :                 case PDO_ATTR_CLIENT_VERSION: {
     563             : #if defined(__GNUC__) || defined(PHP_WIN32)
     564           0 :                         info_func_t info_func = NULL;
     565             : #ifdef __GNUC__
     566           0 :                         info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
     567             : #else
     568             :                         HMODULE l = GetModuleHandle("fbclient");
     569             : 
     570             :                         if (!l && !(l = GetModuleHandle("gds32"))) {
     571             :                                 break;
     572             :                         }
     573             :                         info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
     574             : #endif
     575           0 :                         if (info_func) {
     576           0 :                                 info_func(tmp);
     577           0 :                                 ZVAL_STRING(val,tmp,1);
     578             :                         } else {
     579           0 :                                 ZVAL_STRING(val,"Firebird 1.0/Interbase 6",1);
     580             :                         }
     581             : #else
     582             :                         ZVAL_NULL(val);
     583             : #endif
     584             :                         }
     585           0 :                         return 1;
     586             :                         
     587             :                 case PDO_ATTR_SERVER_VERSION:
     588             :                 case PDO_ATTR_SERVER_INFO:
     589           0 :                         *tmp = 0;
     590             :                         
     591           0 :                         if (!isc_version(&H->db, firebird_info_cb, (void*)tmp)) {
     592           0 :                                 ZVAL_STRING(val,tmp,1);
     593           0 :                                 return 1;
     594             :                         }
     595             :                         
     596             :                 case PDO_ATTR_FETCH_TABLE_NAMES:
     597           0 :                         ZVAL_BOOL(val, H->fetch_table_names);
     598           0 :                         return 1;
     599             :         }
     600           0 :         return 0;
     601             : }       
     602             : /* }}} */
     603             :         
     604             : /* called by PDO to retrieve driver-specific information about an error that has occurred */
     605          14 : static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
     606             : {       
     607          14 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     608          14 :         const ISC_STATUS *s = H->isc_status;
     609             :         char buf[400];
     610          14 :         long i = 0, l, sqlcode = isc_sqlcode(s);
     611             : 
     612          14 :         if (sqlcode) {
     613          10 :                 add_next_index_long(info, sqlcode);
     614             : 
     615          62 :                 while ((sizeof(buf)>(i+2))&&(l = fb_interpret(&buf[i],(sizeof(buf)-i-2),&s))) {
     616          42 :                         i += l;
     617          42 :                         strcpy(&buf[i++], " ");
     618             :                 }
     619          10 :                 add_next_index_string(info, buf, 1);
     620           4 :         } else if (H->last_app_error) {
     621           1 :                 add_next_index_long(info, -999);
     622           1 :                 add_next_index_string(info, const_cast(H->last_app_error),1);
     623             :         }
     624          14 :         return 1;
     625             : }
     626             : /* }}} */
     627             : 
     628             : static struct pdo_dbh_methods firebird_methods = { /* {{{ */
     629             :         firebird_handle_closer,
     630             :         firebird_handle_preparer,
     631             :         firebird_handle_doer,
     632             :         firebird_handle_quoter,
     633             :         firebird_handle_begin,
     634             :         firebird_handle_commit,
     635             :         firebird_handle_rollback,
     636             :         firebird_handle_set_attribute,
     637             :         NULL, /* last_id not supported */
     638             :         pdo_firebird_fetch_error_func,
     639             :         firebird_handle_get_attribute,
     640             :         NULL /* check_liveness */
     641             : };
     642             : /* }}} */
     643             : 
     644             : /* the driver-specific PDO handle constructor */
     645         119 : static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
     646             : {
     647             :         struct pdo_data_src_parser vars[] = {
     648             :                 { "dbname", NULL, 0 },
     649             :                 { "charset",  NULL,   0 },
     650             :                 { "role", NULL,       0 }
     651         119 :         };
     652         119 :         int i, ret = 0;
     653         119 :         short buf_len = 256, dpb_len;
     654             : 
     655         119 :         pdo_firebird_db_handle *H = dbh->driver_data = pecalloc(1,sizeof(*H),dbh->is_persistent);
     656             : 
     657         119 :         php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 3);
     658             :         
     659             :         do {
     660             :                 static char const dpb_flags[] = { 
     661             :                         isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name };
     662         119 :                 char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval };
     663         119 :                 char dpb_buffer[256] = { isc_dpb_version1 }, *dpb;
     664             :                 
     665         119 :                 dpb = dpb_buffer + 1; 
     666             : 
     667             :                 /* loop through all the provided arguments and set dpb fields accordingly */
     668         595 :                 for (i = 0; i < sizeof(dpb_flags); ++i) {
     669         476 :                         if (dpb_values[i] && buf_len > 0) {
     670         238 :                                 dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_flags[i], (unsigned char)strlen(dpb_values[i]),
     671             :                                         dpb_values[i]);
     672         238 :                                 dpb += dpb_len;
     673         238 :                                 buf_len -= dpb_len;
     674             :                         }
     675             :                 }
     676             :                 
     677             :                 /* fire it up baby! */
     678         119 :                 if (isc_attach_database(H->isc_status, 0, vars[0].optval, &H->db,(short)(dpb-dpb_buffer), dpb_buffer)) {
     679           0 :                         break;
     680             :                 }
     681             :                 
     682         119 :                 dbh->methods = &firebird_methods;
     683         119 :                 dbh->native_case = PDO_CASE_UPPER;
     684         119 :                 dbh->alloc_own_columns = 1;
     685             :                 
     686         119 :                 ret = 1;
     687             :                 
     688             :         } while (0);
     689             :                 
     690         476 :         for (i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) {
     691         357 :                 if (vars[i].freeme) {
     692         119 :                         efree(vars[i].optval);
     693             :                 }
     694             :         }
     695             : 
     696         119 :         if (!dbh->methods) {
     697             :                 char errmsg[512];
     698           0 :                 const ISC_STATUS *s = H->isc_status;
     699           0 :                 fb_interpret(errmsg, sizeof(errmsg),&s);
     700           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), H->isc_status[1] TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
     701             :                                 "HY000", H->isc_status[1], errmsg);
     702             :         }
     703             : 
     704         119 :         if (!ret) {
     705           0 :                 firebird_handle_closer(dbh TSRMLS_CC);
     706             :         }
     707             : 
     708         119 :         return ret;
     709             : }
     710             : /* }}} */
     711             : 
     712             : 
     713             : pdo_driver_t pdo_firebird_driver = { /* {{{ */
     714             :         PDO_DRIVER_HEADER(firebird),
     715             :         pdo_firebird_handle_factory
     716             : };
     717             : /* }}} */
     718             : 
     719             : /*
     720             :  * Local variables:
     721             :  * tab-width: 4
     722             :  * c-basic-offset: 4
     723             :  * End:
     724             :  * vim600: noet sw=4 ts=4 fdm=marker
     725             :  * vim<600: noet sw=4 ts=4
     726             :  */

Generated by: LCOV version 1.10

Generated at Sun, 20 Apr 2014 03:52:12 +0000 (4 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.