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: 174 270 64.4 %
Date: 2014-10-22 Functions: 11 14 78.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       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*, zend_long, XSQLDA*, isc_stmt_handle*,
      37             :         HashTable* TSRMLS_DC);
      38             : 
      39             : /* map driver specific error message to PDO error */
      40         287 : void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, zend_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         287 :         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         287 :         strcpy(*error_code, "HY000");
      91             : #endif
      92         287 : }
      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           9 :                 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         103 : static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, zend_long sql_len, /* {{{ */
     136             :         pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
     137             : {
     138         103 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     139         103 :         pdo_firebird_stmt *S = NULL;
     140             :         HashTable *np;
     141             : 
     142             :         do {
     143         103 :                 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         103 :                 num_sqlda.version = PDO_FB_SQLDA_VERSION;
     149         103 :                 num_sqlda.sqln = 1;
     150             : 
     151         103 :                 ALLOC_HASHTABLE(np);
     152         103 :                 zend_hash_init(np, 8, NULL, NULL, 0);
     153             :                 
     154             :                 /* allocate and prepare statement */
     155         103 :                 if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &num_sqlda, &s, np TSRMLS_CC)) {
     156           1 :                         break;
     157             :                 }
     158             :         
     159             :                 /* allocate a statement handle struct of the right size (struct out_sqlda is inlined) */
     160         102 :                 S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld));
     161         102 :                 S->H = H;
     162         102 :                 S->stmt = s;
     163         102 :                 S->fetch_buf = ecalloc(1,sizeof(char*) * num_sqlda.sqld);
     164         102 :                 S->out_sqlda.version = PDO_FB_SQLDA_VERSION;
     165         102 :                 S->out_sqlda.sqln = stmt->column_count = num_sqlda.sqld;
     166         102 :                 S->named_params = np;
     167             : 
     168             :                 /* determine the statement type */
     169         102 :                 if (isc_dsql_sql_info(H->isc_status, &s, sizeof(info), const_cast(info), sizeof(result),
     170             :                                 result)) {
     171           0 :                         break;
     172             :                 }
     173         102 :                 S->statement_type = result[3];       
     174             :                 
     175             :                 /* fill the output sqlda with information about the prepared query */
     176         102 :                 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         102 :                 if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &num_sqlda)) {
     183           0 :                         break;
     184             :                 }
     185             :                 
     186         102 :                 if (num_sqlda.sqld) {
     187          23 :                         S->in_sqlda = ecalloc(1,XSQLDA_LENGTH(num_sqlda.sqld));
     188          23 :                         S->in_sqlda->version = PDO_FB_SQLDA_VERSION;
     189          23 :                         S->in_sqlda->sqln = num_sqlda.sqld;
     190             :                 
     191          23 :                         if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
     192           0 :                                 break;
     193             :                         }
     194             :                 }
     195             :         
     196         102 :                 stmt->driver_data = S;
     197         102 :                 stmt->methods = &firebird_stmt_methods;
     198         102 :                 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
     199             :         
     200         102 :                 return 1;
     201             : 
     202             :         } while (0);
     203             : 
     204           1 :         RECORD_ERROR(dbh);
     205             :         
     206           1 :         zend_hash_destroy(np);
     207           1 :         FREE_HASHTABLE(np);
     208             :         
     209           1 :         if (S) {
     210           0 :                 if (S->in_sqlda) {
     211           0 :                         efree(S->in_sqlda);
     212             :                 }
     213           0 :                 efree(S);
     214             :         }
     215             :         
     216           1 :         return 0;
     217             : }
     218             : /* }}} */
     219             : 
     220             : /* called by PDO to execute a statement that doesn't produce a result set */
     221         472 : static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, zend_long sql_len TSRMLS_DC) /* {{{ */
     222             : {
     223         472 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     224         472 :         isc_stmt_handle stmt = NULL;
     225             :         static char const info_count[] = { isc_info_sql_records };
     226             :         char result[64];
     227         472 :         int ret = 0;
     228             :         XSQLDA in_sqlda, out_sqlda;
     229             :                 
     230             :         /* TODO no placeholders in exec() for now */
     231         472 :         in_sqlda.version = out_sqlda.version = PDO_FB_SQLDA_VERSION;
     232         472 :         in_sqlda.sqld = out_sqlda.sqld = 0;
     233         472 :         out_sqlda.sqln = 1;
     234             :         
     235             :         /* allocate and prepare statement */
     236         472 :         if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &out_sqlda, &stmt, 0 TSRMLS_CC)) {
     237         274 :                 return -1;
     238             :         }
     239             : 
     240             :         /* execute the statement */
     241         198 :         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         198 :         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         198 :         if (result[0] == isc_info_sql_records) {
     254          92 :                 unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
     255             : 
     256         552 :                 while (result[i] != isc_info_end && i < result_size) {
     257         368 :                         short len = (short)isc_vax_integer(&result[i+1],2);
     258         368 :                         if (result[i] != isc_info_req_select_count) {
     259         276 :                                 ret += isc_vax_integer(&result[i+3],len);
     260             :                         }
     261         368 :                         i += len+3;
     262             :                 }
     263             :         }
     264             :         
     265             :         /* commit if we're in auto_commit mode */
     266         198 :         if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
     267           2 :                 RECORD_ERROR(dbh);
     268             :         }
     269             : 
     270         198 :         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         108 : static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     316             : {
     317         108 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     318         108 :         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         108 :         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         108 :         return 1;
     364             : }
     365             : /* }}} */
     366             : 
     367             : /* called by PDO to commit a transaction */
     368           0 : static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     369             : {
     370           0 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     371             : 
     372           0 :         if (isc_commit_transaction(H->isc_status, &H->tr)) {
     373           0 :                 RECORD_ERROR(dbh);
     374           0 :                 return 0;
     375             :         }
     376           0 :         return 1;
     377             : }
     378             : /* }}} */
     379             : 
     380             : /* called by PDO to rollback a transaction */
     381         108 : static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     382             : {
     383         108 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     384             : 
     385         108 :         if (isc_rollback_transaction(H->isc_status, &H->tr)) {
     386           0 :                 RECORD_ERROR(dbh);
     387           0 :                 return 0;
     388             :         }
     389         108 :         return 1;
     390             : }
     391             : /* }}} */
     392             : 
     393             : /* used by prepare and exec to allocate a statement handle and prepare the SQL */
     394         575 : static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const char *sql, zend_long sql_len, /* {{{ */
     395             :         XSQLDA *out_sqlda, isc_stmt_handle *s, HashTable *named_params TSRMLS_DC)
     396             : {
     397         575 :         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         575 :         zend_long l, pindex = -1;
     400             :                 
     401             :         /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
     402         575 :         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         575 :         if (dbh->auto_commit && !dbh->in_txn) {
     409             :                 /* dbh->transaction_flags = PDO_TRANS_READ_UNCOMMITTED; */
     410             : 
     411         108 :                 if (!firebird_handle_begin(dbh TSRMLS_CC)) {
     412           0 :                         return 0;
     413             :                 }
     414         108 :                 dbh->in_txn = 1;
     415             :         }
     416             :         
     417             :         /* allocate the statement */
     418         575 :         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         575 :         new_sql = c = emalloc(sql_len+1);
     426             :         
     427       17199 :         for (l = in_quote = in_param = 0; l <= sql_len; ++l) {
     428       16624 :                 if ( !(in_quote ^= (sql[l] == '\''))) {
     429       15967 :                         if (!in_param) {
     430       15855 :                                 switch (sql[l]) {
     431             :                                         case ':':
     432          22 :                                                 in_param = 1;
     433          22 :                                                 ppname = pname;
     434          22 :                                                 *ppname++ = sql[l];
     435             :                                         case '?':
     436          45 :                                                 *c++ = '?';
     437          45 :                                                 ++pindex;
     438          45 :                                         continue;
     439             :                                 }
     440             :                         } else {
     441         184 :                                 if ((in_param &= ((sql[l] >= 'A' && sql[l] <= 'Z') || (sql[l] >= 'a' && sql[l] <= 'z')
     442          72 :                                         || (sql[l] >= '0' && sql[l] <= '9') || sql[l] == '_' || sql[l] == '-'))) { 
     443             : 
     444             :                                         
     445          90 :                                         *ppname++ = sql[l];
     446          90 :                                         continue;
     447             :                                 } else {
     448          22 :                                         *ppname++ = 0;
     449          22 :                                         if (named_params) {
     450             :                                                 zval tmp;
     451          22 :                                                 ZVAL_LONG(&tmp, pindex);
     452          22 :                                                 zend_hash_str_update(named_params, pname, (unsigned int)(ppname - pname - 1), &tmp);
     453             :                                         }
     454             :                                 }
     455             :                         }
     456             :                 }
     457       16489 :                 *c++ = sql[l];
     458             :         }
     459             : 
     460             :         /* prepare the statement */
     461         575 :         if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, PDO_FB_DIALECT, out_sqlda)) {
     462         275 :                 RECORD_ERROR(dbh);
     463         275 :                 efree(new_sql);
     464         275 :                 return 0;
     465             :         }
     466             :         
     467         300 :         efree(new_sql);
     468         300 :         return 1;
     469             : }
     470             : /* }}} */
     471             :         
     472             : /* called by PDO to set a driver-specific dbh attribute */
     473           3 : static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC) /* {{{ */
     474             : {
     475           3 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     476             : 
     477           3 :         switch (attr) {
     478             :                 case PDO_ATTR_AUTOCOMMIT:
     479             : 
     480           0 :                         convert_to_boolean(val);
     481             :         
     482             :                         /* ignore if the new value equals the old one */                        
     483           0 :                         if (dbh->auto_commit ^ (Z_TYPE_P(val) == IS_TRUE? 1 : 0)) {
     484           0 :                                 if (dbh->in_txn) {
     485           0 :                                         if (Z_TYPE_P(val) == IS_TRUE) {
     486             :                                                 /* turning on auto_commit with an open transaction is illegal, because
     487             :                                                    we won't know what to do with it */
     488           0 :                                                 H->last_app_error = "Cannot enable auto-commit while a transaction is already open";
     489           0 :                                                 return 0;
     490             :                                         } else {
     491             :                                                 /* close the transaction */
     492           0 :                                                 if (!firebird_handle_commit(dbh TSRMLS_CC)) {
     493           0 :                                                         break;
     494             :                                                 }
     495           0 :                                                 dbh->in_txn = 0;
     496             :                                         }
     497             :                                 }
     498           0 :                                 dbh->auto_commit = Z_TYPE_P(val) == IS_TRUE? 1 : 0;
     499             :                         }
     500           0 :                         return 1;
     501             : 
     502             :                 case PDO_ATTR_FETCH_TABLE_NAMES:
     503           0 :                         convert_to_boolean(val);
     504           0 :                         H->fetch_table_names = Z_TYPE_P(val) == IS_TRUE? 1 : 0;
     505           0 :                         return 1;
     506             : 
     507             :                 case PDO_FB_ATTR_DATE_FORMAT:
     508           0 :                         convert_to_string(val);
     509           0 :                         if (H->date_format) {
     510           0 :                                 efree(H->date_format);
     511             :                         }
     512           0 :                         spprintf(&H->date_format, 0, "%s", Z_STRVAL_P(val)); 
     513           0 :                         return 1;
     514             : 
     515             :                 case PDO_FB_ATTR_TIME_FORMAT:
     516           0 :                         convert_to_string(val);
     517           0 :                         if (H->time_format) {
     518           0 :                                 efree(H->time_format);
     519             :                         }
     520           0 :                         spprintf(&H->time_format, 0, "%s", Z_STRVAL_P(val)); 
     521           0 :                         return 1;
     522             : 
     523             :                 case PDO_FB_ATTR_TIMESTAMP_FORMAT:
     524           0 :                         convert_to_string(val);
     525           0 :                         if (H->timestamp_format) {
     526           0 :                                 efree(H->timestamp_format);
     527             :                         }
     528           0 :                         spprintf(&H->timestamp_format, 0, "%s", Z_STRVAL_P(val)); 
     529           0 :                         return 1;
     530             :         }
     531           3 :         return 0;
     532             : }
     533             : /* }}} */
     534             : 
     535             : /* callback to used to report database server info */
     536           0 : static void firebird_info_cb(void *arg, char const *s) /* {{{ */
     537             : {
     538           0 :         if (arg) {
     539           0 :                 if (*(char*)arg) { /* second call */
     540           0 :                         strcat(arg, " ");
     541             :                 }
     542           0 :                 strcat(arg, s);
     543             :         }
     544           0 : }
     545             : /* }}} */
     546             : 
     547             : /* called by PDO to get a driver-specific dbh attribute */
     548           0 : static int firebird_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC) /* {{{ */
     549             : {
     550           0 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     551             : 
     552           0 :         switch (attr) {
     553             :                 char tmp[512];
     554             :                 
     555             :                 case PDO_ATTR_AUTOCOMMIT:
     556           0 :                         ZVAL_LONG(val,dbh->auto_commit);
     557           0 :                         return 1;
     558             : 
     559             :                 case PDO_ATTR_CONNECTION_STATUS:
     560           0 :                         ZVAL_BOOL(val, !isc_version(&H->db, firebird_info_cb, NULL));
     561           0 :                         return 1;
     562             : 
     563             :                 case PDO_ATTR_CLIENT_VERSION: {
     564             : #if defined(__GNUC__) || defined(PHP_WIN32)
     565           0 :                         info_func_t info_func = NULL;
     566             : #ifdef __GNUC__
     567           0 :                         info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
     568             : #else
     569             :                         HMODULE l = GetModuleHandle("fbclient");
     570             : 
     571             :                         if (!l) {
     572             :                                 break;
     573             :                         }
     574             :                         info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
     575             : #endif
     576           0 :                         if (info_func) {
     577           0 :                                 info_func(tmp);
     578           0 :                                 ZVAL_STRING(val, tmp);
     579             :                         } 
     580             : #else
     581             :                         ZVAL_NULL(val);
     582             : #endif
     583             :                         }
     584           0 :                         return 1;
     585             :                         
     586             :                 case PDO_ATTR_SERVER_VERSION:
     587             :                 case PDO_ATTR_SERVER_INFO:
     588           0 :                         *tmp = 0;
     589             :                         
     590           0 :                         if (!isc_version(&H->db, firebird_info_cb, (void*)tmp)) {
     591           0 :                                 ZVAL_STRING(val, tmp);
     592           0 :                                 return 1;
     593             :                         }
     594             :                         
     595             :                 case PDO_ATTR_FETCH_TABLE_NAMES:
     596           0 :                         ZVAL_BOOL(val, H->fetch_table_names);
     597           0 :                         return 1;
     598             :         }
     599           0 :         return 0;
     600             : }       
     601             : /* }}} */
     602             :         
     603             : /* called by PDO to retrieve driver-specific information about an error that has occurred */
     604           7 : static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
     605             : {       
     606           7 :         pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
     607           7 :         const ISC_STATUS *s = H->isc_status;
     608             :         char buf[400];
     609           7 :         zend_long i = 0, l, sqlcode = isc_sqlcode(s);
     610             : 
     611           7 :         if (sqlcode) {
     612           3 :                 add_next_index_long(info, sqlcode);
     613             : 
     614          18 :                 while ((sizeof(buf)>(i+2))&&(l = fb_interpret(&buf[i],(sizeof(buf)-i-2),&s))) {
     615          12 :                         i += l;
     616          12 :                         strcpy(&buf[i++], " ");
     617             :                 }
     618           3 :                 add_next_index_string(info, buf);
     619           4 :         } else if (H->last_app_error) {
     620           0 :                 add_next_index_long(info, -999);
     621           0 :                 add_next_index_string(info, const_cast(H->last_app_error));
     622             :         }
     623           7 :         return 1;
     624             : }
     625             : /* }}} */
     626             : 
     627             : static struct pdo_dbh_methods firebird_methods = { /* {{{ */
     628             :         firebird_handle_closer,
     629             :         firebird_handle_preparer,
     630             :         firebird_handle_doer,
     631             :         firebird_handle_quoter,
     632             :         firebird_handle_begin,
     633             :         firebird_handle_commit,
     634             :         firebird_handle_rollback,
     635             :         firebird_handle_set_attribute,
     636             :         NULL, /* last_id not supported */
     637             :         pdo_firebird_fetch_error_func,
     638             :         firebird_handle_get_attribute,
     639             :         NULL /* check_liveness */
     640             : };
     641             : /* }}} */
     642             : 
     643             : /* the driver-specific PDO handle constructor */
     644         118 : static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
     645             : {
     646             :         struct pdo_data_src_parser vars[] = {
     647             :                 { "dbname", NULL, 0 },
     648             :                 { "charset",  NULL,   0 },
     649             :                 { "role", NULL,       0 }
     650         118 :         };
     651         118 :         int i, ret = 0;
     652         118 :         short buf_len = 256, dpb_len;
     653             : 
     654         119 :         pdo_firebird_db_handle *H = dbh->driver_data = pecalloc(1,sizeof(*H),dbh->is_persistent);
     655             : 
     656         118 :         php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 3);
     657             :         
     658             :         do {
     659             :                 static char const dpb_flags[] = { 
     660             :                         isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name };
     661         118 :                 char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval };
     662         118 :                 char dpb_buffer[256] = { isc_dpb_version1 }, *dpb;
     663             :                 
     664         118 :                 dpb = dpb_buffer + 1; 
     665             : 
     666             :                 /* loop through all the provided arguments and set dpb fields accordingly */
     667         590 :                 for (i = 0; i < sizeof(dpb_flags); ++i) {
     668         472 :                         if (dpb_values[i] && buf_len > 0) {
     669         236 :                                 dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_flags[i], (unsigned char)strlen(dpb_values[i]),
     670             :                                         dpb_values[i]);
     671         236 :                                 dpb += dpb_len;
     672         236 :                                 buf_len -= dpb_len;
     673             :                         }
     674             :                 }
     675             :                 
     676             :                 /* fire it up baby! */
     677         118 :                 if (isc_attach_database(H->isc_status, 0, vars[0].optval, &H->db,(short)(dpb-dpb_buffer), dpb_buffer)) {
     678           9 :                         break;
     679             :                 }
     680             :                 
     681         109 :                 dbh->methods = &firebird_methods;
     682         109 :                 dbh->native_case = PDO_CASE_UPPER;
     683         109 :                 dbh->alloc_own_columns = 1;
     684             :                 
     685         109 :                 ret = 1;
     686             :                 
     687             :         } while (0);
     688             :                 
     689         472 :         for (i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) {
     690         354 :                 if (vars[i].freeme) {
     691         118 :                         efree(vars[i].optval);
     692             :                 }
     693             :         }
     694             : 
     695         118 :         if (!dbh->methods) {
     696             :                 char errmsg[512];
     697           9 :                 const ISC_STATUS *s = H->isc_status;
     698           9 :                 fb_interpret(errmsg, sizeof(errmsg),&s);
     699           9 :                 zend_throw_exception_ex(php_pdo_get_exception(), H->isc_status[1] TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
     700             :                                 "HY000", H->isc_status[1], errmsg);
     701             :         }
     702             : 
     703         118 :         if (!ret) {
     704           9 :                 firebird_handle_closer(dbh TSRMLS_CC);
     705             :         }
     706             : 
     707         118 :         return ret;
     708             : }
     709             : /* }}} */
     710             : 
     711             : 
     712             : pdo_driver_t pdo_firebird_driver = { /* {{{ */
     713             :         PDO_DRIVER_HEADER(firebird),
     714             :         pdo_firebird_handle_factory
     715             : };
     716             : /* }}} */
     717             : 
     718             : /*
     719             :  * Local variables:
     720             :  * tab-width: 4
     721             :  * c-basic-offset: 4
     722             :  * End:
     723             :  * vim600: noet sw=4 ts=4 fdm=marker
     724             :  * vim<600: noet sw=4 ts=4
     725             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:54 +0000 (2 days ago)

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