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

Generated by: LCOV version 1.10

Generated at Mon, 15 Dec 2014 17:02:46 +0000 (5 days ago)

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