root/ext/pdo_dblib/dblib_stmt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pdo_dblib_get_field_name
  2. pdo_dblib_stmt_cursor_closer
  3. pdo_dblib_stmt_dtor
  4. pdo_dblib_stmt_next_rowset
  5. pdo_dblib_stmt_execute
  6. pdo_dblib_stmt_fetch
  7. pdo_dblib_stmt_describe
  8. pdo_dblib_stmt_get_col
  9. pdo_dblib_stmt_param_hook
  10. pdo_dblib_stmt_get_column_meta

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Author: Wez Furlong <wez@php.net>                                    |
  16   |         Frank M. Kromann <frank@kromann.info>                        |
  17   +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 # include "config.h"
  24 #endif
  25 
  26 #include "php.h"
  27 #include "php_ini.h"
  28 #include "ext/standard/php_string.h"
  29 #include "ext/standard/info.h"
  30 #include "pdo/php_pdo.h"
  31 #include "pdo/php_pdo_driver.h"
  32 #include "php_pdo_dblib.h"
  33 #include "php_pdo_dblib_int.h"
  34 #include "zend_exceptions.h"
  35 
  36 
  37 /* {{{ pdo_dblib_get_field_name
  38  * 
  39  * Return the data type name for a given TDS number
  40  * 
  41  */
  42 static char *pdo_dblib_get_field_name(int type)
  43 {
  44         /* 
  45          * I don't return dbprtype(type) because it does not fully describe the type 
  46          * (example: varchar is reported as char by dbprtype)
  47          * 
  48          * FIX ME: Cache datatypes from server systypes table in pdo_dblib_handle_factory()
  49          *                 to make this future proof.
  50          */
  51          
  52         switch (type) {
  53                 case 31: return "nvarchar";
  54                 case 34: return "image";
  55                 case 35: return "text";
  56                 case 36: return "uniqueidentifier";
  57                 case 37: return "varbinary"; /* & timestamp - Sybase AS12 */
  58                 case 38: return "bigint"; /* & bigintn - Sybase AS12 */
  59                 case 39: return "varchar"; /* & sysname & nvarchar - Sybase AS12 */
  60                 case 40: return "date";
  61                 case 41: return "time";
  62                 case 42: return "datetime2";
  63                 case 43: return "datetimeoffset";
  64                 case 45: return "binary"; /* Sybase AS12 */
  65                 case 47: return "char"; /* & nchar & uniqueidentifierstr Sybase AS12 */
  66                 case 48: return "tinyint";
  67                 case 50: return "bit"; /* Sybase AS12 */
  68                 case 52: return "smallint";
  69                 case 55: return "decimal"; /* Sybase AS12 */
  70                 case 56: return "int";
  71                 case 58: return "smalldatetime";
  72                 case 59: return "real";
  73                 case 60: return "money";
  74                 case 61: return "datetime";
  75                 case 62: return "float";
  76                 case 63: return "numeric"; /* or uint, ubigint, usmallint Sybase AS12 */
  77                 case 98: return "sql_variant";
  78                 case 99: return "ntext";
  79                 case 104: return "bit";
  80                 case 106: return "decimal"; /* decimal n on sybase */
  81                 case 108: return "numeric"; /* numeric n on sybase */
  82                 case 122: return "smallmoney";
  83                 case 127: return "bigint";
  84                 case 165: return "varbinary";
  85                 case 167: return "varchar";
  86                 case 173: return "binary";
  87                 case 175: return "char";
  88                 case 189: return "timestamp";
  89                 case 231: return "nvarchar";
  90                 case 239: return "nchar";
  91                 case 240: return "geometry";
  92                 case 241: return "xml";
  93                 default: return "unknown";
  94         }
  95 }
  96 /* }}} */
  97 
  98 static int pdo_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
  99 {
 100         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 101         pdo_dblib_db_handle *H = S->H;
 102 
 103         /* Cancel any pending results */
 104         dbcancel(H->link);
 105         
 106         return 1;
 107 }
 108 
 109 static int pdo_dblib_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
 110 {
 111         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 112 
 113         efree(S);
 114                 
 115         return 1;
 116 }
 117 
 118 static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
 119 {
 120         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 121         pdo_dblib_db_handle *H = S->H;
 122         RETCODE ret;
 123         
 124         ret = dbresults(H->link);
 125         
 126         if (FAIL == ret) {
 127                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO_DBLIB: dbresults() returned FAIL" TSRMLS_CC);               
 128                 return 0;
 129         }
 130                 
 131         if(NO_MORE_RESULTS == ret) {
 132                 return 0;
 133         }
 134         
 135         stmt->row_count = DBCOUNT(H->link);
 136         stmt->column_count = dbnumcols(H->link);
 137         
 138         return 1;
 139 }
 140 
 141 static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
 142 {
 143         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 144         pdo_dblib_db_handle *H = S->H;
 145         RETCODE ret;
 146         
 147         dbsetuserdata(H->link, (BYTE*) &S->err);
 148         
 149         pdo_dblib_stmt_cursor_closer(stmt TSRMLS_CC);
 150         
 151         if (FAIL == dbcmd(H->link, stmt->active_query_string)) {
 152                 return 0;
 153         }
 154         
 155         if (FAIL == dbsqlexec(H->link)) {
 156                 return 0;
 157         }
 158         
 159         ret = pdo_dblib_stmt_next_rowset(stmt TSRMLS_CC);
 160         
 161         stmt->row_count = DBCOUNT(H->link);
 162         stmt->column_count = dbnumcols(H->link);
 163         
 164         return 1;
 165 }
 166 
 167 static int pdo_dblib_stmt_fetch(pdo_stmt_t *stmt,
 168         enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
 169 {
 170         
 171         RETCODE ret;
 172         
 173         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 174         pdo_dblib_db_handle *H = S->H;
 175         
 176         ret = dbnextrow(H->link);
 177         
 178         if (FAIL == ret) {
 179                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO_DBLIB: dbnextrow() returned FAIL" TSRMLS_CC);
 180                 return 0;
 181         }
 182                 
 183         if(NO_MORE_ROWS == ret) {
 184                 return 0;
 185         }
 186         
 187         return 1;       
 188 }
 189 
 190 static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
 191 {
 192         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 193         pdo_dblib_db_handle *H = S->H;
 194         struct pdo_column_data *col;
 195         char *fname;
 196         
 197         if(colno >= stmt->column_count || colno < 0)  {
 198                 return FAILURE;
 199         }
 200         
 201         col = &stmt->columns[colno];
 202         fname = (char*)dbcolname(H->link, colno+1);
 203 
 204         if (fname && *fname) {
 205                 col->name = estrdup(fname);
 206                 col->namelen = strlen(col->name);
 207         } else {
 208                 col->namelen = spprintf(&col->name, 0, "computed%d", colno);
 209         }
 210         col->maxlen = dbcollen(H->link, colno+1);
 211         col->param_type = PDO_PARAM_STR;
 212                 
 213         return 1;
 214 }
 215 
 216 static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
 217          unsigned long *len, int *caller_frees TSRMLS_DC)
 218 {
 219         
 220         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 221         pdo_dblib_db_handle *H = S->H;
 222         
 223         int coltype;
 224         unsigned int tmp_len;
 225         char *tmp_ptr = NULL;
 226         
 227         coltype = dbcoltype(H->link, colno+1);
 228         
 229         *len = dbdatlen(H->link, colno+1);
 230         *ptr = dbdata(H->link, colno+1);
 231         
 232         if (*len == 0 && *ptr == NULL) {
 233                 return 1;
 234         }
 235         
 236         switch (coltype) {
 237                 case SQLVARBINARY:
 238                 case SQLBINARY:
 239                 case SQLIMAGE:
 240                 case SQLTEXT:
 241                         /* FIXME: Above types should be returned as a stream as they can be VERY large */
 242                 case SQLCHAR:
 243                 case SQLVARCHAR:
 244                         tmp_ptr = emalloc(*len + 1);
 245                         memcpy(tmp_ptr, *ptr, *len);
 246                         tmp_ptr[*len] = '\0';
 247                         *ptr = tmp_ptr;
 248                         break;
 249                 case SQLMONEY:
 250                 case SQLMONEY4:
 251                 case SQLMONEYN: {
 252                         DBFLT8 money_value;
 253                         dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
 254                         *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
 255                         *ptr = tmp_ptr;
 256                         break;
 257                 }
 258                 case SQLUNIQUE: {
 259                         *len = 36+1;
 260                         tmp_ptr = emalloc(*len + 1);
 261 
 262                         /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
 263                         *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
 264                         php_strtoupper(tmp_ptr, *len);
 265                         *ptr = tmp_ptr;
 266                         break;
 267                 }
 268                 case SQLDATETIM4:
 269                 case SQLDATETIME: {
 270                         DBDATETIME dt;
 271                         DBDATEREC di;
 272 
 273                         dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
 274                         dbdatecrack(H->link, &di, &dt);
 275 
 276                         *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
 277 #if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
 278                                         di.year,     di.month,       di.day,        di.hour,     di.minute,     di.second
 279 #else
 280                                         di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
 281 #endif
 282                                 );
 283 
 284                         *ptr = (char*) tmp_ptr;
 285                         break;
 286                 }
 287                 default:
 288                         if (dbwillconvert(coltype, SQLCHAR)) {
 289                                 tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
 290                                 tmp_ptr = emalloc(tmp_len);
 291                                 *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
 292                                 *ptr = tmp_ptr;
 293                         } else {
 294                                 *len = 0; /* FIXME: Silently fails and returns null on conversion errors */
 295                                 *ptr = NULL;
 296                         }
 297         }
 298 
 299         *caller_frees = 1;
 300 
 301         return 1;
 302 }
 303 
 304 static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
 305                 enum pdo_param_event event_type TSRMLS_DC)
 306 {
 307         return 1;
 308 }
 309 
 310 static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
 311 {
 312         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 313         pdo_dblib_db_handle *H = S->H;
 314         DBTYPEINFO* dbtypeinfo;
 315 
 316         if(colno >= stmt->column_count || colno < 0)  {
 317                 return FAILURE;
 318         }
 319 
 320         array_init(return_value);
 321 
 322         dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
 323         
 324         if(!dbtypeinfo) return FAILURE;
 325                 
 326         add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
 327         add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
 328         add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
 329         add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1), 1);
 330         add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)), 1);
 331         add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
 332         add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));
 333 
 334         return 1;
 335 }
 336 
 337 
 338 struct pdo_stmt_methods dblib_stmt_methods = {
 339         pdo_dblib_stmt_dtor,
 340         pdo_dblib_stmt_execute,
 341         pdo_dblib_stmt_fetch,
 342         pdo_dblib_stmt_describe,
 343         pdo_dblib_stmt_get_col,
 344         pdo_dblib_stmt_param_hook,
 345         NULL, /* set attr */
 346         NULL, /* get attr */
 347         pdo_dblib_stmt_get_column_meta, /* meta */
 348         pdo_dblib_stmt_next_rowset, /* nextrow */
 349         pdo_dblib_stmt_cursor_closer
 350 };
 351 

/* [<][>][^][v][top][bottom][index][help] */