From: <mie...@us...> - 2013-05-06 03:19:07
|
Revision: 9190 http://sourceforge.net/p/oorexx/code-0/9190 Author: miesfeld Date: 2013-05-06 03:19:02 +0000 (Mon, 06 May 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/examples/loadPackage.rex incubator/ooSQLite/src/ooSQLite.cpp incubator/ooSQLite/src/ooSQLite.hpp incubator/ooSQLite/src/platform/unix/SysLibrary.cpp incubator/ooSQLite/src/platform/unix/SysLibrary.hpp incubator/ooSQLite/src/platform/unix/unixOS.hpp incubator/ooSQLite/src/platform/windows/SysLibrary.cpp incubator/ooSQLite/src/platform/windows/winOS.hpp incubator/ooSQLite/src/rexx/ooSQLite.cls Added Paths: ----------- incubator/ooSQLite/examples/loadLibrary.rex Added: incubator/ooSQLite/examples/loadLibrary.rex =================================================================== --- incubator/ooSQLite/examples/loadLibrary.rex (rev 0) +++ incubator/ooSQLite/examples/loadLibrary.rex 2013-05-06 03:19:02 UTC (rev 9190) @@ -0,0 +1,170 @@ +#!/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. */ +/* */ +/*----------------------------------------------------------------------------*/ + +/** + * loadLibrary.rex + * + * Demonstrates how to load and use an ooSQLite library file. + * + * The loadLibrary() method loads a shared library containing, presumably, user + * defined SQLite collations, functions, or modules. + * + */ + + os = getOSName() + + if os == 'WINDOWS' then do + libFile = 'user.extensions\examplelibrary.dll' + end + else do + libFile = 'user.extensions/libexamplelibrary.so' + end + + -- 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) + + success = .ooSQLExtensions~loadLibrary(libFile, .array~of('ebcdic', 'reverse', 'halfFunc')) + if \ success then do + say 'Failed to load library' + say ' Error code: ' .ooSQLExtensions~lastErrCode + say ' Error message:' .ooSQLExtensions~lastErrMsg + + return .ooSQLExtensions~lastErrCode + end + + lib = .ooSQLExtensions~getLibrary('examplelibrary') + if lib == .nil then do + say 'Failed to retrieve library from extensions manager' + say ' Error code: ' .ooSQLExtensions~lastErrCode + say ' Error message:' .ooSQLExtensions~lastErrMsg + + return .ooSQLExtensions~lastErrCode + end + + hFunc = lib~getHandle('reverse'); say 'hFunc:' hFunc + + return 0 + + sql = "SELECT * FROM foods where name like 'J%' ORDER BY name COLLATE REVERSE;" + resultSet = dbConn~exec(sql, .true) + + say 'SQL: ' sql + say 'Result Set: ' resultSet + say 'Result Set Class:' resultSet~class + say + say 'Hit enter to continue' + pull + z = printResultSet(resultSet) + + sql = "SELECT * FROM foods where name like 'J%' ORDER BY name COLLATE EBCDIC;" + resultSet = dbConn~exec(sql, .true) + + say 'SQL: ' sql + say 'Result Set: ' resultSet + say 'Result Set Class:' resultSet~class + say + say 'Hit enter to continue' + pull + z = printResultSet(resultSet) + + sql = "SELECT * FROM foods ORDER BY name COLLATE REVERSE;" + resultSet = dbConn~exec(sql, .true) + + say 'SQL: ' sql + say 'Result Set: ' resultSet + say 'Result Set Class:' resultSet~class + say + say 'Hit enter to continue' + pull + z = printResultSet(resultSet) + + sql = "SELECT half(11);" + resultSet = dbConn~exec(sql, .true) + + say 'SQL: ' sql + say 'Result Set: ' resultSet + say 'Result Set Class:' resultSet~class + say + say 'Hit enter to continue' + pull + z = printResultSet(resultSet) + + ret = dbConn~close + + return ret + +::requires 'ooSQLite.cls' + +::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 + +::routine getOSName + + parse upper source os . + if os~abbrev("WIN") then os = "WINDOWS" + return os + + Property changes on: incubator/ooSQLite/examples/loadLibrary.rex ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: incubator/ooSQLite/examples/loadPackage.rex =================================================================== --- incubator/ooSQLite/examples/loadPackage.rex 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/examples/loadPackage.rex 2013-05-06 03:19:02 UTC (rev 9190) @@ -46,13 +46,22 @@ * */ + os = getOSName() + + if os == 'WINDOWS' then do + packageFile = 'user.extensions\examplePackage.dll' + end + else do + packageFile = 'user.extensions/libexamplePackage.so' + end + -- 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) - success = .ooSQLExtensions~loadPackage('user.extensions\examplePackage.dll', dbConn) + success = .ooSQLExtensions~loadPackage(packageFile, dbConn) if \ success then do say 'Failed to load package' say ' Error code: ' .ooSQLExtensions~lastErrCode Modified: incubator/ooSQLite/src/ooSQLite.cpp =================================================================== --- incubator/ooSQLite/src/ooSQLite.cpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/ooSQLite.cpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -8127,7 +8127,52 @@ #define LAST_ERR_MSG_ATTRIBUTE "extensionsLastErrMsgAttribute" #define LAST_ERR_CODE_ATTRIBUTE "extensionsLastErrCodeAttribute" + /** + * Set the library base name. ooSQLLibrary objects are stored in a Rexx table + * using the library base name as the index. + * + * @param pcl + * @param libName + * + * @note We know libName will fit in buf, because the name length is checked in + * SysLibrary. We also know that this library was loaded, we are not + * invoked if the library was not loaded. So we do not need to worry + * about things like libName == "/" + */ +static void setLibBaseName(pCooSQLLibrary pcl, CSTRING libName) +{ + char buf[MAX_LIBRARY_NAME_LENGTH + 1] = { '\0'}; + + char *p = strrchr((char *)libName, OOSQL_SLASH_CHR); + if ( p == NULL ) + { + p = (char *)libName; + } + else + { + p++; + } + strcpy(buf, p); + + p = strrchr(buf, '.'); + if ( p != NULL ) + { + *p = '\0'; + } + + if ( OOSQL_LIBRARY_PREFIX != NULL && strncmp(buf, OOSQL_LIBRARY_PREFIX, OOSQL_LIBRARY_PREFIX_LEN) == 0 ) + { + p = buf + OOSQL_LIBRARY_PREFIX_LEN; + } + else + { + p = buf; + } + strcpy(pcl->baseName, p); +} + +/** * Sets the last error attributes of the object whose method context we are * operating in. * @@ -8153,7 +8198,7 @@ void resetExtensionsLastErr(RexxMethodContext *c, pCooSQLExtensions pcext) { pcext->lastErrCode = TheZeroObj; - pcext->lastErrMsg = c->NullString(); + pcext->lastErrMsg = c->String("no error"); extensionsSetLastErr(c, c->NullString(), TheZeroObj); } @@ -8195,7 +8240,7 @@ * * @note We expect fmt to have exactly 1 %s in it. */ -void extensionsFormatLastErr(RexxMethodContext *c, uint32_t code, char *fmt, char *insert) +void extensionsFormatLastErr(RexxMethodContext *c, uint32_t code, char *fmt, CSTRING insert) { char buf[512]; @@ -8203,6 +8248,24 @@ extensionsSetLastErr(c, c->String(buf), c->UnsignedInt32(code)); } +void extensionsFormatLastErr(RexxMethodContext *c, uint32_t code, char *fmt, RexxObjectPtr insert) +{ + extensionsFormatLastErr(c, code, fmt, c->ObjectToStringValue(insert)); +} + +/** + * Checks that the current version of ooSQLite and SQLite meets the package + * requirements + * + * @param c + * @param pcp + * + * @return bool + * + * @note The interpreter raises an exception for a similar situation. We + * decided to set the last error attributes instead. This could change + * in the future. + */ bool validPackageVersion(RexxMethodContext *c, pCooSQLPackage pcp) { ooSQLitePackageEntry *pa = pcp->packageEntry; @@ -8221,7 +8284,8 @@ snprintf(buf, 512, "Package: %s requires SQLite version: %d current version: %d", pa->packageName, pa->reqSQLiteVersion, sqlite3_libversion_number()); } - userDefinedMsgException(c->threadContext, buf); + + extensionsSetLastErr(c, c->String(buf), c->UnsignedInt32(OO_PACKAGE_NOT_VALID)); return false; } return true; @@ -8350,6 +8414,31 @@ return true; } +bool resolveFunction(RexxMethodContext *c, pCooSQLLibrary pcl, RexxObjectPtr rxName) +{ + resetLibraryLastErr(c, pcl); + + CSTRING procName = c->ObjectToStringValue(rxName); + + SysLibrary *lib = pcl->lib; + void *func = lib->getProcedure(procName); + if ( func == NULL ) + { + pcl->lastErrMsg = c->String(lib->getLastErrMsg()); + pcl->lastErrCode = c->UnsignedInt32(lib->getLastErrCode()); + + lib->resetLastErr(); + extensionsSetLastErr(c, pcl->lastErrMsg, pcl->lastErrCode); + return false; + } + + RexxPointerObject p = c->NewPointer(func); + c->SendMessage2(pcl->functionTable, "PUT", p, rxName); + + return true; +} + + /** ooSQLExtensions::init() */ RexxMethod1(RexxObjectPtr, oosqlext_init_cls, OSELF, self) @@ -8392,17 +8481,55 @@ return pcext->lastErrMsg; } -/** ooSQLite::loadLibrary() [class method] +/** ooSQLExtensions::loadLibrary() [class method] * * Loads a shared library and optionally the extension functions in the * library. * + * @param libName The name of the shared library. This can be simply the + * librayr name, or a pathname for the library. The shared + * library extension can be left off of the name. + * + * If libName contains path information, on both Windows and + * Unix the library loader attempts to load the library + * exactly as specified. If the name is incorrect, the + * library will fail to load. On Unix, the library name + * portion must be exact. For example libexamplepackage.so. + * On Windows, the .dll extension can be left off in this + * case. + * + * If libName does not contain path information, the library + * loader searches for the library in the operating specific + * search order. On Unix, the library name should be + * specified as is customary for Unix. For example + * examplepackage. On Windows, the DLL extension, can be left + * on or off and the name is of course case insensitive. This + * implies that if the shared library is in the path, it can + * be specified exactly the same without regard for the + * operating system. For example: examplepackage + * + * @param procdeures [optional] A function name, or an array of function + * names. If this argument is used, the named function(s) + * in the shared library are resolved at this time. If it + * is omitted, functions are resolved when requested. + * + * If this argument is an array of function names, the + * array must not be sparse. The functions are resolved in + * the order they occur in the array. If an error ocurrs + * while resolving a function, processing the array halts + * at that point. Resolved functions prior to that point + * remain accessible, function names after that point are + * not processed. + * + * @return True on success, false on error. On error, the last error message + * and last error code can be used to determine the cause of the + * error. */ RexxMethod3(RexxObjectPtr, oosqlext_loadLibrary_cls, RexxObjectPtr, libName, OPTIONAL_RexxObjectPtr, procedures, CSELF, pCSelf) { RexxMethodContext *c = context; pCooSQLExtensions pcext = (pCooSQLExtensions)pCSelf; - RexxObjectPtr result = TheNilObj; + RexxObjectPtr result = TheFalseObj; RexxClassObject libCls = rxGetContextClass(context, "ooSQLLibrary"); if ( libCls == NULLOBJECT ) @@ -8417,36 +8544,72 @@ } pCooSQLLibrary pcl = (pCooSQLLibrary)context->ObjectToCSelf(library); - - printf("oosqlext_loadLibrary_cls library CSelf=%p\n", pcl); if ( pcl == NULL ) { - printf("oosqlext_loadPackage_cls failed to get ooSQLLibrary CSelf\n"); + extensionsFormatLastErr(context, OO_NO_CSELF, OO_NO_CSELF_STR, "ooSQLLibrary"); + + pcext->lastErrMsg = (RexxStringObject)c->GetObjectVariable(LAST_ERR_MSG_ATTRIBUTE); + pcext->lastErrCode = c->GetObjectVariable(LAST_ERR_CODE_ATTRIBUTE); goto done_out; } if ( ! pcl->valid ) { - printf("oosqlext_loadPackage_cls ooSQLLibrary is not valid errCode=%d msg=%s\n", - pcl->lib->getLastErrCode(), pcl->lib->getLastErrMsg()); + pcext->lastErrMsg = pcl->lastErrMsg; + pcext->lastErrCode = pcl->lastErrCode; + + extensionsSetLastErr(context, pcl->lastErrMsg, pcl->lastErrCode); goto done_out; } + // If there is a sparse array exception, we will undo this. If there is an + // error resolving a function address, we will set result to false, but keep + // everything else as is up to that point. + c->SendMessage2(pcext->libraryTable, "PUT", library, c->String(pcl->baseName)); + result = TheTrueObj; - CSTRING procName = NULL; - if ( argumentExists(2) ) { - // check if it is an array. + if ( c->IsArray(procedures) ) + { + RexxArrayObject names = (RexxArrayObject)procedures; + size_t count = c->ArrayItems(names); - procName = c->ObjectToStringValue(procedures); + for ( size_t i = 1; i <= count; i++ ) + { + RexxObjectPtr rxName = c->ArrayAt(names, i); + if ( rxName == NULLOBJECT ) + { + sparseArrayException(c->threadContext, 2, i); - void *procedure = pcl->lib->getProcedure(procName); - printf("procName=%s pointer=%p\n", procName, procedure); + c->SendMessage1(pcext->libraryTable, "REMOVE", c->String(pcl->baseName)); + result = TheFalseObj; - if ( procedure != NULL ) + pcl->lib->unload(); + goto done_out; + } + + if ( ! resolveFunction(context, pcl, rxName) ) + { + pcext->lastErrMsg = pcl->lastErrMsg; + pcext->lastErrCode = pcl->lastErrCode; + + extensionsSetLastErr(context, pcl->lastErrMsg, pcl->lastErrCode); + result = TheFalseObj; + break; + } + } + } + else { - return c->NewPointer(procedure); + if ( ! resolveFunction(context, pcl, procedures) ) + { + pcext->lastErrMsg = pcl->lastErrMsg; + pcext->lastErrCode = pcl->lastErrCode; + + extensionsSetLastErr(context, pcl->lastErrMsg, pcl->lastErrCode); + result = TheFalseObj; + } } } @@ -8454,7 +8617,7 @@ return result; } -/** ooSQLite::loadPackage() [class method] +/** ooSQLExtensions::loadPackage() [class method] * * Loads an ooSQLite package library and optionally regsiters the collations, * functions, modules in the package. @@ -8485,6 +8648,9 @@ if ( pcp == NULL ) { extensionsFormatLastErr(context, OO_NO_CSELF, OO_NO_CSELF_STR, "ooSQLPackage"); + + pcext->lastErrMsg = (RexxStringObject)c->GetObjectVariable(LAST_ERR_MSG_ATTRIBUTE); + pcext->lastErrCode = c->GetObjectVariable(LAST_ERR_CODE_ATTRIBUTE); goto done_out; } @@ -8523,6 +8689,57 @@ } +/** ooSQLExtensions::getPackage() [class method] + * + * Gets an ooSQLite package from the extensions manager, if it exists. + * + */ +RexxMethod2(RexxObjectPtr, oosqlext_getPackage_cls, RexxObjectPtr, packageName, CSELF, pCSelf) +{ + RexxMethodContext *c = context; + pCooSQLExtensions pcext = (pCooSQLExtensions)pCSelf; + + resetExtensionsLastErr(context, pcext); + + RexxObjectPtr result = c->SendMessage1(pcext->packageTable, "AT", packageName); + if ( result == NULLOBJECT ) + { + extensionsFormatLastErr(context, OO_NO_SUCH_PACKAGE, OO_NO_SUCH_PACKAGE_STR, (char *)c->ObjectToStringValue(packageName)); + + pcext->lastErrMsg = (RexxStringObject)c->GetObjectVariable(LAST_ERR_MSG_ATTRIBUTE); + pcext->lastErrCode = c->GetObjectVariable(LAST_ERR_CODE_ATTRIBUTE); + result = TheNilObj; + } + return result; +} + + +/** ooSQLExtensions::getLibrary() [class method] + * + * Gets an ooSQLite library from the extensions manager, if it exists. + * + */ +RexxMethod2(RexxObjectPtr, oosqlext_getLibrary_cls, RexxObjectPtr, libraryName, CSELF, pCSelf) +{ + RexxMethodContext *c = context; + pCooSQLExtensions pcext = (pCooSQLExtensions)pCSelf; + + resetExtensionsLastErr(context, pcext); + + RexxObjectPtr result = c->SendMessage1(pcext->libraryTable, "AT", libraryName); + if ( result == TheNilObj ) + { + extensionsFormatLastErr(context, OO_NO_SUCH_LIBRARY, OO_NO_SUCH_LIBRARY_STR, libraryName); + + pcext->lastErrMsg = (RexxStringObject)c->GetObjectVariable(LAST_ERR_MSG_ATTRIBUTE); + pcext->lastErrCode = c->GetObjectVariable(LAST_ERR_CODE_ATTRIBUTE); + result = TheNilObj; + } + return result; +} + + + /** * Methods for the .ooSQLPackage class. * @@ -8678,12 +8895,13 @@ pcl->functionTable = rxNewBuiltinObject(context->threadContext, "TABLE"); pcl->valid = true; + setLibBaseName(pcl, libName); + (*setter)(pcl->sqliteAPIs); return NULLOBJECT; } - /** ooSQLLibrary::lastErrCode [attribute get] */ RexxMethod1(RexxObjectPtr, oosqllib_getLastErrCode_atr, CSELF, pCSelf) @@ -8692,7 +8910,7 @@ return pcl->lastErrCode; } -/** ooSQLExtensions::lastErrMsg [attribute get] +/** ooSQLLibrary::lastErrMsg [attribute get] */ RexxMethod1(RexxStringObject, oosqllib_getLastErrMsg_atr, CSELF, pCSelf) { @@ -8701,6 +8919,39 @@ } +/** ooSQLLibrary::getHandle() [class method] + * + * Gets the function handle from an ooSQLite library. + * + */ +RexxMethod2(RexxObjectPtr, oosqllib_getHandle_cls, RexxObjectPtr, funcName, CSELF, pCSelf) +{ + RexxMethodContext *c = context; + pCooSQLLibrary pcl = (pCooSQLLibrary)pCSelf; + + resetLibraryLastErr(context, pcl); + + RexxObjectPtr result = c->SendMessage1(pcl->functionTable, "AT", funcName); + if ( result != TheNilObj ) + { + return result; + } + + if ( resolveFunction(context, pcl, funcName) ) + { + result = c->SendMessage1(pcl->functionTable, "AT", funcName); + } + else + { + extensionsSetLastErr(context, pcl->lastErrMsg, pcl->lastErrCode); + result = TheNilObj; + } + + return result; +} + + + #define ooSQLite_Routines_Section @@ -11854,6 +12105,8 @@ REXX_METHOD_PROTOTYPE(oosqlext_getLastErrCode_atr); REXX_METHOD_PROTOTYPE(oosqlext_getLastErrMsg_atr); +REXX_METHOD_PROTOTYPE(oosqlext_getLibrary_cls); +REXX_METHOD_PROTOTYPE(oosqlext_getPackage_cls); REXX_METHOD_PROTOTYPE(oosqlext_loadLibrary_cls); REXX_METHOD_PROTOTYPE(oosqlext_loadPackage_cls); @@ -11869,6 +12122,8 @@ REXX_METHOD_PROTOTYPE(oosqllib_getLastErrCode_atr); REXX_METHOD_PROTOTYPE(oosqllib_getLastErrMsg_atr); +REXX_METHOD_PROTOTYPE(oosqllib_getHandle_cls); + // __rtn_helper_class REXX_METHOD_PROTOTYPE(hlpr_init_cls); @@ -12053,6 +12308,8 @@ REXX_METHOD(oosqlext_getLastErrCode_atr, oosqlext_getLastErrCode_atr), REXX_METHOD(oosqlext_getLastErrMsg_atr, oosqlext_getLastErrMsg_atr), + REXX_METHOD(oosqlext_getLibrary_cls, oosqlext_getLibrary_cls), + REXX_METHOD(oosqlext_getPackage_cls, oosqlext_getPackage_cls), REXX_METHOD(oosqlext_loadLibrary_cls, oosqlext_loadLibrary_cls), REXX_METHOD(oosqlext_loadPackage_cls, oosqlext_loadPackage_cls), @@ -12068,6 +12325,8 @@ REXX_METHOD(oosqllib_getLastErrCode_atr, oosqllib_getLastErrCode_atr), REXX_METHOD(oosqllib_getLastErrMsg_atr, oosqllib_getLastErrMsg_atr), + REXX_METHOD(oosqllib_getHandle_cls, oosqllib_getHandle_cls), + // __rtn_helper_class REXX_METHOD(hlpr_init_cls, hlpr_init_cls), Modified: incubator/ooSQLite/src/ooSQLite.hpp =================================================================== --- incubator/ooSQLite/src/ooSQLite.hpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/ooSQLite.hpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -63,7 +63,10 @@ #define OO_BACKUP_IN_PROGRESS 1003 #define OO_BACKUP_DB_ERRSTATE 1004 #define OO_NO_CSELF 1005 -#define OO_ERR_LAST 1005 +#define OO_PACKAGE_NOT_VALID 1006 +#define OO_NO_SUCH_PACKAGE 1007 +#define OO_NO_SUCH_LIBRARY 1008 +#define OO_ERR_LAST 1008 #define OO_INTERNAL_ERR_STR "an unexpected ooSQLite internal error occurred" #define OO_WRONG_ARG_TYPE_STR "an argument to a ooSQLite method or fucntion is the wrong type" @@ -71,6 +74,9 @@ #define OO_BACKUP_IN_PROGRESS_STR "ooSQLite method or function can not be invoked when backup is in progress" #define OO_BACKUP_DB_ERRSTATE_STR "backup not possible, source or destination database is in error state" #define OO_NO_CSELF_STR "internal error failed to get %s C Self" +#define OO_PACKAGE_NOT_VALID_STR "the current version of ooSQLite or SQLite does not meet the package requirements" +#define OO_NO_SUCH_PACKAGE_STR "package %s is not loaded" +#define OO_NO_SUCH_LIBRARY_STR "library %s is not loaded" #define VALID_VERSION_TYPES "[O]neLine [F]ull [C]ompact [L]ibVersion [N]umber [S]ourceID" #define RECORD_FORMATS_LIST "OO_ARRAY_OF_ARRAYS, OO_ARRAY_OF_DIRECTORIES, OO_STEM_OF_STEMS, or OO_CLASSIC_STEM" @@ -257,6 +263,7 @@ /* Struct for the ooSQLLibrary object CSelf. */ typedef struct _oosqlLibraryCSelf { + char baseName[MAX_LIBRARY_NAME_LENGTH + 1]; RexxObjectPtr functionTable; // A Rexx table object used to hold the resolved functions in the library SysLibrary *lib; // SysLibrary object used to load the package. SqlApiVector sqliteAPIs; // Pointer to the SQLite API vector. Modified: incubator/ooSQLite/src/platform/unix/SysLibrary.cpp =================================================================== --- incubator/ooSQLite/src/platform/unix/SysLibrary.cpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/platform/unix/SysLibrary.cpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -42,6 +42,9 @@ * from the interpreter's SysLibrary implmentation. * */ + +#include "unixOS.hpp" +#include <oorexxapi.h> #include "SysLibrary.hpp" #include <stdlib.h> #include <string.h> @@ -49,7 +52,6 @@ #include <dlfcn.h> -#define MAX_LIBRARY_NAME_LENGTH 255 #define LIBARY_NAME_BUFFER_LENGTH (MAX_LIBRARY_NAME_LENGTH + sizeof("/usr/lib/lib") + sizeof(OOSQLITE_SHARED_LIBRARY_EXT)) SysLibrary::SysLibrary() @@ -75,7 +77,7 @@ void *func = dlsym(libraryHandle, name); if ( func == NULL ) { - setLastErr(); + setLastErr(PROCEDURE_NOT_FOUND_RC); } return func; } @@ -94,6 +96,11 @@ */ bool SysLibrary::load(const char *name) { + if ( libraryHandle != NULL ) + { + return true; + } + char nameBuffer[LIBARY_NAME_BUFFER_LENGTH]; resetLastErr(); @@ -117,7 +124,7 @@ libraryHandle = dlopen(nameBuffer, RTLD_LAZY); if ( libraryHandle == NULL ) { - setLastErr(); + setLastErr(MODULE_NOT_FOUND_RC); return false; } return true; @@ -144,7 +151,7 @@ /** * Sets the last error variables. */ -void SysLibrary::setLastErr() +void SysLibrary::setLastErr(uint32_t rc) { char *temp = dlerror(); @@ -152,7 +159,7 @@ if ( lastErrMsg != NULL ) { strcpy(lastErrMsg, temp); - lastErrCode = 1; + lastErrCode = rc; } } Modified: incubator/ooSQLite/src/platform/unix/SysLibrary.hpp =================================================================== --- incubator/ooSQLite/src/platform/unix/SysLibrary.hpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/platform/unix/SysLibrary.hpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -55,14 +55,14 @@ void resetLastErr(); void reset(); inline char *getLastErrMsg() { return lastErrMsg; } - inline int getLastErrCode() { return lastErrCode; } + inline uint32_t getLastErrCode() { return lastErrCode; } protected: - void setLastErr(); + void setLastErr(uint32_t); - void *libraryHandle; - char *lastErrMsg; - int lastErrCode; + void *libraryHandle; + char *lastErrMsg; + uint32_t lastErrCode; }; #endif Modified: incubator/ooSQLite/src/platform/unix/unixOS.hpp =================================================================== --- incubator/ooSQLite/src/platform/unix/unixOS.hpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/platform/unix/unixOS.hpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -44,6 +44,15 @@ #define TRUE 1 #define FALSE 0 +#define MAX_LIBRARY_NAME_LENGTH 255 +#define OOSQL_SLASH_CHR '/' +#define OOSQL_LIBRARY_PREFIX "lib" +#define OOSQL_LIBRARY_PREFIX_LEN 3 + +// These are the Windows system error codes, we will use the same codes on Unix. +#define MODULE_NOT_FOUND_RC 126 +#define PROCEDURE_NOT_FOUND_RC 127 + sqlite3_mutex *crit_sec = (sqlite3_mutex *)0; #define CRITICAL_SECTION_ENTER sqlite3_mutex_enter(crit_sec); Modified: incubator/ooSQLite/src/platform/windows/SysLibrary.cpp =================================================================== --- incubator/ooSQLite/src/platform/windows/SysLibrary.cpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/platform/windows/SysLibrary.cpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -92,18 +92,33 @@ */ bool SysLibrary::load(const char *name) { - if ( libraryHandle == NULL ) + if ( libraryHandle != NULL ) { - SetLastError(0); - resetLastErr(); + return true; + } - libraryHandle = LoadLibrary(name); - if ( libraryHandle == NULL ) + if ( strlen(name) > MAX_LIBRARY_NAME_LENGTH ) + { + char *fmt = "Library name: %s is too long"; + + lastErrMsg = (char *)LocalAlloc(LPTR, strlen(name) + strlen(fmt) + 1); + if ( lastErrMsg != NULL ) { - setLastErr("LoadLibrary", name); - return false; + sprintf(lastErrMsg, fmt, name); + lastErrCode = 1; } + return false; } + + SetLastError(0); + resetLastErr(); + + libraryHandle = LoadLibrary(name); + if ( libraryHandle == NULL ) + { + setLastErr("LoadLibrary", name); + return false; + } return true; } Modified: incubator/ooSQLite/src/platform/windows/winOS.hpp =================================================================== --- incubator/ooSQLite/src/platform/windows/winOS.hpp 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/platform/windows/winOS.hpp 2013-05-06 03:19:02 UTC (rev 9190) @@ -53,7 +53,12 @@ #define snprintf _snprintf #define oosqlGetCurrentThreadId() GetCurrentThreadId() +#define MAX_LIBRARY_NAME_LENGTH 255 +#define OOSQL_SLASH_CHR '\\' +#define OOSQL_LIBRARY_PREFIX NULL +#define OOSQL_LIBRARY_PREFIX_LEN 0 + #ifdef NEED_DLL_MAIN CRITICAL_SECTION crit_sec = {0}; Modified: incubator/ooSQLite/src/rexx/ooSQLite.cls =================================================================== --- incubator/ooSQLite/src/rexx/ooSQLite.cls 2013-05-05 18:12:14 UTC (rev 9189) +++ incubator/ooSQLite/src/rexx/ooSQLite.cls 2013-05-06 03:19:02 UTC (rev 9190) @@ -258,6 +258,8 @@ ::attribute lastErrCode get class external "LIBRARY oosqlite oosqlext_getLastErrCode_atr" ::attribute lastErrMsg get class external "LIBRARY oosqlite oosqlext_getLastErrMsg_atr" +::method getLibrary class external "LIBRARY oosqlite oosqlext_getLibrary_cls" +::method getPackage class external "LIBRARY oosqlite oosqlext_getPackage_cls" ::method loadLibrary class external "LIBRARY oosqlite oosqlext_loadLibrary_cls" ::method loadPackage class external "LIBRARY oosqlite oosqlext_loadPackage_cls" @@ -285,7 +287,9 @@ ::attribute lastErrCode get class external "LIBRARY oosqlite oosqllib_getLastErrCode_atr" ::attribute lastErrMsg get class external "LIBRARY oosqlite oosqllib_getLastErrMsg_atr" +::method getHandle get class external "LIBRARY oosqlite oosqllib_getHandle_cls" + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\ Functional Section |