From 074ba3fbc092a4a379a34471e778897be5bfa268 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 19 May 2004 17:35:39 +0000 Subject: [PATCH] Added lastInsertId() method for retrieving last insert id. Made affectedRows() work for MySQL. Populate error value in MySQL on error. --- ext/pdo/pdo_dbh.c | 24 +++++++++++++++- ext/pdo/pdo_sql_parser.c | 4 +-- ext/pdo/php_pdo_driver.h | 14 ++++++---- ext/pdo_mysql/mysql_driver.c | 46 ++++++++++++++++++++++++------- ext/pdo_mysql/mysql_statement.c | 9 +++--- ext/pdo_mysql/php_pdo_mysql_int.h | 11 +++++++- 6 files changed, 84 insertions(+), 24 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 83eaf8d621c..3151712aa22 100755 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -287,10 +287,31 @@ static PHP_METHOD(PDO, affectedRows) RETURN_FALSE; } - RETURN_LONG(dbh->affected_rows); + if (!dbh->methods->affected) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver affected rows retrieval."); + } else { + RETURN_LONG(dbh->methods->affected(dbh)); + } } /* }}} */ +/* {{{ proto int PDO::lastInsertId() + Returns the number id of rows that we affected by the last call to PDO::exec(). Not always meaningful. */ +static PHP_METHOD(PDO, lastInsertId) +{ + pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (ZEND_NUM_ARGS()) { + RETURN_FALSE; + } + + if (!dbh->methods->last_id) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver last inserted id retrieval."); + } else { + RETURN_LONG(dbh->methods->last_id(dbh)); + } +} +/* }}} */ function_entry pdo_dbh_functions[] = { PHP_ME(PDO, prepare, NULL, ZEND_ACC_PUBLIC) @@ -300,6 +321,7 @@ function_entry pdo_dbh_functions[] = { PHP_ME(PDO, setAttribute, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, exec, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, affectedRows, NULL, ZEND_ACC_PUBLIC) + PHP_ME(PDO, lastInsertId, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 3cdfa10d0a3..00b131ceb73 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.5 on Tue May 18 12:42:13 2004 */ -#line 1 "/home/george/src/pecl/pdo/pdo_sql_parser.re" +/* Generated by re2c 0.5 on Tue May 18 15:32:50 2004 */ +#line 1 "/home/rei/php5/ext/pdo/pdo_sql_parser.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 598aa05badb..2629aa739fa 100755 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -114,7 +114,7 @@ typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh TSRMLS_DC); 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 int (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, int sql_len TSRMLS_DC); +typedef int (*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); @@ -125,6 +125,12 @@ typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC); /* setting and getting of attributes */ typedef int (*pdo_dbh_set_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); +/* return affected rows */ +typedef long (*pdo_dbh_affected_func)(pdo_dbh_t *dbh TSRMLS_DC); + +/* return last insert id */ +typedef long (*pdo_dbh_last_id_func)(pdo_dbh_t *dbh TSRMLS_DC); + struct pdo_dbh_methods { pdo_dbh_close_func closer; pdo_dbh_prepare_func preparer; @@ -134,6 +140,8 @@ struct pdo_dbh_methods { pdo_dbh_txn_func commit; pdo_dbh_txn_func rollback; pdo_dbh_set_attr_func set_attribute; + pdo_dbh_affected_func affected; + pdo_dbh_last_id_func last_id; }; /* }}} */ @@ -231,10 +239,6 @@ struct _pdo_dbh_t { const char *data_source; unsigned long data_source_len; - /* the number of rows affected by last $dbh->exec(). Not always - * meaningful */ - int affected_rows; - /* the global error code. */ enum pdo_error_type error_code; #if 0 diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 3d8ffc0513a..2aed63dd3f4 100755 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -55,6 +55,10 @@ static int mysql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ mysql_close(H->server); H->server = NULL; } + if (H->mysql_error) { + efree(H->mysql_error); + H->mysql_error = NULL; + } return 0; } /* }}} */ @@ -71,11 +75,31 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, return 1; } -static int mysql_handle_doer(pdo_dbh_t *dbh, const char *sql TSRMLS_DC) +static int mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) { pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - return 0; + if (mysql_real_query(H->server, sql, sql_len)) { + pdo_mysql_error(H); + return 0; + } else { + return 1; + } +} + +static long pdo_mysql_affected_rows(pdo_dbh_t *dbh TSRMLS_DC) +{ + pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; + my_ulonglong afr = mysql_affected_rows(H->server); + + return afr == (my_ulonglong) - 1 ? 0 : (long) afr; +} + +static long pdo_mysql_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) +{ + pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; + + return (long) mysql_insert_id(H->server); } static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC) @@ -95,7 +119,13 @@ static struct pdo_dbh_methods mysql_methods = { mysql_handle_closer, mysql_handle_preparer, mysql_handle_doer, - mysql_handle_quoter + mysql_handle_quoter, + NULL, + NULL, + NULL, + NULL, + pdo_mysql_affected_rows, + pdo_mysql_last_insert_id }; static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ @@ -120,7 +150,8 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ /* allocate an environment */ /* handle for the server */ - dbh->driver_data = H->server = mysql_init(NULL); + H->server = mysql_init(NULL); + dbh->driver_data = H; if(vars[2].optval && strcmp("localhost", vars[2].optval)) { host = vars[2].optval; port = atoi(vars[3].optval); @@ -131,8 +162,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ dbname = vars[1].optval; if(mysql_real_connect(H->server, host, dbh->username, dbh->password, dbname, port, unix_socket, 0) == NULL) { - H->last_err = mysql_errno(H->server); - pdo_mysql_error("pdo_mysql_handle_factory", H->last_err); + pdo_mysql_error(H); goto cleanup; } @@ -154,10 +184,6 @@ cleanup: } } - if (!ret) { - mysql_handle_closer(dbh TSRMLS_CC); - } - return ret; } /* }}} */ diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index 0bd3cb31a66..6f8d70a06ad 100755 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -65,13 +65,11 @@ static int mysql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) if(mysql_real_query(H->server, stmt->active_query_string, stmt->active_query_stringlen) != 0) { - H->last_err = S->last_err = mysql_errno(H->server); - pdo_mysql_error("execute failed", S->last_err); + pdo_mysql_error(H); return 0; } if((S->result = mysql_use_result(H->server)) == NULL) { - H->last_err = S->last_err = mysql_errno(H->server); - pdo_mysql_error("mysql_use_result() failed", S->last_err); + pdo_mysql_error(H); return 0; } if(!stmt->executed) { @@ -94,6 +92,7 @@ static int mysql_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) if((S->current_data = mysql_fetch_row(S->result)) == NULL) { /* there seems to be no way of distinguishing 'no data' from 'error' */ + pdo_mysql_error(S->H); return 0; } S->current_lengths = mysql_fetch_lengths(S->result); @@ -137,7 +136,7 @@ static int mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned } if(colno >= mysql_num_fields(S->result)) { /* error invalid column */ - pdo_mysql_error("invalid column", 0); + pdo_mysql_error(S->H); return 0; } *ptr = estrndup(S->current_data[colno], S->current_lengths[colno] +1); diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h index 3a3e4bfa62b..b95e9c765e3 100755 --- a/ext/pdo_mysql/php_pdo_mysql_int.h +++ b/ext/pdo_mysql/php_pdo_mysql_int.h @@ -27,6 +27,8 @@ typedef struct { MYSQL *server; int last_err; + unsigned int mysql_errno; + char *mysql_error; unsigned attached:1; unsigned _reserved:31; } pdo_mysql_db_handle; @@ -54,7 +56,14 @@ typedef struct { extern pdo_driver_t pdo_mysql_driver; extern int _pdo_mysql_error(char *what, int mysql_errno, const char *file, int line TSRMLS_DC); -#define pdo_mysql_error(w,s) _pdo_mysql_error(w, s, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_mysql_error(s) \ + s->mysql_errno = mysql_errno(s->server); \ + if (s->mysql_error) { \ + efree(s->mysql_error); \ + } \ + s->mysql_error = estrdup(mysql_error(s->server)); + + extern int mysql_handle_error(pdo_dbh_t *dbh, pdo_mysql_db_handle *H, int errcode); extern struct pdo_stmt_methods mysql_stmt_methods;