diff --git a/main/lib/db/CConnection.c b/main/lib/db/CConnection.c index cec0963b9..220448b6f 100644 --- a/main/lib/db/CConnection.c +++ b/main/lib/db/CConnection.c @@ -145,6 +145,7 @@ static void close_connection(CCONNECTION *_object) THIS->driver->Close(&THIS->db); GB.FreeString(&THIS->db.charset); + GB.FreeString(&THIS->db.full_version); THIS->db.handle = NULL; THIS->driver = NULL; @@ -210,6 +211,16 @@ BEGIN_PROPERTY(Connection_Version) END_PROPERTY +BEGIN_PROPERTY(Connection_FullVersion) + + CHECK_DB(); + CHECK_OPEN(); + + GB.ReturnString(THIS->db.full_version); + +END_PROPERTY + + BEGIN_PROPERTY(Connection_Timeout) if (READ_PROPERTY) @@ -466,7 +477,7 @@ BEGIN_METHOD(Connection_Exec, GB_STRING query; GB_VALUE param[0]) END_METHOD -BEGIN_METHOD(Connection_Create, GB_STRING table) +BEGIN_METHOD(Connection_Create, GB_STRING table; GB_BOOLEAN ret) CRESULT *result; char *table = GB.ToZeroString(ARG(table)); @@ -483,7 +494,14 @@ BEGIN_METHOD(Connection_Create, GB_STRING table) result = DB_MakeResult(THIS, RESULT_CREATE, table, NULL); if (result) + { + if (THIS->db.flags.no_returning) + DB_Debug("gb.db", "'RETURNING' keyword is not supported by this '%s' connection", THIS->driver->name); + else + result->returning = VARGOPT(ret, FALSE); + GB.ReturnObject(result); + } else GB.ReturnNull(); @@ -759,6 +777,7 @@ GB_DESC CConnectionDesc[] = //GB_PROPERTY("Timezone", "i", Connection_Timezone), GB_PROPERTY_READ("Charset", "s", Connection_Charset), GB_PROPERTY_READ("Version", "i", Connection_Version), + GB_PROPERTY_READ("FullVersion", "s", Connection_FullVersion), GB_PROPERTY_READ("Opened", "b", Connection_Opened), GB_PROPERTY_READ("Error", "i", Connection_Error), //GB_PROPERTY_READ("Transaction", "i", Connection_Transaction), @@ -773,7 +792,7 @@ GB_DESC CConnectionDesc[] = GB_METHOD("Limit", "Connection", Connection_Limit, "(Limit)i"), GB_METHOD("Exec", "Result", Connection_Exec, "(Request)s(Arguments)."), - GB_METHOD("Create", "Result", Connection_Create, "(Table)s"), + GB_METHOD("Create", "Result", Connection_Create, "(Table)s[(Return)b]"), GB_METHOD("Find", "Result", Connection_Find, "(Table)s[(Request)s(Arguments).]"), GB_METHOD("Edit", "Result", Connection_Edit, "(Table)s[(Request)s(Arguments).]"), GB_METHOD("Delete", NULL, Connection_Delete, "(Table)s[(Request)s(Arguments).]"), @@ -817,6 +836,7 @@ GB_DESC CDBDesc[] = GB_STATIC_PROPERTY_READ("Charset", "s", Connection_Charset), GB_STATIC_PROPERTY_READ("Version", "i", Connection_Version), + GB_STATIC_PROPERTY_READ("FullVersion", "s", Connection_FullVersion), GB_STATIC_PROPERTY_READ("Opened", "b", Connection_Opened), GB_STATIC_PROPERTY_READ("Error", "i", Connection_Error), //GB_STATIC_PROPERTY_READ("Transaction", "i", Connection_Transaction), @@ -830,7 +850,7 @@ GB_DESC CDBDesc[] = GB_STATIC_METHOD("Limit", "Connection", Connection_Limit, "(Limit)i"), GB_STATIC_METHOD("Exec", "Result", Connection_Exec, "(Request)s(Arguments)."), - GB_STATIC_METHOD("Create", "Result", Connection_Create, "(Table)s"), + GB_STATIC_METHOD("Create", "Result", Connection_Create, "(Table)s[(Return)b]"), GB_STATIC_METHOD("Find", "Result", Connection_Find, "(Table)s[(Request)s(Arguments).]"), GB_STATIC_METHOD("Edit", "Result", Connection_Edit, "(Table)s[(Request)s(Arguments).]"), GB_STATIC_METHOD("Delete", NULL, Connection_Delete, "(Table)s[(Request)s(Arguments).]"), diff --git a/main/lib/db/CResult.c b/main/lib/db/CResult.c index d639f8173..33eb46bfc 100644 --- a/main/lib/db/CResult.c +++ b/main/lib/db/CResult.c @@ -653,9 +653,14 @@ END_METHOD BEGIN_METHOD_VOID(Result_Update) - int i; + int i, j; bool comma; DB_INFO *info = &THIS->info; + int ret_first = -1; + int ret_count = 0; + GB_VARIANT_VALUE *ret_buffer; + bool err; + DB_RESULT res; if (check_available(THIS)) return; @@ -717,8 +722,55 @@ BEGIN_METHOD_VOID(Result_Update) q_add(" )"); - if (!THIS->driver->Exec(&THIS->conn->db, q_get(), NULL, "Cannot create record: &1")) - void_buffer(THIS); + if (THIS->returning) + { + comma = FALSE; + for (i = 0; i < info->nfield; i++) + { + if (info->field[i].type == DB_T_SERIAL) + { + ret_count++; + if (comma) + q_add(", "); + else + { + q_add(" RETURNING "); + ret_first = i; + } + q_add(THIS->driver->GetQuote()); + q_add(info->field[i].name); + q_add(THIS->driver->GetQuote()); + comma = TRUE; + } + } + + GB.Alloc(POINTER(&ret_buffer), sizeof(GB_VARIANT_VALUE) * ret_count); + for (i = 0; i < ret_count; i++) + ret_buffer[i].type = GB_T_NULL; + } + + if (ret_count) + err = THIS->driver->Exec(&THIS->conn->db, q_get(), &res, "Cannot create record: &1"); + else + err = THIS->driver->Exec(&THIS->conn->db, q_get(), NULL, "Cannot create record: &1"); + + if (!err) + { + if (!THIS->returning) + void_buffer(THIS); + else if (ret_count) + { + if (THIS->driver->Result.Fill(&THIS->conn->db, res, 0, ret_buffer, FALSE) == DB_OK) + { + THIS->buffer[ret_first] = ret_buffer[0]; + for (i = ret_first + 1, j = 1; i < info->nfield; i++) + { + if (info->field[i].type == DB_T_SERIAL) + THIS->buffer[i] = ret_buffer[j++]; + } + } + } + } break; diff --git a/main/lib/db/CResult.h b/main/lib/db/CResult.h index 4295cc511..d4883314e 100644 --- a/main/lib/db/CResult.h +++ b/main/lib/db/CResult.h @@ -68,6 +68,7 @@ typedef unsigned available : 1; unsigned no_seek : 1; unsigned mode : 2; + unsigned returning : 1; } CRESULT; diff --git a/main/lib/db/gb.db.h b/main/lib/db/gb.db.h index 414a7f69c..556aacb7e 100644 --- a/main/lib/db/gb.db.h +++ b/main/lib/db/gb.db.h @@ -49,8 +49,9 @@ typedef typedef struct { void *handle; /* Connection handle */ - int version; /* Version of the database system */ - char *charset; /* Charset used by the database */ + int version; /* Version of the database server */ + char *full_version; /* Full version of the database server */ + char *charset; /* Charset used by the database server */ void *data; /* Can be used by the driver for storing its own private data */ int error; /* Last SQL error code raise by a query */ int timeout; /* Connection timeout */ @@ -65,6 +66,7 @@ typedef //unsigned no_case : 1; /* table, field and index names must be converted to lower case */ unsigned schema : 1; /* If table names can be prefixed by a schema name and a dot */ unsigned no_collation : 1; /* No collation support at field level */ + unsigned no_returning : 1; /* Database does not support RETURNING keyword */ unsigned system : 1; /* system database */ } flags;