1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.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/info.h" 29#include "pdo/php_pdo.h" 30#include "pdo/php_pdo_driver.h" 31#include "php_pdo_dblib.h" 32#include "php_pdo_dblib_int.h" 33#include "zend_exceptions.h" 34 35static int dblib_fetch_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) 36{ 37 pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; 38 pdo_dblib_err *einfo = &H->err; 39 pdo_dblib_stmt *S = NULL; 40 char *message; 41 char *msg; 42 43 if (stmt) { 44 S = (pdo_dblib_stmt*)stmt->driver_data; 45 einfo = &S->err; 46 } 47 48 if (einfo->dberr == SYBESMSG && einfo->lastmsg) { 49 msg = einfo->lastmsg; 50 } else if (einfo->dberr == SYBESMSG && DBLIB_G(err).lastmsg) { 51 msg = DBLIB_G(err).lastmsg; 52 DBLIB_G(err).lastmsg = NULL; 53 } else { 54 msg = einfo->dberrstr; 55 } 56 57 spprintf(&message, 0, "%s [%d] (severity %d) [%s]", 58 msg, einfo->dberr, einfo->severity, stmt ? stmt->active_query_string : ""); 59 60 add_next_index_long(info, einfo->dberr); 61 add_next_index_string(info, message, 0); 62 add_next_index_long(info, einfo->oserr); 63 add_next_index_long(info, einfo->severity); 64 if (einfo->oserrstr) { 65 add_next_index_string(info, einfo->oserrstr, 1); 66 } 67 68 return 1; 69} 70 71 72static int dblib_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) 73{ 74 pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; 75 76 if (H) { 77 if (H->link) { 78 dbclose(H->link); 79 H->link = NULL; 80 } 81 if (H->login) { 82 dbfreelogin(H->login); 83 H->login = NULL; 84 } 85 pefree(H, dbh->is_persistent); 86 dbh->driver_data = NULL; 87 } 88 return 0; 89} 90 91static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC) 92{ 93 pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; 94 pdo_dblib_stmt *S = ecalloc(1, sizeof(*S)); 95 96 S->H = H; 97 stmt->driver_data = S; 98 stmt->methods = &dblib_stmt_methods; 99 stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; 100 S->err.sqlstate = stmt->error_code; 101 102 return 1; 103} 104 105static long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) 106{ 107 pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; 108 RETCODE ret, resret; 109 110 dbsetuserdata(H->link, (BYTE*)&H->err); 111 112 if (FAIL == dbcmd(H->link, sql)) { 113 return -1; 114 } 115 116 if (FAIL == dbsqlexec(H->link)) { 117 return -1; 118 } 119 120 resret = dbresults(H->link); 121 122 if (resret == FAIL) { 123 return -1; 124 } 125 126 ret = dbnextrow(H->link); 127 if (ret == FAIL) { 128 return -1; 129 } 130 131 if (dbnumcols(H->link) <= 0) { 132 return DBCOUNT(H->link); 133 } 134 135 /* throw away any rows it might have returned */ 136 dbcanquery(H->link); 137 138 return DBCOUNT(H->link); 139} 140 141static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC) 142{ 143 pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; 144 char *q; 145 int l = 1; 146 147 *quoted = q = safe_emalloc(2, unquotedlen, 3); 148 *q++ = '\''; 149 150 while (unquotedlen--) { 151 if (*unquoted == '\'') { 152 *q++ = '\''; 153 *q++ = '\''; 154 l += 2; 155 } else { 156 *q++ = *unquoted; 157 ++l; 158 } 159 unquoted++; 160 } 161 162 *q++ = '\''; 163 *q++ = '\0'; 164 *quotedlen = l+1; 165 166 return 1; 167} 168 169static struct pdo_dbh_methods dblib_methods = { 170 dblib_handle_closer, 171 dblib_handle_preparer, 172 dblib_handle_doer, 173 dblib_handle_quoter, 174 NULL, 175 NULL, 176 NULL, 177 NULL, 178 NULL, /* last insert */ 179 dblib_fetch_error, /* fetch error */ 180 NULL, /* get attr */ 181 NULL, /* check liveness */ 182}; 183 184static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) 185{ 186 pdo_dblib_db_handle *H; 187 int i, ret = 0; 188 struct pdo_data_src_parser vars[] = { 189 { "charset", NULL, 0 }, 190 { "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 }, 191 { "host", "127.0.0.1", 0 }, 192 { "dbname", NULL, 0 }, 193 { "secure", NULL, 0 }, /* DBSETLSECURE */ 194 /* TODO: DBSETLVERSION ? */ 195 }; 196 197 php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5); 198 199 H = pecalloc(1, sizeof(*H), dbh->is_persistent); 200 H->login = dblogin(); 201 H->err.sqlstate = dbh->error_code; 202 203 if (!H->login) { 204 goto cleanup; 205 } 206 207 if (dbh->username) { 208 DBSETLUSER(H->login, dbh->username); 209 } 210 if (dbh->password) { 211 DBSETLPWD(H->login, dbh->password); 212 } 213 214#if !PHP_DBLIB_IS_MSSQL 215 if (vars[0].optval) { 216 DBSETLCHARSET(H->login, vars[0].optval); 217 } 218#endif 219 220 DBSETLAPP(H->login, vars[1].optval); 221 222#if PHP_DBLIB_IS_MSSQL 223 dbprocerrhandle(H->login, (EHANDLEFUNC) error_handler); 224 dbprocmsghandle(H->login, (MHANDLEFUNC) msg_handler); 225#endif 226 227 H->link = dbopen(H->login, vars[2].optval); 228 229 if (H->link == NULL) { 230 goto cleanup; 231 } 232 233 /* dblib do not return more than this length from text/image */ 234 DBSETOPT(H->link, DBTEXTLIMIT, "2147483647"); 235 236 /* limit text/image from network */ 237 DBSETOPT(H->link, DBTEXTSIZE, "2147483647"); 238 239 if (vars[3].optval && FAIL == dbuse(H->link, vars[3].optval)) { 240 goto cleanup; 241 } 242 243 ret = 1; 244 dbh->max_escaped_char_length = 2; 245 dbh->alloc_own_columns = 1; 246 247cleanup: 248 for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) { 249 if (vars[i].freeme) { 250 efree(vars[i].optval); 251 } 252 } 253 254 dbh->methods = &dblib_methods; 255 dbh->driver_data = H; 256 257 if (!ret) { 258 zend_throw_exception_ex(php_pdo_get_exception(), DBLIB_G(err).dberr TSRMLS_CC, 259 "SQLSTATE[%s] %s (severity %d)", 260 DBLIB_G(err).sqlstate, 261 DBLIB_G(err).dberrstr, 262 DBLIB_G(err).severity); 263 } 264 265 return ret; 266} 267 268pdo_driver_t pdo_dblib_driver = { 269#if PDO_DBLIB_IS_MSSQL 270 PDO_DRIVER_HEADER(mssql), 271#elif defined(PHP_WIN32) 272 PDO_DRIVER_HEADER(sybase), 273#else 274 PDO_DRIVER_HEADER(dblib), 275#endif 276 pdo_dblib_handle_factory 277}; 278 279