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

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:18 +0000 (5 days ago)

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