/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef PHP_PDO_DRIVER_H #define PHP_PDO_DRIVER_H #include "php_pdo.h" /* forward declarations */ typedef struct _pdo_dbh_t pdo_dbh_t; typedef struct _pdo_stmt_t pdo_stmt_t; struct pdo_bound_param_data; #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define PDO_DRIVER_API 20041027 enum pdo_param_type { PDO_PARAM_NULL, PDO_PARAM_INT, PDO_PARAM_STR, PDO_PARAM_LOB, PDO_PARAM_STMT, /* hierarchical result set */ }; enum pdo_fetch_type { PDO_FETCH_USE_DEFAULT, PDO_FETCH_LAZY, PDO_FETCH_ASSOC, PDO_FETCH_NUM, PDO_FETCH_BOTH, PDO_FETCH_OBJ, PDO_FETCH_BOUND, /* return true/false only; rely on bound columns */ PDO_FETCH_COLUMN, /* fetch a numbered column only */ PDO_FETCH_CLASS, /* create an instance of named class, call ctor and set properties */ PDO_FETCH_INTO, /* fetch row into an existing object */ PDO_FETCH__MAX /* must be last */ }; enum pdo_attribute_type { PDO_ATTR_AUTOCOMMIT, /* use to turn on or off auto-commit mode */ PDO_ATTR_SCROLL, /* ask for a scrollable cursor (when you prepare()) */ PDO_ATTR_PREFETCH, /* configure the prefetch size for drivers that support it */ PDO_ATTR_TIMEOUT, /* connection timeout in seconds */ PDO_ATTR_ERRMODE, /* control how errors are handled */ PDO_ATTR_SERVER_VERSION, /* database server version */ PDO_ATTR_CLIENT_VERSION, /* client library version */ PDO_ATTR_SERVER_INFO, /* server information */ PDO_ATTR_CONNECTION_STATUS, /* connection status */ PDO_ATTR_CASE, /* control case folding for portability */ PDO_ATTR_CURSOR_NAME, /* name a cursor for use in "WHERE CURRENT OF " */ PDO_ATTR_CURSOR, /* cursor type */ PDO_ATTR_ORACLE_NULLS, /* convert empty strings to NULL */ PDO_ATTR_PERSISTENT, /* pconnect style connection */ /* this defines the start of the range for driver specific options. * Drivers should define their own attribute constants beginning with this * value. */ PDO_ATTR_DRIVER_SPECIFIC = 1000 }; enum pdo_cursor_type { PDO_CURSOR_FWDONLY, /* forward only cursor (default) */ PDO_CURSOR_SCROLL, /* scrollable cursor */ }; /* generic error code values. * Don't want to go overboard with these. * */ enum pdo_error_type { PDO_ERR_NONE, /* no error condition */ PDO_ERR_CANT_MAP, /* no way to map native error to the generic codes; consult the native error for more info */ PDO_ERR_SYNTAX, PDO_ERR_CONSTRAINT, PDO_ERR_NOT_FOUND, PDO_ERR_ALREADY_EXISTS, PDO_ERR_NOT_IMPLEMENTED, PDO_ERR_MISMATCH, PDO_ERR_TRUNCATED, PDO_ERR_DISCONNECTED, PDO_ERR_NO_PERM, }; enum pdo_error_mode { PDO_ERRMODE_SILENT, /* just set error codes */ PDO_ERRMODE_WARNING, /* raise E_WARNING */ PDO_ERRMODE_EXCEPTION, /* throw exceptions */ }; enum pdo_case_conversion { PDO_CASE_NATURAL, PDO_CASE_UPPER, PDO_CASE_LOWER }; /* {{{ utils for reading attributes set as driver_options */ static inline long pdo_attr_lval(zval *options, enum pdo_fetch_type option_name, long defval TSRMLS_DC) { zval **v; if (options && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) { convert_to_long_ex(v); return Z_LVAL_PP(v); } return defval; } /* }}} */ /* This structure is registered with PDO when a PDO driver extension is * initialized */ typedef struct { const char *driver_name; unsigned long driver_name_len; unsigned long api_version; /* needs to be compatible with PDO */ #define PDO_DRIVER_HEADER(name) \ #name, sizeof(#name)-1, \ PDO_DRIVER_API /* create driver specific portion of the database handle and stash it into * the dbh. dbh contains the data source string and flags for this * instance. You MUST respect dbh->is_persistent and pass that flag to * pemalloc() for all allocations that are stored in the dbh or your instance * data in the db, otherwise you will crash PHP when persistent connections * are used. */ int (*db_handle_factory)(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC); } pdo_driver_t; /* {{{ methods for a database handle */ /* close or otherwise disconnect the database */ typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh TSRMLS_DC); /* prepare a statement and stash driver specific portion into stmt */ typedef int (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC); /* execute a statement (that does not return a result set) */ typedef long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC); /* quote a string */ typedef int (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC); /* transaction related */ typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC); /* setting of attributes */ typedef int (*pdo_dbh_set_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); /* return last insert id */ typedef long (*pdo_dbh_last_id_func)(pdo_dbh_t *dbh TSRMLS_DC); /* fetch error information. if stmt is not null, fetch information pertaining * to the statement, otherwise fetch global error information. The driver * should add the following information to the array "info" in this order: * - native error code * - string representation of the error code ... any other optional driver * specific data ... */ typedef int (*pdo_dbh_fetch_error_func)(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC); /* fetching of attributes */ typedef int (*pdo_dbh_get_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); /* checking/pinging persistent connections; return SUCCESS if the connection * is still alive and ready to be used, FAILURE otherwise. * You may set this handler to NULL, which is equivalent to returning SUCCESS. */ typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh TSRMLS_DC); struct pdo_dbh_methods { pdo_dbh_close_func closer; pdo_dbh_prepare_func preparer; pdo_dbh_do_func doer; pdo_dbh_quote_func quoter; pdo_dbh_txn_func begin; pdo_dbh_txn_func commit; pdo_dbh_txn_func rollback; pdo_dbh_set_attr_func set_attribute; pdo_dbh_last_id_func last_id; pdo_dbh_fetch_error_func fetch_err; pdo_dbh_get_attr_func get_attribute; pdo_dbh_check_liveness_func check_liveness; }; /* }}} */ /* {{{ methods for a statement handle */ /* free the statement handle */ typedef int (*pdo_stmt_dtor_func)(pdo_stmt_t *stmt TSRMLS_DC); /* start the query */ typedef int (*pdo_stmt_execute_func)(pdo_stmt_t *stmt TSRMLS_DC); /* causes the next row in the set to be fetched; indicates if there are no * more rows */ typedef int (*pdo_stmt_fetch_func)(pdo_stmt_t *stmt TSRMLS_DC); /* queries information about the type of a column, by index (0 based). * Driver should populate stmt->columns[colno] with appropriate info */ typedef int (*pdo_stmt_describe_col_func)(pdo_stmt_t *stmt, int colno TSRMLS_DC); /* retrieves pointer and size of the value for a column */ typedef int (*pdo_stmt_get_col_data_func)(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC); /* hook for bound params */ enum pdo_param_event { PDO_PARAM_EVT_ALLOC, PDO_PARAM_EVT_FREE, PDO_PARAM_EVT_EXEC_PRE, PDO_PARAM_EVT_EXEC_POST, PDO_PARAM_EVT_FETCH_PRE, PDO_PARAM_EVT_FETCH_POST, }; 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); /* setting of attributes */ typedef int (*pdo_stmt_set_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); /* fetching of attributes */ typedef int (*pdo_stmt_get_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); /* retrieves meta data for a numbered column. * Returns SUCCESS/FAILURE. * On SUCCESS, fill in return_value with an array with the following fields. * If a particular field is not supported, then the driver simply does not add it to * the array, so that scripts can use isset() to check for it. * * ### this is just a rough first cut, and subject to change ### * * these are added by PDO itself, based on data from the describe handler: * name => the column name * len => the length/size of the column * precision => precision of the column * pdo_type => an integer, one of the PDO_PARAM_XXX values * * scale => the floating point scale * table => the table for that column * type => a string representation of the type, mapped to the PHP equivalent type name * native_type => a string representation of the type, native style, if different from * the mapped name. * flags => an array of flags including zero or more of the following: * primary_key, not_null, unique_key, multiple_key, unsigned, auto_increment, blob * * Any driver specific data should be returned using a prefixed key or value. * Eg: custom data for the mysql driver would use either * 'mysql:foobar' => 'some data' // to add a new key to the array * or * 'flags' => array('not_null', 'mysql:some_flag'); // to add data to an existing key */ typedef int (*pdo_stmt_get_column_meta_func)(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC); struct pdo_stmt_methods { pdo_stmt_dtor_func dtor; pdo_stmt_execute_func executer; pdo_stmt_fetch_func fetcher; pdo_stmt_describe_col_func describer; pdo_stmt_get_col_data_func get_col; pdo_stmt_param_hook_func param_hook; pdo_stmt_set_attr_func set_attribute; pdo_stmt_get_attr_func get_attribute; pdo_stmt_get_column_meta_func get_column_meta; }; /* }}} */ enum pdo_placeholder_support { PDO_PLACEHOLDER_NONE=0, PDO_PLACEHOLDER_NAMED=1, PDO_PLACEHOLDER_POSITIONAL=2 }; /* represents a connection to a database */ struct _pdo_dbh_t { /* these items mst appear in this order at the beginning of the struct so that this can be cast as a zend_object. we need this to allow the extending class to escape all the custom handlers that PDO decalres. */ zend_class_entry *ce; HashTable *properties; unsigned int in_get:1; unsigned int in_set:1; /* driver specific methods */ struct pdo_dbh_methods *methods; /* driver specific data */ void *driver_data; /* credentials */ char *username, *password; /* if true, then data stored and pointed at by this handle must all be * persistently allocated */ unsigned is_persistent:1; /* if true, driver should act as though a COMMIT were executed between * each executed statement; otherwise, COMMIT must be carried out manually * */ unsigned auto_commit:1; /* if true, the handle has been closed and will not function anymore */ unsigned is_closed:1; /* if true, the driver requires that memory be allocated explicitly for * the columns that are returned */ unsigned alloc_own_columns:1; /* if true, the driver supports placeholders and can implement * bindParam() for its prepared statements, if false, PDO should * emulate prepare and bind on its behalf */ unsigned supports_placeholders:2; /* if true, commit or rollBack is allowed to be called */ unsigned in_txn:1; /* max length a single character can become after correct quoting */ unsigned max_escaped_char_length:3; /* when set, convert empty strings to NULL */ unsigned oracle_nulls:1; /* the sum of the number of bits here and the bit fields preceeding should * equal 32 */ unsigned _reserved_flags:21; /* data source string used to open this handle */ const char *data_source; unsigned long data_source_len; /* the global error code. */ enum pdo_error_type error_code; enum pdo_error_mode error_mode; enum pdo_case_conversion native_case, desired_case; /* persistent hash key associated with this handle */ const char *persistent_id; int persistent_id_len; unsigned int refcount; }; /* describes a column */ struct pdo_column_data { char *name; long namelen; unsigned long maxlen; enum pdo_param_type param_type; unsigned long precision; }; /* describes a bound parameter */ struct pdo_bound_param_data { long paramno; /* if -1, then it has a name, and we don't know the index *yet* */ char *name; long namelen; long max_value_len; /* as a hint for pre-allocation */ zval *parameter; /* the variable itself */ enum pdo_param_type param_type; /* desired or suggested type */ zval *driver_params; /* optional parameter(s) for the driver */ void *driver_data; pdo_stmt_t *stmt; /* for convenience in dtor */ int is_param; /* parameter or column ? */ }; /* represents a prepared statement */ struct _pdo_stmt_t { /* driver specifics */ struct pdo_stmt_methods *methods; void *driver_data; /* if true, we've already successfully executed this statement at least * once */ unsigned executed:1; unsigned _reserved:31; /* the number of columns in the result set; not valid until after * the statement has been executed at least once. In some cases, might * not be valid until fetch (at the driver level) has been called at least once. * */ int column_count; struct pdo_column_data *columns; /* we want to keep the dbh alive while we live, so we own a reference */ zval database_object_handle; pdo_dbh_t *dbh; /* keep track of bound input parameters. Some drivers support * input/output parameters, but you can't rely on that working */ HashTable *bound_params; /* keep track of PHP variables bound to named (or positional) columns * in the result set */ HashTable *bound_columns; /* not always meaningful */ long row_count; /* used to hold the statement's current query */ char *query_string; int query_stringlen; /* the copy of the query with expanded binds ONLY for emulated-prepare drivers */ char *active_query_string; int active_query_stringlen; /* the cursor specific error code. */ enum pdo_error_type error_code; /* for lazy fetches, we always return the same lazy object handle. * Let's keep it here. */ zval lazy_object_ref; unsigned long refcount; /* defaults for fetches */ enum pdo_fetch_type default_fetch_type; union { int column; struct { zend_class_entry *ce; zval *ctor_args; } cls; zval *into; } fetch; }; /* call this in MINIT to register your PDO driver */ PDO_API int php_pdo_register_driver(pdo_driver_t *driver); /* call this in MSHUTDOWN to unregister your PDO driver */ PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver); /* For the convenience of drivers, this function will parse a data source * string, of the form "name=value; name2=value2" and populate variables * according to the data you pass in and array of pdo_data_src_parser structures */ struct pdo_data_src_parser { const char *optname; char *optval; int freeme; }; PDO_API int php_pdo_parse_data_source(const char *data_source, unsigned long data_source_len, struct pdo_data_src_parser *parsed, int nparams); PDO_API zend_class_entry *php_pdo_get_exception(void); #endif /* PHP_PDO_DRIVER_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */