1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 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 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | /* $Id$ */ |
20 | |
21 | #ifndef PHP_PDO_DRIVER_H |
22 | #define PHP_PDO_DRIVER_H |
23 | |
24 | #include "php_pdo.h" |
25 | |
26 | /* forward declarations */ |
27 | typedef struct _pdo_dbh_t pdo_dbh_t; |
28 | typedef struct _pdo_stmt_t pdo_stmt_t; |
29 | struct pdo_bound_param_data; |
30 | |
31 | #ifdef PHP_WIN32 |
32 | typedef __int64 pdo_int64_t; |
33 | typedef unsigned __int64 pdo_uint64_t; |
34 | #else |
35 | typedef long long int pdo_int64_t; |
36 | typedef unsigned long long int pdo_uint64_t; |
37 | #endif |
38 | PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC); |
39 | |
40 | #ifndef TRUE |
41 | # define TRUE 1 |
42 | #endif |
43 | #ifndef FALSE |
44 | # define FALSE 0 |
45 | #endif |
46 | |
47 | #define PDO_DRIVER_API 20080721 |
48 | |
49 | enum pdo_param_type { |
50 | PDO_PARAM_NULL, |
51 | |
52 | /* int as in long (the php native int type). |
53 | * If you mark a column as an int, PDO expects get_col to return |
54 | * a pointer to a long */ |
55 | PDO_PARAM_INT, |
56 | |
57 | /* get_col ptr should point to start of the string buffer */ |
58 | PDO_PARAM_STR, |
59 | |
60 | /* get_col: when len is 0 ptr should point to a php_stream *, |
61 | * otherwise it should behave like a string. Indicate a NULL field |
62 | * value by setting the ptr to NULL */ |
63 | PDO_PARAM_LOB, |
64 | |
65 | /* get_col: will expect the ptr to point to a new PDOStatement object handle, |
66 | * but this isn't wired up yet */ |
67 | PDO_PARAM_STMT, /* hierarchical result set */ |
68 | |
69 | /* get_col ptr should point to a zend_bool */ |
70 | PDO_PARAM_BOOL, |
71 | |
72 | /* get_col ptr should point to a zval* |
73 | and the driver is responsible for adding correct type information to get_column_meta() |
74 | */ |
75 | PDO_PARAM_ZVAL, |
76 | |
77 | /* magic flag to denote a parameter as being input/output */ |
78 | PDO_PARAM_INPUT_OUTPUT = 0x80000000 |
79 | }; |
80 | |
81 | #define PDO_PARAM_FLAGS 0xFFFF0000 |
82 | |
83 | #define PDO_PARAM_TYPE(x) ((x) & ~PDO_PARAM_FLAGS) |
84 | |
85 | enum pdo_fetch_type { |
86 | PDO_FETCH_USE_DEFAULT, |
87 | PDO_FETCH_LAZY, |
88 | PDO_FETCH_ASSOC, |
89 | PDO_FETCH_NUM, |
90 | PDO_FETCH_BOTH, |
91 | PDO_FETCH_OBJ, |
92 | PDO_FETCH_BOUND, /* return true/false only; rely on bound columns */ |
93 | PDO_FETCH_COLUMN, /* fetch a numbered column only */ |
94 | PDO_FETCH_CLASS, /* create an instance of named class, call ctor and set properties */ |
95 | PDO_FETCH_INTO, /* fetch row into an existing object */ |
96 | PDO_FETCH_FUNC, /* fetch into function and return its result */ |
97 | PDO_FETCH_NAMED, /* like PDO_FETCH_ASSOC, but can handle duplicate names */ |
98 | PDO_FETCH_KEY_PAIR, /* fetch into an array where the 1st column is a key and all subsequent columns are values */ |
99 | PDO_FETCH__MAX /* must be last */ |
100 | }; |
101 | |
102 | #define PDO_FETCH_FLAGS 0xFFFF0000 /* fetchAll() modes or'd to PDO_FETCH_XYZ */ |
103 | #define PDO_FETCH_GROUP 0x00010000 /* fetch into groups */ |
104 | #define PDO_FETCH_UNIQUE 0x00030000 /* fetch into groups assuming first col is unique */ |
105 | #define PDO_FETCH_CLASSTYPE 0x00040000 /* fetch class gets its class name from 1st column */ |
106 | #define PDO_FETCH_SERIALIZE 0x00080000 /* fetch class instances by calling serialize */ |
107 | #define PDO_FETCH_PROPS_LATE 0x00100000 /* fetch props after calling ctor */ |
108 | |
109 | /* fetch orientation for scrollable cursors */ |
110 | enum pdo_fetch_orientation { |
111 | PDO_FETCH_ORI_NEXT, /* default: fetch the next available row */ |
112 | PDO_FETCH_ORI_PRIOR, /* scroll back to prior row and fetch that */ |
113 | PDO_FETCH_ORI_FIRST, /* scroll to the first row and fetch that */ |
114 | PDO_FETCH_ORI_LAST, /* scroll to the last row and fetch that */ |
115 | PDO_FETCH_ORI_ABS, /* scroll to an absolute numbered row and fetch that */ |
116 | PDO_FETCH_ORI_REL /* scroll relative to the current row, and fetch that */ |
117 | }; |
118 | |
119 | enum pdo_attribute_type { |
120 | PDO_ATTR_AUTOCOMMIT, /* use to turn on or off auto-commit mode */ |
121 | PDO_ATTR_PREFETCH, /* configure the prefetch size for drivers that support it. Size is in KB */ |
122 | PDO_ATTR_TIMEOUT, /* connection timeout in seconds */ |
123 | PDO_ATTR_ERRMODE, /* control how errors are handled */ |
124 | PDO_ATTR_SERVER_VERSION, /* database server version */ |
125 | PDO_ATTR_CLIENT_VERSION, /* client library version */ |
126 | PDO_ATTR_SERVER_INFO, /* server information */ |
127 | PDO_ATTR_CONNECTION_STATUS, /* connection status */ |
128 | PDO_ATTR_CASE, /* control case folding for portability */ |
129 | PDO_ATTR_CURSOR_NAME, /* name a cursor for use in "WHERE CURRENT OF <name>" */ |
130 | PDO_ATTR_CURSOR, /* cursor type */ |
131 | PDO_ATTR_ORACLE_NULLS, /* convert empty strings to NULL */ |
132 | PDO_ATTR_PERSISTENT, /* pconnect style connection */ |
133 | PDO_ATTR_STATEMENT_CLASS, /* array(classname, array(ctor_args)) to specify the class of the constructed statement */ |
134 | PDO_ATTR_FETCH_TABLE_NAMES, /* include table names in the column names, where available */ |
135 | PDO_ATTR_FETCH_CATALOG_NAMES, /* include the catalog/db name names in the column names, where available */ |
136 | PDO_ATTR_DRIVER_NAME, /* name of the driver (as used in the constructor) */ |
137 | PDO_ATTR_STRINGIFY_FETCHES, /* converts integer/float types to strings during fetch */ |
138 | PDO_ATTR_MAX_COLUMN_LEN, /* make database calculate maximum length of data found in a column */ |
139 | PDO_ATTR_DEFAULT_FETCH_MODE, /* Set the default fetch mode */ |
140 | PDO_ATTR_EMULATE_PREPARES, /* use query emulation rather than native */ |
141 | |
142 | /* this defines the start of the range for driver specific options. |
143 | * Drivers should define their own attribute constants beginning with this |
144 | * value. */ |
145 | PDO_ATTR_DRIVER_SPECIFIC = 1000 |
146 | }; |
147 | |
148 | enum pdo_cursor_type { |
149 | PDO_CURSOR_FWDONLY, /* forward only cursor (default) */ |
150 | PDO_CURSOR_SCROLL /* scrollable cursor */ |
151 | }; |
152 | |
153 | /* SQL-92 SQLSTATE error codes. |
154 | |
155 | The character string value returned for an SQLSTATE consists of a two-character |
156 | class value followed by a three-character subclass value. A class value of 01 |
157 | indicates a warning and is accompanied by a return code of |
158 | SQL_SUCCESS_WITH_INFO. |
159 | |
160 | Class values other than '01', except for the class 'IM', |
161 | indicate an error and are accompanied by a return code of SQL_ERROR. The class |
162 | 'IM' is specific to warnings and errors that derive from the implementation of |
163 | ODBC itself. |
164 | |
165 | The subclass value '000' in any class indicates that there is no |
166 | subclass for that SQLSTATE. The assignment of class and subclass values is |
167 | defined by SQL-92. |
168 | */ |
169 | |
170 | typedef char pdo_error_type[6]; /* SQLSTATE */ |
171 | |
172 | |
173 | #define PDO_ERR_NONE "00000" |
174 | |
175 | enum pdo_error_mode { |
176 | PDO_ERRMODE_SILENT, /* just set error codes */ |
177 | PDO_ERRMODE_WARNING, /* raise E_WARNING */ |
178 | PDO_ERRMODE_EXCEPTION /* throw exceptions */ |
179 | }; |
180 | |
181 | enum pdo_case_conversion { |
182 | PDO_CASE_NATURAL, |
183 | PDO_CASE_UPPER, |
184 | PDO_CASE_LOWER |
185 | }; |
186 | |
187 | /* oracle interop settings */ |
188 | enum pdo_null_handling { |
189 | PDO_NULL_NATURAL = 0, |
190 | PDO_NULL_EMPTY_STRING = 1, |
191 | PDO_NULL_TO_STRING = 2 |
192 | }; |
193 | |
194 | /* {{{ utils for reading attributes set as driver_options */ |
195 | static inline long pdo_attr_lval(zval *options, enum pdo_attribute_type option_name, long defval TSRMLS_DC) |
196 | { |
197 | zval **v; |
198 | |
199 | if (options && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) { |
200 | convert_to_long_ex(v); |
201 | return Z_LVAL_PP(v); |
202 | } |
203 | return defval; |
204 | } |
205 | static inline char *pdo_attr_strval(zval *options, enum pdo_attribute_type option_name, char *defval TSRMLS_DC) |
206 | { |
207 | zval **v; |
208 | |
209 | if (options && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) { |
210 | convert_to_string_ex(v); |
211 | return estrndup(Z_STRVAL_PP(v), Z_STRLEN_PP(v)); |
212 | } |
213 | return defval ? estrdup(defval) : NULL; |
214 | } |
215 | /* }}} */ |
216 | |
217 | /* This structure is registered with PDO when a PDO driver extension is |
218 | * initialized */ |
219 | typedef struct { |
220 | const char *driver_name; |
221 | unsigned long driver_name_len; |
222 | unsigned long api_version; /* needs to be compatible with PDO */ |
223 | |
224 | #define (name) \ |
225 | #name, sizeof(#name)-1, \ |
226 | PDO_DRIVER_API |
227 | |
228 | /* create driver specific portion of the database handle and stash it into |
229 | * the dbh. dbh contains the data source string and flags for this |
230 | * instance. You MUST respect dbh->is_persistent and pass that flag to |
231 | * pemalloc() for all allocations that are stored in the dbh or your instance |
232 | * data in the db, otherwise you will crash PHP when persistent connections |
233 | * are used. |
234 | */ |
235 | int (*db_handle_factory)(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC); |
236 | |
237 | } pdo_driver_t; |
238 | |
239 | /* {{{ methods for a database handle */ |
240 | |
241 | /* close or otherwise disconnect the database */ |
242 | typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh TSRMLS_DC); |
243 | |
244 | /* prepare a statement and stash driver specific portion into stmt */ |
245 | typedef int (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC); |
246 | |
247 | /* execute a statement (that does not return a result set) */ |
248 | typedef long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC); |
249 | |
250 | /* quote a string */ |
251 | typedef int (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC); |
252 | |
253 | /* transaction related */ |
254 | typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC); |
255 | |
256 | /* setting of attributes */ |
257 | typedef int (*pdo_dbh_set_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); |
258 | |
259 | /* return last insert id. NULL indicates error condition, otherwise, the return value |
260 | * MUST be an emalloc'd NULL terminated string. */ |
261 | typedef char *(*pdo_dbh_last_id_func)(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC); |
262 | |
263 | /* fetch error information. if stmt is not null, fetch information pertaining |
264 | * to the statement, otherwise fetch global error information. The driver |
265 | * should add the following information to the array "info" in this order: |
266 | * - native error code |
267 | * - string representation of the error code ... any other optional driver |
268 | * specific data ... */ |
269 | typedef int (*pdo_dbh_fetch_error_func)(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC); |
270 | |
271 | /* fetching of attributes */ |
272 | typedef int (*pdo_dbh_get_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); |
273 | |
274 | /* checking/pinging persistent connections; return SUCCESS if the connection |
275 | * is still alive and ready to be used, FAILURE otherwise. |
276 | * You may set this handler to NULL, which is equivalent to returning SUCCESS. */ |
277 | typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh TSRMLS_DC); |
278 | |
279 | /* called at request end for each persistent dbh; this gives the driver |
280 | * the opportunity to safely release resources that only have per-request |
281 | * scope */ |
282 | typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh TSRMLS_DC); |
283 | |
284 | /* for adding methods to the dbh or stmt objects |
285 | pointer to a list of driver specific functions. The convention is |
286 | to prefix the function names using the PDO driver name; this will |
287 | reduce the chance of collisions with future functionality in the |
288 | PDO class or in user code (they can extend the PDO object). |
289 | */ |
290 | enum { |
291 | PDO_DBH_DRIVER_METHOD_KIND_DBH = 0, |
292 | PDO_DBH_DRIVER_METHOD_KIND_STMT, |
293 | PDO_DBH_DRIVER_METHOD_KIND__MAX |
294 | }; |
295 | |
296 | typedef const zend_function_entry *(*pdo_dbh_get_driver_methods_func)(pdo_dbh_t *dbh, int kind TSRMLS_DC); |
297 | |
298 | struct pdo_dbh_methods { |
299 | pdo_dbh_close_func closer; |
300 | pdo_dbh_prepare_func preparer; |
301 | pdo_dbh_do_func doer; |
302 | pdo_dbh_quote_func quoter; |
303 | pdo_dbh_txn_func begin; |
304 | pdo_dbh_txn_func commit; |
305 | pdo_dbh_txn_func rollback; |
306 | pdo_dbh_set_attr_func set_attribute; |
307 | pdo_dbh_last_id_func last_id; |
308 | pdo_dbh_fetch_error_func fetch_err; |
309 | pdo_dbh_get_attr_func get_attribute; |
310 | pdo_dbh_check_liveness_func check_liveness; |
311 | pdo_dbh_get_driver_methods_func get_driver_methods; |
312 | pdo_dbh_request_shutdown persistent_shutdown; |
313 | pdo_dbh_txn_func in_transaction; |
314 | }; |
315 | |
316 | /* }}} */ |
317 | |
318 | /* {{{ methods for a statement handle */ |
319 | |
320 | /* free the statement handle */ |
321 | typedef int (*pdo_stmt_dtor_func)(pdo_stmt_t *stmt TSRMLS_DC); |
322 | |
323 | /* start the query */ |
324 | typedef int (*pdo_stmt_execute_func)(pdo_stmt_t *stmt TSRMLS_DC); |
325 | |
326 | /* causes the next row in the set to be fetched; indicates if there are no |
327 | * more rows. The ori and offset params modify which row should be returned, |
328 | * if the stmt represents a scrollable cursor */ |
329 | typedef int (*pdo_stmt_fetch_func)(pdo_stmt_t *stmt, |
330 | enum pdo_fetch_orientation ori, long offset TSRMLS_DC); |
331 | |
332 | /* queries information about the type of a column, by index (0 based). |
333 | * Driver should populate stmt->columns[colno] with appropriate info */ |
334 | typedef int (*pdo_stmt_describe_col_func)(pdo_stmt_t *stmt, int colno TSRMLS_DC); |
335 | |
336 | /* retrieves pointer and size of the value for a column. |
337 | * Note that PDO expects the driver to manage the lifetime of this data; |
338 | * it will copy the value into a zval on behalf of the script. |
339 | * If the driver sets caller_frees, ptr should point to emalloc'd memory |
340 | * and PDO will free it as soon as it is done using it. |
341 | */ |
342 | typedef int (*pdo_stmt_get_col_data_func)(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC); |
343 | |
344 | /* hook for bound params */ |
345 | enum pdo_param_event { |
346 | PDO_PARAM_EVT_ALLOC, |
347 | PDO_PARAM_EVT_FREE, |
348 | PDO_PARAM_EVT_EXEC_PRE, |
349 | PDO_PARAM_EVT_EXEC_POST, |
350 | PDO_PARAM_EVT_FETCH_PRE, |
351 | PDO_PARAM_EVT_FETCH_POST, |
352 | PDO_PARAM_EVT_NORMALIZE |
353 | }; |
354 | |
355 | typedef int (*pdo_stmt_param_hook_func)(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC); |
356 | |
357 | /* setting of attributes */ |
358 | typedef int (*pdo_stmt_set_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); |
359 | |
360 | /* fetching of attributes */ |
361 | typedef int (*pdo_stmt_get_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); |
362 | |
363 | /* retrieves meta data for a numbered column. |
364 | * Returns SUCCESS/FAILURE. |
365 | * On SUCCESS, fill in return_value with an array with the following fields. |
366 | * If a particular field is not supported, then the driver simply does not add it to |
367 | * the array, so that scripts can use isset() to check for it. |
368 | * |
369 | * ### this is just a rough first cut, and subject to change ### |
370 | * |
371 | * these are added by PDO itself, based on data from the describe handler: |
372 | * name => the column name |
373 | * len => the length/size of the column |
374 | * precision => precision of the column |
375 | * pdo_type => an integer, one of the PDO_PARAM_XXX values |
376 | * |
377 | * scale => the floating point scale |
378 | * table => the table for that column |
379 | * type => a string representation of the type, mapped to the PHP equivalent type name |
380 | * native_type => a string representation of the type, native style, if different from |
381 | * the mapped name. |
382 | * flags => an array of flags including zero or more of the following: |
383 | * primary_key, not_null, unique_key, multiple_key, unsigned, auto_increment, blob |
384 | * |
385 | * Any driver specific data should be returned using a prefixed key or value. |
386 | * Eg: custom data for the mysql driver would use either |
387 | * 'mysql:foobar' => 'some data' // to add a new key to the array |
388 | * or |
389 | * 'flags' => array('not_null', 'mysql:some_flag'); // to add data to an existing key |
390 | */ |
391 | typedef int (*pdo_stmt_get_column_meta_func)(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC); |
392 | |
393 | /* advances the statement to the next rowset of the batch. |
394 | * If it returns 1, PDO will tear down its idea of columns |
395 | * and meta data. If it returns 0, PDO will indicate an error |
396 | * to the caller. */ |
397 | typedef int (*pdo_stmt_next_rowset_func)(pdo_stmt_t *stmt TSRMLS_DC); |
398 | |
399 | /* closes the active cursor on a statement, leaving the prepared |
400 | * statement ready for re-execution. Useful to explicitly state |
401 | * that you are done with a given rowset, without having to explicitly |
402 | * fetch all the rows. */ |
403 | typedef int (*pdo_stmt_cursor_closer_func)(pdo_stmt_t *stmt TSRMLS_DC); |
404 | |
405 | struct pdo_stmt_methods { |
406 | pdo_stmt_dtor_func dtor; |
407 | pdo_stmt_execute_func executer; |
408 | pdo_stmt_fetch_func fetcher; |
409 | pdo_stmt_describe_col_func describer; |
410 | pdo_stmt_get_col_data_func get_col; |
411 | pdo_stmt_param_hook_func param_hook; |
412 | pdo_stmt_set_attr_func set_attribute; |
413 | pdo_stmt_get_attr_func get_attribute; |
414 | pdo_stmt_get_column_meta_func get_column_meta; |
415 | pdo_stmt_next_rowset_func next_rowset; |
416 | pdo_stmt_cursor_closer_func cursor_closer; |
417 | }; |
418 | |
419 | /* }}} */ |
420 | |
421 | enum pdo_placeholder_support { |
422 | PDO_PLACEHOLDER_NONE=0, |
423 | PDO_PLACEHOLDER_NAMED=1, |
424 | PDO_PLACEHOLDER_POSITIONAL=2 |
425 | }; |
426 | |
427 | /* represents a connection to a database */ |
428 | struct _pdo_dbh_t { |
429 | /* these items must appear in this order at the beginning of the |
430 | struct so that this can be cast as a zend_object. we need this |
431 | to allow the extending class to escape all the custom handlers |
432 | that PDO declares. |
433 | */ |
434 | zend_object std; |
435 | |
436 | /* driver specific methods */ |
437 | struct pdo_dbh_methods *methods; |
438 | /* driver specific data */ |
439 | void *driver_data; |
440 | |
441 | /* credentials */ |
442 | char *username, *password; |
443 | |
444 | /* if true, then data stored and pointed at by this handle must all be |
445 | * persistently allocated */ |
446 | unsigned is_persistent:1; |
447 | |
448 | /* if true, driver should act as though a COMMIT were executed between |
449 | * each executed statement; otherwise, COMMIT must be carried out manually |
450 | * */ |
451 | unsigned auto_commit:1; |
452 | |
453 | /* if true, the handle has been closed and will not function anymore */ |
454 | unsigned is_closed:1; |
455 | |
456 | /* if true, the driver requires that memory be allocated explicitly for |
457 | * the columns that are returned */ |
458 | unsigned alloc_own_columns:1; |
459 | |
460 | /* if true, commit or rollBack is allowed to be called */ |
461 | unsigned in_txn:1; |
462 | |
463 | /* max length a single character can become after correct quoting */ |
464 | unsigned max_escaped_char_length:3; |
465 | |
466 | /* oracle compat; see enum pdo_null_handling */ |
467 | unsigned oracle_nulls:2; |
468 | |
469 | /* when set, convert int/floats to strings */ |
470 | unsigned stringify:1; |
471 | |
472 | /* the sum of the number of bits here and the bit fields preceding should |
473 | * equal 32 */ |
474 | unsigned _reserved_flags:21; |
475 | |
476 | /* data source string used to open this handle */ |
477 | const char *data_source; |
478 | unsigned long data_source_len; |
479 | |
480 | /* the global error code. */ |
481 | pdo_error_type error_code; |
482 | |
483 | enum pdo_error_mode error_mode; |
484 | |
485 | enum pdo_case_conversion native_case, desired_case; |
486 | |
487 | /* persistent hash key associated with this handle */ |
488 | const char *persistent_id; |
489 | int persistent_id_len; |
490 | unsigned int refcount; |
491 | |
492 | /* driver specific "class" methods for the dbh and stmt */ |
493 | HashTable *cls_methods[PDO_DBH_DRIVER_METHOD_KIND__MAX]; |
494 | |
495 | pdo_driver_t *driver; |
496 | |
497 | zend_class_entry *def_stmt_ce; |
498 | |
499 | zval *def_stmt_ctor_args; |
500 | |
501 | /* when calling PDO::query(), we need to keep the error |
502 | * context from the statement around until we next clear it. |
503 | * This will allow us to report the correct error message |
504 | * when PDO::query() fails */ |
505 | pdo_stmt_t *query_stmt; |
506 | zval query_stmt_zval; |
507 | |
508 | /* defaults for fetches */ |
509 | enum pdo_fetch_type default_fetch_type; |
510 | }; |
511 | |
512 | /* describes a column */ |
513 | struct pdo_column_data { |
514 | char *name; |
515 | int namelen; |
516 | unsigned long maxlen; |
517 | enum pdo_param_type param_type; |
518 | unsigned long precision; |
519 | |
520 | /* don't touch this unless your name is dbdo */ |
521 | void *dbdo_data; |
522 | }; |
523 | |
524 | /* describes a bound parameter */ |
525 | struct pdo_bound_param_data { |
526 | long paramno; /* if -1, then it has a name, and we don't know the index *yet* */ |
527 | char *name; |
528 | int namelen; |
529 | |
530 | long max_value_len; /* as a hint for pre-allocation */ |
531 | |
532 | zval *parameter; /* the variable itself */ |
533 | enum pdo_param_type param_type; /* desired or suggested type */ |
534 | |
535 | zval *driver_params; /* optional parameter(s) for the driver */ |
536 | void *driver_data; |
537 | |
538 | pdo_stmt_t *stmt; /* for convenience in dtor */ |
539 | int is_param; /* parameter or column ? */ |
540 | }; |
541 | |
542 | /* represents a prepared statement */ |
543 | struct _pdo_stmt_t { |
544 | /* these items must appear in this order at the beginning of the |
545 | struct so that this can be cast as a zend_object. we need this |
546 | to allow the extending class to escape all the custom handlers |
547 | that PDO declares. |
548 | */ |
549 | zend_object std; |
550 | |
551 | /* driver specifics */ |
552 | struct pdo_stmt_methods *methods; |
553 | void *driver_data; |
554 | |
555 | /* if true, we've already successfully executed this statement at least |
556 | * once */ |
557 | unsigned executed:1; |
558 | /* if true, the statement supports placeholders and can implement |
559 | * bindParam() for its prepared statements, if false, PDO should |
560 | * emulate prepare and bind on its behalf */ |
561 | unsigned supports_placeholders:2; |
562 | |
563 | unsigned _reserved:29; |
564 | |
565 | /* the number of columns in the result set; not valid until after |
566 | * the statement has been executed at least once. In some cases, might |
567 | * not be valid until fetch (at the driver level) has been called at least once. |
568 | * */ |
569 | int column_count; |
570 | struct pdo_column_data *columns; |
571 | |
572 | /* we want to keep the dbh alive while we live, so we own a reference */ |
573 | zval database_object_handle; |
574 | pdo_dbh_t *dbh; |
575 | |
576 | /* keep track of bound input parameters. Some drivers support |
577 | * input/output parameters, but you can't rely on that working */ |
578 | HashTable *bound_params; |
579 | /* When rewriting from named to positional, this maps positions to names */ |
580 | HashTable *bound_param_map; |
581 | /* keep track of PHP variables bound to named (or positional) columns |
582 | * in the result set */ |
583 | HashTable *bound_columns; |
584 | |
585 | /* not always meaningful */ |
586 | long row_count; |
587 | |
588 | /* used to hold the statement's current query */ |
589 | char *query_string; |
590 | int query_stringlen; |
591 | |
592 | /* the copy of the query with expanded binds ONLY for emulated-prepare drivers */ |
593 | char *active_query_string; |
594 | int active_query_stringlen; |
595 | |
596 | /* the cursor specific error code. */ |
597 | pdo_error_type error_code; |
598 | |
599 | /* for lazy fetches, we always return the same lazy object handle. |
600 | * Let's keep it here. */ |
601 | zval lazy_object_ref; |
602 | unsigned long refcount; |
603 | |
604 | /* defaults for fetches */ |
605 | enum pdo_fetch_type default_fetch_type; |
606 | union { |
607 | int column; |
608 | struct { |
609 | zend_class_entry *ce; |
610 | zval *ctor_args; /* freed */ |
611 | zval *retval_ptr; |
612 | zend_fcall_info fci; |
613 | zend_fcall_info_cache fcc; |
614 | } cls; |
615 | struct { |
616 | zval *function; |
617 | zval *fetch_args; /* freed */ |
618 | zval *object; |
619 | zend_fcall_info fci; |
620 | zend_fcall_info_cache fcc; |
621 | zval **values; /* freed */ |
622 | } func; |
623 | zval *into; |
624 | } fetch; |
625 | |
626 | /* used by the query parser for driver specific |
627 | * parameter naming (see pgsql driver for example) */ |
628 | const char *named_rewrite_template; |
629 | }; |
630 | |
631 | /* call this in MINIT to register your PDO driver */ |
632 | PDO_API int php_pdo_register_driver(pdo_driver_t *driver); |
633 | /* call this in MSHUTDOWN to unregister your PDO driver */ |
634 | PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver); |
635 | |
636 | /* For the convenience of drivers, this function will parse a data source |
637 | * string, of the form "name=value; name2=value2" and populate variables |
638 | * according to the data you pass in and array of pdo_data_src_parser structures */ |
639 | struct pdo_data_src_parser { |
640 | const char *optname; |
641 | char *optval; |
642 | int freeme; |
643 | }; |
644 | |
645 | PDO_API int php_pdo_parse_data_source(const char *data_source, |
646 | unsigned long data_source_len, struct pdo_data_src_parser *parsed, |
647 | int nparams); |
648 | |
649 | PDO_API zend_class_entry *php_pdo_get_dbh_ce(void); |
650 | PDO_API zend_class_entry *php_pdo_get_exception(void); |
651 | |
652 | PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, |
653 | char **outquery, int *outquery_len TSRMLS_DC); |
654 | |
655 | PDO_API void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, |
656 | const char *sqlstate, const char *supp TSRMLS_DC); |
657 | |
658 | PDO_API void php_pdo_dbh_addref(pdo_dbh_t *dbh TSRMLS_DC); |
659 | PDO_API void php_pdo_dbh_delref(pdo_dbh_t *dbh TSRMLS_DC); |
660 | |
661 | PDO_API void php_pdo_stmt_addref(pdo_stmt_t *stmt TSRMLS_DC); |
662 | PDO_API void php_pdo_stmt_delref(pdo_stmt_t *stmt TSRMLS_DC); |
663 | |
664 | |
665 | #endif /* PHP_PDO_DRIVER_H */ |
666 | /* |
667 | * Local variables: |
668 | * tab-width: 4 |
669 | * c-basic-offset: 4 |
670 | * End: |
671 | * vim600: noet sw=4 ts=4 fdm=marker |
672 | * vim<600: noet sw=4 ts=4 |
673 | */ |
674 | |