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
dblib_fetch_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info TSRMLS_DC)35 static 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
dblib_handle_closer(pdo_dbh_t * dbh TSRMLS_DC)72 static 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
dblib_handle_preparer(pdo_dbh_t * dbh,const char * sql,long sql_len,pdo_stmt_t * stmt,zval * driver_options TSRMLS_DC)91 static 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
dblib_handle_doer(pdo_dbh_t * dbh,const char * sql,long sql_len TSRMLS_DC)105 static 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
dblib_handle_quoter(pdo_dbh_t * dbh,const char * unquoted,int unquotedlen,char ** quoted,int * quotedlen,enum pdo_param_type paramtype TSRMLS_DC)141 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)
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
169 static 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
pdo_dblib_handle_factory(pdo_dbh_t * dbh,zval * driver_options TSRMLS_DC)184 static 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
247 cleanup:
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
268 pdo_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