1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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: George Schlossnagle <george@omniti.com> |
16 : | Wez Furlong <wez@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: mysql_driver.c 272374 2008-12-31 11:17:49Z sebastian $ */
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_mysql.h"
32 : #include "php_pdo_mysql_int.h"
33 : #include <mysqld_error.h>
34 : #include "zend_exceptions.h"
35 :
36 :
37 0 : const char *pdo_mysql_get_sqlstate(unsigned int my_errno) {
38 0 : switch (my_errno) {
39 : /* import auto-generated case: code */
40 : #include "php_pdo_mysql_sqlstate.h"
41 0 : default: return "HY000";
42 : }
43 : }
44 :
45 : int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
46 320 : {
47 320 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
48 : pdo_error_type *pdo_err;
49 : pdo_mysql_error_info *einfo;
50 320 : pdo_mysql_stmt *S = NULL;
51 :
52 320 : if (stmt) {
53 2 : S = (pdo_mysql_stmt*)stmt->driver_data;
54 2 : pdo_err = &stmt->error_code;
55 2 : einfo = &S->einfo;
56 : } else {
57 318 : pdo_err = &dbh->error_code;
58 318 : einfo = &H->einfo;
59 : }
60 :
61 : #if HAVE_MYSQL_STMT_PREPARE
62 320 : if (S && S->stmt) {
63 0 : einfo->errcode = mysql_stmt_errno(S->stmt);
64 : }
65 : else
66 : #endif
67 : {
68 320 : einfo->errcode = mysql_errno(H->server);
69 : }
70 :
71 320 : einfo->file = file;
72 320 : einfo->line = line;
73 :
74 320 : if (einfo->errmsg) {
75 194 : pefree(einfo->errmsg, dbh->is_persistent);
76 194 : einfo->errmsg = NULL;
77 : }
78 :
79 320 : if (einfo->errcode) {
80 320 : if (2014 != einfo->errcode) {
81 320 : einfo->errmsg = pestrdup(mysql_error(H->server), dbh->is_persistent);
82 : } else {
83 0 : einfo->errmsg = pestrdup(
84 : "Cannot execute queries while other unbuffered queries are active. "
85 : "Consider using PDOStatement::fetchAll(). Alternatively, if your code "
86 : "is only ever going to run against mysql, you may enable query "
87 : "buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.",
88 : dbh->is_persistent);
89 : }
90 : } else { /* no error */
91 0 : strcpy(*pdo_err, PDO_ERR_NONE);
92 0 : return 0;
93 : }
94 :
95 : #if HAVE_MYSQL_SQLSTATE
96 : # if HAVE_MYSQL_STMT_PREPARE
97 322 : if (S && S->stmt) {
98 0 : strcpy(*pdo_err, mysql_stmt_sqlstate(S->stmt));
99 : } else
100 : # endif
101 : {
102 320 : strcpy(*pdo_err, mysql_sqlstate(H->server));
103 : }
104 : #else
105 : strcpy(*pdo_err, pdo_mysql_get_sqlstate(einfo->errcode));
106 : #endif
107 :
108 320 : if (!dbh->methods) {
109 0 : zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
110 : *pdo_err, einfo->errcode, einfo->errmsg);
111 : }
112 : /* printf("** [%s:%d] %s %s\n", file, line, *pdo_err, einfo->errmsg); */
113 :
114 320 : return einfo->errcode;
115 : }
116 : /* }}} */
117 :
118 : static int pdo_mysql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
119 29 : {
120 29 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
121 29 : pdo_mysql_error_info *einfo = &H->einfo;
122 :
123 29 : if (stmt) {
124 27 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
125 27 : einfo = &S->einfo;
126 : } else {
127 2 : einfo = &H->einfo;
128 : }
129 :
130 29 : if (einfo->errcode) {
131 3 : add_next_index_long(info, einfo->errcode);
132 3 : add_next_index_string(info, einfo->errmsg, 1);
133 : }
134 :
135 29 : return 1;
136 : }
137 :
138 : static int mysql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
139 123 : {
140 123 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
141 :
142 123 : if (H) {
143 123 : if (H->server) {
144 123 : mysql_close(H->server);
145 123 : H->server = NULL;
146 : }
147 123 : if (H->einfo.errmsg) {
148 123 : pefree(H->einfo.errmsg, dbh->is_persistent);
149 123 : H->einfo.errmsg = NULL;
150 : }
151 123 : pefree(H, dbh->is_persistent);
152 123 : dbh->driver_data = NULL;
153 : }
154 123 : return 0;
155 : }
156 : /* }}} */
157 :
158 : static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
159 146 : {
160 146 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
161 146 : pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt));
162 : #if HAVE_MYSQL_STMT_PREPARE
163 146 : char *nsql = NULL;
164 146 : int nsql_len = 0;
165 : int ret;
166 : int server_version;
167 : #endif
168 :
169 146 : S->H = H;
170 146 : stmt->driver_data = S;
171 146 : stmt->methods = &mysql_stmt_methods;
172 :
173 146 : if (H->emulate_prepare) {
174 141 : goto end;
175 : }
176 :
177 : #if HAVE_MYSQL_STMT_PREPARE
178 5 : server_version = mysql_get_server_version(H->server);
179 5 : if (server_version < 40100) {
180 0 : goto fallback;
181 : }
182 5 : stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
183 5 : ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
184 :
185 5 : if (ret == 1) {
186 : /* query was rewritten */
187 0 : sql = nsql;
188 0 : sql_len = nsql_len;
189 5 : } else if (ret == -1) {
190 : /* failed to parse */
191 0 : strcpy(dbh->error_code, stmt->error_code);
192 0 : return 0;
193 : }
194 :
195 5 : if (!(S->stmt = mysql_stmt_init(H->server))) {
196 0 : pdo_mysql_error(dbh);
197 0 : if (nsql) {
198 0 : efree(nsql);
199 : }
200 0 : return 0;
201 : }
202 :
203 5 : if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
204 : /* TODO: might need to pull statement specific info here? */
205 : /* if the query isn't supported by the protocol, fallback to emulation */
206 0 : if (mysql_errno(H->server) == 1295) {
207 0 : if (nsql) {
208 0 : efree(nsql);
209 : }
210 0 : goto fallback;
211 : }
212 0 : pdo_mysql_error(dbh);
213 0 : if (nsql) {
214 0 : efree(nsql);
215 : }
216 0 : return 0;
217 : }
218 5 : if (nsql) {
219 0 : efree(nsql);
220 : }
221 :
222 5 : S->num_params = mysql_stmt_param_count(S->stmt);
223 :
224 5 : if (S->num_params) {
225 0 : S->params = ecalloc(S->num_params, sizeof(MYSQL_BIND));
226 0 : S->in_null = ecalloc(S->num_params, sizeof(my_bool));
227 0 : S->in_length = ecalloc(S->num_params, sizeof(unsigned long));
228 : }
229 :
230 5 : dbh->alloc_own_columns = 1;
231 :
232 5 : S->max_length = pdo_attr_lval(driver_options, PDO_ATTR_MAX_COLUMN_LEN, 0 TSRMLS_CC);
233 :
234 5 : return 1;
235 :
236 141 : fallback:
237 : #endif
238 141 : end:
239 141 : stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
240 :
241 141 : return 1;
242 : }
243 :
244 : static long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
245 541 : {
246 541 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
247 :
248 541 : if (mysql_real_query(H->server, sql, sql_len)) {
249 318 : pdo_mysql_error(dbh);
250 318 : return -1;
251 : } else {
252 223 : my_ulonglong c = mysql_affected_rows(H->server);
253 223 : if (c == (my_ulonglong) -1) {
254 0 : pdo_mysql_error(dbh);
255 0 : return (H->einfo.errcode ? -1 : 0);
256 : } else {
257 223 : return c;
258 : }
259 : }
260 : }
261 :
262 : static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
263 1 : {
264 1 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
265 1 : char *id = php_pdo_int64_to_str(mysql_insert_id(H->server) TSRMLS_CC);
266 1 : *len = strlen(id);
267 1 : return id;
268 : }
269 :
270 : static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
271 156 : {
272 156 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
273 156 : *quoted = safe_emalloc(2, unquotedlen, 3);
274 156 : *quotedlen = mysql_real_escape_string(H->server, *quoted + 1, unquoted, unquotedlen);
275 156 : (*quoted)[0] =(*quoted)[++*quotedlen] = '\'';
276 156 : (*quoted)[++*quotedlen] = '\0';
277 156 : return 1;
278 : }
279 :
280 : static int mysql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
281 3 : {
282 3 : return 0 <= mysql_handle_doer(dbh, ZEND_STRL("START TRANSACTION") TSRMLS_CC);
283 : }
284 :
285 : static int mysql_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
286 1 : {
287 1 : return 0 <= mysql_handle_doer(dbh, ZEND_STRL("COMMIT") TSRMLS_CC);
288 : }
289 :
290 : static int mysql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
291 2 : {
292 2 : return 0 <= mysql_handle_doer(dbh, ZEND_STRL("ROLLBACK") TSRMLS_CC);
293 : }
294 :
295 : static int mysql_handle_autocommit(pdo_dbh_t *dbh TSRMLS_DC)
296 0 : {
297 0 : if (dbh->auto_commit) {
298 0 : return 0 <= mysql_handle_doer(dbh, ZEND_STRL("SET AUTOCOMMIT=1") TSRMLS_CC);
299 : } else {
300 0 : return 0 <= mysql_handle_doer(dbh, ZEND_STRL("SET AUTOCOMMIT=0") TSRMLS_CC);
301 : }
302 : }
303 :
304 : static int pdo_mysql_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
305 9 : {
306 9 : switch (attr) {
307 : case PDO_ATTR_AUTOCOMMIT:
308 :
309 0 : convert_to_boolean(val);
310 :
311 : /* ignore if the new value equals the old one */
312 0 : if (dbh->auto_commit ^ Z_BVAL_P(val)) {
313 0 : dbh->auto_commit = Z_BVAL_P(val);
314 0 : mysql_handle_autocommit(dbh TSRMLS_CC);
315 : }
316 0 : return 1;
317 :
318 : case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
319 3 : ((pdo_mysql_db_handle *)dbh->driver_data)->buffered = Z_BVAL_P(val);
320 3 : return 1;
321 : case PDO_MYSQL_ATTR_DIRECT_QUERY:
322 : case PDO_ATTR_EMULATE_PREPARES:
323 6 : ((pdo_mysql_db_handle *)dbh->driver_data)->emulate_prepare = Z_BVAL_P(val);
324 6 : return 1;
325 : default:
326 0 : return 0;
327 : }
328 : }
329 :
330 : static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
331 0 : {
332 0 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
333 :
334 0 : switch (attr) {
335 : case PDO_ATTR_CLIENT_VERSION:
336 0 : ZVAL_STRING(return_value, (char *)mysql_get_client_info(), 1);
337 0 : break;
338 :
339 : case PDO_ATTR_SERVER_VERSION:
340 0 : ZVAL_STRING(return_value, (char *)mysql_get_server_info(H->server), 1);
341 0 : break;
342 :
343 : case PDO_ATTR_CONNECTION_STATUS:
344 0 : ZVAL_STRING(return_value, (char *)mysql_get_host_info(H->server), 1);
345 0 : break;
346 :
347 : case PDO_ATTR_SERVER_INFO: {
348 : char *tmp;
349 :
350 0 : if ((tmp = (char *)mysql_stat(H->server))) {
351 0 : ZVAL_STRING(return_value, tmp, 1);
352 : } else {
353 0 : pdo_mysql_error(dbh);
354 0 : return -1;
355 : }
356 : }
357 0 : break;
358 :
359 : case PDO_ATTR_AUTOCOMMIT:
360 0 : ZVAL_LONG(return_value, dbh->auto_commit);
361 0 : return 1;
362 :
363 : case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
364 0 : ZVAL_LONG(return_value, H->buffered);
365 0 : return 1;
366 :
367 : case PDO_MYSQL_ATTR_DIRECT_QUERY:
368 0 : ZVAL_LONG(return_value, H->emulate_prepare);
369 0 : return 1;
370 :
371 : case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE:
372 0 : ZVAL_LONG(return_value, H->max_buffer_size);
373 0 : return 1;
374 :
375 : default:
376 0 : return 0;
377 : }
378 :
379 0 : return 1;
380 : }
381 :
382 : static int pdo_mysql_check_liveness(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
383 0 : {
384 0 : pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
385 : #if MYSQL_VERSION_ID <= 32230
386 : void (*handler) (int);
387 : unsigned int my_errno;
388 : #endif
389 :
390 : #if MYSQL_VERSION_ID > 32230
391 0 : if (mysql_ping(H->server)) {
392 0 : return FAILURE;
393 : }
394 : #else /* no mysql_ping() */
395 : handler=signal(SIGPIPE, SIG_IGN);
396 : mysql_stat(H->server);
397 : switch (mysql_errno(H->server)) {
398 : case CR_SERVER_GONE_ERROR:
399 : /* case CR_SERVER_LOST: I'm not sure this means the same as "gone" for us */
400 : signal(SIGPIPE, handler);
401 : return FAILURE;
402 : default:
403 : break;
404 : }
405 : signal(SIGPIPE, handler);
406 : #endif /* end mysql_ping() */
407 0 : return SUCCESS;
408 : }
409 : /* }}} */
410 :
411 : static struct pdo_dbh_methods mysql_methods = {
412 : mysql_handle_closer,
413 : mysql_handle_preparer,
414 : mysql_handle_doer,
415 : mysql_handle_quoter,
416 : mysql_handle_begin,
417 : mysql_handle_commit,
418 : mysql_handle_rollback,
419 : pdo_mysql_set_attribute,
420 : pdo_mysql_last_insert_id,
421 : pdo_mysql_fetch_error_func,
422 : pdo_mysql_get_attribute,
423 : pdo_mysql_check_liveness
424 : };
425 :
426 : #ifndef PDO_MYSQL_UNIX_ADDR
427 : # ifdef PHP_WIN32
428 : # define PDO_MYSQL_UNIX_ADDR "MySQL"
429 : # else
430 : # define PDO_MYSQL_UNIX_ADDR "/tmp/mysql.sock"
431 : # endif
432 : #endif
433 :
434 : static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
435 124 : {
436 : pdo_mysql_db_handle *H;
437 124 : int i, ret = 0;
438 124 : char *host = NULL, *unix_socket = NULL;
439 124 : unsigned int port = 3306;
440 : char *dbname;
441 : struct pdo_data_src_parser vars[] = {
442 : { "charset", NULL, 0 },
443 : { "dbname", "", 0 },
444 : { "host", "localhost", 0 },
445 : { "port", "3306", 0 },
446 : { "unix_socket", PDO_MYSQL_UNIX_ADDR, 0 },
447 124 : };
448 : int connect_opts = 0
449 : #ifdef CLIENT_MULTI_RESULTS
450 : |CLIENT_MULTI_RESULTS
451 : #endif
452 : #ifdef CLIENT_MULTI_STATEMENTS
453 : |CLIENT_MULTI_STATEMENTS
454 : #endif
455 124 : ;
456 :
457 124 : php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
458 :
459 124 : H = pecalloc(1, sizeof(pdo_mysql_db_handle), dbh->is_persistent);
460 :
461 124 : H->einfo.errcode = 0;
462 124 : H->einfo.errmsg = NULL;
463 :
464 : /* allocate an environment */
465 :
466 : /* handle for the server */
467 124 : if (!(H->server = mysql_init(NULL))) {
468 0 : pdo_mysql_error(dbh);
469 0 : goto cleanup;
470 : }
471 :
472 124 : dbh->driver_data = H;
473 124 : H->max_buffer_size = 1024*1024;
474 124 : H->buffered = H->emulate_prepare = 1;
475 :
476 : /* handle MySQL options */
477 124 : if (driver_options) {
478 0 : long connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC);
479 0 : long local_infile = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_LOCAL_INFILE, 0 TSRMLS_CC);
480 0 : char *init_cmd = NULL, *default_file = NULL, *default_group = NULL;
481 :
482 0 : H->buffered = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_USE_BUFFERED_QUERY, 1 TSRMLS_CC);
483 :
484 0 : H->emulate_prepare = pdo_attr_lval(driver_options,
485 : PDO_MYSQL_ATTR_DIRECT_QUERY, H->emulate_prepare TSRMLS_CC);
486 0 : H->emulate_prepare = pdo_attr_lval(driver_options,
487 : PDO_ATTR_EMULATE_PREPARES, H->emulate_prepare TSRMLS_CC);
488 :
489 0 : H->max_buffer_size = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_MAX_BUFFER_SIZE, H->max_buffer_size TSRMLS_CC);
490 :
491 0 : if (mysql_options(H->server, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout)) {
492 0 : pdo_mysql_error(dbh);
493 0 : goto cleanup;
494 : }
495 :
496 0 : if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) {
497 0 : local_infile = 0;
498 : }
499 : #ifdef MYSQL_OPT_LOCAL_INFILE
500 : if (mysql_options(H->server, MYSQL_OPT_LOCAL_INFILE, (const char *)&local_infile)) {
501 : pdo_mysql_error(dbh);
502 : goto cleanup;
503 : }
504 : #endif
505 : #ifdef MYSQL_OPT_RECONNECT
506 : /* since 5.0.3, the default for this option is 0 if not specified.
507 : * we want the old behaviour */
508 : {
509 : long reconnect = 1;
510 : mysql_options(H->server, MYSQL_OPT_RECONNECT, (const char*)&reconnect);
511 : }
512 : #endif
513 :
514 0 : init_cmd = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_INIT_COMMAND, NULL TSRMLS_CC);
515 0 : if (init_cmd) {
516 0 : if (mysql_options(H->server, MYSQL_INIT_COMMAND, (const char *)init_cmd)) {
517 0 : efree(init_cmd);
518 0 : pdo_mysql_error(dbh);
519 0 : goto cleanup;
520 : }
521 0 : efree(init_cmd);
522 : }
523 :
524 0 : default_file = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_READ_DEFAULT_FILE, NULL TSRMLS_CC);
525 0 : if (default_file) {
526 0 : if (mysql_options(H->server, MYSQL_READ_DEFAULT_FILE, (const char *)default_file)) {
527 0 : efree(default_file);
528 0 : pdo_mysql_error(dbh);
529 0 : goto cleanup;
530 : }
531 0 : efree(default_file);
532 : }
533 :
534 0 : default_group= pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_READ_DEFAULT_GROUP, NULL TSRMLS_CC);
535 0 : if (default_group) {
536 0 : if (mysql_options(H->server, MYSQL_READ_DEFAULT_GROUP, (const char *)default_group)) {
537 0 : efree(default_group);
538 0 : pdo_mysql_error(dbh);
539 0 : goto cleanup;
540 : }
541 0 : efree(default_group);
542 : }
543 : }
544 :
545 124 : dbname = vars[1].optval;
546 124 : host = vars[2].optval;
547 124 : if(vars[3].optval) {
548 124 : port = atoi(vars[3].optval);
549 : }
550 124 : if (vars[2].optval && !strcmp("localhost", vars[2].optval)) {
551 124 : unix_socket = vars[4].optval;
552 : }
553 124 : if (mysql_real_connect(H->server, host, dbh->username, dbh->password, dbname, port, unix_socket, connect_opts) == NULL) {
554 0 : pdo_mysql_error(dbh);
555 0 : goto cleanup;
556 : }
557 :
558 124 : if (!dbh->auto_commit) {
559 0 : mysql_handle_autocommit(dbh TSRMLS_CC);
560 : }
561 :
562 124 : H->attached = 1;
563 :
564 124 : dbh->alloc_own_columns = 1;
565 124 : dbh->max_escaped_char_length = 2;
566 124 : dbh->methods = &mysql_methods;
567 :
568 124 : ret = 1;
569 :
570 124 : cleanup:
571 744 : for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
572 620 : if (vars[i].freeme) {
573 248 : efree(vars[i].optval);
574 : }
575 : }
576 :
577 124 : dbh->methods = &mysql_methods;
578 :
579 124 : return ret;
580 : }
581 : /* }}} */
582 :
583 : pdo_driver_t pdo_mysql_driver = {
584 : PDO_DRIVER_HEADER(mysql),
585 : pdo_mysql_handle_factory
586 : };
587 :
588 : /*
589 : * Local variables:
590 : * tab-width: 4
591 : * c-basic-offset: 4
592 : * End:
593 : * vim600: noet sw=4 ts=4 fdm=marker
594 : * vim<600: noet sw=4 ts=4
595 : */
|