php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
odbc_driver.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#include "php_ini.h"
23#include "ext/standard/info.h"
24#include "ext/pdo/php_pdo.h"
26/* this file actually lives in main/ */
27#include "php_odbc_utils.h"
28#include "php_pdo_odbc.h"
29#include "php_pdo_odbc_int.h"
30#include "zend_exceptions.h"
31
32static void pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
33{
35 pdo_odbc_errinfo *einfo = &H->einfo;
37 zend_string *message = NULL;
38
39 if (stmt) {
40 S = (pdo_odbc_stmt*)stmt->driver_data;
41 einfo = &S->einfo;
42 }
43
44 message = strpprintf(0, "%s (%s[%ld] at %s:%d)",
45 einfo->last_err_msg,
46 einfo->what, (long) einfo->last_error,
47 einfo->file, einfo->line);
48
49 add_next_index_long(info, einfo->last_error);
50 add_next_index_str(info, message);
52}
53
54
55void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line) /* {{{ */
56{
57 SQLRETURN rc;
58 SQLSMALLINT errmsgsize = 0;
59 SQLHANDLE eh;
60 SQLSMALLINT htype, recno = 1;
62 pdo_odbc_errinfo *einfo = &H->einfo;
64 pdo_error_type *pdo_err = &dbh->error_code;
65
66 if (stmt) {
67 S = (pdo_odbc_stmt*)stmt->driver_data;
68
69 einfo = &S->einfo;
70 pdo_err = &stmt->error_code;
71 }
72
73 if (statement == SQL_NULL_HSTMT && S) {
74 statement = S->stmt;
75 }
76
77 if (statement) {
78 htype = SQL_HANDLE_STMT;
79 eh = statement;
80 } else if (H->dbc) {
81 htype = SQL_HANDLE_DBC;
82 eh = H->dbc;
83 } else {
84 htype = SQL_HANDLE_ENV;
85 eh = H->env;
86 }
87
88 rc = SQLGetDiagRec(htype, eh, recno++, (SQLCHAR *) einfo->last_state, &einfo->last_error,
89 (SQLCHAR *) einfo->last_err_msg, sizeof(einfo->last_err_msg)-1, &errmsgsize);
90
91 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
92 errmsgsize = 0;
93 }
94
95 einfo->last_err_msg[errmsgsize] = '\0';
96 einfo->file = file;
97 einfo->line = line;
98 einfo->what = what;
99
100 strcpy(*pdo_err, einfo->last_state);
101/* printf("@@ SQLSTATE[%s] %s\n", *pdo_err, einfo->last_err_msg); */
102 if (!dbh->methods) {
103 zend_throw_exception_ex(php_pdo_get_exception(), einfo->last_error, "SQLSTATE[%s] %s: %d %s",
104 *pdo_err, what, einfo->last_error, einfo->last_err_msg);
105 }
106
107 /* just like a cursor, once you start pulling, you need to keep
108 * going until the end; SQL Server (at least) will mess with the
109 * actual cursor state if you don't finish retrieving all the
110 * diagnostic records (which can be generated by PRINT statements
111 * in the query, for instance). */
112 while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
113 SQLCHAR discard_state[6];
114 SQLCHAR discard_buf[1024];
115 SQLINTEGER code;
116 rc = SQLGetDiagRec(htype, eh, recno++, discard_state, &code,
117 discard_buf, sizeof(discard_buf)-1, &errmsgsize);
118 }
119
120}
121/* }}} */
122
123static void odbc_handle_closer(pdo_dbh_t *dbh)
124{
126
127 if (H->dbc != SQL_NULL_HANDLE) {
128 SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK);
129 SQLDisconnect(H->dbc);
130 SQLFreeHandle(SQL_HANDLE_DBC, H->dbc);
131 H->dbc = NULL;
132 }
133 SQLFreeHandle(SQL_HANDLE_ENV, H->env);
134 H->env = NULL;
135 pefree(H, dbh->is_persistent);
136 dbh->driver_data = NULL;
137}
138
139static bool odbc_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
140{
141 RETCODE rc;
143 pdo_odbc_stmt *S = ecalloc(1, sizeof(*S));
144 enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY;
145 int ret;
146 zend_string *nsql = NULL;
147
148 S->H = H;
149 S->assume_utf8 = H->assume_utf8;
150
151 /* before we prepare, we need to peek at the query; if it uses named parameters,
152 * we want PDO to rewrite them for us */
153 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
154 ret = pdo_parse_params(stmt, sql, &nsql);
155
156 if (ret == 1) {
157 /* query was re-written */
158 sql = nsql;
159 } else if (ret == -1) {
160 /* couldn't grok it */
161 strcpy(dbh->error_code, stmt->error_code);
162 efree(S);
163 return false;
164 }
165
166 rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &S->stmt);
167
168 if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) {
169 efree(S);
170 if (nsql) {
171 zend_string_release(nsql);
172 }
173 pdo_odbc_drv_error("SQLAllocStmt");
174 return false;
175 }
176
177 stmt->driver_data = S;
178
179 cursor_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY);
180 if (cursor_type != PDO_CURSOR_FWDONLY) {
181 rc = SQLSetStmtAttr(S->stmt, SQL_ATTR_CURSOR_SCROLLABLE, (void*)SQL_SCROLLABLE, 0);
182 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
183 pdo_odbc_stmt_error("SQLSetStmtAttr: SQL_ATTR_CURSOR_SCROLLABLE");
184 SQLFreeHandle(SQL_HANDLE_STMT, S->stmt);
185 if (nsql) {
186 zend_string_release(nsql);
187 }
188 return false;
189 }
190 }
191
192 rc = SQLPrepare(S->stmt, (SQLCHAR *) ZSTR_VAL(sql), SQL_NTS);
193 if (nsql) {
194 zend_string_release(nsql);
195 }
196
197 stmt->methods = &odbc_stmt_methods;
198
199 if (rc != SQL_SUCCESS) {
200 pdo_odbc_stmt_error("SQLPrepare");
201 if (rc != SQL_SUCCESS_WITH_INFO) {
202 /* clone error information into the db handle */
203 strcpy(H->einfo.last_err_msg, S->einfo.last_err_msg);
204 H->einfo.file = S->einfo.file;
205 H->einfo.line = S->einfo.line;
206 H->einfo.what = S->einfo.what;
207 strcpy(dbh->error_code, stmt->error_code);
208 }
209 }
210
211 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
212 return false;
213 }
214 return true;
215}
216
217static zend_long odbc_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
218{
220 RETCODE rc;
221 SQLLEN row_count = -1;
222 PDO_ODBC_HSTMT stmt;
223
224 rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &stmt);
225 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
226 pdo_odbc_drv_error("SQLAllocHandle: STMT");
227 return -1;
228 }
229
230 rc = SQLExecDirect(stmt, (SQLCHAR *) ZSTR_VAL(sql), ZSTR_LEN(sql));
231
232 if (rc == SQL_NO_DATA) {
233 /* If SQLExecDirect executes a searched update or delete statement that
234 * does not affect any rows at the data source, the call to
235 * SQLExecDirect returns SQL_NO_DATA. */
236 row_count = 0;
237 goto out;
238 }
239
240 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
241 pdo_odbc_doer_error("SQLExecDirect");
242 goto out;
243 }
244
245 rc = SQLRowCount(stmt, &row_count);
246 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
247 pdo_odbc_doer_error("SQLRowCount");
248 goto out;
249 }
250 if (row_count == -1) {
251 row_count = 0;
252 }
253out:
254 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
255 return row_count;
256}
257
258/* TODO: Do ODBC quoter
259static int odbc_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type param_type )
260{
261 // pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
262 // TODO: figure it out
263 return 0;
264}
265*/
266
267static bool odbc_handle_begin(pdo_dbh_t *dbh)
268{
269 if (dbh->auto_commit) {
270 /* we need to disable auto-commit now, to be able to initiate a transaction */
271 RETCODE rc;
273
274 rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);
275 if (rc != SQL_SUCCESS) {
276 pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = OFF");
277 return false;
278 }
279 }
280 return true;
281}
282
283static bool odbc_handle_commit(pdo_dbh_t *dbh)
284{
286 RETCODE rc;
287
288 rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_COMMIT);
289
290 if (rc != SQL_SUCCESS) {
291 pdo_odbc_drv_error("SQLEndTran: Commit");
292
293 if (rc != SQL_SUCCESS_WITH_INFO) {
294 return false;
295 }
296 }
297
298 if (dbh->auto_commit) {
299 /* turn auto-commit back on again */
300 rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
301 if (rc != SQL_SUCCESS) {
302 pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON");
303 return false;
304 }
305 }
306 return true;
307}
308
309static bool odbc_handle_rollback(pdo_dbh_t *dbh)
310{
312 RETCODE rc;
313
314 rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK);
315
316 if (rc != SQL_SUCCESS) {
317 pdo_odbc_drv_error("SQLEndTran: Rollback");
318
319 if (rc != SQL_SUCCESS_WITH_INFO) {
320 return false;
321 }
322 }
323 if (dbh->auto_commit && H->dbc) {
324 /* turn auto-commit back on again */
325 rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
326 if (rc != SQL_SUCCESS) {
327 pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON");
328 return false;
329 }
330 }
331
332 return true;
333}
334
335static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
336{
338 bool bval;
339
340 switch (attr) {
342 if (!pdo_get_bool_param(&bval, val)) {
343 return false;
344 }
345 H->assume_utf8 = bval;
346 return true;
348 if (!pdo_get_bool_param(&bval, val)) {
349 return false;
350 }
351 if (dbh->in_txn) {
352 pdo_raise_impl_error(dbh, NULL, "HY000", "Cannot change autocommit mode while a transaction is already open");
353 return false;
354 }
355 if (dbh->auto_commit ^ bval) {
356 dbh->auto_commit = bval;
357 RETCODE rc = SQLSetConnectAttr(
358 H->dbc,
359 SQL_ATTR_AUTOCOMMIT,
360 dbh->auto_commit ? (SQLPOINTER) SQL_AUTOCOMMIT_ON : (SQLPOINTER) SQL_AUTOCOMMIT_OFF,
361 SQL_IS_INTEGER
362 );
363 if (rc != SQL_SUCCESS) {
365 dbh->auto_commit ? "SQLSetConnectAttr AUTOCOMMIT = ON" : "SQLSetConnectAttr AUTOCOMMIT = OFF"
366 );
367 return false;
368 }
369 }
370 return true;
371 default:
372 strcpy(H->einfo.last_err_msg, "Unknown Attribute");
373 H->einfo.what = "setAttribute";
374 strcpy(H->einfo.last_state, "IM001");
375 return false;
376 }
377}
378
379static int pdo_odbc_get_info_string(pdo_dbh_t *dbh, SQLUSMALLINT type, zval *val)
380{
381 RETCODE rc;
382 SQLSMALLINT out_len;
383 char buf[256];
385 rc = SQLGetInfo(H->dbc, type, (SQLPOINTER)buf, sizeof(buf), &out_len);
386 /* returning -1 is treated as an error, not as unsupported */
387 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
388 return -1;
389 }
390 ZVAL_STRINGL(val, buf, out_len);
391 return 1;
392}
393
394static int odbc_handle_get_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
395{
397 switch (attr) {
399 ZVAL_STRING(val, "ODBC-" PDO_ODBC_TYPE);
400 return 1;
401
403 return pdo_odbc_get_info_string(dbh, SQL_DBMS_VER, val);
405 return pdo_odbc_get_info_string(dbh, SQL_DBMS_NAME, val);
407 case PDO_ATTR_TIMEOUT:
409 break;
411 ZVAL_BOOL(val, H->assume_utf8);
412 return 1;
415 return 1;
416 }
417 return 0;
418}
419
420static zend_result odbc_handle_check_liveness(pdo_dbh_t *dbh)
421{
422 RETCODE ret;
423 UCHAR d_name[32];
424 SQLSMALLINT len;
425 SQLUINTEGER dead = SQL_CD_FALSE;
427
428 ret = SQLGetConnectAttr(H->dbc, SQL_ATTR_CONNECTION_DEAD, &dead, 0, NULL);
429 if (ret == SQL_SUCCESS && dead == SQL_CD_TRUE) {
430 /* Bail early here, since we know it's gone */
431 return FAILURE;
432 }
433 /*
434 * If the driver doesn't support SQL_ATTR_CONNECTION_DEAD, or if
435 * it returns false (which could be a false positive), fall back
436 * to using SQL_DATA_SOURCE_READ_ONLY, which isn't semantically
437 * correct, but works with many drivers.
438 */
439 ret = SQLGetInfo(H->dbc, SQL_DATA_SOURCE_READ_ONLY, d_name,
440 sizeof(d_name), &len);
441
442 if (ret != SQL_SUCCESS || len == 0) {
443 return FAILURE;
444 }
445 return SUCCESS;
446}
447
448static const struct pdo_dbh_methods odbc_methods = {
449 odbc_handle_closer,
450 odbc_handle_preparer,
451 odbc_handle_doer,
452 NULL, /* quoter */
453 odbc_handle_begin,
454 odbc_handle_commit,
455 odbc_handle_rollback,
456 odbc_handle_set_attr,
457 NULL, /* last id */
458 pdo_odbc_fetch_error_func,
459 odbc_handle_get_attr, /* get attr */
460 odbc_handle_check_liveness, /* check_liveness */
461 NULL, /* get_driver_methods */
462 NULL, /* request_shutdown */
463 NULL, /* in transaction, use PDO's internal tracking mechanism */
464 NULL, /* get_gc */
465 NULL /* scanner */
466};
467
468static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
469{
471 RETCODE rc;
472 int use_direct = 0;
473 zend_ulong cursor_lib;
474
475 H = pecalloc(1, sizeof(*H), dbh->is_persistent);
476
477 dbh->driver_data = H;
478
479 rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &H->env);
480 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
481 pdo_odbc_drv_error("SQLAllocHandle: ENV");
482 goto fail;
483 }
484
485 rc = SQLSetEnvAttr(H->env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
486
487 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
488 pdo_odbc_drv_error("SQLSetEnvAttr: ODBC3");
489 goto fail;
490 }
491
492#ifdef SQL_ATTR_CONNECTION_POOLING
493 if (pdo_odbc_pool_on != SQL_CP_OFF) {
494 rc = SQLSetEnvAttr(H->env, SQL_ATTR_CP_MATCH, (void*)pdo_odbc_pool_mode, 0);
495 if (rc != SQL_SUCCESS) {
496 pdo_odbc_drv_error("SQLSetEnvAttr: SQL_ATTR_CP_MATCH");
497 goto fail;
498 }
499 }
500#endif
501
502 rc = SQLAllocHandle(SQL_HANDLE_DBC, H->env, &H->dbc);
503 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
504 pdo_odbc_drv_error("SQLAllocHandle: DBC");
505 goto fail;
506 }
507
508 rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT,
509 (SQLPOINTER)(intptr_t)(dbh->auto_commit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF), SQL_IS_INTEGER);
510 if (rc != SQL_SUCCESS) {
511 pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT");
512 goto fail;
513 }
514
515 /* set up the cursor library, if needed, or if configured explicitly */
516 cursor_lib = pdo_attr_lval(driver_options, PDO_ODBC_ATTR_USE_CURSOR_LIBRARY, SQL_CUR_USE_IF_NEEDED);
517 rc = SQLSetConnectAttr(H->dbc, SQL_ODBC_CURSORS, (void*)cursor_lib, SQL_IS_INTEGER);
518 if (rc != SQL_SUCCESS && cursor_lib != SQL_CUR_USE_IF_NEEDED) {
519 pdo_odbc_drv_error("SQLSetConnectAttr SQL_ODBC_CURSORS");
520 goto fail;
521 }
522
523 /* a connection string may have = but not ; - i.e. "DSN=PHP" */
524 if (strchr(dbh->data_source, '=')) {
525 SQLCHAR dsnbuf[1024];
526 SQLSMALLINT dsnbuflen;
527
528 use_direct = 1;
529
530 size_t db_len = strlen(dbh->data_source);
531 bool use_uid_arg = dbh->username != NULL && !php_memnistr(dbh->data_source, "uid=", strlen("uid="), dbh->data_source + db_len);
532 bool use_pwd_arg = dbh->password != NULL && !php_memnistr(dbh->data_source, "pwd=", strlen("pwd="), dbh->data_source + db_len);
533
534 if (use_uid_arg || use_pwd_arg) {
535 char *db = (char*) emalloc(db_len + 1);
536 strcpy(db, dbh->data_source);
537 char *db_end = db + db_len;
538 db_end--;
539 if ((unsigned char)*(db_end) == ';') {
540 *db_end = '\0';
541 }
542
543 char *uid = NULL, *pwd = NULL, *dsn = NULL;
544 bool should_quote_uid, should_quote_pwd;
545 size_t new_dsn_size;
546
547 if (use_uid_arg) {
549 if (should_quote_uid) {
550 size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->username);
551 uid = emalloc(estimated_length);
552 php_odbc_connstr_quote(uid, dbh->username, estimated_length);
553 } else {
554 uid = dbh->username;
555 }
556
557 if (!use_pwd_arg) {
558 new_dsn_size = strlen(db) + strlen(uid) + strlen(";UID=;") + 1;
559 dsn = pemalloc(new_dsn_size, dbh->is_persistent);
560 snprintf(dsn, new_dsn_size, "%s;UID=%s;", db, uid);
561 }
562 }
563
564 if (use_pwd_arg) {
566 if (should_quote_pwd) {
567 size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->password);
568 pwd = emalloc(estimated_length);
569 php_odbc_connstr_quote(pwd, dbh->password, estimated_length);
570 } else {
571 pwd = dbh->password;
572 }
573
574 if (!use_uid_arg) {
575 new_dsn_size = strlen(db) + strlen(pwd) + strlen(";PWD=;") + 1;
576 dsn = pemalloc(new_dsn_size, dbh->is_persistent);
577 snprintf(dsn, new_dsn_size, "%s;PWD=%s;", db, pwd);
578 }
579 }
580
581 if (use_uid_arg && use_pwd_arg) {
582 new_dsn_size = strlen(db)
583 + strlen(uid) + strlen(pwd)
584 + strlen(";UID=;PWD=;") + 1;
585 dsn = pemalloc(new_dsn_size, dbh->is_persistent);
586 snprintf(dsn, new_dsn_size, "%s;UID=%s;PWD=%s;", db, uid, pwd);
587 }
588
589 pefree((char*)dbh->data_source, dbh->is_persistent);
590 dbh->data_source = dsn;
591 if (uid && should_quote_uid) {
592 efree(uid);
593 }
594 if (pwd && should_quote_pwd) {
595 efree(pwd);
596 }
597 efree(db);
598 }
599
600 rc = SQLDriverConnect(H->dbc, NULL, (SQLCHAR *) dbh->data_source, strlen(dbh->data_source),
601 dsnbuf, sizeof(dsnbuf)-1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
602 }
603 if (!use_direct) {
604 rc = SQLConnect(H->dbc, (SQLCHAR *) dbh->data_source, SQL_NTS, (SQLCHAR *) dbh->username, SQL_NTS, (SQLCHAR *) dbh->password, SQL_NTS);
605 }
606
607 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
608 pdo_odbc_drv_error(use_direct ? "SQLDriverConnect" : "SQLConnect");
609 goto fail;
610 }
611
612 /* TODO: if we want to play nicely, we should check to see if the driver really supports ODBC v3 or not */
613
614 dbh->methods = &odbc_methods;
615 dbh->alloc_own_columns = 1;
616
617 return 1;
618
619fail:
620 dbh->methods = &odbc_methods;
621 return 0;
622}
623/* }}} */
624
626 PDO_DRIVER_HEADER(odbc),
627 pdo_odbc_handle_factory
628};
size_t len
Definition apprentice.c:174
file(string $filename, int $flags=0, $context=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
zend_ffi_type * type
Definition ffi.c:3812
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
#define S(s, l, r)
Definition hash_gost.c:121
#define SUCCESS
Definition hash_sha3.c:261
#define H(x, y, z)
Definition md5.c:146
const SQL_CUR_USE_IF_NEEDED
Definition odbc.stub.php:61
const SQL_ODBC_CURSORS
Definition odbc.stub.php:51
const pdo_driver_t pdo_odbc_driver
void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line)
Definition odbc_driver.c:55
const struct pdo_stmt_methods odbc_stmt_methods
Definition odbc_stmt.c:866
PDO_API zend_class_entry * php_pdo_get_exception(void)
Definition pdo.c:62
void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, pdo_error_type sqlstate, const char *supp)
Definition pdo_dbh.c:68
PDO_API bool pdo_get_bool_param(bool *bval, zval *value)
Definition pdo_dbh.c:792
#define php_memnistr
Definition php.h:344
int line
Definition php_ffi.h:54
PHPAPI size_t php_odbc_connstr_estimate_quote_length(const char *in_str)
PHPAPI bool php_odbc_connstr_is_quoted(const char *str)
PHPAPI size_t php_odbc_connstr_quote(char *out_str, const char *in_str, size_t out_str_size)
PHPAPI bool php_odbc_connstr_should_quote(const char *str)
#define SQLCHAR
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery)
struct _pdo_dbh_t pdo_dbh_t
#define PDO_DRIVER_HEADER(name)
pdo_cursor_type
@ PDO_CURSOR_FWDONLY
struct _pdo_stmt_t pdo_stmt_t
char pdo_error_type[6]
@ PDO_PLACEHOLDER_POSITIONAL
@ PDO_ATTR_CONNECTION_STATUS
@ PDO_ATTR_SERVER_VERSION
@ PDO_ATTR_SERVER_INFO
@ PDO_ATTR_AUTOCOMMIT
@ PDO_ATTR_PREFETCH
@ PDO_ATTR_CURSOR
@ PDO_ATTR_TIMEOUT
@ PDO_ATTR_CLIENT_VERSION
#define PDO_ODBC_HSTMT
@ PDO_ODBC_ATTR_ASSUME_UTF8
@ PDO_ODBC_ATTR_USE_CURSOR_LIBRARY
#define PDO_ODBC_TYPE
#define pdo_odbc_doer_error(what)
#define pdo_odbc_stmt_error(what)
#define pdo_odbc_drv_error(what)
#define UCHAR(x)
Definition scanf.c:92
bool fail
Definition session.c:1065
#define strpprintf
Definition spprintf.h:30
const char * data_source
unsigned is_persistent
void * driver_data
pdo_error_type error_code
unsigned alloc_own_columns
unsigned auto_commit
const struct pdo_dbh_methods * methods
pdo_error_type error_code
char last_err_msg[SQL_MAX_MESSAGE_LENGTH]
ZEND_API zend_result add_next_index_long(zval *arg, zend_long n)
Definition zend_API.c:2132
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str)
Definition zend_API.c:2177
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define pemalloc(size, persistent)
Definition zend_alloc.h:189
#define pecalloc(nmemb, size, persistent)
Definition zend_alloc.h:200
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
#define snprintf
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_string zend_string
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
@ FAILURE
Definition zend_types.h:61
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define ZVAL_BOOL(z, b)
zval * ret
out($f, $s)