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

LTP GCOV extension - code coverage report
Current view: directory - pdo_firebird - firebird_driver.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 261
Code covered: 62.5 % Executed lines: 163
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:34 +0000 (36 hours ago)

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