Annotation of embedaddon/php/ext/pdo_dblib/dblib_driver.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 20: /* $Id$ */
1.1 misho 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:
1.1.1.3 ! misho 35: /* Cache of the server supported datatypes, initialized in handle_factory */
! 36: zval* pdo_dblib_datatypes;
! 37:
1.1 misho 38: static int dblib_fetch_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
39: {
40: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
41: pdo_dblib_err *einfo = &H->err;
42: pdo_dblib_stmt *S = NULL;
43: char *message;
44: char *msg;
45:
46: if (stmt) {
47: S = (pdo_dblib_stmt*)stmt->driver_data;
48: einfo = &S->err;
49: }
50:
51: if (einfo->dberr == SYBESMSG && einfo->lastmsg) {
52: msg = einfo->lastmsg;
53: } else if (einfo->dberr == SYBESMSG && DBLIB_G(err).lastmsg) {
54: msg = DBLIB_G(err).lastmsg;
55: DBLIB_G(err).lastmsg = NULL;
56: } else {
57: msg = einfo->dberrstr;
58: }
59:
60: spprintf(&message, 0, "%s [%d] (severity %d) [%s]",
61: msg, einfo->dberr, einfo->severity, stmt ? stmt->active_query_string : "");
62:
63: add_next_index_long(info, einfo->dberr);
64: add_next_index_string(info, message, 0);
65: add_next_index_long(info, einfo->oserr);
66: add_next_index_long(info, einfo->severity);
67: if (einfo->oserrstr) {
68: add_next_index_string(info, einfo->oserrstr, 1);
69: }
70:
71: return 1;
72: }
73:
74:
75: static int dblib_handle_closer(pdo_dbh_t *dbh TSRMLS_DC)
76: {
77: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
78:
79: if (H) {
80: if (H->link) {
81: dbclose(H->link);
82: H->link = NULL;
83: }
84: if (H->login) {
85: dbfreelogin(H->login);
86: H->login = NULL;
87: }
88: pefree(H, dbh->is_persistent);
89: dbh->driver_data = NULL;
90: }
91: return 0;
92: }
93:
94: static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
95: {
96: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
97: pdo_dblib_stmt *S = ecalloc(1, sizeof(*S));
98:
99: S->H = H;
100: stmt->driver_data = S;
101: stmt->methods = &dblib_stmt_methods;
102: stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
103: S->err.sqlstate = stmt->error_code;
104:
105: return 1;
106: }
107:
108: static long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
109: {
110: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
111: RETCODE ret, resret;
112:
113: dbsetuserdata(H->link, (BYTE*)&H->err);
114:
115: if (FAIL == dbcmd(H->link, sql)) {
116: return -1;
117: }
118:
119: if (FAIL == dbsqlexec(H->link)) {
120: return -1;
121: }
122:
123: resret = dbresults(H->link);
124:
125: if (resret == FAIL) {
126: return -1;
127: }
128:
129: ret = dbnextrow(H->link);
130: if (ret == FAIL) {
131: return -1;
132: }
133:
134: if (dbnumcols(H->link) <= 0) {
135: return DBCOUNT(H->link);
136: }
137:
138: /* throw away any rows it might have returned */
139: dbcanquery(H->link);
140:
141: return DBCOUNT(H->link);
142: }
143:
144: static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
145: {
146: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
147: char *q;
148: int l = 1;
149:
150: *quoted = q = safe_emalloc(2, unquotedlen, 3);
151: *q++ = '\'';
152:
153: while (unquotedlen--) {
154: if (*unquoted == '\'') {
155: *q++ = '\'';
156: *q++ = '\'';
157: l += 2;
158: } else {
159: *q++ = *unquoted;
160: ++l;
161: }
162: unquoted++;
163: }
164:
165: *q++ = '\'';
166: *q++ = '\0';
167: *quotedlen = l+1;
168:
169: return 1;
170: }
171:
1.1.1.2 misho 172: static int pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
173: {
174: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
175: RETCODE ret;
176:
177: if (FAIL == dbcmd(H->link, cmd)) {
178: return 0;
179: }
180:
181: if (FAIL == dbsqlexec(H->link)) {
182: return 0;
183: }
184:
185: return 1;
186: }
187:
188: static int dblib_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
189: {
190: return pdo_dblib_transaction_cmd("BEGIN TRANSACTION", dbh TSRMLS_CC);
191: }
192:
193: static int dblib_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
194: {
195: return pdo_dblib_transaction_cmd("COMMIT TRANSACTION", dbh TSRMLS_CC);
196: }
197:
198: static int dblib_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
199: {
200: return pdo_dblib_transaction_cmd("ROLLBACK TRANSACTION", dbh TSRMLS_CC);
201: }
202:
203: char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
204: {
205: pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
206:
207: RETCODE ret;
208: char *id = NULL;
209:
210: /*
211: * Would use scope_identity() but it's not implemented on Sybase
212: */
213:
214: if (FAIL == dbcmd(H->link, "SELECT @@IDENTITY")) {
215: return NULL;
216: }
217:
218: if (FAIL == dbsqlexec(H->link)) {
219: return NULL;
220: }
221:
222: ret = dbresults(H->link);
223: if (ret == FAIL || ret == NO_MORE_RESULTS) {
224: dbcancel(H->link);
225: return NULL;
226: }
227:
228: ret = dbnextrow(H->link);
229:
230: if (ret == FAIL || ret == NO_MORE_ROWS) {
231: dbcancel(H->link);
232: return NULL;
233: }
234:
235: if (dbdatlen(H->link, 1) == 0) {
236: dbcancel(H->link);
237: return NULL;
238: }
239:
240: id = emalloc(32);
241: *len = dbconvert(NULL, (dbcoltype(H->link, 1)) , (dbdata(H->link, 1)) , (dbdatlen(H->link, 1)), SQLCHAR, id, (DBINT)-1);
242:
243: dbcancel(H->link);
244: return id;
245: }
246:
1.1 misho 247: static struct pdo_dbh_methods dblib_methods = {
248: dblib_handle_closer,
249: dblib_handle_preparer,
250: dblib_handle_doer,
251: dblib_handle_quoter,
1.1.1.2 misho 252: dblib_handle_begin, /* begin */
253: dblib_handle_commit, /* commit */
254: dblib_handle_rollback, /* rollback */
255: NULL, /*set attr */
256: dblib_handle_last_id, /* last insert id */
1.1 misho 257: dblib_fetch_error, /* fetch error */
258: NULL, /* get attr */
259: NULL, /* check liveness */
1.1.1.2 misho 260: NULL, /* get driver methods */
261: NULL, /* request shutdown */
262: NULL /* in transaction */
1.1 misho 263: };
264:
265: static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
266: {
267: pdo_dblib_db_handle *H;
1.1.1.3 ! misho 268: int i, nvars, nvers, ret = 0;
! 269: int *val;
! 270:
! 271: const pdo_dblib_keyval tdsver[] = {
! 272: {"4.2",DBVERSION_42}
! 273: ,{"4.6",DBVERSION_46}
! 274: ,{"5.0",DBVERSION_70} /* FIXME: This does not work with Sybase, but environ will */
! 275: ,{"6.0",DBVERSION_70}
! 276: ,{"7.0",DBVERSION_70}
! 277: ,{"7.1",DBVERSION_71}
! 278: ,{"7.2",DBVERSION_72}
! 279: ,{"8.0",DBVERSION_72}
! 280: ,{"10.0",DBVERSION_100}
! 281: ,{"auto",0} /* Only works with FreeTDS. Other drivers will bork */
! 282:
! 283: };
! 284:
! 285: nvers = sizeof(tdsver)/sizeof(tdsver[0]);
! 286:
1.1 misho 287: struct pdo_data_src_parser vars[] = {
1.1.1.3 ! misho 288: { "charset", NULL, 0 }
! 289: ,{ "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 }
! 290: ,{ "host", "127.0.0.1", 0 }
! 291: ,{ "dbname", NULL, 0 }
! 292: ,{ "secure", NULL, 0 } /* DBSETLSECURE */
! 293: ,{ "version", NULL, 0 } /* DBSETLVERSION */
1.1 misho 294: };
1.1.1.3 ! misho 295:
! 296: nvars = sizeof(vars)/sizeof(vars[0]);
! 297:
! 298: php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, nvars);
1.1 misho 299:
300: H = pecalloc(1, sizeof(*H), dbh->is_persistent);
301: H->login = dblogin();
302: H->err.sqlstate = dbh->error_code;
303:
304: if (!H->login) {
305: goto cleanup;
306: }
307:
1.1.1.3 ! misho 308: DBERRHANDLE(H->login, (EHANDLEFUNC) error_handler);
! 309: DBMSGHANDLE(H->login, (MHANDLEFUNC) msg_handler);
! 310:
! 311: if(vars[5].optval) {
! 312: for(i=0;i<nvers;i++) {
! 313: if(strcmp(vars[5].optval,tdsver[i].key) == 0) {
! 314: if(FAIL==dbsetlversion(H->login, tdsver[i].value)) {
! 315: pdo_raise_impl_error(dbh, NULL, "HY000", "PDO_DBLIB: Failed to set version specified in connection string." TSRMLS_CC);
! 316: goto cleanup;
! 317: }
! 318: break;
! 319: }
! 320: }
! 321:
! 322: if (i==nvers) {
! 323: printf("Invalid version '%s'\n", vars[5].optval);
! 324: pdo_raise_impl_error(dbh, NULL, "HY000", "PDO_DBLIB: Invalid version specified in connection string." TSRMLS_CC);
! 325: goto cleanup; /* unknown version specified */
! 326: }
! 327: }
! 328:
1.1 misho 329: if (dbh->username) {
1.1.1.3 ! misho 330: if(FAIL == DBSETLUSER(H->login, dbh->username)) {
! 331: goto cleanup;
! 332: }
1.1 misho 333: }
1.1.1.3 ! misho 334:
1.1 misho 335: if (dbh->password) {
1.1.1.3 ! misho 336: if(FAIL == DBSETLPWD(H->login, dbh->password)) {
! 337: goto cleanup;
! 338: }
1.1 misho 339: }
340:
341: #if !PHP_DBLIB_IS_MSSQL
342: if (vars[0].optval) {
343: DBSETLCHARSET(H->login, vars[0].optval);
344: }
345: #endif
346:
347: DBSETLAPP(H->login, vars[1].optval);
348:
349: H->link = dbopen(H->login, vars[2].optval);
350:
1.1.1.3 ! misho 351: if (!H->link) {
1.1 misho 352: goto cleanup;
353: }
354:
355: /* dblib do not return more than this length from text/image */
356: DBSETOPT(H->link, DBTEXTLIMIT, "2147483647");
1.1.1.2 misho 357:
1.1 misho 358: /* limit text/image from network */
359: DBSETOPT(H->link, DBTEXTSIZE, "2147483647");
360:
1.1.1.2 misho 361: /* allow double quoted indentifiers */
1.1.1.3 ! misho 362: DBSETOPT(H->link, DBQUOTEDIDENT, "1");
1.1.1.2 misho 363:
1.1.1.3 ! misho 364: if (vars[3].optval) {
! 365: DBSETLDBNAME(H->login, vars[3].optval);
1.1 misho 366: }
367:
368: ret = 1;
369: dbh->max_escaped_char_length = 2;
370: dbh->alloc_own_columns = 1;
371:
1.1.1.3 ! misho 372: #if 0
! 373: /* Cache the supported data types from the servers systypes table */
! 374: if(dbcmd(H->link, "select usertype, name from systypes order by usertype") != FAIL) {
! 375: if(dbsqlexec(H->link) != FAIL) {
! 376: dbresults(H->link);
! 377: while (dbnextrow(H->link) == SUCCESS) {
! 378: val = dbdata(H->link, 1);
! 379: add_index_string(pdo_dblib_datatypes, *val, dbdata(H->link, 2), 1);
! 380: }
! 381: }
! 382: /* Throw out any remaining resultsets */
! 383: dbcancel(H-link);
! 384: }
! 385: #endif
! 386:
! 387:
! 388:
1.1 misho 389: cleanup:
1.1.1.3 ! misho 390: for (i = 0; i < nvars; i++) {
1.1 misho 391: if (vars[i].freeme) {
392: efree(vars[i].optval);
393: }
394: }
395:
396: dbh->methods = &dblib_methods;
397: dbh->driver_data = H;
398:
399: if (!ret) {
400: zend_throw_exception_ex(php_pdo_get_exception(), DBLIB_G(err).dberr TSRMLS_CC,
401: "SQLSTATE[%s] %s (severity %d)",
402: DBLIB_G(err).sqlstate,
403: DBLIB_G(err).dberrstr,
404: DBLIB_G(err).severity);
405: }
406:
407: return ret;
408: }
409:
410: pdo_driver_t pdo_dblib_driver = {
411: #if PDO_DBLIB_IS_MSSQL
412: PDO_DRIVER_HEADER(mssql),
413: #elif defined(PHP_WIN32)
1.1.1.2 misho 414: #define PDO_DBLIB_IS_SYBASE
1.1 misho 415: PDO_DRIVER_HEADER(sybase),
416: #else
417: PDO_DRIVER_HEADER(dblib),
418: #endif
419: pdo_dblib_handle_factory
420: };
421:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>