Back to index

php5  5.3.10
dblib_stmt.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Author: Wez Furlong <wez@php.net>                                    |
00016   |         Frank M. Kromann <frank@kromann.info>                        |
00017   +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: dblib_stmt.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 # include "config.h"
00024 #endif
00025 
00026 #include "php.h"
00027 #include "php_ini.h"
00028 #include "ext/standard/php_string.h"
00029 #include "ext/standard/info.h"
00030 #include "pdo/php_pdo.h"
00031 #include "pdo/php_pdo_driver.h"
00032 #include "php_pdo_dblib.h"
00033 #include "php_pdo_dblib_int.h"
00034 #include "zend_exceptions.h"
00035 
00036 static void free_rows(pdo_dblib_stmt *S TSRMLS_DC)
00037 {
00038        int i, j;
00039        
00040        for (i = 0; i < S->nrows; i++) {
00041               for (j = 0; j < S->ncols; j++) {
00042                      pdo_dblib_colval *val = &S->rows[i*S->ncols] + j;
00043                      if (val->data) {
00044                             efree(val->data);
00045                             val->data = NULL;
00046                      }
00047               }
00048        }
00049        efree(S->rows);
00050        S->rows = NULL;
00051        S->nrows = 0;
00052 }
00053 
00054 static int pdo_dblib_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
00055 {
00056        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00057 
00058        if (S->rows) {
00059               free_rows(S TSRMLS_CC);
00060        }
00061        if (S->cols) {
00062               efree(S->cols);
00063        }
00064        efree(S);
00065 
00066        return 1;
00067 }
00068 
00069 static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
00070 {
00071        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00072        pdo_dblib_db_handle *H = S->H;
00073        RETCODE resret, ret;
00074        int i, j;
00075        int arows;
00076        unsigned int size;
00077        
00078        dbsetuserdata(H->link, &S->err);
00079 
00080        if (S->rows) {
00081               /* clean them up */
00082               free_rows(S TSRMLS_CC);
00083        }
00084 
00085        if (FAIL == dbcmd(H->link, stmt->active_query_string)) {
00086               return 0;
00087        }
00088        if (FAIL == dbsqlexec(H->link)) {
00089               return 0;
00090        }
00091        
00092        resret = dbresults(H->link);
00093        if (resret == FAIL) {
00094               return 0;
00095        }
00096 
00097        ret = dbnextrow(H->link);
00098 
00099        stmt->row_count = DBCOUNT(H->link);
00100 
00101     if (ret == NO_MORE_ROWS) {
00102        return 1;
00103     }
00104     
00105        if (!S->cols) {
00106               S->ncols = dbnumcols(H->link);
00107 
00108               if (S->ncols <= 0) {
00109                      return 1;
00110               }
00111 
00112               S->cols = ecalloc(S->ncols, sizeof(pdo_dblib_col));
00113               stmt->column_count = S->ncols;
00114        
00115               for (i = 0, j = 0; i < S->ncols; i++) {
00116                      char *tmp = NULL;
00117 
00118                      S->cols[i].coltype = dbcoltype(H->link, i+1);
00119                      S->cols[i].name = (char*)dbcolname(H->link, i+1);
00120 
00121                      if (!strlen(S->cols[i].name)) {
00122                             if (j) {
00123                                    spprintf(&tmp, 0, "computed%d", j++);
00124                                    strlcpy(S->cols[i].name, tmp, strlen(tmp)+1);
00125                                    efree(tmp);
00126                             } else {
00127                                    S->cols[i].name = "computed";
00128                                    j++;
00129                             }
00130                      }
00131 
00132                      S->cols[i].source = (char*)dbcolsource(H->link, i+1);
00133                      tmp = estrdup(S->cols[i].source ? S->cols[i].source : "");
00134                      S->cols[i].source = tmp;
00135                      efree(tmp);
00136 
00137                      S->cols[i].maxlen = dbcollen(H->link, i+1);
00138               }
00139        }
00140 
00141        arows = 100;
00142        size = S->ncols * sizeof(pdo_dblib_colval);
00143        S->rows = safe_emalloc(arows, size, 0);
00144 
00145        /* let's fetch all the data */
00146        do {
00147               if (S->nrows >= arows) {
00148                      arows *= 2;
00149                      S->rows = erealloc(S->rows, arows * size);
00150               }
00151               for (i = 0; i < S->ncols; i++) {
00152                      pdo_dblib_colval *val = &S->rows[S->nrows * S->ncols + i];
00153 
00154                      if (dbdatlen(H->link, i+1) == 0 && dbdata(H->link, i+1) == NULL) {
00155                             val->len = 0;
00156                             val->data = NULL;
00157                      } else {
00158                             switch (S->cols[i].coltype) {
00159                                    case SQLCHAR:
00160                                    case SQLTEXT:
00161                                    case SQLVARBINARY:
00162                                    case SQLBINARY:
00163                                    case SQLIMAGE:
00164                                           val->len = dbdatlen(H->link, i+1);
00165                                           val->data = emalloc(val->len + 1);
00166                                           memcpy(val->data, dbdata(H->link, i+1), val->len);
00167                                           val->data[val->len] = '\0';
00168                                           break;
00169                                    case SQLMONEY:
00170                                    case SQLMONEY4:
00171                                    case SQLMONEYN: {
00172                                           DBFLT8 money_value;
00173                                           dbconvert(NULL, S->cols[i].coltype, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLFLT8, (LPBYTE)&money_value, 8);
00174                                           val->len = spprintf(&val->data, 0, "%.4f", money_value);
00175                                           }
00176                                           break;
00177 #ifdef SQLUNIQUE
00178                                    case SQLUNIQUE: {
00179 #else
00180                                    case 36: { /* FreeTDS hack, also used by ext/mssql */
00181 #endif
00182                                           val->len = 36+1;
00183                                           val->data = emalloc(val->len + 1);
00184 
00185                                           /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
00186 #ifdef SQLUNIQUE
00187                                           val->len = dbconvert(NULL, SQLUNIQUE, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
00188 #else
00189                                           val->len = dbconvert(NULL, 36, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
00190 #endif
00191                                           php_strtoupper(val->data, val->len);
00192                                           break;
00193                                           }
00194                                    default:
00195                                           if (dbwillconvert(S->cols[i].coltype, SQLCHAR)) {
00196                                                  val->len = 32 + (2 * dbdatlen(H->link, i+1));
00197                                                  val->data = emalloc(val->len);
00198 
00199                                                  val->len = dbconvert(NULL, S->cols[i].coltype, dbdata(H->link, i+1),
00200                                                                dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
00201 
00202                                                  if (val->len >= 0) {
00203                                                         val->data[val->len] = '\0';
00204                                                  }
00205                                           } else {
00206                                                  val->len = 0;
00207                                                  val->data = NULL;
00208                                           }
00209                             }
00210                      }
00211               }
00212 
00213               S->nrows++;
00214 
00215               ret = dbnextrow(H->link);
00216 
00217               if (ret == BUF_FULL) {
00218                      dbclrbuf(H->link, DBLASTROW(H->link)-1);
00219               }
00220        } while (ret != FAIL && ret != NO_MORE_ROWS);
00221 
00222        if (resret != NO_MORE_RESULTS) {
00223               /* there are additional result sets available */
00224               dbresults(H->link);
00225               /* cancel pending rows */
00226               dbcanquery(H->link);
00227 
00228               /* TODO: figure out a sane solution */
00229        }
00230 
00231        S->current = -1;
00232               
00233        return 1;     
00234 }
00235 
00236 static int pdo_dblib_stmt_fetch(pdo_stmt_t *stmt,
00237        enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
00238 {
00239        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00240 
00241        if (!S->rows) {
00242               return 0;
00243        }
00244        
00245        if (++S->current < S->nrows) {
00246               return 1;
00247        }
00248 
00249        return 0;
00250 }
00251 
00252 static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
00253 {
00254        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00255        struct pdo_column_data *col = &stmt->columns[colno];
00256 
00257        if (!S->rows) {
00258               return 0;
00259        }
00260 
00261        col->maxlen = S->cols[colno].maxlen;      
00262        col->namelen = strlen(S->cols[colno].name);      
00263        col->name = estrdup(S->cols[colno].name);
00264        col->param_type = PDO_PARAM_STR;
00265               
00266        return 1;
00267 }
00268 
00269 static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
00270         unsigned long *len, int *caller_frees TSRMLS_DC)
00271 {
00272        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00273        pdo_dblib_colval *val = &S->rows[S->current * S->ncols + colno];
00274 
00275        *ptr = val->data;
00276        *len = val->len;
00277        return 1;
00278 }
00279 
00280 static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
00281               enum pdo_param_event event_type TSRMLS_DC)
00282 {
00283        return 1;
00284 }
00285 
00286 static int dblib_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
00287 {
00288        pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
00289 
00290        if (S->rows) {
00291               free_rows(S TSRMLS_CC);
00292               S->rows = NULL;
00293        }
00294 
00295        return 1;
00296 }
00297 
00298 struct pdo_stmt_methods dblib_stmt_methods = {
00299        pdo_dblib_stmt_dtor,
00300        pdo_dblib_stmt_execute,
00301        pdo_dblib_stmt_fetch,
00302        pdo_dblib_stmt_describe,
00303        pdo_dblib_stmt_get_col,
00304        pdo_dblib_stmt_param_hook,
00305        NULL, /* set attr */
00306        NULL, /* get attr */
00307        NULL, /* meta */
00308        NULL, /* nextrow */
00309        dblib_dblib_stmt_cursor_closer
00310 };
00311