From fa585cc90dbc022f5c11aa72a83e5c92852b0772 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 6 Sep 2021 14:13:07 +0200 Subject: [PATCH 01/19] Fixed issue #281 (SYS.RAW type with Oracle AQ) --- include/ocilibc/api.h | 2 +- src/dequeue.c | 27 +++++++++--------- src/environment.c | 3 ++ src/import.h | 1 + src/message.c | 4 ++- src/oci/api.h | 16 +++++++++++ src/typeinfo.c | 64 ++++++++++++++++++++++++++++++++++++------- tests/TestQueue.cpp | 62 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 154 insertions(+), 25 deletions(-) diff --git a/include/ocilibc/api.h b/include/ocilibc/api.h index d6785504..bfb317ea 100644 --- a/include/ocilibc/api.h +++ b/include/ocilibc/api.h @@ -16311,7 +16311,7 @@ OCI_SYM_PUBLIC boolean OCI_API OCI_QueueStop * @note * Possible values for parameter 'queue_payload_type' : * - For Oracle types (UDT) : use the type name ([schema.].type_name) - * - For RAW data : use "SYS.RAW" or "RAW" + * - For RAW data : use "SYS.RAW" or "RAW" (depending on Oracle versions - For latest ones, use "RAW") * * @note * Possible values for parameter 'message_grouping' : diff --git a/src/dequeue.c b/src/dequeue.c index 957a3155..1d75b61f 100644 --- a/src/dequeue.c +++ b/src/dequeue.c @@ -329,26 +329,27 @@ OCI_Msg * OcilibDequeueGetMessage if (OCI_SUCCESSFUL(ret)) { /* get payload */ - - if (OCI_UNKNOWN != dequeue->typinf->typecode) + + if (p_ind && (OCI_IND_NULL != (*(OCIInd *) p_ind))) { - if (p_ind && (OCI_IND_NULL != (*(OCIInd *) p_ind))) + dequeue->msg->ind = *(OCIInd *) p_ind; + + if (OCI_UNKNOWN != dequeue->typinf->typecode) { - dequeue->msg->ind = *(OCIInd *) p_ind; dequeue->msg->obj = OcilibObjectInitialize - ( - dequeue->typinf->con, - (OCI_Object*)dequeue->msg->obj, - dequeue->msg->payload, - dequeue->typinf, - NULL, -1, TRUE - ); + ( + dequeue->typinf->con, + (OCI_Object*)dequeue->msg->obj, + dequeue->msg->payload, + dequeue->typinf, + NULL, -1, TRUE + ); CHECK_NULL(dequeue->msg->obj) - - msg = dequeue->msg; } + + msg = dequeue->msg; } } diff --git a/src/environment.c b/src/environment.c index b9920e6f..469fadc1 100644 --- a/src/environment.c +++ b/src/environment.c @@ -419,6 +419,7 @@ OCIARRAYDESCRIPTORALLOC OCIArrayDescriptorAlloc = NULL; OCIARRAYDESCRIPTORFREE OCIArrayDescriptorFree = NULL; OCICLIENTVERSION OCIClientVersion = NULL; OCITYPEBYREF OCITypeByRef = NULL; +OCITYPEBYNAME OCITypeByName = NULL; OCINUMBERTOINT OCINumberToInt = NULL; OCINUMBERFROMINT OCINumberFromInt = NULL; OCINUMBERTOREAL OCINumberToReal = NULL; @@ -1071,6 +1072,8 @@ boolean OcilibEnvironmentInitialize LIB_SYMBOL(Env.lib_handle, "OCITypeByRef", OCITypeByRef, OCITYPEBYREF); + LIB_SYMBOL(Env.lib_handle, "OCITypeByName", OCITypeByName, + OCITYPEBYNAME); LIB_SYMBOL(Env.lib_handle, "OCINumberToInt", OCINumberToInt, OCINUMBERTOINT); diff --git a/src/import.h b/src/import.h index 1a4e928c..b498d5c0 100644 --- a/src/import.h +++ b/src/import.h @@ -186,6 +186,7 @@ extern OCIARRAYDESCRIPTORALLOC OCIArrayDescriptorAlloc; extern OCIARRAYDESCRIPTORFREE OCIArrayDescriptorFree; extern OCICLIENTVERSION OCIClientVersion; extern OCITYPEBYREF OCITypeByRef; +extern OCITYPEBYNAME OCITypeByName; extern OCINUMBERTOINT OCINumberToInt; extern OCINUMBERFROMINT OCINumberFromInt; extern OCINUMBERTOREAL OCINumberToReal; diff --git a/src/message.c b/src/message.c index 0d14a559..74c98433 100644 --- a/src/message.c +++ b/src/message.c @@ -122,7 +122,7 @@ boolean OcilibMessageFree /* free message RAW payload if necessary */ - if (NULL != msg->id && (OCI_UNKNOWN == msg->typinf->typecode)) + if (NULL != msg->payload && (OCI_UNKNOWN == msg->typinf->typecode)) { CHECK_OCI ( @@ -133,6 +133,8 @@ boolean OcilibMessageFree ) } + msg->payload = NULL; + /* free message ID */ if (NULL != msg->id) diff --git a/src/oci/api.h b/src/oci/api.h index 8de420d6..f764214e 100644 --- a/src/oci/api.h +++ b/src/oci/api.h @@ -1097,6 +1097,22 @@ typedef sword (*OCITYPEBYREF) OCIType **tdo ); +typedef sword (*OCITYPEBYNAME) +( + OCIEnv *env, + OCIError *err, + const OCISvcCtx *svc, + const oratext* schema_name, + ub4 s_length, + const oratext *type_name, + ub4 t_length, + const oratext *version_name, + ub4 v_length, + OCIDuration pin_duration, + OCITypeGetOpt get_option, + OCIType **tdo +); + typedef sword (*OCIOBJECTNEW) ( OCIEnv *env, diff --git a/src/typeinfo.c b/src/typeinfo.c index ecf70422..b3508800 100644 --- a/src/typeinfo.c +++ b/src/typeinfo.c @@ -139,6 +139,10 @@ OCI_TypeInfo * OcilibTypeInfoGet size_t max_chars = sizeof(buffer) / sizeof(otext) - 1; dbtext* dbstr1 = NULL; int dbsize1 = -1; + dbtext* dbstr2 = NULL; + int dbsize2 = -1; + dbtext* dbstr3 = NULL; + int dbsize3 = -1; sb4 pbsp = 1; otext obj_schema[OCI_SIZE_OBJ_NAME + 1]; @@ -242,17 +246,52 @@ OCI_TypeInfo * OcilibTypeInfoGet dschp, &pbsp, sizeof(pbsp), con->err ) - + /* describe call */ - CHECK_OCI - ( - con->err, - OCIDescribeAny, - con->cxt, con->err, (dvoid *) dbstr1, - (ub4) dbsize1, OCI_OTYPE_NAME, - OCI_DEFAULT, OCI_PTYPE_UNK, dschp - ) + if (OCI_TIF_TYPE == type) + { + OCIType* tdo = NULL; + + /* for types, as OCIDescribeAny() doest not support some cases like SYS.RAW anymore + like on previous Oracle versions, let's use OCITypeByName() + */ + + dbstr2 = OcilibStringGetDBString(typinf->schema, &dbsize2); + dbstr3 = OcilibStringGetDBString(typinf->name, &dbsize3); + + CHECK_OCI + ( + con->err, + OCITypeByName, + con->env, con->err, con->cxt, + (CONST text*) dbstr2, dbsize2, + (CONST text*) dbstr3, dbsize3, + (text*)0, 0, + OCI_DURATION_SESSION, OCI_TYPEGET_ALL, + &tdo + ) + + CHECK_OCI + ( + con->err, + OCIDescribeAny, + con->cxt, con->err, tdo, + (ub4) 0, OCI_OTYPE_PTR, + OCI_DEFAULT, OCI_PTYPE_UNK, dschp + ) + } + else + { + CHECK_OCI + ( + con->err, + OCIDescribeAny, + con->cxt, con->err, (dvoid*)dbstr1, + (ub4)dbsize1, OCI_OTYPE_NAME, + OCI_DEFAULT, OCI_PTYPE_UNK, dschp + ) + } /* get parameter handle */ @@ -415,7 +454,10 @@ OCI_TypeInfo * OcilibTypeInfoGet } default: { - THROW(OcilibExceptionDatatypeNotSupported, typinf->typecode) + if (!pdt) + { + THROW(OcilibExceptionDatatypeNotSupported, typinf->typecode) + } break; } } @@ -550,6 +592,8 @@ OCI_TypeInfo * OcilibTypeInfoGet CLEANUP_AND_EXIT_FUNC ( OcilibStringReleaseDBString(dbstr1); + OcilibStringReleaseDBString(dbstr2); + OcilibStringReleaseDBString(dbstr3); /* free temporary strings */ diff --git a/tests/TestQueue.cpp b/tests/TestQueue.cpp index 2bb3929c..1a107f7e 100644 --- a/tests/TestQueue.cpp +++ b/tests/TestQueue.cpp @@ -182,4 +182,66 @@ TEST(TestQueue, MessageWithConsumers) ASSERT_TRUE(OCI_Cleanup()); ExecDML(OTEXT("drop type TestQueueMessageWithConsumersType")); +} + + +TEST(TestQueue, SingleRawMessage) +{ + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + // no check - for cleanup + OCI_QueueStop(conn, OTEXT("TestQueueSingleRawMessage"), TRUE, TRUE, FALSE); + OCI_QueueDrop(conn, OTEXT("TestQueueSingleRawMessage")); + OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleRawMessageTable"), TRUE); + // end no check + + ASSERT_TRUE(OCI_QueueTableCreate(conn, OTEXT("TestQueueSingleRawMessageTable"), OTEXT("RAW"), NULL, NULL, FALSE, OCI_AGM_NONE, NULL, 0, 0, NULL)); + ASSERT_TRUE(OCI_QueueCreate(conn, OTEXT("TestQueueSingleRawMessage"), OTEXT("TestQueueSingleRawMessageTable"), OCI_AQT_NORMAL, 0, 0, 0, FALSE, NULL)); + ASSERT_TRUE(OCI_QueueStart(conn, OTEXT("TestQueueSingleRawMessage"), TRUE, TRUE)); + + const auto inf = OCI_TypeInfoGet(conn, OTEXT("SYS.RAW"), OCI_TIF_TYPE); + ASSERT_NE(nullptr, inf); + + const auto enq = OCI_EnqueueCreate(inf, OTEXT("TestQueueSingleRawMessage")); + ASSERT_NE(nullptr, enq); + + const auto deq = OCI_DequeueCreate(inf, OTEXT("TestQueueSingleRawMessage")); + ASSERT_NE(nullptr, deq); + + const auto msg_in = OCI_MsgCreate(inf); + ASSERT_NE(nullptr, msg_in); + + const auto byteBring = ostring(OTEXT("123456789")); + ASSERT_TRUE(OCI_MsgSetRaw(msg_in, static_cast(byteBring.data()), static_cast(byteBring.size()))); + + ASSERT_TRUE(OCI_EnqueuePut(enq, msg_in)); + + ASSERT_TRUE(OCI_MsgFree(msg_in)); + + ASSERT_TRUE(OCI_Commit(conn)); + + const auto msg_out = OCI_DequeueGet(deq); + ASSERT_NE(nullptr, msg_out); + + otext buffer[100] = OTEXT(""); + unsigned int size = 100; + ASSERT_TRUE(OCI_MsgGetRaw(msg_out, static_cast(buffer), &size)); + + ASSERT_EQ(byteBring, ostring(buffer)); + ASSERT_EQ(byteBring.size(), size); + + ASSERT_TRUE(OCI_EnqueueFree(enq)); + ASSERT_TRUE(OCI_DequeueFree(deq)); + + ASSERT_TRUE(OCI_Commit(conn)); + + ASSERT_TRUE(OCI_QueueStop(conn, OTEXT("TestQueueSingleRawMessage"), TRUE, TRUE, FALSE)); + ASSERT_TRUE(OCI_QueueDrop(conn, OTEXT("TestQueueSingleRawMessage"))); + ASSERT_TRUE(OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleRawMessageTable"), TRUE)); + + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); } \ No newline at end of file From 663b0f8937ba7c3139632710c227cfa3a82298d9 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 6 Sep 2021 14:16:21 +0200 Subject: [PATCH 02/19] Fix for issue #272 (code sanitizer finding) --- include/ocilibcpp/detail/support/BindObjectAdaptor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ocilibcpp/detail/support/BindObjectAdaptor.hpp b/include/ocilibcpp/detail/support/BindObjectAdaptor.hpp index 5981f3fc..fb0dee2c 100644 --- a/include/ocilibcpp/detail/support/BindObjectAdaptor.hpp +++ b/include/ocilibcpp/detail/support/BindObjectAdaptor.hpp @@ -72,7 +72,7 @@ namespace ocilib template BindObjectAdaptor::~BindObjectAdaptor() noexcept { - delete core::OnDeallocate(_data); + delete[] core::OnDeallocate(_data); } template From 93ecd475a85255bfe5aaf36cf7923ea19fd43273 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 6 Sep 2021 18:23:33 +0200 Subject: [PATCH 03/19] Fixed Issue #278. Was a multi-threading race condition issue on the TypeInfo Object internal ref counter management. Internal list locking mecanism was also modified to avoid race conditions such the one that could occurs in OcilibTypeInfoGet() between the lookup and the creation --- src/array.c | 23 +++++++- src/callback.c | 8 ++- src/connection.c | 61 ++++++++++++++++---- src/environment.c | 52 +++++++++++------ src/list.c | 85 +++++++++++++++++---------- src/list.h | 10 ++++ src/macros.h | 9 ++- src/object.c | 8 ++- src/pool.c | 20 ++++++- src/statement.c | 20 ++++++- src/subscription.c | 22 +++++-- src/transaction.c | 21 +++++-- src/typeinfo.c | 121 ++++++++++++++++++++++++++++++++------- src/types.h | 1 + tests/TestCollection.cpp | 4 +- 15 files changed, 365 insertions(+), 100 deletions(-) diff --git a/src/array.c b/src/array.c index f4905603..a2d6e602 100644 --- a/src/array.c +++ b/src/array.c @@ -223,7 +223,14 @@ OCI_Array * OcilibArrayCreate /* create array object */ - arr = OcilibListAppend(Env.arrs, sizeof(*arr)); + LOCK_LIST + ( + Env.arrs, + { + arr = OcilibListAppend(Env.arrs, sizeof(*arr)); + } + ) + CHECK_NULL(arr) arr->con = con; @@ -297,10 +304,20 @@ boolean OcilibArrayFreeFromHandles CHECK_PTR(OCI_IPC_VOID, handles) - arr = OcilibListFind(Env.arrs, (POCI_LIST_FIND) OcilibArrayFindAny, handles); + LOCK_LIST + ( + Env.arrs, + { + arr = OcilibListFind(Env.arrs, (POCI_LIST_FIND)OcilibArrayFindAny, handles); + if (NULL != arr) + { + OcilibListRemove(Env.arrs, arr); + } + } + ) + CHECK_NULL(arr) - OcilibListRemove(Env.arrs, arr); OcilibArrayDispose(arr); FREE(arr) diff --git a/src/callback.c b/src/callback.c index 88f1d3ab..b185de85 100644 --- a/src/callback.c +++ b/src/callback.c @@ -632,7 +632,13 @@ void OcilibCallbackHAEvent /* notify all related connections */ - OcilibListForEachWithParam(Env.cons, ¶ms, (POCI_LIST_FOR_EACH_WITH_PARAM)OcilibProcHAEventInvoke); + LOCK_LIST + ( + Env.cons, + { + OcilibListForEachWithParam(Env.cons, ¶ms, (POCI_LIST_FOR_EACH_WITH_PARAM)OcilibProcHAEventInvoke); + } + ) /* get next server */ diff --git a/src/connection.c b/src/connection.c index 73aaa429..95c63790 100644 --- a/src/connection.c +++ b/src/connection.c @@ -112,7 +112,16 @@ OCI_Connection * OcilibConnectionAllocate /* create connection object */ - OCI_Connection *con = OcilibListAppend(Env.cons, sizeof(*con)); + OCI_Connection* con = NULL; + + LOCK_LIST + ( + Env.cons, + { + con = OcilibListAppend(Env.cons, sizeof(*con)); + } + ) + CHECK_NULL(con) con->alloc_handles = (0 == (mode & OCI_SESSION_XA)); @@ -958,25 +967,48 @@ static boolean OcilibConnectionLogOff } /* dissociate connection from existing subscriptions */ - - OcilibListForEachWithParam(Env.subs, con, (POCI_LIST_FOR_EACH_WITH_PARAM) OcilibConnectionDetachSubscriptions); + LOCK_LIST + ( + Env.subs, + { + OcilibListForEachWithParam(Env.subs, con, (POCI_LIST_FOR_EACH_WITH_PARAM)OcilibConnectionDetachSubscriptions); + } + ) WARNING_DISABLE_CAST_FUNC_TYPE /* free all statements */ - OcilibListForEach(con->stmts, (POCI_LIST_FOR_EACH)OcilibStatementDispose); - OcilibListClear(con->stmts); + LOCK_LIST + ( + con->stmts, + { + OcilibListForEach(con->stmts, (POCI_LIST_FOR_EACH)OcilibStatementDispose); + OcilibListClear(con->stmts); + } + ) /* free all type info objects */ - OcilibListForEach(con->tinfs, (POCI_LIST_FOR_EACH)OcilibTypeInfoDispose); - OcilibListClear(con->tinfs); + LOCK_LIST + ( + con->tinfs, + { + OcilibListForEach(con->tinfs, (POCI_LIST_FOR_EACH)OcilibTypeInfoDispose); + OcilibListClear(con->tinfs); + } + ) /* free all transactions */ - OcilibListForEach(con->trsns, (POCI_LIST_FOR_EACH)OcilibTransactionDispose); - OcilibListClear(con->trsns); + LOCK_LIST + ( + con->trsns, + { + OcilibListForEach(con->trsns, (POCI_LIST_FOR_EACH)OcilibTransactionDispose); + OcilibListClear(con->trsns); + } + ) WARNING_RESTORE_CAST_FUNC_TYPE @@ -1211,8 +1243,15 @@ boolean OcilibConnectionFree CHECK_PTR(OCI_IPC_CONNECTION, con) - OcilibConnectionDispose(con); - OcilibListRemove(Env.cons, con); + LOCK_LIST + ( + Env.cons, + { + OcilibListRemove(Env.cons, con); + } + ) + + CHECK(OcilibConnectionDispose(con)) FREE(con) diff --git a/src/environment.c b/src/environment.c index 469fadc1..b8019a0c 100644 --- a/src/environment.c +++ b/src/environment.c @@ -1530,29 +1530,47 @@ boolean OcilibEnvironmentCleanup /* dispose list items */ - OcilibListForEach(Env.arrs, (POCI_LIST_FOR_EACH)OcilibArrayDispose); - OcilibListForEach(Env.subs, (POCI_LIST_FOR_EACH)OcilibSubscriptionDispose); - OcilibListForEach(Env.cons, (POCI_LIST_FOR_EACH)OcilibConnectionDispose); - OcilibListForEach(Env.pools, (POCI_LIST_FOR_EACH)OcilibPoolDispose); - - /* free all arrays */ + LOCK_LIST + ( + Env.arrs, + { + OcilibListForEach(Env.arrs, (POCI_LIST_FOR_EACH)OcilibArrayDispose); + OcilibListClear(Env.arrs); + } + ) - OcilibListClear(Env.arrs); - OcilibListFree(Env.arrs); + LOCK_LIST + ( + Env.subs, + { + OcilibListClear(Env.subs); + OcilibListForEach(Env.subs, (POCI_LIST_FOR_EACH)OcilibSubscriptionDispose); + } + ) - /* free all subscriptions */ + LOCK_LIST + ( + Env.cons, + { + OcilibListClear(Env.cons); + OcilibListForEach(Env.cons, (POCI_LIST_FOR_EACH)OcilibConnectionDispose); + } + ) - OcilibListClear(Env.subs); - OcilibListFree(Env.subs); + LOCK_LIST + ( + Env.pools, + { + OcilibListClear(Env.pools); + OcilibListForEach(Env.pools, (POCI_LIST_FOR_EACH)OcilibPoolDispose); + } + ) - /* free all connections */ + /* free all lists */ - OcilibListClear(Env.cons); + OcilibListFree(Env.arrs); + OcilibListFree(Env.subs); OcilibListFree(Env.cons); - - /* free all pools */ - - OcilibListClear(Env.pools); OcilibListFree(Env.pools); /* free key map */ diff --git a/src/list.c b/src/list.c index b6c41fcc..7ac0de1c 100644 --- a/src/list.c +++ b/src/list.c @@ -24,35 +24,18 @@ #include "memory.h" #include "mutex.h" -#define ACQUIRE_LOCK() \ - \ - if (NULL != list->mutex) \ - { \ - CHECK(OcilibMutexAcquire(list->mutex)) \ - } - -#define RELEASE_LOCK() \ - \ - if (NULL != list->mutex) \ - { \ - CHECK(OcilibMutexRelease(list->mutex)) \ - } - #define LIST_FOR_EACH(exp) \ \ if (list) \ { \ OCI_Item *item = NULL; \ - ACQUIRE_LOCK() \ item = list->head; \ while (item) \ { \ exp; \ item = item->next; \ } \ - RELEASE_LOCK() \ } - /* --------------------------------------------------------------------------------------------- * * OcilibListCreateItem * --------------------------------------------------------------------------------------------- */ @@ -171,6 +154,7 @@ boolean OcilibListFree if (NULL!= list->mutex) { OcilibMutexFree(list->mutex); + list->mutex = NULL; } OcilibErrorResetSource(NULL, list); @@ -203,8 +187,6 @@ void * OcilibListAppend CHECK_PTR(OCI_IPC_LIST, list) - ACQUIRE_LOCK() - item = OcilibListCreateItem(list->type, size); CHECK_NULL(item) @@ -226,8 +208,6 @@ void * OcilibListAppend list->count++; - RELEASE_LOCK() - SET_RETVAL(item->data) EXIT_FUNC() @@ -252,8 +232,6 @@ boolean OcilibListClear CHECK_PTR(OCI_IPC_LIST, list) - ACQUIRE_LOCK() - /* walk along the list to free item's buffer */ item = list->head; @@ -273,8 +251,6 @@ boolean OcilibListClear list->head = NULL; list->count = 0; - RELEASE_LOCK() - SET_SUCCESS() EXIT_FUNC() @@ -355,8 +331,6 @@ boolean OcilibListRemove CHECK_PTR(OCI_IPC_LIST, list) CHECK_PTR(OCI_IPC_VOID, data) - ACQUIRE_LOCK() - item = list->head; boolean found = FALSE; @@ -394,8 +368,6 @@ boolean OcilibListRemove list->count--; } - RELEASE_LOCK() - SET_RETVAL(found) EXIT_FUNC() @@ -467,3 +439,58 @@ void * OcilibListFind EXIT_FUNC() } + +/* --------------------------------------------------------------------------------------------- * +* OcilibListLock +* --------------------------------------------------------------------------------------------- */ + +boolean OcilibListLock +( + OCI_List* list +) +{ + ENTER_FUNC + ( + /* returns */ boolean, FALSE, + /* context */ OCI_IPC_LIST, list + ) + + CHECK_PTR(OCI_IPC_LIST, list) + + if (NULL != list->mutex) + { + CHECK(OcilibMutexAcquire(list->mutex)) + } + + SET_SUCCESS() + + EXIT_FUNC() +} + +/* --------------------------------------------------------------------------------------------- * +* OcilibListUnlock +* --------------------------------------------------------------------------------------------- */ + +boolean OcilibListUnlock +( + OCI_List* list +) +{ + ENTER_FUNC + ( + /* returns */ boolean, FALSE, + /* context */ OCI_IPC_LIST, list + ) + + CHECK_PTR(OCI_IPC_LIST, list) + + if (NULL != list->mutex) + { + CHECK(OcilibMutexRelease(list->mutex)) + } + + SET_SUCCESS() + + EXIT_FUNC() +} + diff --git a/src/list.h b/src/list.h index b75fed92..26057a49 100644 --- a/src/list.h +++ b/src/list.h @@ -93,4 +93,14 @@ OCI_SYM_LOCAL void * OcilibListFind void * param ); +OCI_SYM_LOCAL boolean OcilibListLock +( + OCI_List* list +); + +OCI_SYM_LOCAL boolean OcilibListUnlock +( + OCI_List* list +); + #endif /* OCILIB_LIST_H_INCLUDED */ diff --git a/src/macros.h b/src/macros.h index 25783b48..aab86ec5 100644 --- a/src/macros.h +++ b/src/macros.h @@ -472,6 +472,13 @@ ExitLabel: \ ( \ err, OCIAttrSet, (void*) (handle), (ub4) (htype), (void*) (value), \ (ub4) (size), (ub4) (atype), err \ - ) \ + ) + + +#define LOCK_LIST(list, exp) \ + \ + OcilibListLock(list); \ + exp \ + OcilibListUnlock(list); \ #endif /* OCILIB_MACROS_H_INCLUDED */ diff --git a/src/object.c b/src/object.c index 9ca98d66..c66312ab 100644 --- a/src/object.c +++ b/src/object.c @@ -202,7 +202,13 @@ static OCI_TypeInfo * ObjectGetRealTypeInfo(OCI_TypeInfo *typinf, void *object) /* first try to find it in list */ - parent = OcilibListFind(typinf->con->tinfs, (POCI_LIST_FIND)OcilibObjectTypeInfoFind, tdo); + LOCK_LIST + ( + typinf->con->tinfs, + { + parent = OcilibListFind(typinf->con->tinfs, (POCI_LIST_FIND)OcilibObjectTypeInfoFind, tdo); + } + ) /* if found, it will be assigned in the cleanup part */ diff --git a/src/pool.c b/src/pool.c index a5b276cf..832eb0e6 100644 --- a/src/pool.c +++ b/src/pool.c @@ -169,7 +169,14 @@ OCI_Pool * OcilibPoolCreate /* create pool object */ - pool = OcilibListAppend(Env.pools, sizeof(*pool)); + LOCK_LIST + ( + Env.pools, + { + pool = OcilibListAppend(Env.pools, sizeof(*pool)); + } + ) + CHECK_NULL(pool) pool->mode = mode; @@ -388,8 +395,15 @@ boolean OcilibPoolFree CHECK_PTR(OCI_IPC_POOL, pool) - OcilibPoolDispose(pool); - OcilibListRemove(Env.pools, pool); + LOCK_LIST + ( + Env.pools, + { + OcilibListRemove(Env.pools, pool); + } + ) + + CHECK(OcilibPoolDispose(pool)) FREE(pool) diff --git a/src/statement.c b/src/statement.c index 23a4c64f..b2fc10c8 100644 --- a/src/statement.c +++ b/src/statement.c @@ -1520,7 +1520,16 @@ OCI_Statement * OcilibStatementCreate /* create statement object */ - OCI_Statement *stmt = OcilibListAppend(con->stmts, sizeof(*stmt)); + OCI_Statement *stmt = NULL; + + LOCK_LIST + ( + con->stmts, + { + stmt = OcilibListAppend(con->stmts, sizeof(*stmt)); + } + ) + CHECK_NULL(stmt) SET_RETVAL(OcilibStatementInitialize(con, (OCI_Statement*)stmt, NULL, FALSE, NULL)) @@ -1546,8 +1555,15 @@ boolean OcilibStatementFree CHECK_PTR(OCI_IPC_STATEMENT, stmt) CHECK_OBJECT_FETCHED(stmt) + LOCK_LIST + ( + stmt->con->stmts, + { + OcilibListRemove(stmt->con->stmts, stmt); + } + ) + OcilibStatementDispose(stmt); - OcilibListRemove(stmt->con->stmts, stmt); FREE(stmt) diff --git a/src/subscription.c b/src/subscription.c index 73c7bb96..d0991ef8 100644 --- a/src/subscription.c +++ b/src/subscription.c @@ -172,7 +172,14 @@ OCI_Subscription * OcilibSubscriptionRegister /* create subscription object */ - sub = OcilibListAppend(Env.subs, sizeof(*sub)); + LOCK_LIST + ( + Env.subs, + { + sub = OcilibListAppend(Env.subs, sizeof(*sub)); + } + ) + CHECK_NULL(sub) /* allocate error handle */ @@ -326,8 +333,8 @@ OCI_Subscription * OcilibSubscriptionRegister { OcilibStringReleaseDBString(dbstr); - OcilibSubscriptionDispose(sub); - OcilibListRemove(Env.subs, sub); + OcilibSubscriptionUnregister(sub); + FREE(sub) } ) @@ -350,8 +357,15 @@ boolean OcilibSubscriptionUnregister CHECK_PTR(OCI_IPC_NOTIFY, sub) + LOCK_LIST + ( + Env.subs, + { + OcilibListRemove(Env.subs, sub); + } + ) + OcilibSubscriptionDispose(sub); - OcilibListRemove(Env.subs, sub); FREE(sub); diff --git a/src/transaction.c b/src/transaction.c index 27dc4022..d35d2f19 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -86,7 +86,14 @@ OCI_Transaction * OcilibTransactionCreate /* create transaction object */ - trans = OcilibListAppend(con->trsns, sizeof(*trans)); + LOCK_LIST + ( + con->trsns, + { + trans = OcilibListAppend(con->trsns, sizeof(*trans)); + } + ) + CHECK_NULL(trans) trans->con = con; @@ -141,11 +148,17 @@ boolean OcilibTransactionFree CHECK_PTR(OCI_IPC_TRANSACTION, trans) - OcilibTransactionDispose(trans); - /* remove transaction from internal list */ - OcilibListRemove(trans->con->trsns, trans); + LOCK_LIST + ( + trans->con->trsns, + { + OcilibListRemove(trans->con->trsns, trans); + } + ) + + CHECK(OcilibTransactionDispose(trans)) FREE(trans) diff --git a/src/typeinfo.c b/src/typeinfo.c index b3508800..68a0dd43 100644 --- a/src/typeinfo.c +++ b/src/typeinfo.c @@ -24,6 +24,7 @@ #include "list.h" #include "macros.h" #include "memory.h" +#include "mutex.h" #include "stringutils.h" static unsigned int TypeInfoTypeValues[] = @@ -39,7 +40,7 @@ typedef struct TypeInfoFindParams otext * schema; otext * name; } TypeInfoFindParams; - + /* --------------------------------------------------------------------------------------------- * * OcilibTypeInfoFind * --------------------------------------------------------------------------------------------- */ @@ -54,6 +55,70 @@ static boolean OcilibTypeInfoFind(OCI_TypeInfo *typinf, TypeInfoFindParams *find OcilibStringCaseCompare(typinf->schema, find_params->schema) == 0; } + +/* --------------------------------------------------------------------------------------------- * + * OcilibTypeInfoUpdateRefCounter + * --------------------------------------------------------------------------------------------- */ + +static void OcilibTypeInfoUpdateRefCounter(OCI_TypeInfo* typinf, sb2 value) +{ + if (typinf == NULL) + { + return; + } + + if (NULL != typinf->mutex) + { + OcilibMutexAcquire(typinf->mutex); + } + + typinf->refcount += value; + + if (NULL != typinf->mutex) + { + OcilibMutexRelease(typinf->mutex); + } +} + +/* --------------------------------------------------------------------------------------------- * + * OcilibTypeInfoFindOrCreate + * --------------------------------------------------------------------------------------------- */ + +static OCI_TypeInfo* OcilibTypeInfoFindOrCreate(OCI_Connection* con, TypeInfoFindParams* p_find_params, boolean* p_is_created) +{ + *p_is_created = FALSE; + + OCI_TypeInfo* typinf = OcilibListFind(con->tinfs, (POCI_LIST_FIND)OcilibTypeInfoFind, p_find_params); + + if (NULL == typinf) + { + typinf = OcilibListAppend(con->tinfs, sizeof(OCI_TypeInfo)); + if (typinf == NULL) + { + return typinf; + } + + typinf->con = con; + typinf->name = OcilibStringDuplicate(p_find_params->name); + typinf->schema = OcilibStringDuplicate(p_find_params->schema); + typinf->struct_size = 0; + typinf->align = 0; + + if (LIB_THREADED) + { + typinf->mutex = OcilibMutexCreateInternal(); + } + + *p_is_created = TRUE; + } + + /* increment type info reference counter on success */ + + OcilibTypeInfoUpdateRefCounter(typinf, 1); + + return typinf; +} + /* --------------------------------------------------------------------------------------------- * * OcilibTypeInfoDispose * --------------------------------------------------------------------------------------------- */ @@ -81,6 +146,12 @@ boolean OcilibTypeInfoDispose FREE(typinf->schema) FREE(typinf->offsets) + if (NULL != typinf->mutex) + { + OcilibMutexFree(typinf->mutex); + typinf->mutex = NULL; + } + OcilibErrorResetSource(NULL, typinf); SET_SUCCESS() @@ -148,6 +219,8 @@ OCI_TypeInfo * OcilibTypeInfoGet otext obj_schema[OCI_SIZE_OBJ_NAME + 1]; otext obj_name[OCI_SIZE_OBJ_NAME + 1]; + boolean is_created = FALSE; + CHECK_PTR(OCI_IPC_CONNECTION, con) CHECK_PTR(OCI_IPC_STRING, name) CHECK_ENUM_VALUE(type, TypeInfoTypeValues, OTEXT("Type")) @@ -200,23 +273,22 @@ OCI_TypeInfo * OcilibTypeInfoGet find_params.name = obj_name; find_params.schema = obj_schema; - typinf = OcilibListFind(con->tinfs, (POCI_LIST_FIND)OcilibTypeInfoFind, &find_params); + LOCK_LIST + ( + con->tinfs, + { + typinf = OcilibTypeInfoFindOrCreate(con, &find_params, &is_created); + } + ) + + CHECK_NULL(typinf) /* Not found, so create type object */ - if (NULL == typinf) + if (is_created) { - typinf = OcilibListAppend(con->tinfs, sizeof(OCI_TypeInfo)); - CHECK_NULL(typinf) - /* allocate describe handle */ - - typinf->con = con; - typinf->name = OcilibStringDuplicate(obj_name); - typinf->schema = OcilibStringDuplicate(obj_schema); - typinf->struct_size = 0; - typinf->align = 0; - + CHECK(OcilibMemoryAllocHandle(typinf->con->env, (dvoid **)(void *)&dschp, OCI_HTYPE_DESCRIBE)) /* perform describe */ @@ -570,15 +642,11 @@ OCI_TypeInfo * OcilibTypeInfoGet } } } - } - - /* free describe handle */ - OcilibMemoryFreeHandle(dschp, OCI_HTYPE_DESCRIBE); - - /* increment type info reference counter on success */ + /* free describe handle */ - typinf->refcount++; + OcilibMemoryFreeHandle(dschp, OCI_HTYPE_DESCRIBE); + } /* type checking sanity checks */ @@ -629,11 +697,20 @@ boolean OcilibTypeInfoFree CHECK_PTR(OCI_IPC_TYPE_INFO, typinf) - typinf->refcount--; + /* decrement type info reference counter on success */ + + OcilibTypeInfoUpdateRefCounter(typinf, -1); if (typinf->refcount == 0) { - OcilibListRemove(typinf->con->tinfs, typinf); + LOCK_LIST + ( + typinf->con->tinfs, + { + OcilibListRemove(typinf->con->tinfs, typinf); + } + ) + OcilibTypeInfoDispose(typinf); FREE(typinf) diff --git a/src/types.h b/src/types.h index 2bdd3637..706bb828 100644 --- a/src/types.h +++ b/src/types.h @@ -714,6 +714,7 @@ struct OCI_TypeInfo OCI_Connection *con; /* pointer to connection object */ OCI_Column *cols; /* array of column datatype info */ OCI_TypeInfo *parent_type; /* parent super type for derived type */ + OCI_Mutex * mutex; /* mutex handle for ref counting */ OCIType *tdo; /* datatype object type */ otext *name; /* name of the type info object */ otext *schema; /* owner of the type info object */ diff --git a/tests/TestCollection.cpp b/tests/TestCollection.cpp index d3d0534f..97ff04c1 100644 --- a/tests/TestCollection.cpp +++ b/tests/TestCollection.cpp @@ -128,7 +128,7 @@ TEST(TestCollection, SelectVarray) ExecDML(OTEXT("insert into SelectVarray_Table values('category 1', SelectVarray_Coll(SelectVarray_Type(1, 'name 1'), SelectVarray_Type(2, 'name 2')))")); ExecDML(OTEXT("insert into SelectVarray_Table values('category 2', SelectVarray_Coll(SelectVarray_Type(3, 'name 3'), SelectVarray_Type(4, 'name 4')))")); - SelectCollection(OTEXT("SELECT * from SelectVarray_Table")); + SelectCollection(OTEXT("SELECT * from SelectVarray_Table order by category")); ExecDML(OTEXT("drop table SelectVarray_Table")); ExecDML(OTEXT("drop type SelectVarray_Coll")); @@ -144,7 +144,7 @@ TEST(TestCollection, SelectNestedTable) ExecDML(OTEXT("insert into SelectNestedTable_Table values('category 1', SelectNestedTable_Coll(SelectNestedTable_Type(1, 'name 1'), SelectNestedTable_Type(2, 'name 2')))")); ExecDML(OTEXT("insert into SelectNestedTable_Table values('category 2', SelectNestedTable_Coll(SelectNestedTable_Type(3, 'name 3'), SelectNestedTable_Type(4, 'name 4')))")); - SelectCollection(OTEXT("SELECT * from SelectNestedTable_Table")); + SelectCollection(OTEXT("SELECT * from SelectNestedTable_Table order by category")); ExecDML(OTEXT("drop table SelectNestedTable_Table")); ExecDML(OTEXT("drop type SelectNestedTable_Coll")); From afadcd099ab51d7dd897e3141cfede5f0710e938 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 6 Sep 2021 19:05:21 +0200 Subject: [PATCH 04/19] Abour issue #278, removed the internal ref counter for OCI_TypeObject instances and made OCI_TypeInfoFree() to do nohting --- include/ocilibc/api.h | 5 ++-- src/typeinfo.c | 59 ------------------------------------------- src/types.h | 2 -- 3 files changed, 3 insertions(+), 63 deletions(-) diff --git a/include/ocilibc/api.h b/include/ocilibc/api.h index bfb317ea..9819803d 100644 --- a/include/ocilibc/api.h +++ b/include/ocilibc/api.h @@ -13067,12 +13067,13 @@ OCI_SYM_PUBLIC OCI_Connection * OCI_API OCI_TypeInfoGetConnection * @param typinf - Type info handle * * @note - * this call is optional. + * this call is DEPRECATED. * OCI_TypeInfo object are internally tracked and * automatically freed when their related connection is freed + * Thus this method does nothing * * @return - * TRUE on success otherwise FALSE + * TRUE if input handle is valid otherwise FALSE * */ diff --git a/src/typeinfo.c b/src/typeinfo.c index 68a0dd43..882679da 100644 --- a/src/typeinfo.c +++ b/src/typeinfo.c @@ -55,31 +55,6 @@ static boolean OcilibTypeInfoFind(OCI_TypeInfo *typinf, TypeInfoFindParams *find OcilibStringCaseCompare(typinf->schema, find_params->schema) == 0; } - -/* --------------------------------------------------------------------------------------------- * - * OcilibTypeInfoUpdateRefCounter - * --------------------------------------------------------------------------------------------- */ - -static void OcilibTypeInfoUpdateRefCounter(OCI_TypeInfo* typinf, sb2 value) -{ - if (typinf == NULL) - { - return; - } - - if (NULL != typinf->mutex) - { - OcilibMutexAcquire(typinf->mutex); - } - - typinf->refcount += value; - - if (NULL != typinf->mutex) - { - OcilibMutexRelease(typinf->mutex); - } -} - /* --------------------------------------------------------------------------------------------- * * OcilibTypeInfoFindOrCreate * --------------------------------------------------------------------------------------------- */ @@ -104,18 +79,9 @@ static OCI_TypeInfo* OcilibTypeInfoFindOrCreate(OCI_Connection* con, TypeInfoFin typinf->struct_size = 0; typinf->align = 0; - if (LIB_THREADED) - { - typinf->mutex = OcilibMutexCreateInternal(); - } - *p_is_created = TRUE; } - /* increment type info reference counter on success */ - - OcilibTypeInfoUpdateRefCounter(typinf, 1); - return typinf; } @@ -146,12 +112,6 @@ boolean OcilibTypeInfoDispose FREE(typinf->schema) FREE(typinf->offsets) - if (NULL != typinf->mutex) - { - OcilibMutexFree(typinf->mutex); - typinf->mutex = NULL; - } - OcilibErrorResetSource(NULL, typinf); SET_SUCCESS() @@ -697,25 +657,6 @@ boolean OcilibTypeInfoFree CHECK_PTR(OCI_IPC_TYPE_INFO, typinf) - /* decrement type info reference counter on success */ - - OcilibTypeInfoUpdateRefCounter(typinf, -1); - - if (typinf->refcount == 0) - { - LOCK_LIST - ( - typinf->con->tinfs, - { - OcilibListRemove(typinf->con->tinfs, typinf); - } - ) - - OcilibTypeInfoDispose(typinf); - - FREE(typinf) - } - SET_SUCCESS() EXIT_FUNC() diff --git a/src/types.h b/src/types.h index 706bb828..f2f5c378 100644 --- a/src/types.h +++ b/src/types.h @@ -714,7 +714,6 @@ struct OCI_TypeInfo OCI_Connection *con; /* pointer to connection object */ OCI_Column *cols; /* array of column datatype info */ OCI_TypeInfo *parent_type; /* parent super type for derived type */ - OCI_Mutex * mutex; /* mutex handle for ref counting */ OCIType *tdo; /* datatype object type */ otext *name; /* name of the type info object */ otext *schema; /* owner of the type info object */ @@ -725,7 +724,6 @@ struct OCI_TypeInfo ub2 typecode; /* Oracle type code */ ub2 colcode; /* Oracle collection code */ ub2 nb_cols; /* number of columns */ - ub2 refcount; /* reference counter */ ub1 is_final; /* is is a virtual type that can be inherited ? */ }; From 888299baa07a6ddb0172f018085cfdc960e200e4 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 6 Sep 2021 19:17:22 +0200 Subject: [PATCH 05/19] fixed #282 --- src/connection.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/connection.c b/src/connection.c index 95c63790..c232144b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1955,15 +1955,13 @@ boolean OcilibConnectionEnableServerOutput { const unsigned int charsize = sizeof(otext); - /* check parameter ranges ( Oracle 10g increased the size of output line */ + const unsigned int max_lnsize = (con->ver_num >= OCI_10_2) ? OCI_OUPUT_LSIZE_10G : OCI_OUPUT_LSIZE; - if (con->ver_num >= OCI_10_2 && lnsize > OCI_OUPUT_LSIZE_10G) - { - lnsize = OCI_OUPUT_LSIZE_10G; - } - else if (lnsize > OCI_OUPUT_LSIZE) + /* check parameter ranges (Oracle 10g increased the size of output line) */ + + if (lnsize > max_lnsize) { - lnsize = OCI_OUPUT_LSIZE; + lnsize = max_lnsize; } con->svopt->arrsize = arrsize; From 0f34a962bf588164892508bdd9b65e8de138af3b Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 7 Sep 2021 09:39:05 +0200 Subject: [PATCH 06/19] Fixed issue #283. Now OCI_EnqueuePut() and OCI_DequeueGet() can handle NULL payload. Alos fixed OCI_MsgGetOriginalID() & OCI_MsgSetOriginalID() More Tests will be added on AQ method in an upcoming commit. --- src/dequeue.c | 4 +- src/enqueue.c | 9 +-- src/message.c | 21 +++---- tests/TestQueue.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 148 insertions(+), 23 deletions(-) diff --git a/src/dequeue.c b/src/dequeue.c index 1d75b61f..f83eb96c 100644 --- a/src/dequeue.c +++ b/src/dequeue.c @@ -328,6 +328,8 @@ OCI_Msg * OcilibDequeueGetMessage if (OCI_SUCCESSFUL(ret)) { + msg = dequeue->msg; + /* get payload */ if (p_ind && (OCI_IND_NULL != (*(OCIInd *) p_ind))) @@ -348,8 +350,6 @@ OCI_Msg * OcilibDequeueGetMessage CHECK_NULL(dequeue->msg->obj) } - - msg = dequeue->msg; } } diff --git a/src/enqueue.c b/src/enqueue.c index b65d6cd0..674ec3db 100644 --- a/src/enqueue.c +++ b/src/enqueue.c @@ -145,13 +145,10 @@ boolean OcilibEnqueuePut /* get payload */ - if (OCI_UNKNOWN != enqueue->typinf->typecode) + if (OCI_UNKNOWN != enqueue->typinf->typecode && OCI_IND_NULL != msg->ind) { - if (OCI_IND_NULL != msg->ind) - { - payload = msg->obj->handle; - ind = msg->obj->tab_ind; - } + payload = msg->obj->handle; + ind = msg->obj->tab_ind; } else { diff --git a/src/message.c b/src/message.c index 74c98433..33386d31 100644 --- a/src/message.c +++ b/src/message.c @@ -655,21 +655,17 @@ boolean OcilibMessageGetID CHECK_PTR(OCI_IPC_VOID, id) CHECK_PTR(OCI_IPC_VOID, len) + unsigned int max_len = 0; + *len = 0; + if (msg->id) { const ub4 raw_len = OCIRawSize(msg->typinf->con->env, msg->id); - if (*len > raw_len) - { - *len = raw_len; - } + *len = min(max_len, raw_len); memcpy(id, OCIRawPtr(msg->typinf->con->env, msg->id), (size_t) (*len)); } - else - { - *len = 0; - } SET_SUCCESS() @@ -694,11 +690,13 @@ boolean OcilibMessageGetOriginalID ) OCIRaw *value = NULL; + unsigned int max_len = 0; CHECK_PTR(OCI_IPC_MSG, msg) CHECK_PTR(OCI_IPC_VOID, id) CHECK_PTR(OCI_IPC_VOID, len) + max_len = *len; *len = 0; CHECK_ATTRIB_GET @@ -712,10 +710,7 @@ boolean OcilibMessageGetOriginalID { const ub4 raw_len = OCIRawSize(msg->typinf->con->env, value); - if (*len > raw_len) - { - *len = raw_len; - } + *len = min(max_len, raw_len); memcpy(id, OCIRawPtr(msg->typinf->con->env, value), (size_t) (*len)); } @@ -757,7 +752,7 @@ boolean OcilibMessageSetOriginalID CHECK_ATTRIB_SET ( OCI_DTYPE_AQMSG_PROPERTIES, OCI_ATTR_ORIGINAL_MSGID, - msg->proph, &value, 0, + msg->proph, value, 0, msg->typinf->con->err ) diff --git a/tests/TestQueue.cpp b/tests/TestQueue.cpp index 1a107f7e..8d5b2fda 100644 --- a/tests/TestQueue.cpp +++ b/tests/TestQueue.cpp @@ -183,8 +183,6 @@ TEST(TestQueue, MessageWithConsumers) ExecDML(OTEXT("drop type TestQueueMessageWithConsumersType")); } - - TEST(TestQueue, SingleRawMessage) { ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); @@ -244,4 +242,139 @@ TEST(TestQueue, SingleRawMessage) ASSERT_TRUE(OCI_ConnectionFree(conn)); ASSERT_TRUE(OCI_Cleanup()); +} + +TEST(TestQueue, SingleRawMessageEmptyPayload) +{ + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + // no check - for cleanup + OCI_QueueStop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload"), TRUE, TRUE, FALSE); + OCI_QueueDrop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload")); + OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayloadTable"), TRUE); + // end no check + + ASSERT_TRUE(OCI_QueueTableCreate(conn, OTEXT("TestQueueSingleRawMessageEmptyPayloadTable"), OTEXT("RAW"), NULL, NULL, FALSE, OCI_AGM_NONE, NULL, 0, 0, NULL)); + ASSERT_TRUE(OCI_QueueCreate(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload"), OTEXT("TestQueueSingleRawMessageEmptyPayloadTable"), OCI_AQT_NORMAL, 0, 0, 0, FALSE, NULL)); + ASSERT_TRUE(OCI_QueueStart(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload"), TRUE, TRUE)); + + const auto inf = OCI_TypeInfoGet(conn, OTEXT("SYS.RAW"), OCI_TIF_TYPE); + ASSERT_NE(nullptr, inf); + + const auto enq = OCI_EnqueueCreate(inf, OTEXT("TestQueueSingleRawMessageEmptyPayload")); + ASSERT_NE(nullptr, enq); + + const auto deq = OCI_DequeueCreate(inf, OTEXT("TestQueueSingleRawMessageEmptyPayload")); + ASSERT_NE(nullptr, deq); + + const auto msg_in = OCI_MsgCreate(inf); + ASSERT_NE(nullptr, msg_in); + + const auto byteBring = ostring(OTEXT("123456789")); + ASSERT_TRUE(OCI_MsgSetOriginalID(msg_in, static_cast(byteBring.data()), static_cast(byteBring.size()))); + + ASSERT_TRUE(OCI_EnqueuePut(enq, msg_in)); + + ASSERT_TRUE(OCI_MsgFree(msg_in)); + + ASSERT_TRUE(OCI_Commit(conn)); + + const auto msg_out = OCI_DequeueGet(deq); + ASSERT_NE(nullptr, msg_out); + + otext buffer[100] = OTEXT(""); + unsigned int size = 100; + ASSERT_TRUE(OCI_MsgGetOriginalID(msg_out, static_cast(buffer), &size)); + + ASSERT_EQ(byteBring, ostring(buffer)); + ASSERT_EQ(byteBring.size(), size); + + otext payload[100] = OTEXT(""); + unsigned int payloadSize = 100; + ASSERT_TRUE(OCI_MsgGetRaw(msg_out, static_cast(buffer), &payloadSize)); + ASSERT_EQ(0, payloadSize); + + ASSERT_TRUE(OCI_EnqueueFree(enq)); + ASSERT_TRUE(OCI_DequeueFree(deq)); + + ASSERT_TRUE(OCI_Commit(conn)); + + ASSERT_TRUE(OCI_QueueStop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload"), TRUE, TRUE, FALSE)); + ASSERT_TRUE(OCI_QueueDrop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayload"))); + ASSERT_TRUE(OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleRawMessageEmptyPayloadTable"), TRUE)); + + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); +} + + +TEST(TestQueue, SingleMessageEmptyPayload) +{ + ExecDML(OTEXT("create type TestQueueSingleMessageEmptyPayloadType as object(title varchar2(50), content varchar2(100))")); + + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + // no check - for cleanup + OCI_QueueStop(conn, OTEXT("TestQueueSingleMessageEmptyPayload"), TRUE, TRUE, FALSE); + OCI_QueueDrop(conn, OTEXT("TestQueueSingleMessageEmptyPayload")); + OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleMessageEmptyPayloadTable"), TRUE); + // end no check + + ASSERT_TRUE(OCI_QueueTableCreate(conn, OTEXT("TestQueueSingleMessageEmptyPayloadTable"), OTEXT("TestQueueSingleMessageEmptyPayloadType"), NULL, NULL, FALSE, OCI_AGM_NONE, NULL, 0, 0, NULL)); + ASSERT_TRUE(OCI_QueueCreate(conn, OTEXT("TestQueueSingleMessageEmptyPayload"), OTEXT("TestQueueSingleMessageEmptyPayloadTable"), OCI_AQT_NORMAL, 0, 0, 0, FALSE, NULL)); + ASSERT_TRUE(OCI_QueueStart(conn, OTEXT("TestQueueSingleMessageEmptyPayload"), TRUE, TRUE)); + + const auto inf = OCI_TypeInfoGet(conn, OTEXT("TestQueueSingleMessageEmptyPayloadType"), OCI_TIF_TYPE); + ASSERT_NE(nullptr, inf); + + const auto enq = OCI_EnqueueCreate(inf, OTEXT("TestQueueSingleMessageEmptyPayload")); + ASSERT_NE(nullptr, enq); + + const auto deq = OCI_DequeueCreate(inf, OTEXT("TestQueueSingleMessageEmptyPayload")); + ASSERT_NE(nullptr, deq); + + const auto msg_in = OCI_MsgCreate(inf); + ASSERT_NE(nullptr, msg_in); + + const auto byteBring = ostring(OTEXT("123456789")); + ASSERT_TRUE(OCI_MsgSetOriginalID(msg_in, static_cast(byteBring.data()), static_cast(byteBring.size()))); + + ASSERT_TRUE(OCI_EnqueuePut(enq, msg_in)); + + ASSERT_TRUE(OCI_MsgFree(msg_in)); + + ASSERT_TRUE(OCI_Commit(conn)); + + const auto msg_out = OCI_DequeueGet(deq); + ASSERT_NE(nullptr, msg_out); + + otext buffer[100] = OTEXT(""); + unsigned int size = 100; + ASSERT_TRUE(OCI_MsgGetOriginalID(msg_out, static_cast(buffer), &size)); + + ASSERT_EQ(byteBring, ostring(buffer)); + ASSERT_EQ(byteBring.size(), size); + + const auto obj_out = OCI_MsgGetObject(msg_out); + ASSERT_EQ(nullptr, obj_out); + + ASSERT_TRUE(OCI_EnqueueFree(enq)); + ASSERT_TRUE(OCI_DequeueFree(deq)); + + ASSERT_TRUE(OCI_Commit(conn)); + + ASSERT_TRUE(OCI_QueueStop(conn, OTEXT("TestQueueSingleMessageEmptyPayload"), TRUE, TRUE, FALSE)); + ASSERT_TRUE(OCI_QueueDrop(conn, OTEXT("TestQueueSingleMessageEmptyPayload"))); + ASSERT_TRUE(OCI_QueueTableDrop(conn, OTEXT("TestQueueSingleMessageEmptyPayloadTable"), TRUE)); + + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); + + ExecDML(OTEXT("drop type TestQueueSingleMessageEmptyPayloadType")); } \ No newline at end of file From 57255d0e7484825d8dda75fe99a46037b183e9f2 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 7 Sep 2021 21:52:54 +0200 Subject: [PATCH 07/19] fixed previous commit --- .vs/VSWorkspaceState.json | 11 ++ .vs/slnx.sqlite | Bin 0 -> 651264 bytes demo/ocilib_demo.cpp | 210 ++++++++++++++++++++++++- proj/test/ocilib++_demo_vs2019.vcxproj | 3 +- src/message.c | 2 +- 5 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 .vs/VSWorkspaceState.json create mode 100644 .vs/slnx.sqlite diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 00000000..2c53785b --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,11 @@ +{ + "ExpandedNodes": [ + "", + "\\include", + "\\include\\ocilibcpp\\detail", + "\\include\\ocilibcpp\\detail\\support", + "\\src" + ], + "SelectedNode": "\\src\\connection.c", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..b8c394e497cf81c2a4a6715fb28ddff60d857001 GIT binary patch literal 651264 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

O`8pt%Lur1J-Q^%(-ZntfL};Sp88+n!8-XCVs5 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ْMkd9(9&Woju+gS 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%0A!1>-4+Z3MQY{dh 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 literal 0 HcmV?d00001 diff --git a/demo/ocilib_demo.cpp b/demo/ocilib_demo.cpp index 6f934d3d..bd23fa07 100644 --- a/demo/ocilib_demo.cpp +++ b/demo/ocilib_demo.cpp @@ -36,6 +36,9 @@ using namespace ocilib; #include #include #include +#include +#include +#include /* --------------------------------------------------------------------------------------------- * * CONSTANTS @@ -235,11 +238,216 @@ inline ostring GetArg(oarg *arg) return res; } + #define INPUT_SIZE 2048 + #define ORACLE_BUFFER_SIZE 1000 + + + void err_handler(OCI_Error* err) + { + printf(OCI_ErrorGetString(err)); + } + + void mainsssss() + { + std::vector> container; + + for (auto i = 1; i < INPUT_SIZE * 2; i++) + { + container.push_back({ i, "value " + std::to_string(i) }); + } + + OCI_Initialize(err_handler, nullptr, OCI_ENV_DEFAULT); + + auto cn = OCI_ConnectionCreate("db18c", "usr", "pwd", OCI_SESSION_DEFAULT); + auto st = OCI_StatementCreate(cn); + + OCI_Prepare(st, "INSERT INTO mytable (id, str) VALUES(:1, :2)"); + OCI_BindArraySetSize(st, ORACLE_BUFFER_SIZE); + + auto values = std::unique_ptr(new int[ORACLE_BUFFER_SIZE]); + OCI_BindArrayOfInts(st, ":1", values.get(), 0); + + auto size_without_null_terminal_character = 1000; + auto max_size_with_null_terminator = 1000 + 1; + + auto str_values = std::unique_ptr(new char[ORACLE_BUFFER_SIZE * max_size_with_null_terminator]); + OCI_BindArrayOfStrings(st, ":2", str_values.get(), size_without_null_terminal_character, 0); + + for (auto container_index = 0; container_index < container.size(); container_index += ORACLE_BUFFER_SIZE) + { + auto partial_index = 0; + for (; (partial_index < ORACLE_BUFFER_SIZE) && (container_index + partial_index < container.size()); ++partial_index) + { + auto [val, str_val] = container[container_index + partial_index]; + + values[partial_index] = val; + std::copy(begin(str_val), end(str_val), &str_values[partial_index * max_size_with_null_terminator]); + + str_values[partial_index * max_size_with_null_terminator + str_val.size()] = '\0'; + } + + OCI_BindArraySetSize(st, partial_index); + OCI_Execute(st); + } + + OCI_Commit(cn); + + OCI_Cleanup(); + } + +void mainsss() +{ + constexpr auto InputSize = 2048; + constexpr auto ChunkSize = 1000; + + std::vector> container; + + for (auto i = 1; i < InputSize; i++) + { + container.push_back({ i, std::to_string(i) }); + } + + try + { + Environment::Initialize(Environment::Default | Environment::Threaded); + Connection con("db18c", "usr", "pwd", Environment::SessionDefault); + Statement st(con); + + std::vector ids; + std::vector values; + + ids.resize(ChunkSize); + values.resize(ChunkSize); + + st.Prepare("INSERT INTO mytable (id, str) VALUES(:1, :2)"); + st.SetBindArraySize(ChunkSize); + st.Bind(":1", ids, BindInfo::In); + st.Bind(":2", values, 50, BindInfo::In); + + for (auto container_index = 0; container_index < container.size(); container_index += ChunkSize) + { + auto partial_index = 0; + for (; (partial_index < ChunkSize) && (container_index + partial_index < container.size()); ++partial_index) + { + auto [val, str_val] = container[container_index + partial_index]; + + ids[partial_index] = val; + values[partial_index] = str_val; + } + + st.SetBindArraySize(partial_index); + + st.ExecutePrepared(); + } + + con.Commit(); + } + catch (Exception& ex) + { + ocout << ex.GetMessage() << oendl; + } +} + + +class my_entity +{ +public: +std::optional id; +std::optional code; +std::optional state; +std::optional serial_no; +std::optional group_id; +}; + +int main() +{ + ocilib::Environment::Initialize(ocilib::Environment::Threaded); + + ocilib::Pool oci_pool("localhost:1521/db19c", "usr", "pwd", + ocilib::Pool::ConnectionPool, 200, 300); + + + + auto worker_lambda = [](ocilib::Pool& pool) + { + + try + { + auto result = 0; + + auto conn = pool.GetConnection(); + + ocilib::Statement stmt(conn); + + auto entity_db_obj = ocilib::Object(ocilib::TypeInfo(conn, "MY_ENTITY_OBJ", ocilib::TypeInfo::Type)); + + entity_db_obj.Set("ID", 2); + + std::cout << (void*) &entity_db_obj << std::endl; + /* + std::string sql = R"( + BEGIN + :RESULT := MY_PACKAGE_PKG.GET_ENTITY_BY_CODE(:CODE , :ENTITY_INFO); + END; + )"; + stmt.Prepare(sql); + stmt.Bind(":RESULT", result, ocilib::BindInfo::Out); + std::string entity_code = "00000001"; + stmt.Bind(":CODE", entity_code, 8, ocilib::BindInfo::In); + stmt.Bind(":ENTITY_INFO", entity_db_obj, ocilib::BindInfo::Out); + + stmt.ExecutePrepared(); + + if (result) + { + my_entity one_entity; + if (!entity_db_obj.IsAttributeNull("ID")) + one_entity.id = entity_db_obj.Get("ID"); + + if (!entity_db_obj.IsAttributeNull("CODE")) + one_entity.code = entity_db_obj.Get("CODE"); + + if (!entity_db_obj.IsAttributeNull("STATE")) + one_entity.state = static_cast(entity_db_obj.Get("STATE")); + + if (!entity_db_obj.IsAttributeNull("SERIAL_NO")) + one_entity.serial_no = entity_db_obj.Get("SERIAL_NO"); + + conn.Close(); + }*/ + + conn.Close(); + + } + catch (const ocilib::Exception& ex) + { + throw std::runtime_error(ex.what()); + } + }; + + std::vector threads(1); + + for (int i = 0; i < 1; i++) + { + threads[i] = std::thread( + worker_lambda, std::ref(oci_pool) + ); + } + + for (int i = 0; i < 1; i++) + if (threads[i].joinable()) + threads[i].join(); + + ocilib::Environment::Cleanup(); + + return 0; +} + /* --------------------------------------------------------------------------------------------- * * main * --------------------------------------------------------------------------------------------- */ -int omain(int argc, oarg* argv[]) +int omains(int argc, oarg* argv[]) { ostring home; ostring dbs; diff --git a/proj/test/ocilib++_demo_vs2019.vcxproj b/proj/test/ocilib++_demo_vs2019.vcxproj index 21e4c5b3..3e39f622 100644 --- a/proj/test/ocilib++_demo_vs2019.vcxproj +++ b/proj/test/ocilib++_demo_vs2019.vcxproj @@ -113,9 +113,10 @@ Level3 Disabled - WIN32;_DEBUG;OCI_CHARSET_WIDE;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + stdcpplatest Console diff --git a/src/message.c b/src/message.c index 33386d31..0af44ee0 100644 --- a/src/message.c +++ b/src/message.c @@ -655,7 +655,7 @@ boolean OcilibMessageGetID CHECK_PTR(OCI_IPC_VOID, id) CHECK_PTR(OCI_IPC_VOID, len) - unsigned int max_len = 0; + unsigned int max_len = *len; *len = 0; if (msg->id) From de2741062b1ebe16f8dbcc154efc1f4f665366fb Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 7 Sep 2021 21:55:48 +0200 Subject: [PATCH 08/19] Revert "fixed previous commit" This reverts commit 57255d0e7484825d8dda75fe99a46037b183e9f2. --- .vs/VSWorkspaceState.json | 11 -- .vs/slnx.sqlite | Bin 651264 -> 0 bytes demo/ocilib_demo.cpp | 210 +------------------------ proj/test/ocilib++_demo_vs2019.vcxproj | 3 +- src/message.c | 2 +- 5 files changed, 3 insertions(+), 223 deletions(-) delete mode 100644 .vs/VSWorkspaceState.json delete mode 100644 .vs/slnx.sqlite diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index 2c53785b..00000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ExpandedNodes": [ - "", - "\\include", - "\\include\\ocilibcpp\\detail", - "\\include\\ocilibcpp\\detail\\support", - "\\src" - ], - "SelectedNode": "\\src\\connection.c", - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index b8c394e497cf81c2a4a6715fb28ddff60d857001..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 651264 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

O`8pt%Lur1J-Q^%(-ZntfL};Sp88+n!8-XCVs5 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ْMkd9(9&Woju+gS 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%0A!1>-4+Z3MQY{dh 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 diff --git a/demo/ocilib_demo.cpp b/demo/ocilib_demo.cpp index bd23fa07..6f934d3d 100644 --- a/demo/ocilib_demo.cpp +++ b/demo/ocilib_demo.cpp @@ -36,9 +36,6 @@ using namespace ocilib; #include #include #include -#include -#include -#include /* --------------------------------------------------------------------------------------------- * * CONSTANTS @@ -238,216 +235,11 @@ inline ostring GetArg(oarg *arg) return res; } - #define INPUT_SIZE 2048 - #define ORACLE_BUFFER_SIZE 1000 - - - void err_handler(OCI_Error* err) - { - printf(OCI_ErrorGetString(err)); - } - - void mainsssss() - { - std::vector> container; - - for (auto i = 1; i < INPUT_SIZE * 2; i++) - { - container.push_back({ i, "value " + std::to_string(i) }); - } - - OCI_Initialize(err_handler, nullptr, OCI_ENV_DEFAULT); - - auto cn = OCI_ConnectionCreate("db18c", "usr", "pwd", OCI_SESSION_DEFAULT); - auto st = OCI_StatementCreate(cn); - - OCI_Prepare(st, "INSERT INTO mytable (id, str) VALUES(:1, :2)"); - OCI_BindArraySetSize(st, ORACLE_BUFFER_SIZE); - - auto values = std::unique_ptr(new int[ORACLE_BUFFER_SIZE]); - OCI_BindArrayOfInts(st, ":1", values.get(), 0); - - auto size_without_null_terminal_character = 1000; - auto max_size_with_null_terminator = 1000 + 1; - - auto str_values = std::unique_ptr(new char[ORACLE_BUFFER_SIZE * max_size_with_null_terminator]); - OCI_BindArrayOfStrings(st, ":2", str_values.get(), size_without_null_terminal_character, 0); - - for (auto container_index = 0; container_index < container.size(); container_index += ORACLE_BUFFER_SIZE) - { - auto partial_index = 0; - for (; (partial_index < ORACLE_BUFFER_SIZE) && (container_index + partial_index < container.size()); ++partial_index) - { - auto [val, str_val] = container[container_index + partial_index]; - - values[partial_index] = val; - std::copy(begin(str_val), end(str_val), &str_values[partial_index * max_size_with_null_terminator]); - - str_values[partial_index * max_size_with_null_terminator + str_val.size()] = '\0'; - } - - OCI_BindArraySetSize(st, partial_index); - OCI_Execute(st); - } - - OCI_Commit(cn); - - OCI_Cleanup(); - } - -void mainsss() -{ - constexpr auto InputSize = 2048; - constexpr auto ChunkSize = 1000; - - std::vector> container; - - for (auto i = 1; i < InputSize; i++) - { - container.push_back({ i, std::to_string(i) }); - } - - try - { - Environment::Initialize(Environment::Default | Environment::Threaded); - Connection con("db18c", "usr", "pwd", Environment::SessionDefault); - Statement st(con); - - std::vector ids; - std::vector values; - - ids.resize(ChunkSize); - values.resize(ChunkSize); - - st.Prepare("INSERT INTO mytable (id, str) VALUES(:1, :2)"); - st.SetBindArraySize(ChunkSize); - st.Bind(":1", ids, BindInfo::In); - st.Bind(":2", values, 50, BindInfo::In); - - for (auto container_index = 0; container_index < container.size(); container_index += ChunkSize) - { - auto partial_index = 0; - for (; (partial_index < ChunkSize) && (container_index + partial_index < container.size()); ++partial_index) - { - auto [val, str_val] = container[container_index + partial_index]; - - ids[partial_index] = val; - values[partial_index] = str_val; - } - - st.SetBindArraySize(partial_index); - - st.ExecutePrepared(); - } - - con.Commit(); - } - catch (Exception& ex) - { - ocout << ex.GetMessage() << oendl; - } -} - - -class my_entity -{ -public: -std::optional id; -std::optional code; -std::optional state; -std::optional serial_no; -std::optional group_id; -}; - -int main() -{ - ocilib::Environment::Initialize(ocilib::Environment::Threaded); - - ocilib::Pool oci_pool("localhost:1521/db19c", "usr", "pwd", - ocilib::Pool::ConnectionPool, 200, 300); - - - - auto worker_lambda = [](ocilib::Pool& pool) - { - - try - { - auto result = 0; - - auto conn = pool.GetConnection(); - - ocilib::Statement stmt(conn); - - auto entity_db_obj = ocilib::Object(ocilib::TypeInfo(conn, "MY_ENTITY_OBJ", ocilib::TypeInfo::Type)); - - entity_db_obj.Set("ID", 2); - - std::cout << (void*) &entity_db_obj << std::endl; - /* - std::string sql = R"( - BEGIN - :RESULT := MY_PACKAGE_PKG.GET_ENTITY_BY_CODE(:CODE , :ENTITY_INFO); - END; - )"; - stmt.Prepare(sql); - stmt.Bind(":RESULT", result, ocilib::BindInfo::Out); - std::string entity_code = "00000001"; - stmt.Bind(":CODE", entity_code, 8, ocilib::BindInfo::In); - stmt.Bind(":ENTITY_INFO", entity_db_obj, ocilib::BindInfo::Out); - - stmt.ExecutePrepared(); - - if (result) - { - my_entity one_entity; - if (!entity_db_obj.IsAttributeNull("ID")) - one_entity.id = entity_db_obj.Get("ID"); - - if (!entity_db_obj.IsAttributeNull("CODE")) - one_entity.code = entity_db_obj.Get("CODE"); - - if (!entity_db_obj.IsAttributeNull("STATE")) - one_entity.state = static_cast(entity_db_obj.Get("STATE")); - - if (!entity_db_obj.IsAttributeNull("SERIAL_NO")) - one_entity.serial_no = entity_db_obj.Get("SERIAL_NO"); - - conn.Close(); - }*/ - - conn.Close(); - - } - catch (const ocilib::Exception& ex) - { - throw std::runtime_error(ex.what()); - } - }; - - std::vector threads(1); - - for (int i = 0; i < 1; i++) - { - threads[i] = std::thread( - worker_lambda, std::ref(oci_pool) - ); - } - - for (int i = 0; i < 1; i++) - if (threads[i].joinable()) - threads[i].join(); - - ocilib::Environment::Cleanup(); - - return 0; -} - /* --------------------------------------------------------------------------------------------- * * main * --------------------------------------------------------------------------------------------- */ -int omains(int argc, oarg* argv[]) +int omain(int argc, oarg* argv[]) { ostring home; ostring dbs; diff --git a/proj/test/ocilib++_demo_vs2019.vcxproj b/proj/test/ocilib++_demo_vs2019.vcxproj index 3e39f622..21e4c5b3 100644 --- a/proj/test/ocilib++_demo_vs2019.vcxproj +++ b/proj/test/ocilib++_demo_vs2019.vcxproj @@ -113,10 +113,9 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;OCI_CHARSET_WIDE;_CONSOLE;%(PreprocessorDefinitions) - stdcpplatest Console diff --git a/src/message.c b/src/message.c index 0af44ee0..33386d31 100644 --- a/src/message.c +++ b/src/message.c @@ -655,7 +655,7 @@ boolean OcilibMessageGetID CHECK_PTR(OCI_IPC_VOID, id) CHECK_PTR(OCI_IPC_VOID, len) - unsigned int max_len = *len; + unsigned int max_len = 0; *len = 0; if (msg->id) From fc3a5fd3e45032d7c18fad46ab1dfc314f2d8b9a Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 7 Sep 2021 21:56:58 +0200 Subject: [PATCH 09/19] fixed commit for issue #283 --- src/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message.c b/src/message.c index 33386d31..0af44ee0 100644 --- a/src/message.c +++ b/src/message.c @@ -655,7 +655,7 @@ boolean OcilibMessageGetID CHECK_PTR(OCI_IPC_VOID, id) CHECK_PTR(OCI_IPC_VOID, len) - unsigned int max_len = 0; + unsigned int max_len = *len; *len = 0; if (msg->id) From c371644e7d07ce45f4eb6286df1bf2379e9bc264 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 14 Sep 2021 08:58:18 +0200 Subject: [PATCH 10/19] implement enhancement #284 --- src/enqueue.c | 2 +- tests/TestQueue.cpp | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/enqueue.c b/src/enqueue.c index 674ec3db..05f5ea21 100644 --- a/src/enqueue.c +++ b/src/enqueue.c @@ -183,7 +183,7 @@ boolean OcilibEnqueuePut ret = OCIAQEnq(enqueue->typinf->con->cxt, enqueue->typinf->con->err, (OraText*)name, enqueue->opth, msg->proph, - enqueue->typinf->tdo, &payload, &ind, NULL, OCI_DEFAULT); + enqueue->typinf->tdo, &payload, &ind, &msg->id, OCI_DEFAULT); /* check returned error code */ diff --git a/tests/TestQueue.cpp b/tests/TestQueue.cpp index 8d5b2fda..75811d62 100644 --- a/tests/TestQueue.cpp +++ b/tests/TestQueue.cpp @@ -183,6 +183,7 @@ TEST(TestQueue, MessageWithConsumers) ExecDML(OTEXT("drop type TestQueueMessageWithConsumersType")); } + TEST(TestQueue, SingleRawMessage) { ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); @@ -347,6 +348,10 @@ TEST(TestQueue, SingleMessageEmptyPayload) ASSERT_TRUE(OCI_EnqueuePut(enq, msg_in)); + otext msgIDIn[100] = OTEXT(""); + unsigned int sizeMsgIDIn = 100; + ASSERT_TRUE(OCI_MsgGetID(msg_in, static_cast(msgIDIn), &sizeMsgIDIn)); + ASSERT_TRUE(OCI_MsgFree(msg_in)); ASSERT_TRUE(OCI_Commit(conn)); @@ -355,11 +360,18 @@ TEST(TestQueue, SingleMessageEmptyPayload) ASSERT_NE(nullptr, msg_out); otext buffer[100] = OTEXT(""); - unsigned int size = 100; - ASSERT_TRUE(OCI_MsgGetOriginalID(msg_out, static_cast(buffer), &size)); + unsigned int sizeBuffer = 100; + ASSERT_TRUE(OCI_MsgGetOriginalID(msg_out, static_cast(buffer), &sizeBuffer)); ASSERT_EQ(byteBring, ostring(buffer)); - ASSERT_EQ(byteBring.size(), size); + ASSERT_EQ(byteBring.size(), sizeBuffer); + + otext msgIDOut[100] = OTEXT(""); + unsigned int sizeMsgIDOut = 100; + ASSERT_TRUE(OCI_MsgGetID(msg_out, static_cast(msgIDOut), &sizeMsgIDOut)); + + ASSERT_EQ(ostring(msgIDIn), ostring(msgIDOut)); + ASSERT_EQ(sizeMsgIDIn, sizeMsgIDOut); const auto obj_out = OCI_MsgGetObject(msg_out); ASSERT_EQ(nullptr, obj_out); From d2b50cb385ce3e3960856d2b7785f5cd3c335e0e Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Wed, 6 Oct 2021 15:01:04 +0200 Subject: [PATCH 11/19] Fix regression (memory leak) in OCI_Clenaup from recent commit 93ecd475 in working branch --- src/environment.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/environment.c b/src/environment.c index b8019a0c..2b997948 100644 --- a/src/environment.c +++ b/src/environment.c @@ -1543,8 +1543,8 @@ boolean OcilibEnvironmentCleanup ( Env.subs, { - OcilibListClear(Env.subs); OcilibListForEach(Env.subs, (POCI_LIST_FOR_EACH)OcilibSubscriptionDispose); + OcilibListClear(Env.subs); } ) @@ -1552,8 +1552,8 @@ boolean OcilibEnvironmentCleanup ( Env.cons, { - OcilibListClear(Env.cons); OcilibListForEach(Env.cons, (POCI_LIST_FOR_EACH)OcilibConnectionDispose); + OcilibListClear(Env.cons); } ) @@ -1561,8 +1561,8 @@ boolean OcilibEnvironmentCleanup ( Env.pools, { - OcilibListClear(Env.pools); OcilibListForEach(Env.pools, (POCI_LIST_FOR_EACH)OcilibPoolDispose); + OcilibListClear(Env.pools); } ) From 175c36575835229356056fb5e2fa0bbca9ea2f86 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Wed, 17 Nov 2021 09:15:58 +0100 Subject: [PATCH 12/19] Fixed Issue #288 - wrong buffer size computation for RAW columns in OCI_GetString() --- proj/test/ocilib++_demo_vs2019.vcxproj | 2 +- src/resultset.c | 29 +++++++------- tests/TestReportedIssuesCApi.cpp | 53 ++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/proj/test/ocilib++_demo_vs2019.vcxproj b/proj/test/ocilib++_demo_vs2019.vcxproj index 21e4c5b3..68985e69 100644 --- a/proj/test/ocilib++_demo_vs2019.vcxproj +++ b/proj/test/ocilib++_demo_vs2019.vcxproj @@ -113,7 +113,7 @@ Level3 Disabled - WIN32;_DEBUG;OCI_CHARSET_WIDE;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;OCI_CHARSET_ANSI;_CONSOLE;%(PreprocessorDefinitions) diff --git a/src/resultset.c b/src/resultset.c index 882e1b4d..82b4f84e 100644 --- a/src/resultset.c +++ b/src/resultset.c @@ -1855,7 +1855,7 @@ const otext * OcilibResultsetGetString { OCI_Error *err = OcilibErrorGet(TRUE, TRUE); - unsigned int bufsize = OCI_SIZE_TMP_CVT; + unsigned int buffer_size = OCI_SIZE_TMP_CVT; unsigned int data_size = 0; switch (def->col.datatype) @@ -1882,8 +1882,9 @@ const otext * OcilibResultsetGetString } case OCI_CDT_RAW: { - data = OcilibDefineGetData(def); - data_size = ((ub2*)def->buf.lens)[def->rs->row_cur - 1]; + data = OcilibDefineGetData(def); + data_size = ((ub2*)def->buf.lens)[def->rs->row_cur - 1]; + buffer_size = data_size * 2; break; } case OCI_CDT_REF: @@ -1897,12 +1898,12 @@ const otext * OcilibResultsetGetString if (lg) { - bufsize = OcilibLongGetSize(lg); + buffer_size = OcilibLongGetSize(lg); if (OCI_BLONG == def->col.subtype) { /* here we have binary long, it will be output in hexadecimal */ - bufsize *= 2; + buffer_size *= 2; } } @@ -1916,12 +1917,12 @@ const otext * OcilibResultsetGetString if (lob) { - bufsize = (unsigned int)OcilibLobGetLength(lob); + buffer_size = (unsigned int)OcilibLobGetLength(lob); if (OCI_BLOB == def->col.subtype) { /* here we have binary blob, it will be output in hexadecimal */ - bufsize *= 2; + buffer_size *= 2; } } @@ -1936,12 +1937,12 @@ const otext * OcilibResultsetGetString if (file) { - bufsize = (unsigned int) ostrlen(OTEXT("/")); + buffer_size = (unsigned int) ostrlen(OTEXT("/")); OcilibFileGetInfo(file); - bufsize += (unsigned int) (file->dir ? ostrlen(file->dir) : 0); - bufsize += (unsigned int) (file->name ? ostrlen(file->name) : 0); + buffer_size += (unsigned int) (file->dir ? ostrlen(file->dir) : 0); + buffer_size += (unsigned int) (file->name ? ostrlen(file->name) : 0); } data = file; @@ -1953,7 +1954,7 @@ const otext * OcilibResultsetGetString if (obj) { - CHECK(OcilibObjectToString(obj, &bufsize, NULL)) + CHECK(OcilibObjectToString(obj, &buffer_size, NULL)) } data = obj; @@ -1965,7 +1966,7 @@ const otext * OcilibResultsetGetString if (coll) { - CHECK(OcilibCollectionToString(coll, &bufsize, NULL)) + CHECK(OcilibCollectionToString(coll, &buffer_size, NULL)) } data = coll; @@ -1977,7 +1978,7 @@ const otext * OcilibResultsetGetString if (stmt && stmt->sql) { - bufsize = (unsigned int) ostrlen(stmt->sql); + buffer_size = (unsigned int) ostrlen(stmt->sql); } data = stmt; @@ -1991,7 +1992,7 @@ const otext * OcilibResultsetGetString CHECK(NULL == err || OCI_UNKNOWN == err->type) - CHECK(OcilibStringRequestBuffer(&def->buf.tmpbuf, &def->buf.tmpsize, bufsize)) + CHECK(OcilibStringRequestBuffer(&def->buf.tmpbuf, &def->buf.tmpsize, buffer_size)) CHECK(OcilibStringGetFromType(rs->stmt->con, &def->col, data, data_size, def->buf.tmpbuf, def->buf.tmpsize, FALSE)) diff --git a/tests/TestReportedIssuesCApi.cpp b/tests/TestReportedIssuesCApi.cpp index 754fea07..1ea31219 100644 --- a/tests/TestReportedIssuesCApi.cpp +++ b/tests/TestReportedIssuesCApi.cpp @@ -253,5 +253,58 @@ TEST(ReportedIssuesCApi, Issue262) ExecDML(OTEXT("DROP TABLE test_urowid")); } +TEST(ReportedIssuesCApi, Issue288) +{ + ExecDML(OTEXT("drop table TestIssue288")); + ExecDML(OTEXT("create table TestIssue288 (id number, val raw(2000))")); + ExecDML(OTEXT("insert into TestIssue288 " + "select lvl - 1, hextoraw(val) from " + "( " + " with l as(select level as lvl from dual connect by level < 102) " + " select lvl, listagg('FF', '') within group(order by null) as val " + " from l connect by level < lvl and prior lvl = lvl and prior sys_guid() is not null " + " group by lvl " + ") " + "where lvl > 1")); + + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + const auto stmt = OCI_StatementCreate(conn); + ASSERT_NE(nullptr, stmt); + + ASSERT_TRUE(OCI_ExecuteStmt(stmt, OTEXT("select id, val, length(val) from TestIssue288 order by id"))); + + auto rslt = OCI_GetResultset(stmt); + ASSERT_NE(nullptr, rslt); + + auto counter = 0u; + + while (OCI_FetchNext(rslt)) + { + counter++; + + auto id = OCI_GetInt(rslt, 1); + auto val = OCI_GetString(rslt, 2); + auto len = OCI_GetInt(rslt, 3); + + ASSERT_NE(nullptr, val); + + ASSERT_EQ(counter, id); + ASSERT_EQ(counter *2, len); + ASSERT_EQ(len, ostrlen(val)); + } + + ASSERT_EQ(100u, counter); + + ASSERT_TRUE(OCI_StatementFree(stmt)); + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); + + ExecDML(OTEXT("drop table TestIssue288")); +} + INSTANTIATE_TEST_CASE_P(ReportedIssuesCApi, ReportedIssues247, ::testing::ValuesIn(TimestampTypes)); From 6f9071b21a27151c6d04417187247562c2f3a883 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 29 Nov 2021 18:38:51 +0100 Subject: [PATCH 13/19] Renaming Visual studio and project files --- proj/dll/{ocilib_dll_vs2019.sln => ocilib_dll.sln} | 2 +- .../dll/{ocilib_dll_vs2019.vcxproj => ocilib_dll.vcxproj} | 8 ++++---- ..._vs2019.vcxproj.filters => ocilib_dll.vcxproj.filters} | 0 proj/test/{ocilib++_demo_vs2019.sln => ocilib++_demo.sln} | 0 ...ocilib++_demo_vs2019.vcxproj => ocilib++_demo.vcxproj} | 0 proj/test/{ocilib_demo_vs2019.sln => ocilib_demo.sln} | 0 .../{ocilib_demo_vs2019.vcxproj => ocilib_demo.vcxproj} | 0 7 files changed, 5 insertions(+), 5 deletions(-) rename proj/dll/{ocilib_dll_vs2019.sln => ocilib_dll.sln} (94%) rename proj/dll/{ocilib_dll_vs2019.vcxproj => ocilib_dll.vcxproj} (99%) rename proj/dll/{ocilib_dll_vs2019.vcxproj.filters => ocilib_dll.vcxproj.filters} (100%) rename proj/test/{ocilib++_demo_vs2019.sln => ocilib++_demo.sln} (100%) rename proj/test/{ocilib++_demo_vs2019.vcxproj => ocilib++_demo.vcxproj} (100%) rename proj/test/{ocilib_demo_vs2019.sln => ocilib_demo.sln} (100%) rename proj/test/{ocilib_demo_vs2019.vcxproj => ocilib_demo.vcxproj} (100%) diff --git a/proj/dll/ocilib_dll_vs2019.sln b/proj/dll/ocilib_dll.sln similarity index 94% rename from proj/dll/ocilib_dll_vs2019.sln rename to proj/dll/ocilib_dll.sln index b86a2775..d452c592 100644 --- a/proj/dll/ocilib_dll_vs2019.sln +++ b/proj/dll/ocilib_dll.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29926.136 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCILIB Dynamic Library", "ocilib_dll_vs2019.vcxproj", "{B5B9DE0E-C2BE-4D75-BDA0-CBF81BD18D7D}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCILIB Dynamic Library", "ocilib_dll.vcxproj", "{B5B9DE0E-C2BE-4D75-BDA0-CBF81BD18D7D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/proj/dll/ocilib_dll_vs2019.vcxproj b/proj/dll/ocilib_dll.vcxproj similarity index 99% rename from proj/dll/ocilib_dll_vs2019.vcxproj rename to proj/dll/ocilib_dll.vcxproj index 2d5b3bfa..1caf1d36 100644 --- a/proj/dll/ocilib_dll_vs2019.vcxproj +++ b/proj/dll/ocilib_dll.vcxproj @@ -30,25 +30,25 @@ DynamicLibrary Unicode true - v142 + v143 DynamicLibrary MultiByte true - v142 + v143 DynamicLibrary Unicode true - v142 + v143 DynamicLibrary MultiByte true - v142 + v143 diff --git a/proj/dll/ocilib_dll_vs2019.vcxproj.filters b/proj/dll/ocilib_dll.vcxproj.filters similarity index 100% rename from proj/dll/ocilib_dll_vs2019.vcxproj.filters rename to proj/dll/ocilib_dll.vcxproj.filters diff --git a/proj/test/ocilib++_demo_vs2019.sln b/proj/test/ocilib++_demo.sln similarity index 100% rename from proj/test/ocilib++_demo_vs2019.sln rename to proj/test/ocilib++_demo.sln diff --git a/proj/test/ocilib++_demo_vs2019.vcxproj b/proj/test/ocilib++_demo.vcxproj similarity index 100% rename from proj/test/ocilib++_demo_vs2019.vcxproj rename to proj/test/ocilib++_demo.vcxproj diff --git a/proj/test/ocilib_demo_vs2019.sln b/proj/test/ocilib_demo.sln similarity index 100% rename from proj/test/ocilib_demo_vs2019.sln rename to proj/test/ocilib_demo.sln diff --git a/proj/test/ocilib_demo_vs2019.vcxproj b/proj/test/ocilib_demo.vcxproj similarity index 100% rename from proj/test/ocilib_demo_vs2019.vcxproj rename to proj/test/ocilib_demo.vcxproj From f01839afae42f445b743fa9529612cd0a2250d58 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Mon, 29 Nov 2021 18:39:16 +0100 Subject: [PATCH 14/19] Preparing for release --- ChangeLog | 21 ++ VERSION | 2 +- doxygen/Doxyfile.dox | 478 ++++++++++++++++++++++++--------------- doxygen/Introduction.txt | 2 +- nuget/ocilib.nuspec | 4 +- ocilib.pc | 2 +- proj/dll/main.rc | 16 +- 7 files changed, 331 insertions(+), 194 deletions(-) diff --git a/ChangeLog b/ChangeLog index a5e26714..4b377d58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2021-12-01 Version 4.7.4 Vincent Rogier vince.rogier@ocilib.net + + * Fixes (C API) + + - Issue 284: OCI_MsgGetID() returns a NULL ID after being queued with OCI_DequeuePut() + - Issue 288: OCI_GetString returns null on implicit conversion of a RAW value when it's longer than 64 bytes + - Issue 283: OCI_DequeueGet() returns null pointer when message has empty payload + - Issue 282: PL/SQL Server output wrong internal buffer size on some oracle versions + - Issue 281: ORA-00931 in OCI_TypeInfoGet() when using SYS.RAW type + + * Fixes (C++ API) + + - Issue 272: AddressSanitizer reports mismatched new[] vs delete + - Issue 278: ocilib::Object causes Segmentation fault + + * Miscellaneous + + - Updated compilers for MS Windows prebuilt binaries + * VS2022 17.0.1 for 32/64 bit DLLs + * VC runtime (statically linked) updated from vc142 to vc143 + 2021-03-09 Version 4.7.3 Vincent Rogier vince.rogier@ocilib.net * Fixes (C API) diff --git a/VERSION b/VERSION index 87b18a56..b48b2de9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.7.3 +4.7.4 diff --git a/doxygen/Doxyfile.dox b/doxygen/Doxyfile.dox index b30bf378..de10faae 100644 --- a/doxygen/Doxyfile.dox +++ b/doxygen/Doxyfile.dox @@ -1,4 +1,4 @@ -# Doxyfile 1.8.15 +# Doxyfile 1.9.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -38,7 +38,7 @@ PROJECT_NAME = "OCILIB (C and C++ Driver for Oracle)" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.7.3 +PROJECT_NUMBER = 4.7.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -93,14 +93,6 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -126,9 +118,9 @@ REPEAT_BRIEF = YES # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. -ABBREVIATE_BRIEF = "The $name class " \ - "The $name widget " \ - "The $name file " \ +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ is \ provides \ specifies \ @@ -170,7 +162,7 @@ FULL_PATH_NAMES = NO # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = "C:/Program Files/doxygen/bin/ " +STRIP_FROM_PATH = "C:/Program Files/doxygen/bin/ " # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -197,6 +189,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -217,6 +219,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -240,25 +250,19 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all @@ -299,19 +303,22 @@ OPTIMIZE_OUTPUT_SLICE = NO # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is -# Fortran), use: inc=Fortran f=C. +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = hpp=C++ @@ -329,7 +336,7 @@ MARKDOWN_SUPPORT = YES # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. +# Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 @@ -445,6 +452,19 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -465,6 +485,12 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -502,6 +528,13 @@ EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = YES +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -519,8 +552,8 @@ HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. +# declarations. If set to NO, these declarations will be included in the +# documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO @@ -539,11 +572,18 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. # The default value is: system dependent. CASE_SENSE_NAMES = NO @@ -562,6 +602,12 @@ HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -719,7 +765,8 @@ FILE_VERSION_FILTER = # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE @@ -765,24 +812,35 @@ WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -827,8 +885,8 @@ INPUT = Introduction.txt \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 @@ -841,11 +899,15 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cpp \ @@ -1067,16 +1129,24 @@ USE_HTAGS = NO VERBATIM_HEADERS = NO # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories @@ -1086,10 +1156,13 @@ CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the -# path to the compilation database (see: -# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files -# were built. This is equivalent to specifying the "-p" option to a clang tool, -# such as clang-check. These options will then be passed to the parser. +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. @@ -1106,13 +1179,6 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = NO -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored @@ -1212,7 +1278,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1222,7 +1288,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 222 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1251,9 +1317,9 @@ HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that -# are dynamically created via Javascript. If disabled, the navigation index will +# are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have Javascript, +# page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1283,10 +1349,11 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. @@ -1328,8 +1395,12 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1359,7 +1430,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1404,7 +1475,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1412,8 +1484,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1421,30 +1493,30 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1487,16 +1559,28 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATOR_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # @@ -1521,6 +1605,17 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML @@ -1541,8 +1636,14 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1552,11 +1653,29 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1569,22 +1688,29 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1612,7 +1738,7 @@ MATHJAX_CODEFILE = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There +# implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH # setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing @@ -1631,7 +1757,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1644,8 +1771,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1716,10 +1844,11 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex # The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to -# generate index for LaTeX. +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. # Note: This tag is used in the generated output file (.tex). # See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. -# The default value is: \makeindex. +# The default value is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_MAKEINDEX_CMD = \makeindex @@ -1739,7 +1868,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -1753,29 +1882,31 @@ PAPER_TYPE = a4wide EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = @@ -1808,9 +1939,11 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = NO -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1818,8 +1951,7 @@ USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode # command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# if errors occur, instead of asking the user for help. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1832,16 +1964,6 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. @@ -1922,16 +2044,6 @@ RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -2028,15 +2140,6 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -2049,6 +2152,10 @@ DOCBOOK_PROGRAMLISTING = NO GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- @@ -2211,12 +2318,6 @@ EXTERNAL_GROUPS = NO EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- @@ -2230,15 +2331,6 @@ PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = NO -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2336,10 +2428,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2529,9 +2643,11 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES diff --git a/doxygen/Introduction.txt b/doxygen/Introduction.txt index cb500f81..31c2f0ab 100644 --- a/doxygen/Introduction.txt +++ b/doxygen/Introduction.txt @@ -17,7 +17,7 @@ @section Version Version information -Current version : 4.7.3 +Current version : 4.7.4 @section Features Main features diff --git a/nuget/ocilib.nuspec b/nuget/ocilib.nuspec index c9173587..5314c193 100644 --- a/nuget/ocilib.nuspec +++ b/nuget/ocilib.nuspec @@ -2,7 +2,7 @@ ocilib - 4.7.3 + 4.7.4 Ocilib Driver for Oracle databases

OCILIB is an open source and cross platform Oracle Driver delivering efficient access to Oracle databases. @@ -18,7 +18,7 @@ It requires Oracle Client libraries (Regular or instant client). Vincent Rogier Vincentt Rogier - https://github.com/vrogier/ocilib/releases/tag/v4.7.3 + https://github.com/vrogier/ocilib/releases/tag/v4.7.4 https://github.com/vrogier/ocilib http://ocilib.net/images/logo-160x120.png images\logo-160x120.png diff --git a/ocilib.pc b/ocilib.pc index b5993bfb..f6eb90a9 100644 --- a/ocilib.pc +++ b/ocilib.pc @@ -5,7 +5,7 @@ includedir=${prefix}/include Name: ocilib Description: OCILIB is an open source and cross platform Oracle Driver that delivers efficient access to Oracle databases. URL: http://www.ocilib.net -Version: 4.7.3 +Version: 4.7.4 Libs: -L${exec_prefix}/lib -locilib Cflags: -I${prefix}/include diff --git a/proj/dll/main.rc b/proj/dll/main.rc index 35c546ef..d3499b4e 100644 --- a/proj/dll/main.rc +++ b/proj/dll/main.rc @@ -2,8 +2,8 @@ #include "resource.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,7,3,0 - PRODUCTVERSION 4,7,3,0 + FILEVERSION 4,7,4,0 + PRODUCTVERSION 4,7,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -20,11 +20,11 @@ BEGIN BEGIN VALUE "CompanyName", "Vincent Rogier" VALUE "FileDescription", "Open source C driver for Oracle databases" - VALUE "FileVersion", "4.7.3.0" + VALUE "FileVersion", "4.7.4.0" VALUE "InternalName", "OCILIB" VALUE "LegalCopyright", "Copyright © 2007-2021" VALUE "ProductName", "OCILIB (C driver for Oracle)" - VALUE "ProductVersion", "4.7.3.0" + VALUE "ProductVersion", "4.7.4.0" END END BLOCK "VarFileInfo" @@ -34,8 +34,8 @@ BEGIN END IDR_VERSION VERSIONINFO - FILEVERSION 4,7,3,0 - PRODUCTVERSION 4,7,3,0 + FILEVERSION 4,7,4,0 + PRODUCTVERSION 4,7,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -52,12 +52,12 @@ BEGIN BEGIN VALUE "CompanyName", "Vincent Rogier" VALUE "FileDescription", "Open source C driver for Oracle databases" - VALUE "FileVersion", "4.7.3.0" + VALUE "FileVersion", "4.7.4.0" VALUE "InternalName", "OCILIB.dll" VALUE "LegalCopyright", "Copyright © 2007-2021" VALUE "OriginalFilename", "OCILIB.dll" VALUE "ProductName", "OCILIB (C driver for Oracle)" - VALUE "ProductVersion", "4.7.3.0" + VALUE "ProductVersion", "4.7.4.0" END END BLOCK "VarFileInfo" From d1533b2e5a4237757b6f9f6e753401939c75c943 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 30 Nov 2021 12:19:27 +0100 Subject: [PATCH 15/19] Added (WIP) integration testing for direct path loading --- tests/TestDirectPath.cpp | 168 +++++++++++++++++++++++++++++ tests/ocilib_tests.vcxproj | 7 +- tests/ocilib_tests.vcxproj.filters | 3 + tests/packages.config | 2 +- 4 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 tests/TestDirectPath.cpp diff --git a/tests/TestDirectPath.cpp b/tests/TestDirectPath.cpp new file mode 100644 index 00000000..0a02ec99 --- /dev/null +++ b/tests/TestDirectPath.cpp @@ -0,0 +1,168 @@ +#include "ocilib_tests.h" +#include "ocilib.hpp" + +using namespace ocilib; + +enum DirectPathErrorTestMode +{ + Default = 0, + InsufficientBufferError, + ConversionError = 1, + LoadError = 2, + ForceLoad = 3 +}; + +class TestDirectPathErrorModes : public ::testing::TestWithParam {}; + +std::vector DirectPathErrorTestModes +{ + DirectPathErrorTestMode::Default, + DirectPathErrorTestMode::InsufficientBufferError, + DirectPathErrorTestMode::InsufficientBufferError | DirectPathErrorTestMode::ForceLoad, + DirectPathErrorTestMode::ConversionError, + DirectPathErrorTestMode::ConversionError | DirectPathErrorTestMode::ForceLoad, + DirectPathErrorTestMode::LoadError, + DirectPathErrorTestMode::LoadError | DirectPathErrorTestMode::ForceLoad, +}; + +TEST(TestDirectPath, Simple) +{ + auto constexpr ArraySize = 10u; + auto constexpr LoadSize = 10u; + auto constexpr ColCount = 3u; + auto constexpr ColSize1 = 20u; + auto constexpr ColSize2 = 30u; + auto constexpr ColSize3 = 8u; + + ExecDML(OTEXT("create table TestDirectPathTable1 (val_int int, val_str varchar2(50), val_date date)")); + ExecDML(OTEXT("truncate table TestDirectPathTable1")); + + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + char val1[ColSize1 + 1]; + char val2[ColSize2 + 1]; + char val3[ColSize3 + 1]; + + int i = 0, j = 0, nb_rows = ArraySize; + boolean res = TRUE; + + const auto table = OCI_TypeInfoGet(conn, OTEXT("TestDirectPathTable1"), OCI_TIF_TABLE); + ASSERT_NE(nullptr, table); + + const auto dp = OCI_DirPathCreate(table, NULL, ColCount, nb_rows); + ASSERT_NE(nullptr, dp); + + /* optional attributes to set */ + + ASSERT_TRUE(OCI_DirPathSetBufferSize(dp, 64000)); + ASSERT_TRUE(OCI_DirPathSetNoLog(dp, TRUE)); + ASSERT_TRUE(OCI_DirPathSetParallel(dp, TRUE)); + + /* describe the target table */ + + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 1, OTEXT("val_int"), ColSize1, nullptr)); + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 2, OTEXT("val_str"), ColSize2, nullptr)); + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 3, OTEXT("val_date"), ColSize3, OTEXT("YYYYMMDD"))); + + /* prepare the load */ + + ASSERT_TRUE(OCI_DirPathPrepare(dp)); + + nb_rows = OCI_DirPathGetMaxRows(dp); + ASSERT_NE(0, nb_rows); + + for (i = 0; i < LoadSize; i++) + { + ASSERT_TRUE(OCI_DirPathReset(dp)); + + for (j = 1; j <= nb_rows; j++) + { + /* fill test values */ + + osprintf(val1, "%04d", i + (i * 100)); + osprintf(val2, "value %05d", j + (i * 100)); + osprintf(val3, "%04d%02d%02d", (j % 23) + 1 + 2000, (j % 11) + 1, (j % 23) + 1); + + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 1, val1, (unsigned int)ostrlen(val1), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 2, val2, (unsigned int)ostrlen(val2), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 3, val3, (unsigned int)ostrlen(val3), TRUE)); + } + + /* load data to the server */ + + while (res) + { + int state = OCI_DirPathConvert(dp); + + if ((state == OCI_DPR_FULL) || (state == OCI_DPR_COMPLETE)) + res = OCI_DirPathLoad(dp); + + if (state == OCI_DPR_COMPLETE) + break; + + if (state == OCI_DPR_ERROR) + break; + } + } + + /* commits changes */ + + ASSERT_TRUE(OCI_DirPathFinish(dp)); + + ASSERT_EQ(ArraySize * LoadSize, OCI_DirPathGetRowCount(dp)); + + /* cleanup */ + + ASSERT_TRUE(OCI_DirPathFree(dp)); + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); + + ExecDML(OTEXT("drop table TestDirectPathTable1")); +} + +TEST(TestDirectPathErrorModes, AllErrorWorkflows) +{ + auto constexpr ArraySize = 10u; + auto constexpr LoadSize = 10u; + auto constexpr ColCount = 3u; + auto constexpr ColSize1 = 20u; + auto constexpr ColSize2 = 30u; + auto constexpr ColSize3 = 8u; + + ExecDML(OTEXT("create table TestDirectPathTable1 (val_int int, val_str varchar2(50), val_date date)")); + ExecDML(OTEXT("truncate table TestDirectPathTable1")); + + ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); + + const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); + ASSERT_NE(nullptr, conn); + + char val1[ColSize1 + 1]; + char val2[ColSize2 + 1]; + char val3[ColSize3 + 1]; + + int i = 0, j = 0, nb_rows = ArraySize; + boolean res = TRUE; + + const auto table = OCI_TypeInfoGet(conn, OTEXT("TestDirectPathTable1"), OCI_TIF_TABLE); + ASSERT_NE(nullptr, table); + + const auto dp = OCI_DirPathCreate(table, NULL, ColCount, nb_rows); + ASSERT_NE(nullptr, dp); + + //TODO + + /* cleanup */ + + ASSERT_TRUE(OCI_DirPathFree(dp)); + ASSERT_TRUE(OCI_ConnectionFree(conn)); + ASSERT_TRUE(OCI_Cleanup()); + + ExecDML(OTEXT("drop table TestDirectPathTable1")); +} + +INSTANTIATE_TEST_CASE_P(TestDirectPathErrorModes, TestDirectPathErrorModes, ::testing::ValuesIn(DirectPathErrorTestModes)); + diff --git a/tests/ocilib_tests.vcxproj b/tests/ocilib_tests.vcxproj index 6b57e6dd..dda78d93 100644 --- a/tests/ocilib_tests.vcxproj +++ b/tests/ocilib_tests.vcxproj @@ -31,7 +31,7 @@ Win32Proj 10.0 Application - v142 + v143 Unicode @@ -116,6 +116,7 @@ + @@ -147,7 +148,7 @@ - + @@ -253,6 +254,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/tests/ocilib_tests.vcxproj.filters b/tests/ocilib_tests.vcxproj.filters index 0bc4517b..fb105ef2 100644 --- a/tests/ocilib_tests.vcxproj.filters +++ b/tests/ocilib_tests.vcxproj.filters @@ -217,6 +217,9 @@ Tests suite + + Tests suite + diff --git a/tests/packages.config b/tests/packages.config index cbf03ab8..dd871dad 100644 --- a/tests/packages.config +++ b/tests/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file From 623e73bed696dbf12bd00d3fe93f0d9561635698 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 30 Nov 2021 12:19:49 +0100 Subject: [PATCH 16/19] Updates demo projects files --- .gitignore | 5 +++++ proj/test/ocilib++_demo.sln | 2 +- proj/test/ocilib++_demo.vcxproj | 8 ++++---- proj/test/ocilib_demo.sln | 2 +- proj/test/ocilib_demo.vcxproj | 6 ++++++ 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 171610db..c0e8f9f1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ /lib32 /lib64 /proj/dll/temp +/proj/test/Win32 +/proj/test/x64 # WinMerge backups *.bak @@ -181,3 +183,6 @@ testlog.manifest /nuget/*.nupkg *Browse.VC.db-wal *Browse.VC.db-shm +/.vs +*.recipe +*.txt diff --git a/proj/test/ocilib++_demo.sln b/proj/test/ocilib++_demo.sln index 1e4a90d8..393adc24 100644 --- a/proj/test/ocilib++_demo.sln +++ b/proj/test/ocilib++_demo.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29926.136 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ocilib++_demo_vs2019", "ocilib++_demo_vs2019.vcxproj", "{22508194-4A82-4EA7-A754-126534AE7108}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ocilib++_demo", "ocilib++_demo.vcxproj", "{22508194-4A82-4EA7-A754-126534AE7108}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/proj/test/ocilib++_demo.vcxproj b/proj/test/ocilib++_demo.vcxproj index 68985e69..bd89c038 100644 --- a/proj/test/ocilib++_demo.vcxproj +++ b/proj/test/ocilib++_demo.vcxproj @@ -32,27 +32,27 @@ Application true MultiByte - v142 + v143 Application true MultiByte - v142 + v143 Application false true Unicode - v142 + v143 Application false true Unicode - v142 + v143 diff --git a/proj/test/ocilib_demo.sln b/proj/test/ocilib_demo.sln index 7e707543..d39aa247 100644 --- a/proj/test/ocilib_demo.sln +++ b/proj/test/ocilib_demo.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 11.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCILIB Demo", "ocilib_demo_vs2019.vcxproj", "{D08196A4-17BC-42CE-A7A9-866905120974}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCILIB Demo", "ocilib_demo.vcxproj", "{D08196A4-17BC-42CE-A7A9-866905120974}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/proj/test/ocilib_demo.vcxproj b/proj/test/ocilib_demo.vcxproj index 0dcfda65..14625f93 100644 --- a/proj/test/ocilib_demo.vcxproj +++ b/proj/test/ocilib_demo.vcxproj @@ -190,6 +190,7 @@ MachineX86 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + false true @@ -238,6 +239,7 @@ MachineX64 + false true @@ -287,6 +289,7 @@ MachineX86 + false true @@ -336,6 +339,7 @@ MachineX64 + false true @@ -384,6 +388,7 @@ MachineX86 + false true @@ -432,6 +437,7 @@ MachineX64 + false true From 6c5ef5e77618de7984140bf615d874ff66543045 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 30 Nov 2021 17:41:02 +0100 Subject: [PATCH 17/19] Fixed issue #291 Added direct path non regression tests --- src/dirpath.c | 4 +- tests/TestDirectPath.cpp | 253 +++++++++++++++++++++++++++++++++++---- 2 files changed, 235 insertions(+), 22 deletions(-) diff --git a/src/dirpath.c b/src/dirpath.c index 81b856f0..e234286c 100644 --- a/src/dirpath.c +++ b/src/dirpath.c @@ -143,7 +143,7 @@ static unsigned int OcilibDirPathArrayToStream if (OCI_DCM_DEFAULT == dp->cvt_mode) { - THROW(OcilibExceptionOCI, dp->con->err, ret) + OcilibExceptionOCI(&call_context, dp->con->err, ret); } break; } @@ -246,7 +246,7 @@ static unsigned int OcilibDirPathLoadStream case OCI_ERROR: { status = OCI_DPR_ERROR; - THROW(OcilibExceptionOCI, dp->con->err, ret) + OcilibExceptionOCI(&call_context, dp->con->err, ret); break; } case OCI_NO_DATA: diff --git a/tests/TestDirectPath.cpp b/tests/TestDirectPath.cpp index 0a02ec99..ab1c7da7 100644 --- a/tests/TestDirectPath.cpp +++ b/tests/TestDirectPath.cpp @@ -6,10 +6,10 @@ using namespace ocilib; enum DirectPathErrorTestMode { Default = 0, - InsufficientBufferError, - ConversionError = 1, - LoadError = 2, - ForceLoad = 3 + InsufficientBufferError = 1, + ConversionError = 2, + LoadError = 4, + ForceLoad = 8 }; class TestDirectPathErrorModes : public ::testing::TestWithParam {}; @@ -17,14 +17,13 @@ class TestDirectPathErrorModes : public ::testing::TestWithParam {}; std::vector DirectPathErrorTestModes { DirectPathErrorTestMode::Default, - DirectPathErrorTestMode::InsufficientBufferError, - DirectPathErrorTestMode::InsufficientBufferError | DirectPathErrorTestMode::ForceLoad, + // DirectPathErrorTestMode::InsufficientBufferError, + // DirectPathErrorTestMode::InsufficientBufferError | DirectPathErrorTestMode::ForceLoad, DirectPathErrorTestMode::ConversionError, DirectPathErrorTestMode::ConversionError | DirectPathErrorTestMode::ForceLoad, DirectPathErrorTestMode::LoadError, - DirectPathErrorTestMode::LoadError | DirectPathErrorTestMode::ForceLoad, + DirectPathErrorTestMode::LoadError | DirectPathErrorTestMode::ForceLoad }; - TEST(TestDirectPath, Simple) { auto constexpr ArraySize = 10u; @@ -42,9 +41,9 @@ TEST(TestDirectPath, Simple) const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); ASSERT_NE(nullptr, conn); - char val1[ColSize1 + 1]; - char val2[ColSize2 + 1]; - char val3[ColSize3 + 1]; + otext val1[ColSize1 + 1]; + otext val2[ColSize2 + 1]; + otext val3[ColSize3 + 1]; int i = 0, j = 0, nb_rows = ArraySize; boolean res = TRUE; @@ -123,7 +122,28 @@ TEST(TestDirectPath, Simple) ExecDML(OTEXT("drop table TestDirectPathTable1")); } -TEST(TestDirectPathErrorModes, AllErrorWorkflows) +void CheckAllErrorWorkflows(OCI_Connection* con, OCI_DirPath* dp, int expected, int result, char* str) +{ + ASSERT_EQ(expected, result) << str; +} + +void CheckAllErrorWorkflowsData(OCI_Connection* con, OCI_DirPath* dp, boolean gen_conv_error, boolean gen_load_error, boolean force) +{ + auto constexpr ArraySize = 10u; + auto constexpr LoadSize = 10u; + auto constexpr TotalCount = ArraySize * LoadSize; + auto constexpr ErrCount = 2u; + + int nb_rows = 0; + + OCI_Immediate(con, "select count(*) from TestDirectPathTable2", OCI_ARG_INT, &nb_rows); + CheckAllErrorWorkflows(con, dp, ((gen_conv_error && force) || gen_load_error) ? (TotalCount - ErrCount) : TotalCount, nb_rows, "total rows in database"); + + OCI_ImmediateFmt(con, "select count(distinct val_int) from TestDirectPathTable2", OCI_ARG_INT, &nb_rows); + CheckAllErrorWorkflows(con, dp, ((gen_conv_error && force) || gen_load_error) ? (TotalCount - ErrCount) : TotalCount, nb_rows, "distinct rows in database"); +} + +TEST_P(TestDirectPathErrorModes, AllErrorWorkflows) { auto constexpr ArraySize = 10u; auto constexpr LoadSize = 10u; @@ -131,29 +151,222 @@ TEST(TestDirectPathErrorModes, AllErrorWorkflows) auto constexpr ColSize1 = 20u; auto constexpr ColSize2 = 30u; auto constexpr ColSize3 = 8u; + auto constexpr ErrCount = 2u; + auto constexpr TotalCount = ArraySize * LoadSize; - ExecDML(OTEXT("create table TestDirectPathTable1 (val_int int, val_str varchar2(50), val_date date)")); - ExecDML(OTEXT("truncate table TestDirectPathTable1")); + auto mode = GetParam(); + + ExecDML(OTEXT("create table TestDirectPathTable2(val_int int not null, val_str varchar2(30), val_date date) partition by range(val_int) ( partition test_dp_1 values less than (501), partition test_dp_2 values less than (1001))")); + ExecDML(OTEXT("truncate table TestDirectPathTable2")); ASSERT_TRUE(OCI_Initialize(nullptr, HOME, OCI_ENV_DEFAULT)); const auto conn = OCI_ConnectionCreate(DBS, USR, PWD, OCI_SESSION_DEFAULT); ASSERT_NE(nullptr, conn); - char val1[ColSize1 + 1]; - char val2[ColSize2 + 1]; - char val3[ColSize3 + 1]; + otext val1[ColSize1 + 1]; + otext val2[ColSize2 + 1]; + otext val3[ColSize3 + 1]; int i = 0, j = 0, nb_rows = ArraySize; boolean res = TRUE; - const auto table = OCI_TypeInfoGet(conn, OTEXT("TestDirectPathTable1"), OCI_TIF_TABLE); + const auto table = OCI_TypeInfoGet(conn, OTEXT("TestDirectPathTable2"), OCI_TIF_TABLE); ASSERT_NE(nullptr, table); const auto dp = OCI_DirPathCreate(table, NULL, ColCount, nb_rows); ASSERT_NE(nullptr, dp); - //TODO + bool force = mode & DirectPathErrorTestMode::ForceLoad; + bool gen_buffer_error = mode & DirectPathErrorTestMode::InsufficientBufferError; + bool gen_conv_error = mode & DirectPathErrorTestMode::ConversionError; + bool gen_load_error = mode & DirectPathErrorTestMode::LoadError; + + /* optional attributes to set */ + + ASSERT_TRUE(OCI_DirPathSetBufferSize(dp, gen_buffer_error ? 100 : 64000)); + ASSERT_TRUE(OCI_DirPathSetConvertMode(dp, force ? OCI_DCM_FORCE : OCI_DCM_DEFAULT)); + + /* describe the target table */ + + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 1, OTEXT("val_int"), ColSize1, nullptr)); + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 2, OTEXT("val_str"), ColSize2, nullptr)); + ASSERT_TRUE(OCI_DirPathSetColumn(dp, 3, OTEXT("val_date"), ColSize3, OTEXT("YYYYMMDD"))); + + /* prepare the load */ + + ASSERT_TRUE(OCI_DirPathPrepare(dp)); + + nb_rows = OCI_DirPathGetMaxRows(dp); + ASSERT_NE(0, nb_rows); + + for (i = 0; i < LoadSize; i++) + { + ASSERT_TRUE(OCI_DirPathReset(dp)); + + /* set the values for the current load iteration */ + for (j = 1; j <= nb_rows; j++) + { + /* conversion and loading errors are performed on the first load for rows 5 and 8 */ + if (i == 0 && (j == 5 || j == 8) && gen_conv_error) + { + /* generate a conversion error - not null clause violation on column val_int */ + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 1, NULL, 0, TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 2, NULL, 0, TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 3, NULL, 0, TRUE)); + } + else if (i == 0 && (j == 5 || j == 8) && gen_load_error) + { + /* generate a load error - if partitioning available, insert value out of declared partitions ranges */ + osprintf(val1, OTEXT("%04d"), 2500); + osprintf(val2, OTEXT("value %05d"), j + (i * ArraySize)); + osprintf(val3, OTEXT("%04d%02d%02d"), (j % 23) + 1 + 2000, (j % 11) + 1, (j % 23) + 1); + + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 1, val1, (unsigned int)ostrlen(val1), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 2, val2, (unsigned int)ostrlen(val2), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 3, val3, (unsigned int)ostrlen(val3), TRUE)); + } + else + { + /* default loading */ + osprintf(val1, OTEXT("%04d"), j + (i * ArraySize)); + osprintf(val2, OTEXT("value %05d"), j + (i * ArraySize)); + osprintf(val3, OTEXT("%04d%02d%02d"), (j % 23) + 1 + 2000, (j % 11) + 1, (j % 23) + 1); + + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 1, val1, (unsigned int)ostrlen(val1), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 2, val2, (unsigned int)ostrlen(val2), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 3, val3, (unsigned int)ostrlen(val3), TRUE)); + } + } + + /* load data to the server */ + while (TRUE) + { + int nb_conv = 0; + int nb_error = 0; + + /* convert data*/ + int state = OCI_DirPathConvert(dp); + + /* retrieve the number of converted rows */ + nb_conv += OCI_DirPathGetAffectedRows(dp); + + /* conversion or loading errors are performed on the first load */ + if (i == 0) + { + if (gen_conv_error && !force && state == OCI_DPR_ERROR) + { + /* on conversion error in default mode, correct values for next conversion */ + int row = OCI_DirPathGetErrorRow(dp); + + osprintf(val1, OTEXT("%04d"), row); + osprintf(val2, OTEXT("value %05d"), row); + osprintf(val3, OTEXT("%04d%02d%02d"), (row % 23) + 1 + 2000, (row % 11) + 1, (row % 23) + 1); + + ASSERT_TRUE(OCI_DirPathSetEntry(dp, row, 1, val1, (unsigned int)ostrlen(val1), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, row, 2, val2, (unsigned int)ostrlen(val2), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, row, 3, val3, (unsigned int)ostrlen(val3), TRUE)); + + nb_conv = 0; + } + + if (gen_conv_error && force && state == OCI_DPR_COMPLETE) + { + /* on conversion error in force mode, check we got the expected errors*/ + int err_row = OCI_DirPathGetErrorRow(dp); + int err_col = OCI_DirPathGetErrorColumn(dp); + + while (err_row != 0) + { + CheckAllErrorWorkflows(conn, dp, nb_error == 0 ? 5 : 8, err_row, "erred converted row index (force mode)"); + CheckAllErrorWorkflows(conn, dp, err_col, 1, "erred column index in force mode"); + + err_row = OCI_DirPathGetErrorRow(dp); + err_col = OCI_DirPathGetErrorColumn(dp); + + nb_error++; + } + + CheckAllErrorWorkflows(conn, dp, ErrCount, nb_error, "conversion errors in force mode"); + } + } + + if (state == OCI_DPR_FULL) + { + /* buffer is too small - load the stream */ + + state = OCI_DirPathLoad(dp); + + /* as the stream cannot accept all rows in one go, + we need to do conversion+load until all rows are processed */ + + while (nb_conv < ArraySize) + { + for (j = 1; j <= nb_rows - nb_conv; j++) + { + osprintf(val1, OTEXT("%04d"), (j + nb_conv) + (i * ArraySize)); + osprintf(val2, OTEXT("value %05d"), (j + nb_conv) + (i * ArraySize)); + osprintf(val3, OTEXT("%04d%02d%02d"), ((j + nb_conv) % 23) + 1 + 2000, ((j + nb_conv) % 11) + 1, ((j + nb_conv) % 23) + 1); + + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 1, val1, (unsigned int)ostrlen(val1), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 2, val2, (unsigned int)ostrlen(val2), TRUE)); + ASSERT_TRUE(OCI_DirPathSetEntry(dp, j, 3, val3, (unsigned int)ostrlen(val3), TRUE)); + } + + /* convert again */ + + state = OCI_DirPathConvert(dp); + + nb_conv = OCI_DirPathGetAffectedRows(dp); + + /* load again */ + + state = OCI_DirPathLoad(dp); + } + + break; + } + else if (state == OCI_DPR_COMPLETE) + { + /* conversion is complete */ + + CheckAllErrorWorkflows(conn, dp, (gen_conv_error && i == 0 && force) ? (ArraySize - ErrCount) : ArraySize, nb_conv, "converted rows"); + + state = OCI_DirPathLoad(dp); + + if (gen_load_error && i == 0) + { + /* on loading error in force mode, check we got the expected errors*/ + int err_row = OCI_DirPathGetErrorRow(dp); + + while (err_row != 0) + { + CheckAllErrorWorkflows(conn, dp, nb_error == 0 ? 5 : 8, err_row, "erred loaded row index"); + + err_row = OCI_DirPathGetErrorRow(dp); + + nb_error++; + } + + CheckAllErrorWorkflows(conn, dp, ErrCount, nb_error, "loading errors in force mode"); + } + + CheckAllErrorWorkflows(conn, dp, (gen_load_error && i == 0) ? nb_conv - ErrCount : nb_conv, OCI_DirPathGetAffectedRows(dp), "loaded rows"); + + break; + } + } + } + + /* commits changes */ + + ASSERT_TRUE(OCI_DirPathFinish(dp)); + + /* verify loading results */ + CheckAllErrorWorkflows(conn, dp, ((gen_conv_error&& force) || gen_load_error) ? (TotalCount - ErrCount) : TotalCount, OCI_DirPathGetRowCount(dp), "total loaded rows"); + + /* check data integrity in database */ + CheckAllErrorWorkflowsData(conn, dp, gen_conv_error, gen_load_error, force); /* cleanup */ @@ -161,7 +374,7 @@ TEST(TestDirectPathErrorModes, AllErrorWorkflows) ASSERT_TRUE(OCI_ConnectionFree(conn)); ASSERT_TRUE(OCI_Cleanup()); - ExecDML(OTEXT("drop table TestDirectPathTable1")); + ExecDML(OTEXT("drop table TestDirectPathTable2")); } INSTANTIATE_TEST_CASE_P(TestDirectPathErrorModes, TestDirectPathErrorModes, ::testing::ValuesIn(DirectPathErrorTestModes)); From e3df9f97fc9cbbb6e632ea39b912402a75a84274 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 30 Nov 2021 17:56:23 +0100 Subject: [PATCH 18/19] Updated changelog --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4b377d58..627fa1b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ -2021-12-01 Version 4.7.4 Vincent Rogier vince.rogier@ocilib.net +2021-11-30 Version 4.7.4 Vincent Rogier vince.rogier@ocilib.net * Fixes (C API) + - Issue 291: OCI_DirPathGetErrorRow() always return 0 since v4.7.0 - Issue 284: OCI_MsgGetID() returns a NULL ID after being queued with OCI_DequeuePut() - Issue 288: OCI_GetString returns null on implicit conversion of a RAW value when it's longer than 64 bytes - Issue 283: OCI_DequeueGet() returns null pointer when message has empty payload From 586bff09b4eb92d873b7f9712f251106376ca119 Mon Sep 17 00:00:00 2001 From: Vincent Rogier Date: Tue, 30 Nov 2021 18:31:09 +0100 Subject: [PATCH 19/19] Update nuspec for v4.7.4 release --- nuget/ocilib.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/ocilib.nuspec b/nuget/ocilib.nuspec index 5314c193..4290a770 100644 --- a/nuget/ocilib.nuspec +++ b/nuget/ocilib.nuspec @@ -27,7 +27,7 @@ It requires Oracle Client libraries (Regular or instant client). https://licenses.nuget.org/Apache-2.0 Copyright 2007-2021 Vincent Rogier Oracle SQL C C++ OCI API Access Driver - +