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 7                                                        |
   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)
  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)
 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)
 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");
 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)
 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);
 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);
 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, zend_long offset)
 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");
 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)
 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 =  zend_string_init(fname, strlen(fname), 0);
 206         } else {
 207                 char buf[16];
 208                 int len;
 209                 
 210                 len = snprintf(buf, sizeof(buf), "computed%d", colno);
 211                 col->name = zend_string_init(buf, len, 0);
 212         }
 213 
 214         col->maxlen = dbcollen(H->link, colno+1);
 215         col->param_type = PDO_PARAM_STR;
 216 
 217         return 1;
 218 }
 219 
 220 static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
 221          zend_ulong *len, int *caller_frees)
 222 {
 223 
 224         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 225         pdo_dblib_db_handle *H = S->H;
 226 
 227         int coltype;
 228         unsigned int tmp_len;
 229         char *tmp_ptr = NULL;
 230 
 231         coltype = dbcoltype(H->link, colno+1);
 232 
 233         *len = dbdatlen(H->link, colno+1);
 234         *ptr = dbdata(H->link, colno+1);
 235 
 236         if (*len == 0 && *ptr == NULL) {
 237                 return 1;
 238         }
 239 
 240         switch (coltype) {
 241                 case SQLVARBINARY:
 242                 case SQLBINARY:
 243                 case SQLIMAGE:
 244                 case SQLTEXT:
 245                         /* FIXME: Above types should be returned as a stream as they can be VERY large */
 246                 case SQLCHAR:
 247                 case SQLVARCHAR:
 248                         tmp_ptr = emalloc(*len + 1);
 249                         memcpy(tmp_ptr, *ptr, *len);
 250                         tmp_ptr[*len] = '\0';
 251                         *ptr = tmp_ptr;
 252                         break;
 253                 case SQLMONEY:
 254                 case SQLMONEY4:
 255                 case SQLMONEYN: {
 256                         DBFLT8 money_value;
 257                         dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
 258                         *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
 259                         *ptr = tmp_ptr;
 260                         break;
 261                 }
 262                 case SQLUNIQUE: {
 263                         *len = 37;
 264                         tmp_ptr = emalloc(*len + 1);
 265                         *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
 266                         php_strtoupper(tmp_ptr, *len);
 267                         tmp_ptr[36] = '\0';
 268                         *ptr = tmp_ptr;
 269                         break;
 270                 }
 271                 case SQLDATETIM4:
 272                 case SQLDATETIME: {
 273                         DBDATETIME dt;
 274                         DBDATEREC di;
 275 
 276                         dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
 277                         dbdatecrack(H->link, &di, &dt);
 278 
 279                         *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
 280 #if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
 281                                         di.year,     di.month,       di.day,        di.hour,     di.minute,     di.second
 282 #else
 283                                         di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
 284 #endif
 285                                 );
 286 
 287                         *ptr = (char*) tmp_ptr;
 288                         break;
 289                 }
 290                 default:
 291                         if (dbwillconvert(coltype, SQLCHAR)) {
 292                                 tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
 293                                 tmp_ptr = emalloc(tmp_len);
 294                                 *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
 295                                 *ptr = tmp_ptr;
 296                         } else {
 297                                 *len = 0; /* FIXME: Silently fails and returns null on conversion errors */
 298                                 *ptr = NULL;
 299                         }
 300         }
 301 
 302         *caller_frees = 1;
 303 
 304         return 1;
 305 }
 306 
 307 static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
 308                 enum pdo_param_event event_type)
 309 {
 310         return 1;
 311 }
 312 
 313 static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
 314 {
 315         pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
 316         pdo_dblib_db_handle *H = S->H;
 317         DBTYPEINFO* dbtypeinfo;
 318 
 319         if(colno >= stmt->column_count || colno < 0)  {
 320                 return FAILURE;
 321         }
 322 
 323         array_init(return_value);
 324 
 325         dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
 326 
 327         if(!dbtypeinfo) return FAILURE;
 328 
 329         add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
 330         add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
 331         add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
 332         add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
 333         add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
 334         add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
 335         add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));
 336 
 337         return 1;
 338 }
 339 
 340 
 341 struct pdo_stmt_methods dblib_stmt_methods = {
 342         pdo_dblib_stmt_dtor,
 343         pdo_dblib_stmt_execute,
 344         pdo_dblib_stmt_fetch,
 345         pdo_dblib_stmt_describe,
 346         pdo_dblib_stmt_get_col,
 347         pdo_dblib_stmt_param_hook,
 348         NULL, /* set attr */
 349         NULL, /* get attr */
 350         pdo_dblib_stmt_get_column_meta, /* meta */
 351         pdo_dblib_stmt_next_rowset, /* nextrow */
 352         pdo_dblib_stmt_cursor_closer
 353 };
 354 

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