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

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:53:54 +0000 (9 days ago)

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