From 2c5b2fc105bd6af6571c2bd39d2785c627c6e578 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sat, 26 Feb 2005 17:27:51 +0000 Subject: [PATCH] Alan: moved your fields away, but reserved you a pointer. Changed PDO::lastInsertId() to have following proto: string PDO::lastInsertId([string name]) this allows arbitrary unique identitifers to be returned from the driver. The optional name parameter is for databases that require additional contextual information to be able to return the correct identifier. None currently use it, but pgsql will be on the list of drivers that do. --- ext/pdo/pdo.c | 42 +++++++++++++++++++++++++++++++++- ext/pdo/pdo_dbh.c | 16 +++++++++---- ext/pdo/php_pdo_driver.h | 22 ++++++++++++------ ext/pdo_mysql/mysql_driver.c | 6 +++-- ext/pdo_pgsql/pgsql_driver.c | 10 +++++--- ext/pdo_sqlite/sqlite_driver.c | 9 +++++--- 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index 36dbd2bd5c..795f8f1e59 100755 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -203,7 +203,47 @@ PDO_API int php_pdo_parse_data_source(const char *data_source, return n_matches; } - + +static const char digit_vec[] = "0123456789"; +PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC) +{ + char buffer[65]; + char outbuf[65] = ""; + register char *p; + long long_val; + char *dst = outbuf; + + if (i64 < 0) { + i64 = -i64; + *dst++ = '-'; + } + + if (i64 == 0) { + *dst++ = '0'; + *dst++ = '\0'; + return estrdup(outbuf); + } + + p = &buffer[sizeof(buffer)-1]; + *p = '\0'; + + while ((pdo_uint64_t)i64 > (pdo_uint64_t)LONG_MAX) { + pdo_uint64_t quo = (pdo_uint64_t)i64 / (unsigned int)10; + unsigned int rem = (unsigned int)(i64 - quo*10U); + *--p = digit_vec[rem]; + i64 = (pdo_int64_t)quo; + } + long_val = (long)i64; + while (long_val != 0) { + long quo = long_val / 10; + *--p = digit_vec[(unsigned int)(long_val - quo * 10)]; + long_val = quo; + } + while ((*dst++ = *p++) != 0) + ; + *dst = '\0'; + return estrdup(outbuf); +} /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(pdo) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index e979cc06ac..61979b15f6 100755 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -752,13 +752,15 @@ static PHP_METHOD(PDO, exec) /* }}} */ -/* {{{ proto int PDO::lastInsertId() - Returns the number id of rows that we affected by the last call to PDO::exec(). Not always meaningful. */ +/* {{{ proto string PDO::lastInsertId([string seqname]) + Returns the id of the last row that we affected on this connection. Some databases require a sequence or table name to be passed in. Not always meaningful. */ static PHP_METHOD(PDO, lastInsertId) { pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + char *name = NULL; + int namelen; - if (ZEND_NUM_ARGS()) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &name, &namelen)) { RETURN_FALSE; } @@ -767,7 +769,13 @@ static PHP_METHOD(PDO, lastInsertId) pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support lastInsertId()" TSRMLS_CC); RETURN_FALSE; } else { - RETURN_LONG(dbh->methods->last_id(dbh TSRMLS_CC)); + Z_STRVAL_P(return_value) = dbh->methods->last_id(dbh, name, &Z_STRLEN_P(return_value) TSRMLS_CC); + if (!Z_STRVAL_P(return_value)) { + PDO_HANDLE_DBH_ERR(); + RETURN_FALSE; + } else { + Z_TYPE_P(return_value) = IS_STRING; + } } } /* }}} */ diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index b0937a3e3f..6348349dca 100755 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -28,6 +28,15 @@ typedef struct _pdo_dbh_t pdo_dbh_t; typedef struct _pdo_stmt_t pdo_stmt_t; struct pdo_bound_param_data; +#ifdef PHP_WIN32 +typedef __int64 pdo_int64_t; +typedef unsigned __int64 pdo_uint64_t; +#else +typedef long long int pdo_int64_t; +typedef unsigned long long int pdo_uint64_t; +#endif +PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC); + #ifndef TRUE # define TRUE 1 #endif @@ -35,7 +44,7 @@ struct pdo_bound_param_data; # define FALSE 0 #endif -#define PDO_DRIVER_API 20050222 +#define PDO_DRIVER_API 20050226 enum pdo_param_type { PDO_PARAM_NULL, @@ -231,8 +240,9 @@ 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); +/* return last insert id. NULL indicates error condition, otherwise, the return value + * MUST be an emalloc'd NULL terminated string. */ +typedef char *(*pdo_dbh_last_id_func)(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC); /* fetch error information. if stmt is not null, fetch information pertaining * to the statement, otherwise fetch global error information. The driver @@ -460,10 +470,8 @@ struct pdo_column_data { enum pdo_param_type param_type; unsigned long precision; - /* don't touch the following fields unless your name is dbdo */ - char *native_type_name; - int abstract_type; - int abstract_flags; + /* don't touch this unless your name is dbdo */ + void *dbdo_stuff; }; /* describes a bound parameter */ diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index fe61f55081..cd1c8f0b29 100755 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -160,11 +160,13 @@ static long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRM } } -static long pdo_mysql_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) +static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len, TSRMLS_DC) { pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; + char *id = NULL; - return (long) mysql_insert_id(H->server); + *len = spprintf(&id, 0, "%ld", mysql_insert_id(H->server)); + return id; } 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) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 9134ee769a..72b6781f2d 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -197,15 +197,19 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote return 1; } -static long pdo_pgsql_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) +static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; + char *id = NULL; if (H->pgoid == InvalidOid) { - return -1; + return NULL; } - return (long) H->pgoid; + /* TODO: if name != NULL, pull out last value for that sequence/column */ + + *len = spprintf(&id, 0, "%ld", H->pgoid); + return id; } static int pdo_pgsql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 4810cd0da3..3fe9426e3c 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -156,11 +156,14 @@ static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSR } } -static long pdo_sqlite_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) +static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC) { pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; - - return (long) sqlite3_last_insert_rowid(H->db); + char *id; + + id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC); + *len = strlen(id); + return id; } /* NB: doesn't handle binary strings... use prepared stmts for that */ -- 2.40.0