Add rough cut at fetching meta data.

This commit is contained in:
Wez Furlong 2004-09-26 20:45:44 +00:00
parent f17aa81edc
commit eb0cd48d60
4 changed files with 98 additions and 7 deletions

View File

@ -10,6 +10,8 @@ Low-level:
- field meta data from statement handles
- LOB support via Streams API
- iterator support
- make errors generated at the pdo level (as opposed to driver level) use the
selected error mode.
Not-so-low-level:
- fetchAll(), single row, single column fetches etc.

View File

@ -293,7 +293,7 @@ static PHP_FUNCTION(dbh_constructor)
dbh->auto_commit = pdo_attr_lval(driver_options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
if (!dbh->data_source || !dbh->username || !dbh->password) {
if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory");
}
@ -569,6 +569,12 @@ static PHP_METHOD(PDO, query)
RETURN_LONG(ret);
}
}
static PHP_METHOD(PDO, exec) /* FIXME: nuke on release */
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "This is name deprecated, use PDO::query instead");
PHP_FN(PDO_exec)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
@ -632,6 +638,7 @@ function_entry pdo_dbh_functions[] = {
PHP_ME(PDO, commit, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, rollBack, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, setAttribute, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, exec, NULL, ZEND_ACC_PUBLIC) /* FIXME: nuke on stable release */
PHP_ME(PDO, query, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, lastInsertId, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, errorCode, NULL, ZEND_ACC_PUBLIC)

View File

@ -552,7 +552,7 @@ static PHP_METHOD(PDOStatement, fetchAll)
}
/* }}} */
static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int is_param)
static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int is_param) /* {{{ */
{
struct pdo_bound_param_data param = {0};
@ -577,7 +577,7 @@ static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt,
}
return really_register_bound_param(&param, stmt, is_param TSRMLS_CC);
}
} /* }}} */
/* {{{ proto bool PDOStatement::bindParam(mixed $paramno, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]])
bind a parameter to a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). This isn't supported by all drivers. It should be called prior to execute(). */
@ -706,18 +706,64 @@ static PHP_METHOD(PDOStatement, getAttribute)
}
/* }}} */
/* {{{ proto int PDOStatement::columnCount()
Returns the number of columns in the result set */
static PHP_METHOD(PDOStatement, columnCount)
{
pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (ZEND_NUM_ARGS()) {
RETURN_FALSE;
}
RETURN_LONG(stmt->column_count);
}
/* }}} */
/* {{{ proto array PDOStatement::getColumnMeta(int $column)
Returns meta data for a numbered column */
static PHP_METHOD(PDOStatement, getColumnMeta)
{
pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
long colno;
struct pdo_column_data *col;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &colno)) {
RETURN_FALSE;
}
if (!stmt->methods->get_column_meta) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver does not support meta data");
RETURN_FALSE;
}
PDO_STMT_CLEAR_ERR();
if (FAILURE == stmt->methods->get_column_meta(stmt, colno, return_value TSRMLS_CC)) {
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
/* add stock items */
col = &stmt->columns[colno];
add_assoc_string(return_value, "name", col->name, 1);
add_assoc_long(return_value, "len", col->maxlen); /* FIXME: unsigned ? */
add_assoc_long(return_value, "precision", col->precision);
add_assoc_long(return_value, "pdo_type", col->param_type);
}
/* }}} */
function_entry pdo_dbstmt_functions[] = {
PHP_ME(PDOStatement, execute, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetch, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, bindParam, second_arg_force_ref, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, bindColumn, second_arg_force_ref, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, rowCount, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetchSingle, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetchSingle, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetchAll, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, errorCode, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, errorInfo, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, setAttribute, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, getAttribute, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, columnCount, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, getColumnMeta, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};

View File

@ -35,7 +35,7 @@ struct pdo_bound_param_data;
# define FALSE 0
#endif
#define PDO_DRIVER_API 20040923
#define PDO_DRIVER_API 20040925
enum pdo_param_type {
PDO_PARAM_NULL,
@ -137,7 +137,11 @@ typedef struct {
/* 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 */
* 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;
@ -176,7 +180,9 @@ typedef int (*pdo_dbh_fetch_error_func)(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *
/* fetching of attributes */
typedef int (*pdo_dbh_get_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC);
/* checking/pinging persistent connections */
/* 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 {
@ -233,6 +239,35 @@ typedef int (*pdo_stmt_set_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSR
/* 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;
@ -243,6 +278,7 @@ struct pdo_stmt_methods {
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;
};
/* }}} */