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: 150 365 41.1 %
Date: 2014-07-27 Functions: 9 13 69.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:33 +0000 (3 days ago)

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