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_odbc - odbc_stmt.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 186 369 50.4 %
Date: 2014-11-22 Functions: 10 13 76.9 %
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.0 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_0.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: Wez Furlong <wez@php.net>                                    |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include "php.h"
      26             : #include "php_ini.h"
      27             : #include "ext/standard/info.h"
      28             : #include "pdo/php_pdo.h"
      29             : #include "pdo/php_pdo_driver.h"
      30             : #include "php_pdo_odbc.h"
      31             : #include "php_pdo_odbc_int.h"
      32             : 
      33             : enum pdo_odbc_conv_result {
      34             :         PDO_ODBC_CONV_NOT_REQUIRED,
      35             :         PDO_ODBC_CONV_OK,
      36             :         PDO_ODBC_CONV_FAIL
      37             : };
      38             : 
      39         290 : static int pdo_odbc_sqltype_is_unicode(pdo_odbc_stmt *S, SWORD sqltype)
      40             : {
      41         290 :         if (!S->assume_utf8) return 0;
      42           0 :         switch (sqltype) {
      43             : #ifdef SQL_WCHAR
      44             :                 case SQL_WCHAR:
      45           0 :                         return 1;
      46             : #endif
      47             : #ifdef SQL_WLONGVARCHAR
      48             :                 case SQL_WLONGVARCHAR:
      49           0 :                         return 1;
      50             : #endif
      51             : #ifdef SQL_WVARCHAR
      52             :                 case SQL_WVARCHAR:
      53           0 :                         return 1;
      54             : #endif
      55             :                 default:
      56           0 :                         return 0;
      57             :         }
      58             : }
      59             : 
      60         148 : static int pdo_odbc_utf82ucs2(pdo_stmt_t *stmt, int is_unicode, const char *buf, 
      61             :         zend_ulong buflen, zend_ulong *outlen)
      62             : {
      63             : #ifdef PHP_WIN32
      64             :         if (is_unicode && buflen) {
      65             :                 pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
      66             :                 DWORD ret;
      67             : 
      68             :                 ret = MultiByteToWideChar(CP_UTF8, 0, buf, buflen, NULL, 0);
      69             :                 if (ret == 0) {
      70             :                         /*printf("%s:%d %d [%d] %.*s\n", __FILE__, __LINE__, GetLastError(), buflen, buflen, buf);*/
      71             :                         return PDO_ODBC_CONV_FAIL;
      72             :                 }
      73             : 
      74             :                 ret *= sizeof(WCHAR);
      75             : 
      76             :                 if (S->convbufsize <= ret) {
      77             :                         S->convbufsize = ret + sizeof(WCHAR);
      78             :                         S->convbuf = erealloc(S->convbuf, S->convbufsize);
      79             :                 }
      80             :                 
      81             :                 ret = MultiByteToWideChar(CP_UTF8, 0, buf, buflen, (LPWSTR)S->convbuf, S->convbufsize / sizeof(WCHAR));
      82             :                 if (ret == 0) {
      83             :                         /*printf("%s:%d %d [%d] %.*s\n", __FILE__, __LINE__, GetLastError(), buflen, buflen, buf);*/
      84             :                         return PDO_ODBC_CONV_FAIL;
      85             :                 }
      86             : 
      87             :                 ret *= sizeof(WCHAR);
      88             :                 *outlen = ret;
      89             :                 return PDO_ODBC_CONV_OK;
      90             :         }
      91             : #endif
      92         148 :         return PDO_ODBC_CONV_NOT_REQUIRED;
      93             : }
      94             : 
      95           0 : static int pdo_odbc_ucs22utf8(pdo_stmt_t *stmt, int is_unicode, const char *buf, 
      96             :         zend_ulong buflen, zend_ulong *outlen)
      97             : {
      98             : #ifdef PHP_WIN32
      99             :         if (is_unicode && buflen) {
     100             :                 pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     101             :                 DWORD ret;
     102             : 
     103             :                 ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), NULL, 0, NULL, NULL);
     104             :                 if (ret == 0) {
     105             :                         return PDO_ODBC_CONV_FAIL;
     106             :                 }
     107             : 
     108             :                 if (S->convbufsize <= ret) {
     109             :                         S->convbufsize = ret + 1;
     110             :                         S->convbuf = erealloc(S->convbuf, S->convbufsize);
     111             :                 }
     112             :                 
     113             :                 ret = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)buf, buflen/sizeof(WCHAR), S->convbuf, S->convbufsize, NULL, NULL);
     114             :                 if (ret == 0) {
     115             :                         return PDO_ODBC_CONV_FAIL;
     116             :                 }
     117             : 
     118             :                 *outlen = ret;
     119             :                 S->convbuf[*outlen] = '\0';
     120             :                 return PDO_ODBC_CONV_OK;
     121             :         }
     122             : #endif
     123           0 :         return PDO_ODBC_CONV_NOT_REQUIRED;
     124             : }
     125             : 
     126         110 : static void free_cols(pdo_stmt_t *stmt, pdo_odbc_stmt *S TSRMLS_DC)
     127             : {
     128         110 :         if (S->cols) {
     129             :                 int i;
     130             : 
     131         240 :                 for (i = 0; i < stmt->column_count; i++) {
     132         140 :                         if (S->cols[i].data) {
     133         140 :                                 efree(S->cols[i].data);
     134             :                         }
     135             :                 }
     136         100 :                 efree(S->cols);
     137         100 :                 S->cols = NULL;
     138             :         }
     139         110 : }
     140             : 
     141         110 : static int odbc_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
     142             : {
     143         110 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     144             : 
     145         110 :         if (S->stmt != SQL_NULL_HANDLE) {
     146         110 :                 if (stmt->executed) {
     147          93 :                         SQLCloseCursor(S->stmt);
     148             :                 }
     149         110 :                 SQLFreeHandle(SQL_HANDLE_STMT, S->stmt);
     150         110 :                 S->stmt = SQL_NULL_HANDLE;
     151             :         }
     152             : 
     153         110 :         free_cols(stmt, S TSRMLS_CC);
     154         110 :         if (S->convbuf) {
     155           0 :                 efree(S->convbuf);
     156             :         }
     157         110 :         efree(S);
     158             : 
     159         110 :         return 1;
     160             : }
     161             : 
     162         181 : static int odbc_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
     163             : {
     164             :         RETCODE rc;
     165         181 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     166         181 :         char *buf = NULL;
     167         181 :         SQLLEN row_count = -1;
     168             : 
     169         181 :         if (stmt->executed) {
     170          56 :                 SQLCloseCursor(S->stmt);
     171             :         }
     172             :         
     173         181 :         rc = SQLExecute(S->stmt);    
     174             : 
     175         585 :         while (rc == SQL_NEED_DATA) {
     176             :                 struct pdo_bound_param_data *param;
     177             : 
     178         223 :                 rc = SQLParamData(S->stmt, (SQLPOINTER*)&param);
     179         223 :                 if (rc == SQL_NEED_DATA) {
     180             :                         php_stream *stm;
     181             :                         int len;
     182             :                         pdo_odbc_param *P;
     183             :                         zval *parameter;
     184             :         
     185         149 :                         P = (pdo_odbc_param*)param->driver_data;
     186         298 :                         if (Z_ISREF(param->parameter)) {
     187          39 :                                 parameter = Z_REFVAL(param->parameter);
     188             :                         } else {
     189         110 :                                 parameter = &param->parameter;
     190             :                         }
     191         149 :                         if (Z_TYPE_P(parameter) != IS_RESOURCE) {
     192             :                                 /* they passed in a string */
     193             :                                 zend_ulong ulen;
     194         148 :                                 convert_to_string(parameter);
     195             : 
     196         296 :                                 switch (pdo_odbc_utf82ucs2(stmt, P->is_unicode, 
     197         148 :                                                         Z_STRVAL_P(parameter),
     198         148 :                                                         Z_STRLEN_P(parameter),
     199         148 :                                                         &ulen)) {
     200             :                                         case PDO_ODBC_CONV_NOT_REQUIRED:
     201         148 :                                                 SQLPutData(S->stmt, Z_STRVAL_P(parameter),
     202         148 :                                                         Z_STRLEN_P(parameter));
     203         148 :                                                 break;
     204             :                                         case PDO_ODBC_CONV_OK:
     205           0 :                                                 SQLPutData(S->stmt, S->convbuf, ulen);
     206           0 :                                                 break;
     207             :                                         case PDO_ODBC_CONV_FAIL:
     208           0 :                                                 pdo_odbc_stmt_error("error converting input string");
     209           0 :                                                 SQLCloseCursor(S->stmt);
     210           0 :                                                 if (buf) {
     211           0 :                                                         efree(buf);
     212             :                                                 }
     213           0 :                                                 return 0;
     214             :                                 }
     215         148 :                                 continue;
     216             :                         }
     217             : 
     218             :                         /* we assume that LOBs are binary and don't need charset
     219             :                          * conversion */
     220             : 
     221           1 :                         php_stream_from_zval_no_verify(stm, parameter);
     222           1 :                         if (!stm) {
     223             :                                 /* shouldn't happen either */
     224           0 :                                 pdo_odbc_stmt_error("input LOB is no longer a stream");
     225           0 :                                 SQLCloseCursor(S->stmt);
     226           0 :                                 if (buf) {
     227           0 :                                         efree(buf);
     228             :                                 }
     229           0 :                                 return 0;
     230             :                         }
     231             : 
     232             :                         /* now suck data from the stream and stick it into the database */
     233           1 :                         if (buf == NULL) {
     234           1 :                                 buf = emalloc(8192);
     235             :                         }
     236             : 
     237             :                         do {
     238           2 :                                 len = php_stream_read(stm, buf, 8192);
     239           2 :                                 if (len == 0) {
     240           1 :                                         break;
     241             :                                 }
     242           1 :                                 SQLPutData(S->stmt, buf, len);
     243           1 :                         } while (1);
     244             :                 }
     245             :         }
     246             : 
     247         181 :         if (buf) {
     248           1 :                 efree(buf);
     249             :         }
     250             : 
     251         181 :         switch (rc) {
     252             :                 case SQL_SUCCESS:
     253         176 :                         break;
     254             :                 case SQL_NO_DATA_FOUND:
     255             :                 case SQL_SUCCESS_WITH_INFO:
     256           0 :                         pdo_odbc_stmt_error("SQLExecute");
     257           0 :                         break;
     258             : 
     259             :                 default:
     260           5 :                         pdo_odbc_stmt_error("SQLExecute");
     261           5 :                         return 0;
     262             :         }
     263             : 
     264         176 :         SQLRowCount(S->stmt, &row_count);
     265         176 :         stmt->row_count = row_count;
     266             : 
     267         176 :         if (!stmt->executed) {
     268             :                 /* do first-time-only definition of bind/mapping stuff */
     269             :                 SQLSMALLINT colcount;
     270             : 
     271             :                 /* how many columns do we have ? */
     272         120 :                 SQLNumResultCols(S->stmt, &colcount);
     273             : 
     274         120 :                 stmt->column_count = (int)colcount;
     275         120 :                 S->cols = ecalloc(colcount, sizeof(pdo_odbc_column));
     276         120 :                 S->going_long = 0;
     277             :         }
     278             : 
     279         176 :         return 1;
     280             : }
     281             : 
     282         974 : static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
     283             :                 enum pdo_param_event event_type TSRMLS_DC)
     284             : {
     285         974 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     286             :         RETCODE rc;
     287         974 :         SWORD sqltype = 0, ctype = 0, scale = 0, nullable = 0;
     288         974 :         SQLULEN precision = 0;
     289             :         pdo_odbc_param *P;
     290             :         zval *parameter;
     291             :         
     292             :         /* we're only interested in parameters for prepared SQL right now */
     293         974 :         if (param->is_param) {
     294             : 
     295         719 :                 switch (event_type) {
     296             :                         case PDO_PARAM_EVT_FETCH_PRE:
     297             :                         case PDO_PARAM_EVT_FETCH_POST:
     298             :                         case PDO_PARAM_EVT_NORMALIZE:
     299             :                                 /* Do nothing */
     300         179 :                                 break;
     301             : 
     302             :                         case PDO_PARAM_EVT_FREE:
     303         120 :                                 P = param->driver_data;
     304         120 :                                 if (P) {
     305         120 :                                         efree(P);
     306             :                                 }
     307         120 :                                 break;
     308             : 
     309             :                         case PDO_PARAM_EVT_ALLOC:
     310             :                         {
     311             :                                 /* figure out what we're doing */
     312         120 :                                 switch (PDO_PARAM_TYPE(param->param_type)) {
     313             :                                         case PDO_PARAM_LOB:
     314           1 :                                                 break;
     315             : 
     316             :                                         case PDO_PARAM_STMT:
     317           0 :                                                 return 0;
     318             :                                         
     319             :                                         default:
     320             :                                                 break;
     321             :                                 }
     322             : 
     323         120 :                                 rc = SQLDescribeParam(S->stmt, (SQLUSMALLINT) param->paramno+1, &sqltype, &precision, &scale, &nullable);
     324         120 :                                 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
     325             :                                         /* MS Access, for instance, doesn't support SQLDescribeParam,
     326             :                                          * so we need to guess */
     327          75 :                                         sqltype = PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB ?
     328             :                                                                         SQL_LONGVARBINARY :
     329             :                                                                         SQL_LONGVARCHAR;
     330          75 :                                         precision = 4000;
     331          75 :                                         scale = 5;
     332          75 :                                         nullable = 1;
     333             : 
     334          75 :                                         if (param->max_value_len > 0) {
     335           0 :                                                 precision = param->max_value_len;
     336             :                                         }
     337             :                                 }
     338         120 :                                 if (sqltype == SQL_BINARY || sqltype == SQL_VARBINARY || sqltype == SQL_LONGVARBINARY) {
     339           0 :                                         ctype = SQL_C_BINARY;
     340             :                                 } else {
     341         120 :                                         ctype = SQL_C_CHAR;
     342             :                                 }
     343             : 
     344         120 :                                 P = emalloc(sizeof(*P));
     345         120 :                                 param->driver_data = P;
     346             : 
     347         120 :                                 P->len = 0; /* is re-populated each EXEC_PRE */
     348         120 :                                 P->outbuf = NULL;
     349             : 
     350         120 :                                 P->is_unicode = pdo_odbc_sqltype_is_unicode(S, sqltype);
     351         120 :                                 if (P->is_unicode) {
     352             :                                         /* avoid driver auto-translation: we'll do it ourselves */
     353           0 :                                         ctype = SQL_C_BINARY;
     354             :                                 }
     355             : 
     356         120 :                                 if ((param->param_type & PDO_PARAM_INPUT_OUTPUT) == PDO_PARAM_INPUT_OUTPUT) {
     357           0 :                                         P->paramtype = SQL_PARAM_INPUT_OUTPUT;
     358         120 :                                 } else if (param->max_value_len <= 0) {
     359         120 :                                         P->paramtype = SQL_PARAM_INPUT;
     360             :                                 } else {
     361           0 :                                         P->paramtype = SQL_PARAM_OUTPUT;
     362             :                                 }
     363             :                                 
     364         120 :                                 if (P->paramtype != SQL_PARAM_INPUT) {
     365           0 :                                         if (PDO_PARAM_TYPE(param->param_type) != PDO_PARAM_NULL) {
     366             :                                                 /* need an explicit buffer to hold result */
     367           0 :                                                 P->len = param->max_value_len > 0 ? param->max_value_len : precision;
     368           0 :                                                 if (P->is_unicode) {
     369           0 :                                                         P->len *= 2;
     370             :                                                 }
     371           0 :                                                 P->outbuf = emalloc(P->len + (P->is_unicode ? 2:1));
     372             :                                         }
     373             :                                 }
     374             :                                 
     375         120 :                                 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB && P->paramtype != SQL_PARAM_INPUT) {
     376           0 :                                         pdo_odbc_stmt_error("Can't bind a lob for output");
     377           0 :                                         return 0;
     378             :                                 }
     379             : 
     380         240 :                                 rc = SQLBindParameter(S->stmt, (SQLUSMALLINT) param->paramno+1,
     381         120 :                                                 P->paramtype, ctype, sqltype, precision, scale,
     382             :                                                 P->paramtype == SQL_PARAM_INPUT ? 
     383             :                                                         (SQLPOINTER)param :
     384             :                                                         P->outbuf,
     385             :                                                 P->len,
     386             :                                                 &P->len
     387             :                                                 );
     388             :         
     389         120 :                                 if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
     390         120 :                                         return 1;
     391             :                                 }
     392           0 :                                 pdo_odbc_stmt_error("SQLBindParameter");
     393           0 :                                 return 0;
     394             :                         }
     395             : 
     396             :                         case PDO_PARAM_EVT_EXEC_PRE:
     397         151 :                                 P = param->driver_data;
     398         302 :                                 if (!Z_ISREF(param->parameter)) {
     399         110 :                                         parameter = &param->parameter;
     400             :                                 } else {
     401          41 :                                         parameter = Z_REFVAL(param->parameter);
     402             :                                 }
     403             : 
     404         151 :                                 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
     405           1 :                                         if (Z_TYPE_P(parameter) == IS_RESOURCE) {
     406             :                                                 php_stream *stm;
     407             :                                                 php_stream_statbuf sb;
     408             : 
     409           1 :                                                 php_stream_from_zval_no_verify(stm, parameter);
     410             : 
     411           1 :                                                 if (!stm) {
     412           0 :                                                         return 0;
     413             :                                                 }
     414             : 
     415           1 :                                                 if (0 == php_stream_stat(stm, &sb)) {
     416           1 :                                                         if (P->outbuf) {
     417             :                                                                 int len, amount;
     418           0 :                                                                 char *ptr = P->outbuf;
     419           0 :                                                                 char *end = P->outbuf + P->len;
     420             : 
     421           0 :                                                                 P->len = 0;
     422             :                                                                 do {
     423           0 :                                                                         amount = end - ptr;
     424           0 :                                                                         if (amount == 0) {
     425           0 :                                                                                 break;
     426             :                                                                         }
     427           0 :                                                                         if (amount > 8192)
     428           0 :                                                                                 amount = 8192;
     429           0 :                                                                         len = php_stream_read(stm, ptr, amount);
     430           0 :                                                                         if (len == 0) {
     431           0 :                                                                                 break;
     432             :                                                                         }
     433           0 :                                                                         ptr += len;
     434           0 :                                                                         P->len += len;
     435           0 :                                                                 } while (1);
     436             : 
     437             :                                                         } else {
     438           1 :                                                                 P->len = SQL_LEN_DATA_AT_EXEC(sb.sb.st_size);
     439             :                                                         }
     440             :                                                 } else {
     441           0 :                                                         if (P->outbuf) {
     442           0 :                                                                 P->len = 0;
     443             :                                                         } else {
     444           0 :                                                                 P->len = SQL_LEN_DATA_AT_EXEC(0);
     445             :                                                         }
     446             :                                                 }
     447             :                                         } else {
     448           0 :                                                 convert_to_string(parameter);
     449           0 :                                                 if (P->outbuf) {
     450           0 :                                                         P->len = Z_STRLEN_P(parameter);
     451           0 :                                                         memcpy(P->outbuf, Z_STRVAL_P(parameter), P->len);
     452             :                                                 } else {
     453           0 :                                                         P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(parameter));
     454             :                                                 }
     455             :                                         }
     456         152 :                                 } else if (Z_TYPE_P(parameter) == IS_NULL || PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL) {
     457           2 :                                         P->len = SQL_NULL_DATA;
     458             :                                 } else {
     459         148 :                                         convert_to_string(parameter);
     460         148 :                                         if (P->outbuf) {
     461             :                                                 zend_ulong ulen;
     462           0 :                                                 switch (pdo_odbc_utf82ucs2(stmt, P->is_unicode,
     463           0 :                                                                 Z_STRVAL_P(parameter),
     464           0 :                                                                 Z_STRLEN_P(parameter),
     465           0 :                                                                 &ulen)) {
     466             :                                                         case PDO_ODBC_CONV_FAIL:
     467             :                                                         case PDO_ODBC_CONV_NOT_REQUIRED:
     468           0 :                                                                 P->len = Z_STRLEN_P(parameter);
     469           0 :                                                                 memcpy(P->outbuf, Z_STRVAL_P(parameter), P->len);
     470           0 :                                                                 break;
     471             :                                                         case PDO_ODBC_CONV_OK:
     472           0 :                                                                 P->len = ulen;
     473           0 :                                                                 memcpy(P->outbuf, S->convbuf, P->len);
     474             :                                                                 break;
     475             :                                                 }
     476             :                                         } else {
     477         148 :                                                 P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(parameter));
     478             :                                         }
     479             :                                 }
     480         151 :                                 return 1;
     481             :                         
     482             :                         case PDO_PARAM_EVT_EXEC_POST:
     483         149 :                                 P = param->driver_data;
     484             : 
     485         149 :                                 if (P->outbuf) {
     486             :                                         zend_ulong ulen;
     487             :                                         char *srcbuf;
     488           0 :                                         zend_ulong srclen = 0;
     489             : 
     490           0 :                                         if (Z_ISREF(param->parameter)) {
     491           0 :                                                 parameter = Z_REFVAL(param->parameter);
     492             :                                         } else {
     493           0 :                                                 parameter = &param->parameter;
     494             :                                         }
     495           0 :                                         zval_ptr_dtor(parameter);
     496           0 :                                         ZVAL_NULL(parameter);
     497             : 
     498           0 :                                         switch (P->len) {
     499             :                                                 case SQL_NULL_DATA:
     500           0 :                                                         break;
     501             :                                                 default:
     502           0 :                                                         switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, P->outbuf, P->len, &ulen)) {
     503             :                                                                 case PDO_ODBC_CONV_FAIL:
     504             :                                                                         /* something fishy, but allow it to come back as binary */
     505             :                                                                 case PDO_ODBC_CONV_NOT_REQUIRED:
     506           0 :                                                                         srcbuf = P->outbuf;
     507           0 :                                                                         srclen = P->len;
     508           0 :                                                                         break;
     509             :                                                                 case PDO_ODBC_CONV_OK:
     510           0 :                                                                         srcbuf = S->convbuf;
     511           0 :                                                                         srclen = ulen;
     512             :                                                                         break;
     513             :                                                         }
     514             :                                                                                 
     515           0 :                                                         ZVAL_NEW_STR(parameter, zend_string_alloc(srclen, 0));
     516           0 :                                                         memcpy(Z_STRVAL_P(parameter), srcbuf, srclen);
     517           0 :                                                         Z_STRVAL_P(parameter)[Z_STRLEN_P(parameter)] = '\0';
     518             :                                         }
     519             :                                 }
     520         149 :                                 return 1;
     521             :                 }
     522             :         }
     523         554 :         return 1;
     524             : }
     525             : 
     526         357 : static int odbc_stmt_fetch(pdo_stmt_t *stmt,
     527             :         enum pdo_fetch_orientation ori, zend_long offset TSRMLS_DC)
     528             : {
     529             :         RETCODE rc;
     530             :         SQLSMALLINT odbcori;
     531         357 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     532             : 
     533         357 :         switch (ori) {
     534         357 :                 case PDO_FETCH_ORI_NEXT:        odbcori = SQL_FETCH_NEXT; break;
     535           0 :                 case PDO_FETCH_ORI_PRIOR:       odbcori = SQL_FETCH_PRIOR; break;
     536           0 :                 case PDO_FETCH_ORI_FIRST:       odbcori = SQL_FETCH_FIRST; break;
     537           0 :                 case PDO_FETCH_ORI_LAST:        odbcori = SQL_FETCH_LAST; break;
     538           0 :                 case PDO_FETCH_ORI_ABS:         odbcori = SQL_FETCH_ABSOLUTE; break;
     539           0 :                 case PDO_FETCH_ORI_REL:         odbcori = SQL_FETCH_RELATIVE; break;
     540             :                 default: 
     541           0 :                         strcpy(stmt->error_code, "HY106");
     542           0 :                         return 0;
     543             :         }
     544         357 :         rc = SQLFetchScroll(S->stmt, odbcori, offset);
     545             : 
     546         357 :         if (rc == SQL_SUCCESS) {
     547         254 :                 return 1;
     548             :         }
     549         103 :         if (rc == SQL_SUCCESS_WITH_INFO) {
     550           0 :                 pdo_odbc_stmt_error("SQLFetchScroll");
     551           0 :                 return 1;
     552             :         }
     553             : 
     554         103 :         if (rc == SQL_NO_DATA) {
     555             :                 /* pdo_odbc_stmt_error("SQLFetchScroll"); */
     556         103 :                 return 0;
     557             :         }
     558             : 
     559           0 :         pdo_odbc_stmt_error("SQLFetchScroll");
     560             : 
     561           0 :         return 0;
     562             : }
     563             : 
     564         170 : static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
     565             : {
     566         170 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     567         170 :         struct pdo_column_data *col = &stmt->columns[colno];
     568             :         RETCODE rc;
     569             :         SWORD   colnamelen;
     570             :         SQLULEN colsize;
     571             :         SQLLEN displaysize;
     572             : 
     573         170 :         rc = SQLDescribeCol(S->stmt, colno+1, S->cols[colno].colname,
     574             :                         sizeof(S->cols[colno].colname)-1, &colnamelen,
     575         170 :                         &S->cols[colno].coltype, &colsize, NULL, NULL);
     576             : 
     577         170 :         if (rc != SQL_SUCCESS) {
     578           0 :                 pdo_odbc_stmt_error("SQLDescribeCol");
     579           0 :                 if (rc != SQL_SUCCESS_WITH_INFO) {
     580           0 :                         return 0;
     581             :                 }
     582             :         }
     583             : 
     584         170 :         rc = SQLColAttribute(S->stmt, colno+1,
     585             :                         SQL_DESC_DISPLAY_SIZE,
     586             :                         NULL, 0, NULL, &displaysize);
     587             : 
     588         170 :         if (rc != SQL_SUCCESS) {
     589           0 :                 pdo_odbc_stmt_error("SQLColAttribute");
     590           0 :                 if (rc != SQL_SUCCESS_WITH_INFO) {
     591           0 :                         return 0;
     592             :                 }
     593             :         }
     594         170 :         colsize = displaysize;
     595             : 
     596         170 :         col->maxlen = S->cols[colno].datalen = colsize;
     597         170 :         col->namelen = colnamelen;
     598         170 :         col->name = estrdup(S->cols[colno].colname);
     599         170 :         S->cols[colno].is_unicode = pdo_odbc_sqltype_is_unicode(S, S->cols[colno].coltype);
     600             : 
     601             :         /* returning data as a string */
     602         170 :         col->param_type = PDO_PARAM_STR;
     603             : 
     604             :         /* tell ODBC to put it straight into our buffer, but only if it
     605             :          * isn't "long" data, and only if we haven't already bound a long
     606             :          * column. */
     607         337 :         if (colsize < 256 && !S->going_long) {
     608         167 :                 S->cols[colno].data = emalloc(colsize+1);
     609         167 :                 S->cols[colno].is_long = 0;
     610             : 
     611         501 :                 rc = SQLBindCol(S->stmt, colno+1,
     612         167 :                         S->cols[colno].is_unicode ? SQL_C_BINARY : SQL_C_CHAR,
     613         167 :                         S->cols[colno].data,
     614         334 :                         S->cols[colno].datalen+1, &S->cols[colno].fetched_len);
     615             : 
     616         167 :                 if (rc != SQL_SUCCESS) {
     617           0 :                         pdo_odbc_stmt_error("SQLBindCol");
     618           0 :                         return 0;
     619             :                 }
     620             :         } else {
     621             :                 /* allocate a smaller buffer to keep around for smaller
     622             :                  * "long" columns */
     623           3 :                 S->cols[colno].data = emalloc(256);
     624           3 :                 S->going_long = 1;
     625           3 :                 S->cols[colno].is_long = 1;
     626             :         }
     627             : 
     628         170 :         return 1;
     629             : }
     630             : 
     631         502 : static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees TSRMLS_DC)
     632             : {
     633         502 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     634         502 :         pdo_odbc_column *C = &S->cols[colno];
     635             :         zend_ulong ulen;
     636             : 
     637             :         /* if it is a column containing "long" data, perform late binding now */
     638         502 :         if (C->is_long) {
     639           2 :                 zend_ulong used = 0;
     640             :                 char *buf;
     641             :                 RETCODE rc;
     642             : 
     643             :                 /* fetch it into C->data, which is allocated with a length
     644             :                  * of 256 bytes; if there is more to be had, we then allocate
     645             :                  * bigger buffer for the caller to free */
     646             : 
     647           2 :                 rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
     648             :                         256, &C->fetched_len);
     649             : 
     650           2 :                 if (rc == SQL_SUCCESS) {
     651             :                         /* all the data fit into our little buffer;
     652             :                          * jump down to the generic bound data case */
     653           2 :                         goto in_data;
     654             :                 }
     655             : 
     656           0 :                 if (rc == SQL_SUCCESS_WITH_INFO) {
     657             :                         /* this is a 'long column'
     658             :                         
     659             :                          read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks
     660             :                          in order into the output buffer
     661             :                         
     662             :                          this loop has to work whether or not SQLGetData() provides the total column length.
     663             :                          calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
     664             :                          for that size would be slower except maybe for extremely long columns.*/
     665             :                         char *buf2;
     666             : 
     667           0 :                         buf2 = emalloc(256);
     668           0 :                         buf = estrndup(C->data, 256);
     669           0 :                         used = 255; /* not 256; the driver NUL terminated the buffer */
     670             :                         
     671             :                         do {
     672           0 :                                 C->fetched_len = 0;
     673             :                                 /* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */
     674           0 :                                 rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len);
     675             :                                 
     676             :                                 /* resize output buffer and reassemble block */
     677           0 :                                 if (rc==SQL_SUCCESS_WITH_INFO) {
     678             :                                         /* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
     679             :                                          states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size)
     680             :                                          (if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */
     681           0 :                                         buf = erealloc(buf, used + 255+1);
     682           0 :                                         memcpy(buf + used, buf2, 255);
     683           0 :                                         used = used + 255;
     684           0 :                                 } else if (rc==SQL_SUCCESS) {
     685           0 :                                         buf = erealloc(buf, used + C->fetched_len+1);
     686           0 :                                         memcpy(buf + used, buf2, C->fetched_len);
     687           0 :                                         used = used + C->fetched_len;
     688             :                                 } else {
     689             :                                         /* includes SQL_NO_DATA */
     690           0 :                                         break;
     691             :                                 }
     692             :                                 
     693           0 :                         } while (1);
     694             :                         
     695           0 :                         efree(buf2);
     696             :                         
     697             :                         /* NULL terminate the buffer once, when finished, for use with the rest of PHP */
     698           0 :                         buf[used] = '\0';
     699             : 
     700           0 :                         *ptr = buf;
     701           0 :                         *caller_frees = 1;
     702           0 :                         *len = used;
     703           0 :                         if (C->is_unicode) {
     704           0 :                                 goto unicode_conv;
     705             :                         }
     706           0 :                         return 1;
     707             :                 }
     708             : 
     709             :                 /* something went caca */
     710           0 :                 *ptr = NULL;
     711           0 :                 *len = 0;
     712           0 :                 return 1;
     713             :         }
     714             : 
     715             : in_data:
     716             :         /* check the indicator to ensure that the data is intact */
     717         502 :         if (C->fetched_len == SQL_NULL_DATA) {
     718             :                 /* A NULL value */
     719           7 :                 *ptr = NULL;
     720           7 :                 *len = 0;
     721           7 :                 return 1;
     722         495 :         } else if (C->fetched_len >= 0) {
     723             :                 /* it was stored perfectly */
     724         495 :                 *ptr = C->data;
     725         495 :                 *len = C->fetched_len;
     726         495 :                 if (C->is_unicode) {
     727           0 :                         goto unicode_conv;
     728             :                 }
     729         495 :                 return 1;
     730             :         } else {
     731             :                 /* no data? */
     732           0 :                 *ptr = NULL;
     733           0 :                 *len = 0;
     734           0 :                 return 1;
     735             :         }
     736             : 
     737             :         unicode_conv:
     738           0 :         switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, *ptr, *len, &ulen)) {
     739             :                 case PDO_ODBC_CONV_FAIL:
     740             :                         /* oh well.  They can have the binary version of it */
     741             :                 case PDO_ODBC_CONV_NOT_REQUIRED:
     742             :                         /* shouldn't happen... */
     743           0 :                         return 1;
     744             : 
     745             :                 case PDO_ODBC_CONV_OK:
     746           0 :                         if (*caller_frees) {
     747           0 :                                 efree(*ptr);
     748             :                         }
     749           0 :                         *ptr = emalloc(ulen + 1);
     750           0 :                         *len = ulen;
     751           0 :                         memcpy(*ptr, S->convbuf, ulen+1);
     752           0 :                         *caller_frees = 1;
     753           0 :                         return 1;
     754             :         }
     755           0 :         return 1;
     756             : }
     757             : 
     758           0 : static int odbc_stmt_set_param(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_DC)
     759             : {
     760             :         SQLRETURN rc;
     761           0 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     762             : 
     763           0 :         switch (attr) {
     764             :                 case PDO_ATTR_CURSOR_NAME:
     765           0 :                         convert_to_string(val);
     766           0 :                         rc = SQLSetCursorName(S->stmt, Z_STRVAL_P(val), Z_STRLEN_P(val));
     767             : 
     768           0 :                         if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
     769           0 :                                 return 1;
     770             :                         }
     771           0 :                         pdo_odbc_stmt_error("SQLSetCursorName");
     772           0 :                         return 0;
     773             : 
     774             :                 case PDO_ODBC_ATTR_ASSUME_UTF8:
     775           0 :                         S->assume_utf8 = zval_is_true(val);
     776           0 :                         return 0;
     777             :                 default:
     778           0 :                         strcpy(S->einfo.last_err_msg, "Unknown Attribute");
     779           0 :                         S->einfo.what = "setAttribute";
     780           0 :                         strcpy(S->einfo.last_state, "IM001");
     781           0 :                         return -1;
     782             :         }
     783             : }
     784             : 
     785           0 : static int odbc_stmt_get_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_DC)
     786             : {
     787             :         SQLRETURN rc;
     788           0 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     789             : 
     790           0 :         switch (attr) {
     791             :                 case PDO_ATTR_CURSOR_NAME:
     792             :                 {
     793             :                         char buf[256];
     794           0 :                         SQLSMALLINT len = 0;
     795           0 :                         rc = SQLGetCursorName(S->stmt, buf, sizeof(buf), &len);
     796             : 
     797           0 :                         if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
     798           0 :                                 ZVAL_STRINGL(val, buf, len);
     799           0 :                                 return 1;
     800             :                         }
     801           0 :                         pdo_odbc_stmt_error("SQLGetCursorName");
     802           0 :                         return 0;
     803             :                 }
     804             : 
     805             :                 case PDO_ODBC_ATTR_ASSUME_UTF8:
     806           0 :                         ZVAL_BOOL(val, S->assume_utf8 ? 1 : 0);
     807           0 :                         return 0;
     808             : 
     809             :                 default:
     810           0 :                         strcpy(S->einfo.last_err_msg, "Unknown Attribute");
     811           0 :                         S->einfo.what = "getAttribute";
     812           0 :                         strcpy(S->einfo.last_state, "IM001");
     813           0 :                         return -1;
     814             :         }
     815             : }
     816             : 
     817          27 : static int odbc_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
     818             : {
     819             :         SQLRETURN rc;
     820             :         SQLSMALLINT colcount;
     821          27 :         pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
     822             : 
     823             :         /* NOTE: can't guarantee that output or input/output parameters
     824             :          * are set until this fella returns SQL_NO_DATA, according to
     825             :          * MSDN ODBC docs */
     826          27 :         rc = SQLMoreResults(S->stmt);
     827             : 
     828          27 :         if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
     829          27 :                 return 0;
     830             :         }
     831             : 
     832           0 :         free_cols(stmt, S TSRMLS_CC);
     833             :         /* how many columns do we have ? */
     834           0 :         SQLNumResultCols(S->stmt, &colcount);
     835           0 :         stmt->column_count = (int)colcount;
     836           0 :         S->cols = ecalloc(colcount, sizeof(pdo_odbc_column));
     837           0 :         S->going_long = 0;
     838             : 
     839           0 :         return 1;
     840             : }
     841             : 
     842             : struct pdo_stmt_methods odbc_stmt_methods = {
     843             :         odbc_stmt_dtor,
     844             :         odbc_stmt_execute,
     845             :         odbc_stmt_fetch,
     846             :         odbc_stmt_describe,
     847             :         odbc_stmt_get_col,
     848             :         odbc_stmt_param_hook,
     849             :         odbc_stmt_set_param,
     850             :         odbc_stmt_get_attr, /* get attr */
     851             :         NULL, /* get column meta */
     852             :         odbc_stmt_next_rowset
     853             : };
     854             : 
     855             : /*
     856             :  * Local variables:
     857             :  * tab-width: 4
     858             :  * c-basic-offset: 4
     859             :  * End:
     860             :  * vim600: noet sw=4 ts=4 fdm=marker
     861             :  * vim<600: noet sw=4 ts=4
     862             :  */

Generated by: LCOV version 1.10

Generated at Sat, 22 Nov 2014 23:01:21 +0000 (4 days ago)

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