From: <mie...@us...> - 2013-04-30 01:59:25
|
Revision: 9180 http://sourceforge.net/p/oorexx/code-0/9180 Author: miesfeld Date: 2013-04-30 01:59:22 +0000 (Tue, 30 Apr 2013) Log Message: ----------- Feature Requests: #541 Allow registration of user defined collations in ooSQLite See ticket [FeaturRequests:#541] #543 Add access to sqlite3_load_extension in ooSQLite See ticket [FeaturRequests:#543] Modified Paths: -------------- incubator/ooSQLite/Makefile.win incubator/ooSQLite/examples/loadExtension.rex incubator/ooSQLite/examples/user.extensions/Makefile.lin incubator/ooSQLite/examples/user.extensions/simpleExtension.c incubator/ooSQLite/src/ooSQLite.cpp incubator/ooSQLite/src/ooSQLite.hpp incubator/ooSQLite/src/platform/windows/winOS.hpp incubator/ooSQLite/src/rexx/ooSQLite.cls Added Paths: ----------- incubator/ooSQLite/examples/collationCustom.rex Removed Paths: ------------- incubator/ooSQLite/examples/collationTest.rex Modified: incubator/ooSQLite/Makefile.win =================================================================== --- incubator/ooSQLite/Makefile.win 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/Makefile.win 2013-04-30 01:59:22 UTC (rev 9180) @@ -197,7 +197,7 @@ @cd ..\..\ dist: all - echo Create distribution file + @echo Create distribution file rexx src\rexx\makeDistFile.rex $(OOSQLITE_VER_STR) clean: Copied: incubator/ooSQLite/examples/collationCustom.rex (from rev 9178, incubator/ooSQLite/examples/collationTest.rex) =================================================================== --- incubator/ooSQLite/examples/collationCustom.rex (rev 0) +++ incubator/ooSQLite/examples/collationCustom.rex 2013-04-30 01:59:22 UTC (rev 9180) @@ -0,0 +1,181 @@ +#!/usr/bin/rexx +/*----------------------------------------------------------------------------*/ +/* */ +/* Copyright (c) 2013-2013 Rexx Language Association. All rights reserved. */ +/* */ +/* This program and the accompanying materials are made available under */ +/* the terms of the Common Public License v1.0 which accompanies this */ +/* distribution. A copy is also available at the following address: */ +/* http://www.oorexx.org/license.html */ +/* */ +/* Redistribution and use in source and binary forms, with or */ +/* without modification, are permitted provided that the following */ +/* conditions are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in */ +/* the documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the name of Rexx Language Association nor the names */ +/* of its contributors may be used to endorse or promote products */ +/* derived from this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */ +/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/*----------------------------------------------------------------------------*/ + +/** + * collationCustom.rex + * + * This example demonstrates the createCollation() and collationNeeded() + * methods of the ooSQLiteConnection class. Both of these methods register + * callback methods in a Rexx object. + */ + + -- Set the result set format to an array of arrays: + .ooSQLite~recordFormat = .ooSQLite~OO_ARRAY_OF_ARRAYS + + dbName = 'ooFoods.rdbx' + + dbConn = .ooSQLiteConnection~new(dbName, .ooSQLite~OPEN_READWRITE) + + -- Instantiate our Rexx object that contains our callback methods. + collater = .Collater~new + + -- In this first example we created a custom collation using a callback method + -- in a Rexx object. + -- + -- 1st arg name of COLLATE function, 2nd arg Rexx object with method + -- 3rd arg collation method, 4th arg any Rexx object + dbConn~createCollation('ReverseSort', collater, 'reverseCollate', collater) + + sql = "SELECT * FROM foods ORDER BY name COLLATE REVERSESORT;" + resultSet = dbConn~exec(sql, .true) + + z = printResultSet(resultSet) + say + + -- When the database connection is closed, the custom collation is unregisterd + ret = dbConn~close + + -- In this second example, we do not create a custom collation. Instead we + -- register a collation needed callback. When SQLite encounters an undefined + -- collation it invokes the callback. Within the callback, the programmer + -- should create the needed collation. + + -- We use a different name for the database connection to emphasis that this + -- is a completely different connection than the dbConn connection above. + connection = .ooSQLiteConnection~new(dbName, .ooSQLite~OPEN_READWRITE) + + connection~collationNeeded(collater, collationNeeded, collater) + + -- With this connection we are going to use 2 different custom collations. + -- Just to show how the collation need call back works. + sql = "SELECT * FROM foods where name like 'J%' ORDER BY name COLLATE REVERSESORT;" + resultSet = connection~exec(sql, .true) + + z = printResultSet(resultSet) + say + + -- Use a second collation here. + sql = "SELECT * FROM foods ORDER BY name COLLATE CASEDREVERSESORT;" + resultSet = connection~exec(sql, .true) + + z = printResultSet(resultSet) + say + + -- Always close any open database connections. + ret = connection~close + + return ret + +::requires 'ooSQLite.cls' + +-- The Collater class is used to define our callback methods. +::class 'Collater' + +-- Our registered callback method. SQLite invokes this method when it +-- encounters and undefined collation. +::method collationNeeded + use arg dbConn, collationName, userData + + say 'collationNeeded() collation name:' collationName + say + + -- We check the collation name to determine which collation to create. + if collationName~caseLessCompare('ReverseSort') == 0 then do + -- 1st arg name of COLLATE function, 2nd arg Rexx object with method + -- 3rd arg collation method, 4th arg any Rexx object + dbConn~createCollation('ReverseSort', self, 'reverseCollate', self) + end + + if collationName~caseLessCompare('CasedReverseSort') == 0 then do + -- 1st arg name of COLLATE function, 2nd arg Rexx object with method + -- 3rd arg collation method, 4th arg any Rexx object + dbConn~createCollation('CasedReverseSort', self, 'reverseCollateWithCase', self) + end + + -- Must return a result + return .ooSQLiteConstants~OK + +-- Our first registered collation method. SQLite invokes this method to compare +-- 2 strings. We must return 0 if the strings are equal, a negative number if the +-- first string is less than the second, and a positive number if the first +-- string is greater than the second. +-- +-- We just do a caseless reverse sort by negating the return from +-- caselessCompareTo() +::method reverseCollate + use arg str1, str2, userData + + return - str1~caselessCompareTo(str2); + + +-- Our second registere collation method. Here we also do a reverse sort, but +-- we use case sensitive sort. +::method reverseCollateWithCase + use arg str1, str2, userData + + return - str1~CompareTo(str2); + + +-- Common utility routine used to print a result set that is an array of arrays. +::routine printResultSet + use arg rs + + colCount = rs[1]~items + rowCount = rs~items + + line = '' + headers = rs[1] + do j = 1 to colCount + line ||= headers[j]~left(25) + end + + say line + say '='~copies(80) + + do i = 2 to rowCount + line = '' + record = rs[i] + do j = 1 to colCount + line ||= record[j]~left(25) + end + + say line + end + say + + return 0 Deleted: incubator/ooSQLite/examples/collationTest.rex =================================================================== --- incubator/ooSQLite/examples/collationTest.rex 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/examples/collationTest.rex 2013-04-30 01:59:22 UTC (rev 9180) @@ -1,108 +0,0 @@ -#!/usr/bin/rexx -/*----------------------------------------------------------------------------*/ -/* */ -/* Copyright (c) 2012-2013 Rexx Language Association. All rights reserved. */ -/* */ -/* This program and the accompanying materials are made available under */ -/* the terms of the Common Public License v1.0 which accompanies this */ -/* distribution. A copy is also available at the following address: */ -/* http://www.oorexx.org/license.html */ -/* */ -/* Redistribution and use in source and binary forms, with or */ -/* without modification, are permitted provided that the following */ -/* conditions are met: */ -/* */ -/* Redistributions of source code must retain the above copyright */ -/* notice, this list of conditions and the following disclaimer. */ -/* Redistributions in binary form must reproduce the above copyright */ -/* notice, this list of conditions and the following disclaimer in */ -/* the documentation and/or other materials provided with the distribution. */ -/* */ -/* Neither the name of Rexx Language Association nor the names */ -/* of its contributors may be used to endorse or promote products */ -/* derived from this software without specific prior written permission. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ -/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ -/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ -/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ -/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ -/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ -/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ -/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */ -/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ -/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ -/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* */ -/*----------------------------------------------------------------------------*/ - -/** - * collationText.rex - * - * ?? - * - */ - - -- Set the result set format to an array of arrays: - .ooSQLite~recordFormat = .ooSQLite~OO_ARRAY_OF_ARRAYS - - dbName = 'ooFoods.rdbx' - - dbConn = .ooSQLiteConnection~new(dbName, .ooSQLite~OPEN_READWRITE) - - collater = .Collater~new - - -- 1st arg name of COLLATE function, 2nd arg Rexx object with method - -- 3rd arg collation method, 4th arg any Rexx object - dbConn~createCollation('ReverseSort', collater, 'reverseCollate', collater) - - --sql = "SELECT * FROM foods where name like 'J%' ORDER BY name COLLATE REVERSESORT;" - sql = "SELECT * FROM foods ORDER BY name COLLATE REVERSESORT;" - resultSet = dbConn~exec(sql, .true) - - z = printResultSet(resultSet) - - say 'Result Set: ' resultSet - say 'Result Set Class:' resultSet~class - say - - ret = dbConn~close - - return ret - -::requires 'ooSQLite.cls' - -::class 'Collater' - -::method reverseCollate - use arg str1, str2, userData - - return - str1~caselessCompareTo(str2); - -::routine printResultSet - use arg rs - - colCount = rs[1]~items - rowCount = rs~items - - line = '' - headers = rs[1] - do j = 1 to colCount - line ||= headers[j]~left(25) - end - - say line - say '='~copies(80) - - do i = 2 to rowCount - line = '' - record = rs[i] - do j = 1 to colCount - line ||= record[j]~left(25) - end - - say line - end - say - - return 0 Modified: incubator/ooSQLite/examples/loadExtension.rex =================================================================== --- incubator/ooSQLite/examples/loadExtension.rex 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/examples/loadExtension.rex 2013-04-30 01:59:22 UTC (rev 9180) @@ -41,9 +41,13 @@ * * Demonstrates how to load an SQLite extensions file. * - * The extensions are implemented in simpleExtension.cpp which is in the - * user.extensions subdirectory. + * The extensions are implemented in simpleExtension.c which is in the + * user.extensions subdirectory. On Windows simpleExtension.c is compiled into + * a DLL, on Linux it is compiled into a .so file. * + * One of the extensions is a collation, REVERSESORT. After loading the + * extension file, we can use the REVERSESORT collation here. + * */ os = getOSName() @@ -55,7 +59,7 @@ extensionFile = 'user.extensions/libsimpleExtension.so' end - dbName = 'ooFoods.rdbx' + dbName = 'ooFoods.rdbx' -- Set the result set format to an array of arrays: .ooSQLite~recordFormat = .ooSQLite~OO_ARRAY_OF_ARRAYS Modified: incubator/ooSQLite/examples/user.extensions/Makefile.lin =================================================================== --- incubator/ooSQLite/examples/user.extensions/Makefile.lin 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/examples/user.extensions/Makefile.lin 2013-04-30 01:59:22 UTC (rev 9180) @@ -40,7 +40,7 @@ EXTRAINCLUDE=-I ../../src/sqlite -BASEFLAGS = $(EXTRAINCLUDE) +BASEFLAGS = $(EXTRAINCLUDE) -DNULL=1 SO_LFLAGS=-shared -nostartfiles Modified: incubator/ooSQLite/examples/user.extensions/simpleExtension.c =================================================================== --- incubator/ooSQLite/examples/user.extensions/simpleExtension.c 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/examples/user.extensions/simpleExtension.c 2013-04-30 01:59:22 UTC (rev 9180) @@ -53,11 +53,6 @@ * loadExtension() call. */ -#ifdef _WIN32 - #include <windows.h> -#else - #define NULL 0 -#endif /* Normally use sqlite3ext.h, the ooSQLite source uses sqlite3ext.hpp */ #include <sqlite3ext.hpp> Modified: incubator/ooSQLite/src/ooSQLite.cpp =================================================================== --- incubator/ooSQLite/src/ooSQLite.cpp 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/src/ooSQLite.cpp 2013-04-30 01:59:22 UTC (rev 9180) @@ -42,18 +42,11 @@ */ #include "sqlite3.hpp" +#include "ooSQLite.hpp" -#ifdef _WIN32 - #include "platform\windows\winOS.hpp" -#else - #include "platform/unix/unixOS.hpp" -#endif - #include <stdio.h> #include <string.h> -#include "oorexxapi.h" -#include "ooSQLite.hpp" #include "APICommon.hpp" @@ -1535,6 +1528,69 @@ } /** + * The call back function for sqlite3_collation_needed() + * + * @param data + * + * @return void + * + * @notes The Rexx callback method or routine must return a whole number, but + * the actual value is ignored. Within the callback + */ +static void collationNeededCallback(void *data, sqlite3* db, int eTextRep, const char *name) +{ + pCGenericCallback d = (pCGenericCallback)data; + RexxThreadContext *c = d->callbackContext; + + if ( d->initialThreadID != oosqlGetCurrentThreadId() ) + { + if ( ! d->interpreter->AttachThread(&c) ) + { + // There is nothing to be done about this, need to just quit. But, + // I doubt it ever happens. + return; + } + } + + RexxArrayObject args; + RexxStringObject collationName = c->String(name); + RexxObjectPtr reply = NULLOBJECT; + wholenumber_t rc = 0; + + bool isMethod = (d->callbackObj == NULLOBJECT) ? false : true; + + if ( d->userData == NULL ) + { + args = c->ArrayOfThree(d->rexxDB, collationName, TheNilObj); + } + else + { + args = c->ArrayOfThree(d->rexxDB, collationName, d->userData); + } + + if ( isMethod ) + { + reply = c->SendMessage(d->callbackObj, d->callbackMethod, args); + } + else + { + reply = c->CallRoutine(d->callbackRtn, args); + } + + // We just check for errors, we do not actually use rc. + replyIsGood(c, reply, &rc, d->callbackMethod, d->routineName, isMethod); + + c->ReleaseLocalReference(reply); + c->ReleaseLocalReference(collationName); + c->ReleaseLocalReference(args); + + if ( c != d->callbackContext ) + { + c->DetachThread(); + } +} + +/** * The call back function for sqlite3_commit_hook() * * @param data @@ -1551,10 +1607,6 @@ pCGenericCallback d = (pCGenericCallback)data; RexxThreadContext *c = d->callbackContext; - RexxArrayObject args; - RexxObjectPtr reply = NULLOBJECT; - wholenumber_t rc = 0; - bool isMethod = (d->callbackObj == NULLOBJECT) ? false : true; if ( d->initialThreadID != oosqlGetCurrentThreadId() ) @@ -1566,6 +1618,10 @@ } } + RexxArrayObject args; + RexxObjectPtr reply = NULLOBJECT; + wholenumber_t rc = 0; + if ( d->userData == NULL ) { args = c->ArrayOfOne(TheNilObj); @@ -2732,6 +2788,8 @@ return "__rxBusyHandler"; case collation : return "__rxCollation"; + case collationNeeded : + return "__rxCollationNeeded"; case commitHook : return "__rxCommitHook"; case profileHook : @@ -3217,6 +3275,52 @@ return context->Int32(sqlite3_libversion_number()); } +typedef void * (CALLBACK* LPFNDLLFUNC1)(void); + +/** ooSQLite::loadLibrary() [class method] + * + * Loads a shared library and optionally the extension functions in the + * library. + * + */ +RexxMethod3(RexxObjectPtr, oosql_loadLibrary_cls, CSTRING, libName, OPTIONAL_RexxObjectPtr, procedures, CSELF, pCSelf) +{ + RexxMethodContext *c = context; + pCooSQLiteClass pcoosc = (pCooSQLiteClass)pCSelf; + + CSTRING procName = NULL; + LPFNDLLFUNC1 procedure = NULL; + HMODULE libraryHandle = LoadLibrary(libName); + + if ( libraryHandle == NULL ) + { + printf("oosql_loadLibrary_cls LoadLibrary (%s) failed err=%d\n", libName, GetLastError()); + return TheFalseObj; + } + + if ( argumentExists(2) ) + { + // check if it is an array. + + procName = c->ObjectToStringValue(procedures); + procedure = (LPFNDLLFUNC1)GetProcAddress(libraryHandle, procName); + printf("procName=%s pointer=%p\n", procName, procedure); + + if ( procedure != NULL ) + { + void *handle = procedure(); + printf("procName=%s pointer=%p\n", procName, handle); + + if ( handle != NULL ) + { + return c->NewPointer(handle); + } + } + } + + return TheTrueObj; +} + /** ooSQLite::memoryHighWater() * * @@ -3359,13 +3463,15 @@ } /** - * Transitory method used to test various things as they come up. + * Internal use only. * + * Transient method used to test various things as they come up. + * */ RexxMethod1(int, oosql_test_cls, ARGLIST, args) { RexxMethodContext *c = context; - /* + size_t size = c->ArraySize(args); printf("CONSTRAINT_CHECK =%d\n", SQLITE_CONSTRAINT_CHECK ); @@ -3378,10 +3484,7 @@ printf("CONSTRAINT_UNIQUE =%d\n", SQLITE_CONSTRAINT_UNIQUE ); printf("CONSTRAINT_VTAB =%d\n", SQLITE_CONSTRAINT_VTAB ); printf("READONLY_ROLLBACK =%d\n", SQLITE_READONLY_ROLLBACK ); - */ - printf("collationCallback=%p &of=%p\n", collationCallback, &collationCallback); - return 0; } @@ -3485,6 +3588,10 @@ { return "COLLATIONCALLBACK"; // collationCallback() } + else if ( cbt == collationNeeded ) + { + return "COLLATIONNEEDEDCALLBACK"; // collationNeededCallback() + } else if ( cbt == commitHook ) { return "COMMITHOOKCALLBACK"; // commitHookCallback() @@ -3533,6 +3640,12 @@ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF8, NULL, NULL, NULL); result = c->WholeNumber(rc); } + else if ( cbt == collationNeeded ) + { + // Note that docs do not actually say this removes the callback. + rc = sqlite3_collation_needed(db, NULL, NULL); + result = c->WholeNumber(rc); + } else if ( cbt == commitHook ) { cbc = (pCGenericCallback)sqlite3_commit_hook(db, NULL, NULL); @@ -3595,6 +3708,11 @@ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF8, (void *)cbc, collationCallback, NULL); result = c->WholeNumber(rc); } + else if ( cbt == collationNeeded ) + { + rc = sqlite3_collation_needed(db, (void *)cbc, collationNeededCallback); + result = c->WholeNumber(rc); + } else if ( cbt == commitHook ) { oldCbc = (pCGenericCallback)sqlite3_commit_hook(db, commitHookCallback, (void *)cbc); @@ -3660,9 +3778,11 @@ * of them and we don't want them garbage collected out from under us * during a callback. */ -static RexxObjectPtr doCallbackSetup(RexxMethodContext *c, sqlite3 *db, RexxObjectPtr callbackObj, CSTRING mthName, +static RexxObjectPtr doCallbackSetup(RexxMethodContext *c, pCooSQLiteConn pConn, RexxObjectPtr callbackObj, CSTRING mthName, RexxObjectPtr userData, CallbackType cbt, int instructions, CSTRING zName) { + sqlite3 *db = pConn->db; + if ( callbackObj == TheNilObj ) { return removeCallback(c, db, cbt, zName); @@ -3683,6 +3803,7 @@ cbc->callbackObj = c->RequestGlobalReference(callbackObj); cbc->callbackContext = c->threadContext; + cbc->rexxDB = pConn->rexxSelf; cbc->interpreter = c->threadContext->instance; cbc->initialThreadID = oosqlGetCurrentThreadId(); @@ -4515,7 +4636,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - RexxObjectPtr rc = doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, busyHandler, 0, NULL); + RexxObjectPtr rc = doCallbackSetup(context, pConn, callbackObj, mthName, userData, busyHandler, 0, NULL); if ( objIsSqliteOK(context, rc) ) { @@ -4616,6 +4737,53 @@ } +/** ooSQLiteConnection::collationNeeded() + * + * Registers a callback method to be invoked whenever whenever an undefined + * collation sequence is required. + * + * @param callbackObj [required] An instantiated class object with a method + * that is invoked whenever an undefined collation is + * needed. + * + * However, this argument can also be .nil to indicate + * that an already registered callback is to be removed. + * + * @param mthName [optional] The method name that will be invoked during + * the callback. By default, the method invoked will be + * collationNeededCallback(). However, the user can + * specify an alternative method if desired. This + * argument is ignored when the callbackObj argument is + * .nil. + * + * @param userData [optional] This can be any Rexx object the user + * desires. The object will be sent as the secon argument + * to the callback method when it is invoked. This + * argument is ignored when the callbackObj argument is + * .nil. + * + * @return An ooSQLite result code. + * + * @notes When the callback is invoked, the method should register the desired + * collation using createCollation(). + * + * The callback method is sent 3 arguments, the Rexx database + * connection object, the name of the collation, and the userData + * object, or .nil if no userData object was specified. + */ +RexxMethod4(RexxObjectPtr, oosqlconn_collationNeeded, RexxObjectPtr, callbackObj, OPTIONAL_CSTRING, mthName, + OPTIONAL_RexxObjectPtr, userData, CSELF, pCSelf) +{ + pCooSQLiteConn pConn = requiredDB(context, pCSelf); + if ( pConn == NULL ) + { + return context->WholeNumber(SQLITE_MISUSE); + } + + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, collationNeeded, 0, NULL); +} + + /** ooSQLiteConnection::commitHook() * * Registers a callback method to be invoked whenever a transaction is @@ -4657,7 +4825,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, commitHook, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, commitHook, 0, NULL); } @@ -4822,7 +4990,7 @@ mthName = c->ObjectToStringValue(callbackName); } - result = doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, collation, 0, collationName); + result = doCallbackSetup(context, pConn, callbackObj, mthName, userData, collation, 0, collationName); return result; } @@ -5513,7 +5681,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, profileHook, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, profileHook, 0, NULL); } @@ -5579,7 +5747,7 @@ callbackObj = TheNilObj; } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, progressHandler, instructions, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, progressHandler, instructions, NULL); } @@ -5661,7 +5829,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, rollbackHook, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, rollbackHook, 0, NULL); } @@ -5739,7 +5907,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, authorizer, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, authorizer, 0, NULL); } @@ -5835,7 +6003,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, traceHook, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, traceHook, 0, NULL); } @@ -5891,7 +6059,7 @@ return context->WholeNumber(SQLITE_MISUSE); } - return doCallbackSetup(context, pConn->db, callbackObj, mthName, userData, updateHook, 0, NULL); + return doCallbackSetup(context, pConn, callbackObj, mthName, userData, updateHook, 0, NULL); } @@ -5926,6 +6094,26 @@ } /** + * Internal use only, transient testing function. + * + */ +RexxMethod2(int, oosqlconn_test, POINTER, functPointer, CSELF, pCSelf) +{ + int rc = SQLITE_MISUSE; + + fnXCompare f = (fnXCompare)functPointer; + + pCooSQLiteConn pConn = requiredDBCSelf(context, pCSelf); + if ( pConn != NULLOBJECT ) + { + rc = sqlite3_create_collation_v2(pConn->db, "REVERSESORT", SQLITE_UTF8, NULL, + f, NULL); + } + + return rc; +} + +/** * Methods for the .ooSQLiteStmt class. */ #define OOSQLITESTMT_CLASS "ooSQLiteStmt" @@ -10969,6 +11157,7 @@ REXX_METHOD_PROTOTYPE(oosql_errStr_cls); REXX_METHOD_PROTOTYPE(oosql_libVersion_cls); REXX_METHOD_PROTOTYPE(oosql_libVersionNumber_cls); +REXX_METHOD_PROTOTYPE(oosql_loadLibrary_cls); REXX_METHOD_PROTOTYPE(oosql_memoryHighWater_cls); REXX_METHOD_PROTOTYPE(oosql_memoryUsed_cls); REXX_METHOD_PROTOTYPE(oosql_releaseMemory_cls); @@ -11002,8 +11191,9 @@ REXX_METHOD_PROTOTYPE(oosqlconn_busyTimeOut); REXX_METHOD_PROTOTYPE(oosqlconn_changes); REXX_METHOD_PROTOTYPE(oosqlconn_close); +REXX_METHOD_PROTOTYPE(oosqlconn_collationNeeded); +REXX_METHOD_PROTOTYPE(oosqlconn_commitHook); REXX_METHOD_PROTOTYPE(oosqlconn_createCollation); -REXX_METHOD_PROTOTYPE(oosqlconn_commitHook); REXX_METHOD_PROTOTYPE(oosqlconn_dbFileName); REXX_METHOD_PROTOTYPE(oosqlconn_dbMutex); REXX_METHOD_PROTOTYPE(oosqlconn_dbReadOnly); @@ -11034,6 +11224,7 @@ REXX_METHOD_PROTOTYPE(oosqlconn_putStmt); REXX_METHOD_PROTOTYPE(oosqlconn_delStmt); +REXX_METHOD_PROTOTYPE(oosqlconn_test); // .ooSQLiteStmt REXX_METHOD_PROTOTYPE(oosqlstmt_init_cls); @@ -11144,6 +11335,7 @@ REXX_METHOD(oosql_errStr_cls, oosql_errStr_cls), REXX_METHOD(oosql_libVersion_cls, oosql_libVersion_cls), REXX_METHOD(oosql_libVersionNumber_cls, oosql_libVersionNumber_cls), + REXX_METHOD(oosql_loadLibrary_cls, oosql_loadLibrary_cls), REXX_METHOD(oosql_memoryUsed_cls, oosql_memoryUsed_cls), REXX_METHOD(oosql_memoryHighWater_cls, oosql_memoryHighWater_cls), REXX_METHOD(oosql_releaseMemory_cls, oosql_releaseMemory_cls), @@ -11177,8 +11369,9 @@ REXX_METHOD(oosqlconn_busyTimeOut, oosqlconn_busyTimeOut), REXX_METHOD(oosqlconn_changes, oosqlconn_changes), REXX_METHOD(oosqlconn_close, oosqlconn_close), + REXX_METHOD(oosqlconn_collationNeeded, oosqlconn_collationNeeded), + REXX_METHOD(oosqlconn_commitHook, oosqlconn_commitHook), REXX_METHOD(oosqlconn_createCollation, oosqlconn_createCollation), - REXX_METHOD(oosqlconn_commitHook, oosqlconn_commitHook), REXX_METHOD(oosqlconn_dbFileName, oosqlconn_dbFileName), REXX_METHOD(oosqlconn_dbMutex, oosqlconn_dbMutex), REXX_METHOD(oosqlconn_dbReadOnly, oosqlconn_dbReadOnly), @@ -11209,6 +11402,7 @@ REXX_METHOD(oosqlconn_putStmt, oosqlconn_putStmt), REXX_METHOD(oosqlconn_delStmt, oosqlconn_delStmt), + REXX_METHOD(oosqlconn_test, oosqlconn_test), // .ooSQLiteStmt REXX_METHOD(oosqlstmt_init_cls, oosqlstmt_init_cls), Modified: incubator/ooSQLite/src/ooSQLite.hpp =================================================================== --- incubator/ooSQLite/src/ooSQLite.hpp 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/src/ooSQLite.hpp 2013-04-30 01:59:22 UTC (rev 9180) @@ -38,6 +38,23 @@ #ifndef ooSQLite_Included #define ooSQLite_Included +#ifdef __cplusplus +#define BEGIN_EXTERN_C() extern "C" { +#define END_EXTERN_C() } +#else +#define BEGIN_EXTERN_C() +#define END_EXTERN_C() +#endif + +#ifdef _WIN32 + #define NEED_DLL_MAIN + #include "platform\windows\winOS.hpp" +#else + #include "platform/unix/unixOS.hpp" +#endif + +#include "oorexxapi.h" + // The range of errors needs to be contiguous and not include any SQLite error // rc. The next SQLite error rc is 1034. #define OO_ERR_FIRST 1000 @@ -60,6 +77,9 @@ // Buffer size must be plus one -> 4096 #define MAX_ENQUOTE_STRING 4095 +// Type def for the SQLite collation callback. +typedef int(*fnXCompare)(void*,int,const void*,int,const void*); + // Enum for the pragma commands in SQLite3. typedef enum { @@ -114,8 +134,9 @@ authorizer, execCallbackHook, busyHandler, + collation, + collationNeeded, commitHook, - collation, profileHook, progressHandler, rollbackHook, @@ -136,6 +157,7 @@ /* Struct for the ooSQLite class object CSelf. */ typedef struct _oosqlclassCSelf { + RexxObjectPtr externTable; // A Rexx table object used to hold shared library handles and external function pointers RexxObjectPtr nullObj; // Default representation of SQL NULL CSTRING nullStr; // If nullObj is a Rexx string object, the string value of the object ResultSetType format; // The default format of a result set for the current process. @@ -218,7 +240,8 @@ RexxRoutineObject callbackRtn; // Rexx routine to call. RexxObjectPtr callbackObj; // Rexx object to invoke the callback() method on. RexxObjectPtr userData; // A Rexx object that the user wants sent to its Rexx callback. - RexxObjectPtr nullObj; + RexxObjectPtr rexxDB; // The Rexx database connection object, RexxSelf. + RexxObjectPtr nullObj; // The Rexx object that represents SQL NULL for the database connection RexxInstance *interpreter; RexxThreadContext *callbackContext; char **indexes; Modified: incubator/ooSQLite/src/platform/windows/winOS.hpp =================================================================== --- incubator/ooSQLite/src/platform/windows/winOS.hpp 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/src/platform/windows/winOS.hpp 2013-04-30 01:59:22 UTC (rev 9180) @@ -50,19 +50,19 @@ #include <windows.h> #include <shlwapi.h> -#define snprintf _snprintf +#define snprintf _snprintf +#define oosqlGetCurrentThreadId() GetCurrentThreadId() + +#ifdef NEED_DLL_MAIN + CRITICAL_SECTION crit_sec = {0}; #define CRITICAL_SECTION_ENTER EnterCriticalSection(&crit_sec); #define CRITICAL_SECTION_LEAVE LeaveCriticalSection(&crit_sec); -#define oosqlGetCurrentThreadId() GetCurrentThreadId() +BEGIN_EXTERN_C() -#ifdef __cplusplus -extern "C" { -#endif - BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if ( fdwReason == DLL_PROCESS_ATTACH ) @@ -76,10 +76,8 @@ return(TRUE); } -#ifdef __cplusplus -} -#endif +END_EXTERN_C() +#endif /* If defined NEE_DLL_MAIN*/ - #endif Modified: incubator/ooSQLite/src/rexx/ooSQLite.cls =================================================================== --- incubator/ooSQLite/src/rexx/ooSQLite.cls 2013-04-30 01:29:40 UTC (rev 9179) +++ incubator/ooSQLite/src/rexx/ooSQLite.cls 2013-04-30 01:59:22 UTC (rev 9180) @@ -68,6 +68,7 @@ ::method errStr class external "LIBRARY oosqlite oosql_errStr_cls" ::method libVersion class external "LIBRARY oosqlite oosql_libVersion_cls" ::method libVersionNumber class external "LIBRARY oosqlite oosql_libVersionNumber_cls" +::method loadLibrary class external "LIBRARY oosqlite oosql_loadLibrary_cls" ::method memoryHighWater class external "LIBRARY oosqlite oosql_memoryHighWater_cls" ::method memoryUsed class external "LIBRARY oosqlite oosql_memoryUsed_cls" ::method releaseMemory class external "LIBRARY oosqlite oosql_releaseMemory_cls" @@ -107,8 +108,9 @@ ::method busyTimeOut external "LIBRARY oosqlite oosqlconn_busyTimeOut" ::method changes external "LIBRARY oosqlite oosqlconn_changes" ::method close external "LIBRARY oosqlite oosqlconn_close" +::method collationNeeded external "LIBRARY oosqlite oosqlconn_collationNeeded" +::method commitHook external "LIBRARY oosqlite oosqlconn_commitHook" ::method createCollation external "LIBRARY oosqlite oosqlconn_createCollation" -::method commitHook external "LIBRARY oosqlite oosqlconn_commitHook" ::method dbFileName external "LIBRARY oosqlite oosqlconn_dbFileName" ::method dbMutex external "LIBRARY oosqlite oosqlconn_dbMutex" ::method dbReadOnly external "LIBRARY oosqlite oosqlconn_dbReadOnly" @@ -138,6 +140,8 @@ ::method trace external "LIBRARY oosqlite oosqlconn_trace" ::method updateHook external "LIBRARY oosqlite oosqlconn_updateHook" +::method test external "LIBRARY oosqlite oosqlconn_test" + ::method putStmt external "LIBRARY oosqlite oosqlconn_putStmt" -- Internal use only ::method delStmt external "LIBRARY oosqlite oosqlconn_delStmt" -- Internal use only ::attribute ooSQLiteConnectionStmtBag private -- Internal use only |