From e07ac2e4f2588f62bb55aa2b8351a08a810c1586 Mon Sep 17 00:00:00 2001 From: gambas Date: Tue, 20 Mar 2018 16:05:33 +0100 Subject: [PATCH] Connection.LastInsertId is a new property that returns the value of the serial field used in the last inserted row. [GB.DB] * NEW: Connection.LastInsertId is a new property that returns the value of the serial field used in the last inserted row. It is supported on MySQL, PostgreSQL and SQLite3 only. * BUG: Connection.Handle is correctly declared now. [GB.DB.MYSQL] * NEW: Support for Connection.LastInsertId. [GB.DB.ODBC] * NEW: Raise an error if Connection.LastInsertId is used. [GB.DB.POSTGRESQL] * NEW: Support for Connection.LastInsertId. [GB.DB.SQLITE2] * NEW: Raise an error if Connection.LastInsertId is used. [GB.DB.SQLITE3] * NEW: Support for Connection.LastInsertId. --- gb.db.mysql/src/main.c | 23 +++++++++++++++++++++++ gb.db.odbc/src/main.c | 17 +++++++++++++++++ gb.db.postgresql/src/main.c | 22 ++++++++++++++++++++-- gb.db.sqlite2/src/main.cpp | 17 +++++++++++++++++ gb.db.sqlite3/src/main.c | 21 +++++++++++++++++++++ main/lib/db/CConnection.c | 13 +++++++++++-- main/lib/db/CResult.c | 2 +- main/lib/db/gb.db.h | 1 + main/lib/db/gb.db.proto.h | 2 ++ 9 files changed, 113 insertions(+), 5 deletions(-) diff --git a/gb.db.mysql/src/main.c b/gb.db.mysql/src/main.c index 5610dc1dc..78dec8d55 100644 --- a/gb.db.mysql/src/main.c +++ b/gb.db.mysql/src/main.c @@ -946,6 +946,29 @@ static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT *result, con } +/***************************************************************************** + + get_last_insert_id() + + Return the value of the last serial field used in an INSERT statement + + is the database handle, as returned by open_database() + +*****************************************************************************/ + +static int64_t get_last_insert_id(DB_DATABASE *db) +{ + MYSQL_RES *res; + MYSQL_ROW row; + + if (do_query(db, "Unable to retrieve last insert id", &res, "select last_insert_id();", 0)) + return -1; + + row = mysql_fetch_row(res); + return atoll(row[0]); +} + + /***************************************************************************** query_init() diff --git a/gb.db.odbc/src/main.c b/gb.db.odbc/src/main.c index 8cb58c7ca..0990d3166 100644 --- a/gb.db.odbc/src/main.c +++ b/gb.db.odbc/src/main.c @@ -1211,6 +1211,7 @@ fflush(stderr); can be NULL, when we don't care getting the result. *****************************************************************************/ + static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT * result, const char *err) { #ifdef ODBC_DEBUG_HEADER @@ -1329,6 +1330,22 @@ fflush(stderr); } +/***************************************************************************** + + get_last_insert_id() + + Return the value of the last serial field used in an INSERT statement + + is the database handle, as returned by open_database() + +*****************************************************************************/ + +static int64_t get_last_insert_id(DB_DATABASE *db) +{ + GB.Error("Unsupported feature"); + return -1; +} + /***************************************************************************** query_init() diff --git a/gb.db.postgresql/src/main.c b/gb.db.postgresql/src/main.c index ccbcf9bcc..8370e8445 100644 --- a/gb.db.postgresql/src/main.c +++ b/gb.db.postgresql/src/main.c @@ -515,8 +515,7 @@ static void query_get_param(int index, char **str, int *len, char quote) /* Internal function to run a query */ -static int do_query(DB_DATABASE *db, const char *error, PGresult **pres, - const char *qtemp, int nsubst, ...) +static int do_query(DB_DATABASE *db, const char *error, PGresult **pres, const char *qtemp, int nsubst, ...) { PGconn *conn = (PGconn *)db->handle; va_list args; @@ -951,6 +950,25 @@ static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT *result, con } +/***************************************************************************** + + get_last_insert_id() + + Return the value of the last serial field used in an INSERT statement + + is the database handle, as returned by open_database() + +*****************************************************************************/ + +static int64_t get_last_insert_id(DB_DATABASE *db) +{ + PGresult *res; + + if (do_query(db, "Unable to retrieve last insert id: &1", &res, "select lastval()", 0)) + return -1; + + return atoll(PQgetvalue(res, 0, 0)); +} /***************************************************************************** diff --git a/gb.db.sqlite2/src/main.cpp b/gb.db.sqlite2/src/main.cpp index c8b46075d..cc21bc48b 100644 --- a/gb.db.sqlite2/src/main.cpp +++ b/gb.db.sqlite2/src/main.cpp @@ -752,6 +752,23 @@ static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT *result, con } +/***************************************************************************** + + get_last_insert_id() + + Return the value of the last serial field used in an INSERT statement + + is the database handle, as returned by open_database() + +*****************************************************************************/ + +static int64_t get_last_insert_id(DB_DATABASE *db) +{ + GB.Error("Unsupported feature"); + return -1; +} + + /***************************************************************************** query_init() diff --git a/gb.db.sqlite3/src/main.c b/gb.db.sqlite3/src/main.c index cf546fc06..8fc069078 100644 --- a/gb.db.sqlite3/src/main.c +++ b/gb.db.sqlite3/src/main.c @@ -791,6 +791,27 @@ static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT *result, con } +/***************************************************************************** + + get_last_insert_id() + + Return the value of the last serial field used in an INSERT statement + + is the database handle, as returned by open_database() + +*****************************************************************************/ + +static int64_t get_last_insert_id(DB_DATABASE *db) +{ + SQLITE_RESULT *res; + + if (do_query(db, "Unable to retrieve last insert id", &res, "select last_insert_rowid();", 0)) + return -1; + + return atoll(sqlite_query_get_string(res, 0, 0)); +} + + /***************************************************************************** query_init() diff --git a/main/lib/db/CConnection.c b/main/lib/db/CConnection.c index 792e88038..ac9bbad28 100644 --- a/main/lib/db/CConnection.c +++ b/main/lib/db/CConnection.c @@ -763,6 +763,13 @@ BEGIN_PROPERTY(Connection_Handle) END_PROPERTY +BEGIN_PROPERTY(Connection_LastInsertId) + + CHECK_DB(); + GB.ReturnLong((*THIS->driver->GetLastInsertId)(&THIS->db)); + +END_PROPERTY + GB_DESC CConnectionDesc[] = { GB_DECLARE("_Connection", sizeof(CCONNECTION)), @@ -786,7 +793,9 @@ GB_DESC CConnectionDesc[] = //GB_PROPERTY_READ("Transaction", "i", Connection_Transaction), GB_PROPERTY("IgnoreCharset", "b", CCONNECTION_ignore_charset), GB_PROPERTY_READ("Collations", "String[]", Connection_Collations), - GB_STATIC_PROPERTY_READ("Handle", "p", Connection_Handle), + GB_PROPERTY_READ("Handle", "p", Connection_Handle), + + GB_PROPERTY_READ("LastInsertId", "l", Connection_LastInsertId), GB_METHOD("Open", NULL, CCONNECTION_open, NULL), GB_METHOD("Close", NULL, CCONNECTION_close, NULL), @@ -865,7 +874,7 @@ GB_DESC CDBDesc[] = //GB_STATIC_PROPERTY("Views", ".ConnectionViews", CCONNECTION_views), GB_STATIC_PROPERTY("Databases", ".Connection.Databases", CCONNECTION_databases), GB_STATIC_PROPERTY("Users", ".Connection.Users", CCONNECTION_users), - + GB_END_DECLARE }; diff --git a/main/lib/db/CResult.c b/main/lib/db/CResult.c index 289c9060c..8b51e4a6c 100644 --- a/main/lib/db/CResult.c +++ b/main/lib/db/CResult.c @@ -855,7 +855,7 @@ GB_DESC CResultDesc[] = GB_METHOD("Update", NULL, Result_Update, NULL), GB_METHOD("Delete", NULL, Result_Delete, "[(Keep)b]"), - GB_METHOD("GetAll", "Array", Result_GetAll, "(Field)s"), + GB_METHOD("All", "Array", Result_GetAll, "(Field)s"), GB_PROPERTY_READ("Fields", ".Result.Fields", Result_Fields), GB_PROPERTY_READ("Connection", "Connection", Result_Connection), diff --git a/main/lib/db/gb.db.h b/main/lib/db/gb.db.h index 14c6fdfb8..cdad5cc24 100644 --- a/main/lib/db/gb.db.h +++ b/main/lib/db/gb.db.h @@ -151,6 +151,7 @@ typedef int (*Rollback)(DB_DATABASE *db); GB_ARRAY (*GetCollations)(DB_DATABASE *db); const char *(*GetQuote)(void); + int64_t (*GetLastInsertId)(DB_DATABASE *db); struct { void (*Init)(DB_RESULT result, DB_INFO *info, int *count); diff --git a/main/lib/db/gb.db.proto.h b/main/lib/db/gb.db.proto.h index 555e20e45..a270a1981 100644 --- a/main/lib/db/gb.db.proto.h +++ b/main/lib/db/gb.db.proto.h @@ -30,6 +30,7 @@ static const char *get_quote(void); static int open_database(DB_DESC *desc, DB_DATABASE *db); static void close_database(DB_DATABASE *db); static GB_ARRAY get_collations(DB_DATABASE *db); +static int64_t get_last_insert_id(DB_DATABASE *db); static int format_value(GB_VALUE *arg, DB_FORMAT_CALLBACK add); static void format_blob(DB_BLOB *blob, DB_FORMAT_CALLBACK add); static int exec_query(DB_DATABASE *db, const char *query, DB_RESULT *result, const char *err); @@ -89,6 +90,7 @@ static DB_DRIVER _driver = \ rollback_transaction, \ get_collations, \ get_quote, \ + get_last_insert_id, \ { \ query_init, \ query_fill, \