From 91601deb844848dc02959679fd41e1441a76aff4 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Sun, 14 Dec 2014 12:30:27 +0100 Subject: the all-in-one-file version of unqlite --- common/unqlite/api.c | 2789 -------------------------------------------------- 1 file changed, 2789 deletions(-) delete mode 100644 common/unqlite/api.c (limited to 'common/unqlite/api.c') diff --git a/common/unqlite/api.c b/common/unqlite/api.c deleted file mode 100644 index 9915d14..0000000 --- a/common/unqlite/api.c +++ /dev/null @@ -1,2789 +0,0 @@ -/* - * Symisc unQLite: An Embeddable NoSQL (Post Modern) Database Engine. - * Copyright (C) 2012-2013, Symisc Systems http://unqlite.org/ - * Version 1.1.6 - * For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES - * please contact Symisc Systems via: - * legal@symisc.net - * licensing@symisc.net - * contact@symisc.net - * or visit: - * http://unqlite.org/licensing.html - */ - /* $SymiscID: api.c v2.0 FreeBSD 2012-11-08 23:07 stable $ */ -#ifndef UNQLITE_AMALGAMATION -#include "unqliteInt.h" -#endif -/* This file implement the public interfaces presented to host-applications. - * Routines in other files are for internal use by UnQLite and should not be - * accessed by users of the library. - */ -#define UNQLITE_DB_MISUSE(DB) (DB == 0 || DB->nMagic != UNQLITE_DB_MAGIC) -#define UNQLITE_VM_MISUSE(VM) (VM == 0 || VM->nMagic == JX9_VM_STALE) -/* If another thread have released a working instance, the following macros - * evaluates to true. These macros are only used when the library - * is built with threading support enabled. - */ -#define UNQLITE_THRD_DB_RELEASE(DB) (DB->nMagic != UNQLITE_DB_MAGIC) -#define UNQLITE_THRD_VM_RELEASE(VM) (VM->nMagic == JX9_VM_STALE) -/* IMPLEMENTATION: unqlite@embedded@symisc 118-09-4785 */ -/* - * All global variables are collected in the structure named "sUnqlMPGlobal". - * That way it is clear in the code when we are using static variable because - * its name start with sUnqlMPGlobal. - */ -static struct unqlGlobal_Data -{ - SyMemBackend sAllocator; /* Global low level memory allocator */ -#if defined(UNQLITE_ENABLE_THREADS) - const SyMutexMethods *pMutexMethods; /* Mutex methods */ - SyMutex *pMutex; /* Global mutex */ - sxu32 nThreadingLevel; /* Threading level: 0 == Single threaded/1 == Multi-Threaded - * The threading level can be set using the [unqlite_lib_config()] - * interface with a configuration verb set to - * UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE or - * UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI - */ -#endif - SySet kv_storage; /* Installed KV storage engines */ - int iPageSize; /* Default Page size */ - unqlite_vfs *pVfs; /* Underlying virtual file system (Vfs) */ - sxi32 nDB; /* Total number of active DB handles */ - unqlite *pDB; /* List of active DB handles */ - sxu32 nMagic; /* Sanity check against library misuse */ -}sUnqlMPGlobal = { - {0, 0, 0, 0, 0, 0, 0, 0, {0}}, -#if defined(UNQLITE_ENABLE_THREADS) - 0, - 0, - 0, -#endif - {0, 0, 0, 0, 0, 0, 0 }, - UNQLITE_DEFAULT_PAGE_SIZE, - 0, - 0, - 0, - 0 -}; -#define UNQLITE_LIB_MAGIC 0xEA1495BA -#define UNQLITE_LIB_MISUSE (sUnqlMPGlobal.nMagic != UNQLITE_LIB_MAGIC) -/* - * Supported threading level. - * These options have meaning only when the library is compiled with multi-threading - * support. That is, the UNQLITE_ENABLE_THREADS compile time directive must be defined - * when UnQLite is built. - * UNQLITE_THREAD_LEVEL_SINGLE: - * In this mode, mutexing is disabled and the library can only be used by a single thread. - * UNQLITE_THREAD_LEVEL_MULTI - * In this mode, all mutexes including the recursive mutexes on [unqlite] objects - * are enabled so that the application is free to share the same database handle - * between different threads at the same time. - */ -#define UNQLITE_THREAD_LEVEL_SINGLE 1 -#define UNQLITE_THREAD_LEVEL_MULTI 2 -/* - * Find a Key Value storage engine from the set of installed engines. - * Return a pointer to the storage engine methods on success. NULL on failure. - */ -UNQLITE_PRIVATE unqlite_kv_methods * unqliteFindKVStore( - const char *zName, /* Storage engine name [i.e. Hash, B+tree, LSM, etc.] */ - sxu32 nByte /* zName length */ - ) -{ - unqlite_kv_methods **apStore,*pEntry; - sxu32 n,nMax; - /* Point to the set of installed engines */ - apStore = (unqlite_kv_methods **)SySetBasePtr(&sUnqlMPGlobal.kv_storage); - nMax = SySetUsed(&sUnqlMPGlobal.kv_storage); - for( n = 0 ; n < nMax; ++n ){ - pEntry = apStore[n]; - if( nByte == SyStrlen(pEntry->zName) && SyStrnicmp(pEntry->zName,zName,nByte) == 0 ){ - /* Storage engine found */ - return pEntry; - } - } - /* No such entry, return NULL */ - return 0; -} -/* - * Configure the UnQLite library. - * Return UNQLITE_OK on success. Any other return value indicates failure. - * Refer to [unqlite_lib_config()]. - */ -static sxi32 unqliteCoreConfigure(sxi32 nOp, va_list ap) -{ - int rc = UNQLITE_OK; - switch(nOp){ - case UNQLITE_LIB_CONFIG_PAGE_SIZE: { - /* Default page size: Must be a power of two */ - int iPage = va_arg(ap,int); - if( iPage >= UNQLITE_MIN_PAGE_SIZE && iPage <= UNQLITE_MAX_PAGE_SIZE ){ - if( !(iPage & (iPage - 1)) ){ - sUnqlMPGlobal.iPageSize = iPage; - }else{ - /* Invalid page size */ - rc = UNQLITE_INVALID; - } - }else{ - /* Invalid page size */ - rc = UNQLITE_INVALID; - } - break; - } - case UNQLITE_LIB_CONFIG_STORAGE_ENGINE: { - /* Install a key value storage engine */ - unqlite_kv_methods *pMethods = va_arg(ap,unqlite_kv_methods *); - /* Make sure we are delaing with a valid methods */ - if( pMethods == 0 || SX_EMPTY_STR(pMethods->zName) || pMethods->xSeek == 0 || pMethods->xData == 0 - || pMethods->xKey == 0 || pMethods->xDataLength == 0 || pMethods->xKeyLength == 0 - || pMethods->szKv < (int)sizeof(unqlite_kv_engine) ){ - rc = UNQLITE_INVALID; - break; - } - /* Install it */ - rc = SySetPut(&sUnqlMPGlobal.kv_storage,(const void *)&pMethods); - break; - } - case UNQLITE_LIB_CONFIG_VFS:{ - /* Install a virtual file system */ - unqlite_vfs *pVfs = va_arg(ap,unqlite_vfs *); - if( pVfs ){ - sUnqlMPGlobal.pVfs = pVfs; - } - break; - } - case UNQLITE_LIB_CONFIG_USER_MALLOC: { - /* Use an alternative low-level memory allocation routines */ - const SyMemMethods *pMethods = va_arg(ap, const SyMemMethods *); - /* Save the memory failure callback (if available) */ - ProcMemError xMemErr = sUnqlMPGlobal.sAllocator.xMemError; - void *pMemErr = sUnqlMPGlobal.sAllocator.pUserData; - if( pMethods == 0 ){ - /* Use the built-in memory allocation subsystem */ - rc = SyMemBackendInit(&sUnqlMPGlobal.sAllocator, xMemErr, pMemErr); - }else{ - rc = SyMemBackendInitFromOthers(&sUnqlMPGlobal.sAllocator, pMethods, xMemErr, pMemErr); - } - break; - } - case UNQLITE_LIB_CONFIG_MEM_ERR_CALLBACK: { - /* Memory failure callback */ - ProcMemError xMemErr = va_arg(ap, ProcMemError); - void *pUserData = va_arg(ap, void *); - sUnqlMPGlobal.sAllocator.xMemError = xMemErr; - sUnqlMPGlobal.sAllocator.pUserData = pUserData; - break; - } - case UNQLITE_LIB_CONFIG_USER_MUTEX: { -#if defined(UNQLITE_ENABLE_THREADS) - /* Use an alternative low-level mutex subsystem */ - const SyMutexMethods *pMethods = va_arg(ap, const SyMutexMethods *); -#if defined (UNTRUST) - if( pMethods == 0 ){ - rc = UNQLITE_CORRUPT; - } -#endif - /* Sanity check */ - if( pMethods->xEnter == 0 || pMethods->xLeave == 0 || pMethods->xNew == 0){ - /* At least three criticial callbacks xEnter(), xLeave() and xNew() must be supplied */ - rc = UNQLITE_CORRUPT; - break; - } - if( sUnqlMPGlobal.pMutexMethods ){ - /* Overwrite the previous mutex subsystem */ - SyMutexRelease(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); - if( sUnqlMPGlobal.pMutexMethods->xGlobalRelease ){ - sUnqlMPGlobal.pMutexMethods->xGlobalRelease(); - } - sUnqlMPGlobal.pMutex = 0; - } - /* Initialize and install the new mutex subsystem */ - if( pMethods->xGlobalInit ){ - rc = pMethods->xGlobalInit(); - if ( rc != UNQLITE_OK ){ - break; - } - } - /* Create the global mutex */ - sUnqlMPGlobal.pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST); - if( sUnqlMPGlobal.pMutex == 0 ){ - /* - * If the supplied mutex subsystem is so sick that we are unable to - * create a single mutex, there is no much we can do here. - */ - if( pMethods->xGlobalRelease ){ - pMethods->xGlobalRelease(); - } - rc = UNQLITE_CORRUPT; - break; - } - sUnqlMPGlobal.pMutexMethods = pMethods; - if( sUnqlMPGlobal.nThreadingLevel == 0 ){ - /* Set a default threading level */ - sUnqlMPGlobal.nThreadingLevel = UNQLITE_THREAD_LEVEL_MULTI; - } -#endif - break; - } - case UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE: -#if defined(UNQLITE_ENABLE_THREADS) - /* Single thread mode (Only one thread is allowed to play with the library) */ - sUnqlMPGlobal.nThreadingLevel = UNQLITE_THREAD_LEVEL_SINGLE; - jx9_lib_config(JX9_LIB_CONFIG_THREAD_LEVEL_SINGLE); -#endif - break; - case UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI: -#if defined(UNQLITE_ENABLE_THREADS) - /* Multi-threading mode (library is thread safe and database handles and virtual machines - * may be shared between multiple threads). - */ - sUnqlMPGlobal.nThreadingLevel = UNQLITE_THREAD_LEVEL_MULTI; - jx9_lib_config(JX9_LIB_CONFIG_THREAD_LEVEL_MULTI); -#endif - break; - default: - /* Unknown configuration option */ - rc = UNQLITE_CORRUPT; - break; - } - return rc; -} -/* - * [CAPIREF: unqlite_lib_config()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_lib_config(int nConfigOp,...) -{ - va_list ap; - int rc; - if( sUnqlMPGlobal.nMagic == UNQLITE_LIB_MAGIC ){ - /* Library is already initialized, this operation is forbidden */ - return UNQLITE_LOCKED; - } - va_start(ap,nConfigOp); - rc = unqliteCoreConfigure(nConfigOp,ap); - va_end(ap); - return rc; -} -/* - * Global library initialization - * Refer to [unqlite_lib_init()] - * This routine must be called to initialize the memory allocation subsystem, the mutex - * subsystem prior to doing any serious work with the library. The first thread to call - * this routine does the initialization process and set the magic number so no body later - * can re-initialize the library. If subsequent threads call this routine before the first - * thread have finished the initialization process, then the subsequent threads must block - * until the initialization process is done. - */ -static sxi32 unqliteCoreInitialize(void) -{ - const unqlite_kv_methods *pMethods; - const unqlite_vfs *pVfs; /* Built-in vfs */ -#if defined(UNQLITE_ENABLE_THREADS) - const SyMutexMethods *pMutexMethods = 0; - SyMutex *pMaster = 0; -#endif - int rc; - /* - * If the library is already initialized, then a call to this routine - * is a no-op. - */ - if( sUnqlMPGlobal.nMagic == UNQLITE_LIB_MAGIC ){ - return UNQLITE_OK; /* Already initialized */ - } - /* Point to the built-in vfs */ - pVfs = unqliteExportBuiltinVfs(); - /* Install it */ - unqlite_lib_config(UNQLITE_LIB_CONFIG_VFS, pVfs); -#if defined(UNQLITE_ENABLE_THREADS) - if( sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_SINGLE ){ - pMutexMethods = sUnqlMPGlobal.pMutexMethods; - if( pMutexMethods == 0 ){ - /* Use the built-in mutex subsystem */ - pMutexMethods = SyMutexExportMethods(); - if( pMutexMethods == 0 ){ - return UNQLITE_CORRUPT; /* Can't happen */ - } - /* Install the mutex subsystem */ - rc = unqlite_lib_config(UNQLITE_LIB_CONFIG_USER_MUTEX, pMutexMethods); - if( rc != UNQLITE_OK ){ - return rc; - } - } - /* Obtain a static mutex so we can initialize the library without calling malloc() */ - pMaster = SyMutexNew(pMutexMethods, SXMUTEX_TYPE_STATIC_1); - if( pMaster == 0 ){ - return UNQLITE_CORRUPT; /* Can't happen */ - } - } - /* Lock the master mutex */ - rc = UNQLITE_OK; - SyMutexEnter(pMutexMethods, pMaster); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ - if( sUnqlMPGlobal.nMagic != UNQLITE_LIB_MAGIC ){ -#endif - if( sUnqlMPGlobal.sAllocator.pMethods == 0 ){ - /* Install a memory subsystem */ - rc = unqlite_lib_config(UNQLITE_LIB_CONFIG_USER_MALLOC, 0); /* zero mean use the built-in memory backend */ - if( rc != UNQLITE_OK ){ - /* If we are unable to initialize the memory backend, there is no much we can do here.*/ - goto End; - } - } -#if defined(UNQLITE_ENABLE_THREADS) - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE ){ - /* Protect the memory allocation subsystem */ - rc = SyMemBackendMakeThreadSafe(&sUnqlMPGlobal.sAllocator, sUnqlMPGlobal.pMutexMethods); - if( rc != UNQLITE_OK ){ - goto End; - } - } -#endif - SySetInit(&sUnqlMPGlobal.kv_storage,&sUnqlMPGlobal.sAllocator,sizeof(unqlite_kv_methods *)); - /* Install the built-in Key Value storage engines */ - pMethods = unqliteExportMemKvStorage(); /* In-memory storage */ - unqlite_lib_config(UNQLITE_LIB_CONFIG_STORAGE_ENGINE,pMethods); - /* Default disk key/value storage engine */ - pMethods = unqliteExportDiskKvStorage(); /* Disk storage */ - unqlite_lib_config(UNQLITE_LIB_CONFIG_STORAGE_ENGINE,pMethods); - /* Default page size */ - if( sUnqlMPGlobal.iPageSize < UNQLITE_MIN_PAGE_SIZE ){ - unqlite_lib_config(UNQLITE_LIB_CONFIG_PAGE_SIZE,UNQLITE_DEFAULT_PAGE_SIZE); - } - /* Our library is initialized, set the magic number */ - sUnqlMPGlobal.nMagic = UNQLITE_LIB_MAGIC; - rc = UNQLITE_OK; -#if defined(UNQLITE_ENABLE_THREADS) - } /* sUnqlMPGlobal.nMagic != UNQLITE_LIB_MAGIC */ -#endif -End: -#if defined(UNQLITE_ENABLE_THREADS) - /* Unlock the master mutex */ - SyMutexLeave(pMutexMethods, pMaster); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ -#endif - return rc; -} -/* Forward declaration */ -static int unqliteVmRelease(unqlite_vm *pVm); -/* - * Release a single instance of an unqlite database handle. - */ -static int unqliteDbRelease(unqlite *pDb) -{ - unqlite_db *pStore = &pDb->sDB; - unqlite_vm *pVm,*pNext; - int rc = UNQLITE_OK; - if( (pDb->iFlags & UNQLITE_FL_DISABLE_AUTO_COMMIT) == 0 ){ - /* Commit any outstanding transaction */ - rc = unqlitePagerCommit(pStore->pPager); - if( rc != UNQLITE_OK ){ - /* Rollback the transaction */ - rc = unqlitePagerRollback(pStore->pPager,FALSE); - } - }else{ - /* Rollback any outstanding transaction */ - rc = unqlitePagerRollback(pStore->pPager,FALSE); - } - /* Close the pager */ - unqlitePagerClose(pStore->pPager); - /* Release any active VM's */ - pVm = pDb->pVms; - for(;;){ - if( pDb->iVm < 1 ){ - break; - } - /* Point to the next entry */ - pNext = pVm->pNext; - unqliteVmRelease(pVm); - pVm = pNext; - pDb->iVm--; - } - /* Release the Jx9 handle */ - jx9_release(pStore->pJx9); - /* Set a dummy magic number */ - pDb->nMagic = 0x7250; - /* Release the whole memory subsystem */ - SyMemBackendRelease(&pDb->sMem); - /* Commit or rollback result */ - return rc; -} -/* - * Release all resources consumed by the library. - * Note: This call is not thread safe. Refer to [unqlite_lib_shutdown()]. - */ -static void unqliteCoreShutdown(void) -{ - unqlite *pDb, *pNext; - /* Release all active databases handles */ - pDb = sUnqlMPGlobal.pDB; - for(;;){ - if( sUnqlMPGlobal.nDB < 1 ){ - break; - } - pNext = pDb->pNext; - unqliteDbRelease(pDb); - pDb = pNext; - sUnqlMPGlobal.nDB--; - } - /* Release the storage methods container */ - SySetRelease(&sUnqlMPGlobal.kv_storage); -#if defined(UNQLITE_ENABLE_THREADS) - /* Release the mutex subsystem */ - if( sUnqlMPGlobal.pMutexMethods ){ - if( sUnqlMPGlobal.pMutex ){ - SyMutexRelease(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); - sUnqlMPGlobal.pMutex = 0; - } - if( sUnqlMPGlobal.pMutexMethods->xGlobalRelease ){ - sUnqlMPGlobal.pMutexMethods->xGlobalRelease(); - } - sUnqlMPGlobal.pMutexMethods = 0; - } - sUnqlMPGlobal.nThreadingLevel = 0; -#endif - if( sUnqlMPGlobal.sAllocator.pMethods ){ - /* Release the memory backend */ - SyMemBackendRelease(&sUnqlMPGlobal.sAllocator); - } - sUnqlMPGlobal.nMagic = 0x1764; - /* Finally, shutdown the Jx9 library */ - jx9_lib_shutdown(); -} -/* - * [CAPIREF: unqlite_lib_init()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_lib_init(void) -{ - int rc; - rc = unqliteCoreInitialize(); - return rc; -} -/* - * [CAPIREF: unqlite_lib_shutdown()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_lib_shutdown(void) -{ - if( sUnqlMPGlobal.nMagic != UNQLITE_LIB_MAGIC ){ - /* Already shut */ - return UNQLITE_OK; - } - unqliteCoreShutdown(); - return UNQLITE_OK; -} -/* - * [CAPIREF: unqlite_lib_is_threadsafe()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_lib_is_threadsafe(void) -{ - if( sUnqlMPGlobal.nMagic != UNQLITE_LIB_MAGIC ){ - return 0; - } -#if defined(UNQLITE_ENABLE_THREADS) - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE ){ - /* Muli-threading support is enabled */ - return 1; - }else{ - /* Single-threading */ - return 0; - } -#else - return 0; -#endif -} -/* - * - * [CAPIREF: unqlite_lib_version()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_lib_version(void) -{ - return UNQLITE_VERSION; -} -/* - * - * [CAPIREF: unqlite_lib_signature()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_lib_signature(void) -{ - return UNQLITE_SIG; -} -/* - * - * [CAPIREF: unqlite_lib_ident()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_lib_ident(void) -{ - return UNQLITE_IDENT; -} -/* - * - * [CAPIREF: unqlite_lib_copyright()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_lib_copyright(void) -{ - return UNQLITE_COPYRIGHT; -} -/* - * Remove harmfull and/or stale flags passed to the [unqlite_open()] interface. - */ -static unsigned int unqliteSanityzeFlag(unsigned int iFlags) -{ - iFlags &= ~UNQLITE_OPEN_EXCLUSIVE; /* Reserved flag */ - if( iFlags & UNQLITE_OPEN_TEMP_DB ){ - /* Omit journaling for temporary database */ - iFlags |= UNQLITE_OPEN_OMIT_JOURNALING|UNQLITE_OPEN_CREATE; - } - if( (iFlags & (UNQLITE_OPEN_READONLY|UNQLITE_OPEN_READWRITE)) == 0 ){ - /* Auto-append the R+W flag */ - iFlags |= UNQLITE_OPEN_READWRITE; - } - if( iFlags & UNQLITE_OPEN_CREATE ){ - iFlags &= ~(UNQLITE_OPEN_MMAP|UNQLITE_OPEN_READONLY); - /* Auto-append the R+W flag */ - iFlags |= UNQLITE_OPEN_READWRITE; - }else{ - if( iFlags & UNQLITE_OPEN_READONLY ){ - iFlags &= ~UNQLITE_OPEN_READWRITE; - }else if( iFlags & UNQLITE_OPEN_READWRITE ){ - iFlags &= ~UNQLITE_OPEN_MMAP; - } - } - return iFlags; -} -/* - * This routine does the work of initializing a database handle on behalf - * of [unqlite_open()]. - */ -static int unqliteInitDatabase( - unqlite *pDB, /* Database handle */ - SyMemBackend *pParent, /* Master memory backend */ - const char *zFilename, /* Target database */ - unsigned int iFlags /* Open flags */ - ) -{ - unqlite_db *pStorage = &pDB->sDB; - int rc; - /* Initialiaze the memory subsystem */ - SyMemBackendInitFromParent(&pDB->sMem,pParent); -#if defined(UNQLITE_ENABLE_THREADS) - /* No need for internal mutexes */ - SyMemBackendDisbaleMutexing(&pDB->sMem); -#endif - SyBlobInit(&pDB->sErr,&pDB->sMem); - /* Sanityze flags */ - iFlags = unqliteSanityzeFlag(iFlags); - /* Init the pager and the transaction manager */ - rc = unqlitePagerOpen(sUnqlMPGlobal.pVfs,pDB,zFilename,iFlags); - if( rc != UNQLITE_OK ){ - return rc; - } - /* Allocate a new Jx9 engine handle */ - rc = jx9_init(&pStorage->pJx9); - if( rc != JX9_OK ){ - return rc; - } - return UNQLITE_OK; -} -/* - * Allocate and initialize a new UnQLite Virtual Mahcine and attach it - * to the compiled Jx9 script. - */ -static int unqliteInitVm(unqlite *pDb,jx9_vm *pJx9Vm,unqlite_vm **ppOut) -{ - unqlite_vm *pVm; - - *ppOut = 0; - /* Allocate a new VM instance */ - pVm = (unqlite_vm *)SyMemBackendPoolAlloc(&pDb->sMem,sizeof(unqlite_vm)); - if( pVm == 0 ){ - return UNQLITE_NOMEM; - } - /* Zero the structure */ - SyZero(pVm,sizeof(unqlite_vm)); - /* Initialize */ - SyMemBackendInitFromParent(&pVm->sAlloc,&pDb->sMem); - /* Allocate a new collection table */ - pVm->apCol = (unqlite_col **)SyMemBackendAlloc(&pVm->sAlloc,32 * sizeof(unqlite_col *)); - if( pVm->apCol == 0 ){ - goto fail; - } - pVm->iColSize = 32; /* Must be a power of two */ - /* Zero the table */ - SyZero((void *)pVm->apCol,pVm->iColSize * sizeof(unqlite_col *)); -#if defined(UNQLITE_ENABLE_THREADS) - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE ){ - /* Associate a recursive mutex with this instance */ - pVm->pMutex = SyMutexNew(sUnqlMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE); - if( pVm->pMutex == 0 ){ - goto fail; - } - } -#endif - /* Link the VM to the list of active virtual machines */ - pVm->pJx9Vm = pJx9Vm; - pVm->pDb = pDb; - MACRO_LD_PUSH(pDb->pVms,pVm); - pDb->iVm++; - /* Register Jx9 functions */ - unqliteRegisterJx9Functions(pVm); - /* Set the magic number */ - pVm->nMagic = JX9_VM_INIT; /* Same magic number as Jx9 */ - /* All done */ - *ppOut = pVm; - return UNQLITE_OK; -fail: - SyMemBackendRelease(&pVm->sAlloc); - SyMemBackendPoolFree(&pDb->sMem,pVm); - return UNQLITE_NOMEM; -} -/* - * Release an active VM. - */ -static int unqliteVmRelease(unqlite_vm *pVm) -{ - /* Release the Jx9 VM */ - jx9_vm_release(pVm->pJx9Vm); - /* Release the private memory backend */ - SyMemBackendRelease(&pVm->sAlloc); - /* Upper layer will discard this VM from the list - * of active VM. - */ - return UNQLITE_OK; -} -/* - * Return the default page size. - */ -UNQLITE_PRIVATE int unqliteGetPageSize(void) -{ - int iSize = sUnqlMPGlobal.iPageSize; - if( iSize < UNQLITE_MIN_PAGE_SIZE || iSize > UNQLITE_MAX_PAGE_SIZE ){ - iSize = UNQLITE_DEFAULT_PAGE_SIZE; - } - return iSize; -} -/* - * Generate an error message. - */ -UNQLITE_PRIVATE int unqliteGenError(unqlite *pDb,const char *zErr) -{ - int rc; - /* Append the error message */ - rc = SyBlobAppend(&pDb->sErr,(const void *)zErr,SyStrlen(zErr)); - /* Append a new line */ - SyBlobAppend(&pDb->sErr,(const void *)"\n",sizeof(char)); - return rc; -} -/* - * Generate an error message (Printf like). - */ -UNQLITE_PRIVATE int unqliteGenErrorFormat(unqlite *pDb,const char *zFmt,...) -{ - va_list ap; - int rc; - va_start(ap,zFmt); - rc = SyBlobFormatAp(&pDb->sErr,zFmt,ap); - va_end(ap); - /* Append a new line */ - SyBlobAppend(&pDb->sErr,(const void *)"\n",sizeof(char)); - return rc; -} -/* - * Generate an error message (Out of memory). - */ -UNQLITE_PRIVATE int unqliteGenOutofMem(unqlite *pDb) -{ - int rc; - rc = unqliteGenError(pDb,"unQLite is running out of memory"); - return rc; -} -/* - * Configure a working UnQLite database handle. - */ -static int unqliteConfigure(unqlite *pDb,int nOp,va_list ap) -{ - int rc = UNQLITE_OK; - switch(nOp){ - case UNQLITE_CONFIG_JX9_ERR_LOG: - /* Jx9 compile-time error log */ - rc = jx9EngineConfig(pDb->sDB.pJx9,JX9_CONFIG_ERR_LOG,ap); - break; - case UNQLITE_CONFIG_MAX_PAGE_CACHE: { - int max_page = va_arg(ap,int); - /* Maximum number of page to cache (Simple hint). */ - rc = unqlitePagerSetCachesize(pDb->sDB.pPager,max_page); - break; - } - case UNQLITE_CONFIG_ERR_LOG: { - /* Database error log if any */ - const char **pzPtr = va_arg(ap, const char **); - int *pLen = va_arg(ap, int *); - if( pzPtr == 0 ){ - rc = JX9_CORRUPT; - break; - } - /* NULL terminate the error-log buffer */ - SyBlobNullAppend(&pDb->sErr); - /* Point to the error-log buffer */ - *pzPtr = (const char *)SyBlobData(&pDb->sErr); - if( pLen ){ - if( SyBlobLength(&pDb->sErr) > 1 /* NULL '\0' terminator */ ){ - *pLen = (int)SyBlobLength(&pDb->sErr); - }else{ - *pLen = 0; - } - } - break; - } - case UNQLITE_CONFIG_DISABLE_AUTO_COMMIT:{ - /* Disable auto-commit */ - pDb->iFlags |= UNQLITE_FL_DISABLE_AUTO_COMMIT; - break; - } - case UNQLITE_CONFIG_GET_KV_NAME: { - /* Name of the underlying KV storage engine */ - const char **pzPtr = va_arg(ap,const char **); - if( pzPtr ){ - unqlite_kv_engine *pEngine; - pEngine = unqlitePagerGetKvEngine(pDb); - /* Point to the name */ - *pzPtr = pEngine->pIo->pMethods->zName; - } - break; - } - default: - /* Unknown configuration option */ - rc = UNQLITE_UNKNOWN; - break; - } - return rc; -} -/* - * Export the global (master) memory allocator to submodules. - */ -UNQLITE_PRIVATE const SyMemBackend * unqliteExportMemBackend(void) -{ - return &sUnqlMPGlobal.sAllocator; -} -/* - * [CAPIREF: unqlite_open()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_open(unqlite **ppDB,const char *zFilename,unsigned int iMode) -{ - unqlite *pHandle; - int rc; -#if defined(UNTRUST) - if( ppDB == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - *ppDB = 0; - /* One-time automatic library initialization */ - rc = unqliteCoreInitialize(); - if( rc != UNQLITE_OK ){ - return rc; - } - /* Allocate a new database handle */ - pHandle = (unqlite *)SyMemBackendPoolAlloc(&sUnqlMPGlobal.sAllocator, sizeof(unqlite)); - if( pHandle == 0 ){ - return UNQLITE_NOMEM; - } - /* Zero the structure */ - SyZero(pHandle,sizeof(unqlite)); - if( iMode < 1 ){ - /* Assume a read-only database */ - iMode = UNQLITE_OPEN_READONLY|UNQLITE_OPEN_MMAP; - } - /* Init the database */ - rc = unqliteInitDatabase(pHandle,&sUnqlMPGlobal.sAllocator,zFilename,iMode); - if( rc != UNQLITE_OK ){ - goto Release; - } -#if defined(UNQLITE_ENABLE_THREADS) - if( !(iMode & UNQLITE_OPEN_NOMUTEX) && (sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE) ){ - /* Associate a recursive mutex with this instance */ - pHandle->pMutex = SyMutexNew(sUnqlMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE); - if( pHandle->pMutex == 0 ){ - rc = UNQLITE_NOMEM; - goto Release; - } - } -#endif - /* Link to the list of active DB handles */ -#if defined(UNQLITE_ENABLE_THREADS) - /* Enter the global mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ -#endif - MACRO_LD_PUSH(sUnqlMPGlobal.pDB,pHandle); - sUnqlMPGlobal.nDB++; -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave the global mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ -#endif - /* Set the magic number to identify a valid DB handle */ - pHandle->nMagic = UNQLITE_DB_MAGIC; - /* Make the handle available to the caller */ - *ppDB = pHandle; - return UNQLITE_OK; -Release: - SyMemBackendRelease(&pHandle->sMem); - SyMemBackendPoolFree(&sUnqlMPGlobal.sAllocator,pHandle); - return rc; -} -/* - * [CAPIREF: unqlite_config()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_config(unqlite *pDb,int nConfigOp,...) -{ - va_list ap; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - va_start(ap, nConfigOp); - rc = unqliteConfigure(&(*pDb),nConfigOp, ap); - va_end(ap); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_close()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_close(unqlite *pDb) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Release the database handle */ - rc = unqliteDbRelease(pDb); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - /* Release DB mutex */ - SyMutexRelease(sUnqlMPGlobal.pMutexMethods, pDb->pMutex) /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif -#if defined(UNQLITE_ENABLE_THREADS) - /* Enter the global mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ -#endif - /* Unlink from the list of active database handles */ - MACRO_LD_REMOVE(sUnqlMPGlobal.pDB, pDb); - sUnqlMPGlobal.nDB--; -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave the global mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods, sUnqlMPGlobal.pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel == UNQLITE_THREAD_LEVEL_SINGLE */ -#endif - /* Release the memory chunk allocated to this handle */ - SyMemBackendPoolFree(&sUnqlMPGlobal.sAllocator,pDb); - return rc; -} -/* - * [CAPIREF: unqlite_compile()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_compile(unqlite *pDb,const char *zJx9,int nByte,unqlite_vm **ppOut) -{ - jx9_vm *pVm; - int rc; - if( UNQLITE_DB_MISUSE(pDb) || ppOut == 0){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; - } -#endif - /* Compile the Jx9 script first */ - rc = jx9_compile(pDb->sDB.pJx9,zJx9,nByte,&pVm); - if( rc == JX9_OK ){ - /* Allocate a new unqlite VM instance */ - rc = unqliteInitVm(pDb,pVm,ppOut); - if( rc != UNQLITE_OK ){ - /* Release the Jx9 VM */ - jx9_vm_release(pVm); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_compile_file()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_compile_file(unqlite *pDb,const char *zPath,unqlite_vm **ppOut) -{ - jx9_vm *pVm; - int rc; - if( UNQLITE_DB_MISUSE(pDb) || ppOut == 0){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; - } -#endif - /* Compile the Jx9 script first */ - rc = jx9_compile_file(pDb->sDB.pJx9,zPath,&pVm); - if( rc == JX9_OK ){ - /* Allocate a new unqlite VM instance */ - rc = unqliteInitVm(pDb,pVm,ppOut); - if( rc != UNQLITE_OK ){ - /* Release the Jx9 VM */ - jx9_vm_release(pVm); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * Configure an unqlite virtual machine (Mostly Jx9 VM) instance. - */ -static int unqliteVmConfig(unqlite_vm *pVm,sxi32 iOp,va_list ap) -{ - int rc; - rc = jx9VmConfigure(pVm->pJx9Vm,iOp,ap); - return rc; -} -/* - * [CAPIREF: unqlite_vm_config()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_config(unqlite_vm *pVm,int iOp,...) -{ - va_list ap; - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - va_start(ap,iOp); - rc = unqliteVmConfig(pVm,iOp,ap); - va_end(ap); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_vm_exec()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_exec(unqlite_vm *pVm) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Execute the Jx9 bytecode program */ - rc = jx9VmByteCodeExec(pVm->pJx9Vm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_vm_release()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_release(unqlite_vm *pVm) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Release the VM */ - rc = unqliteVmRelease(pVm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave VM mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - /* Release VM mutex */ - SyMutexRelease(sUnqlMPGlobal.pMutexMethods,pVm->pMutex) /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - if( rc == UNQLITE_OK ){ - unqlite *pDb = pVm->pDb; - /* Unlink from the list of active VM's */ -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - MACRO_LD_REMOVE(pDb->pVms, pVm); - pDb->iVm--; - /* Release the memory chunk allocated to this instance */ - SyMemBackendPoolFree(&pDb->sMem,pVm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - } - return rc; -} -/* - * [CAPIREF: unqlite_vm_reset()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_reset(unqlite_vm *pVm) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Reset the Jx9 VM */ - rc = jx9VmReset(pVm->pJx9Vm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_vm_dump()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_dump(unqlite_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Dump the Jx9 VM */ - rc = jx9VmDump(pVm->pJx9Vm,xConsumer,pUserData); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_vm_extract_variable()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_vm_extract_variable(unqlite_vm *pVm,const char *zVarname) -{ - unqlite_value *pValue; - SyString sVariable; - if( UNQLITE_VM_MISUSE(pVm) ){ - return 0; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return 0; /* Another thread have released this instance */ - } -#endif - /* Extract the target variable */ - SyStringInitFromBuf(&sVariable,zVarname,SyStrlen(zVarname)); - pValue = jx9VmExtractVariable(pVm->pJx9Vm,&sVariable); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return pValue; -} -/* - * [CAPIREF: unqlite_create_function()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_create_function(unqlite_vm *pVm, const char *zName,int (*xFunc)(unqlite_context *,int,unqlite_value **),void *pUserData) -{ - SyString sName; - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } - SyStringInitFromBuf(&sName, zName, SyStrlen(zName)); - /* Remove leading and trailing white spaces */ - SyStringFullTrim(&sName); - /* Ticket 1433-003: NULL values are not allowed */ - if( sName.nByte < 1 || xFunc == 0 ){ - return UNQLITE_INVALID; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Install the foreign function */ - rc = jx9VmInstallForeignFunction(pVm->pJx9Vm,&sName,xFunc,pUserData); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_delete_function()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_delete_function(unqlite_vm *pVm, const char *zName) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Unlink the foreign function */ - rc = jx9DeleteFunction(pVm->pJx9Vm,zName); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_create_constant()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_create_constant(unqlite_vm *pVm,const char *zName,void (*xExpand)(unqlite_value *, void *),void *pUserData) -{ - SyString sName; - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } - SyStringInitFromBuf(&sName, zName, SyStrlen(zName)); - /* Remove leading and trailing white spaces */ - SyStringFullTrim(&sName); - if( sName.nByte < 1 ){ - /* Empty constant name */ - return UNQLITE_INVALID; - } - /* TICKET 1433-003: NULL pointer is harmless operation */ - if( xExpand == 0 ){ - return UNQLITE_INVALID; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Install the foreign constant */ - rc = jx9VmRegisterConstant(pVm->pJx9Vm,&sName,xExpand,pUserData); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_delete_constant()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_delete_constant(unqlite_vm *pVm, const char *zName) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Unlink the foreign constant */ - rc = Jx9DeleteConstant(pVm->pJx9Vm,zName); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_value_int()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_int(unqlite_value *pVal, int iValue) -{ - return jx9_value_int(pVal,iValue); -} -/* - * [CAPIREF: unqlite_value_int64()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_int64(unqlite_value *pVal,unqlite_int64 iValue) -{ - return jx9_value_int64(pVal,iValue); -} -/* - * [CAPIREF: unqlite_value_bool()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_bool(unqlite_value *pVal, int iBool) -{ - return jx9_value_bool(pVal,iBool); -} -/* - * [CAPIREF: unqlite_value_null()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_null(unqlite_value *pVal) -{ - return jx9_value_null(pVal); -} -/* - * [CAPIREF: unqlite_value_double()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_double(unqlite_value *pVal, double Value) -{ - return jx9_value_double(pVal,Value); -} -/* - * [CAPIREF: unqlite_value_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_string(unqlite_value *pVal, const char *zString, int nLen) -{ - return jx9_value_string(pVal,zString,nLen); -} -/* - * [CAPIREF: unqlite_value_string_format()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_string_format(unqlite_value *pVal, const char *zFormat,...) -{ - va_list ap; - int rc; - if((pVal->iFlags & MEMOBJ_STRING) == 0 ){ - /* Invalidate any prior representation */ - jx9MemObjRelease(pVal); - MemObjSetType(pVal, MEMOBJ_STRING); - } - va_start(ap, zFormat); - rc = SyBlobFormatAp(&pVal->sBlob, zFormat, ap); - va_end(ap); - return UNQLITE_OK; -} -/* - * [CAPIREF: unqlite_value_reset_string_cursor()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_reset_string_cursor(unqlite_value *pVal) -{ - return jx9_value_reset_string_cursor(pVal); -} -/* - * [CAPIREF: unqlite_value_resource()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_resource(unqlite_value *pVal,void *pUserData) -{ - return jx9_value_resource(pVal,pUserData); -} -/* - * [CAPIREF: unqlite_value_release()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_release(unqlite_value *pVal) -{ - return jx9_value_release(pVal); -} -/* - * [CAPIREF: unqlite_value_to_int()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_to_int(unqlite_value *pValue) -{ - return jx9_value_to_int(pValue); -} -/* - * [CAPIREF: unqlite_value_to_bool()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_to_bool(unqlite_value *pValue) -{ - return jx9_value_to_bool(pValue); -} -/* - * [CAPIREF: unqlite_value_to_int64()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_int64 unqlite_value_to_int64(unqlite_value *pValue) -{ - return jx9_value_to_int64(pValue); -} -/* - * [CAPIREF: unqlite_value_to_double()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -double unqlite_value_to_double(unqlite_value *pValue) -{ - return jx9_value_to_double(pValue); -} -/* - * [CAPIREF: unqlite_value_to_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_value_to_string(unqlite_value *pValue, int *pLen) -{ - return jx9_value_to_string(pValue,pLen); -} -/* - * [CAPIREF: unqlite_value_to_resource()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_value_to_resource(unqlite_value *pValue) -{ - return jx9_value_to_resource(pValue); -} -/* - * [CAPIREF: unqlite_value_compare()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_compare(unqlite_value *pLeft, unqlite_value *pRight, int bStrict) -{ - return jx9_value_compare(pLeft,pRight,bStrict); -} -/* - * [CAPIREF: unqlite_result_int()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_int(unqlite_context *pCtx, int iValue) -{ - return jx9_result_int(pCtx,iValue); -} -/* - * [CAPIREF: unqlite_result_int64()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_int64(unqlite_context *pCtx, unqlite_int64 iValue) -{ - return jx9_result_int64(pCtx,iValue); -} -/* - * [CAPIREF: unqlite_result_bool()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_bool(unqlite_context *pCtx, int iBool) -{ - return jx9_result_bool(pCtx,iBool); -} -/* - * [CAPIREF: unqlite_result_double()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_double(unqlite_context *pCtx, double Value) -{ - return jx9_result_double(pCtx,Value); -} -/* - * [CAPIREF: unqlite_result_null()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_null(unqlite_context *pCtx) -{ - return jx9_result_null(pCtx); -} -/* - * [CAPIREF: unqlite_result_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_string(unqlite_context *pCtx, const char *zString, int nLen) -{ - return jx9_result_string(pCtx,zString,nLen); -} -/* - * [CAPIREF: unqlite_result_string_format()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_string_format(unqlite_context *pCtx, const char *zFormat, ...) -{ - jx9_value *p; - va_list ap; - int rc; - p = pCtx->pRet; - if( (p->iFlags & MEMOBJ_STRING) == 0 ){ - /* Invalidate any prior representation */ - jx9MemObjRelease(p); - MemObjSetType(p, MEMOBJ_STRING); - } - /* Format the given string */ - va_start(ap, zFormat); - rc = SyBlobFormatAp(&p->sBlob, zFormat, ap); - va_end(ap); - return rc; -} -/* - * [CAPIREF: unqlite_result_value()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_value(unqlite_context *pCtx, unqlite_value *pValue) -{ - return jx9_result_value(pCtx,pValue); -} -/* - * [CAPIREF: unqlite_result_resource()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_result_resource(unqlite_context *pCtx, void *pUserData) -{ - return jx9_result_resource(pCtx,pUserData); -} -/* - * [CAPIREF: unqlite_value_is_int()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_int(unqlite_value *pVal) -{ - return jx9_value_is_int(pVal); -} -/* - * [CAPIREF: unqlite_value_is_float()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_float(unqlite_value *pVal) -{ - return jx9_value_is_float(pVal); -} -/* - * [CAPIREF: unqlite_value_is_bool()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_bool(unqlite_value *pVal) -{ - return jx9_value_is_bool(pVal); -} -/* - * [CAPIREF: unqlite_value_is_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_string(unqlite_value *pVal) -{ - return jx9_value_is_string(pVal); -} -/* - * [CAPIREF: unqlite_value_is_null()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_null(unqlite_value *pVal) -{ - return jx9_value_is_null(pVal); -} -/* - * [CAPIREF: unqlite_value_is_numeric()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_numeric(unqlite_value *pVal) -{ - return jx9_value_is_numeric(pVal); -} -/* - * [CAPIREF: unqlite_value_is_callable()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_callable(unqlite_value *pVal) -{ - return jx9_value_is_callable(pVal); -} -/* - * [CAPIREF: unqlite_value_is_scalar()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_scalar(unqlite_value *pVal) -{ - return jx9_value_is_scalar(pVal); -} -/* - * [CAPIREF: unqlite_value_is_json_array()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_json_array(unqlite_value *pVal) -{ - return jx9_value_is_json_array(pVal); -} -/* - * [CAPIREF: unqlite_value_is_json_object()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_json_object(unqlite_value *pVal) -{ - return jx9_value_is_json_object(pVal); -} -/* - * [CAPIREF: unqlite_value_is_resource()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_resource(unqlite_value *pVal) -{ - return jx9_value_is_resource(pVal); -} -/* - * [CAPIREF: unqlite_value_is_empty()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_value_is_empty(unqlite_value *pVal) -{ - return jx9_value_is_empty(pVal); -} -/* - * [CAPIREF: unqlite_array_fetch()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_array_fetch(unqlite_value *pArray, const char *zKey, int nByte) -{ - return jx9_array_fetch(pArray,zKey,nByte); -} -/* - * [CAPIREF: unqlite_array_walk()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_array_walk(unqlite_value *pArray, int (*xWalk)(unqlite_value *, unqlite_value *, void *), void *pUserData) -{ - return jx9_array_walk(pArray,xWalk,pUserData); -} -/* - * [CAPIREF: unqlite_array_add_elem()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_array_add_elem(unqlite_value *pArray, unqlite_value *pKey, unqlite_value *pValue) -{ - return jx9_array_add_elem(pArray,pKey,pValue); -} -/* - * [CAPIREF: unqlite_array_add_strkey_elem()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_array_add_strkey_elem(unqlite_value *pArray, const char *zKey, unqlite_value *pValue) -{ - return jx9_array_add_strkey_elem(pArray,zKey,pValue); -} -/* - * [CAPIREF: unqlite_array_count()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_array_count(unqlite_value *pArray) -{ - return (int)jx9_array_count(pArray); -} -/* - * [CAPIREF: unqlite_vm_new_scalar()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_vm_new_scalar(unqlite_vm *pVm) -{ - unqlite_value *pValue; - if( UNQLITE_VM_MISUSE(pVm) ){ - return 0; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return 0; /* Another thread have released this instance */ - } -#endif - pValue = jx9_new_scalar(pVm->pJx9Vm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return pValue; -} -/* - * [CAPIREF: unqlite_vm_new_array()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_vm_new_array(unqlite_vm *pVm) -{ - unqlite_value *pValue; - if( UNQLITE_VM_MISUSE(pVm) ){ - return 0; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return 0; /* Another thread have released this instance */ - } -#endif - pValue = jx9_new_array(pVm->pJx9Vm); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return pValue; -} -/* - * [CAPIREF: unqlite_vm_release_value()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_vm_release_value(unqlite_vm *pVm,unqlite_value *pValue) -{ - int rc; - if( UNQLITE_VM_MISUSE(pVm) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire VM mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_VM_RELEASE(pVm) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - rc = jx9_release_value(pVm->pJx9Vm,pValue); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pVm->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_context_output()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_output(unqlite_context *pCtx, const char *zString, int nLen) -{ - return jx9_context_output(pCtx,zString,nLen); -} -/* - * [CAPIREF: unqlite_context_output_format()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_output_format(unqlite_context *pCtx,const char *zFormat, ...) -{ - va_list ap; - int rc; - va_start(ap, zFormat); - rc = jx9VmOutputConsumeAp(pCtx->pVm,zFormat, ap); - va_end(ap); - return rc; -} -/* - * [CAPIREF: unqlite_context_throw_error()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_throw_error(unqlite_context *pCtx, int iErr, const char *zErr) -{ - return jx9_context_throw_error(pCtx,iErr,zErr); -} -/* - * [CAPIREF: unqlite_context_throw_error_format()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_throw_error_format(unqlite_context *pCtx, int iErr, const char *zFormat, ...) -{ - va_list ap; - int rc; - if( zFormat == 0){ - return JX9_OK; - } - va_start(ap, zFormat); - rc = jx9VmThrowErrorAp(pCtx->pVm, &pCtx->pFunc->sName, iErr, zFormat, ap); - va_end(ap); - return rc; -} -/* - * [CAPIREF: unqlite_context_random_num()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unsigned int unqlite_context_random_num(unqlite_context *pCtx) -{ - return jx9_context_random_num(pCtx); -} -/* - * [CAPIREF: unqlite_context_random_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_random_string(unqlite_context *pCtx, char *zBuf, int nBuflen) -{ - return jx9_context_random_string(pCtx,zBuf,nBuflen); -} -/* - * [CAPIREF: unqlite_context_user_data()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_context_user_data(unqlite_context *pCtx) -{ - return jx9_context_user_data(pCtx); -} -/* - * [CAPIREF: unqlite_context_push_aux_data()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_context_push_aux_data(unqlite_context *pCtx, void *pUserData) -{ - return jx9_context_push_aux_data(pCtx,pUserData); -} -/* - * [CAPIREF: unqlite_context_peek_aux_data()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_context_peek_aux_data(unqlite_context *pCtx) -{ - return jx9_context_peek_aux_data(pCtx); -} -/* - * [CAPIREF: unqlite_context_pop_aux_data()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_context_pop_aux_data(unqlite_context *pCtx) -{ - return jx9_context_pop_aux_data(pCtx); -} -/* - * [CAPIREF: unqlite_context_result_buf_length()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unsigned int unqlite_context_result_buf_length(unqlite_context *pCtx) -{ - return jx9_context_result_buf_length(pCtx); -} -/* - * [CAPIREF: unqlite_function_name()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char * unqlite_function_name(unqlite_context *pCtx) -{ - return jx9_function_name(pCtx); -} -/* - * [CAPIREF: unqlite_context_new_scalar()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_context_new_scalar(unqlite_context *pCtx) -{ - return jx9_context_new_scalar(pCtx); -} -/* - * [CAPIREF: unqlite_context_new_array()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -unqlite_value * unqlite_context_new_array(unqlite_context *pCtx) -{ - return jx9_context_new_array(pCtx); -} -/* - * [CAPIREF: unqlite_context_release_value()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void unqlite_context_release_value(unqlite_context *pCtx,unqlite_value *pValue) -{ - jx9_context_release_value(pCtx,pValue); -} -/* - * [CAPIREF: unqlite_context_alloc_chunk()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_context_alloc_chunk(unqlite_context *pCtx,unsigned int nByte,int ZeroChunk,int AutoRelease) -{ - return jx9_context_alloc_chunk(pCtx,nByte,ZeroChunk,AutoRelease); -} -/* - * [CAPIREF: unqlite_context_realloc_chunk()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void * unqlite_context_realloc_chunk(unqlite_context *pCtx,void *pChunk,unsigned int nByte) -{ - return jx9_context_realloc_chunk(pCtx,pChunk,nByte); -} -/* - * [CAPIREF: unqlite_context_free_chunk()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -void unqlite_context_free_chunk(unqlite_context *pCtx,void *pChunk) -{ - jx9_context_free_chunk(pCtx,pChunk); -} -/* - * [CAPIREF: unqlite_kv_store()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_store(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen) -{ - unqlite_kv_engine *pEngine; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - if( pEngine->pIo->pMethods->xReplace == 0 ){ - /* Storage engine does not implement such method */ - unqliteGenError(pDb,"xReplace() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - /* Perform the requested operation */ - rc = pEngine->pIo->pMethods->xReplace(pEngine,pKey,nKeyLen,pData,nDataLen); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_store_fmt()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_store_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...) -{ - unqlite_kv_engine *pEngine; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - if( pEngine->pIo->pMethods->xReplace == 0 ){ - /* Storage engine does not implement such method */ - unqliteGenError(pDb,"xReplace() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - SyBlob sWorker; /* Working buffer */ - va_list ap; - SyBlobInit(&sWorker,&pDb->sMem); - /* Format the data */ - va_start(ap,zFormat); - SyBlobFormatAp(&sWorker,zFormat,ap); - va_end(ap); - /* Perform the requested operation */ - rc = pEngine->pIo->pMethods->xReplace(pEngine,pKey,nKeyLen,SyBlobData(&sWorker),SyBlobLength(&sWorker)); - /* Clean up */ - SyBlobRelease(&sWorker); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_append()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_append(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen) -{ - unqlite_kv_engine *pEngine; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - if( pEngine->pIo->pMethods->xAppend == 0 ){ - /* Storage engine does not implement such method */ - unqliteGenError(pDb,"xAppend() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - /* Perform the requested operation */ - rc = pEngine->pIo->pMethods->xAppend(pEngine,pKey,nKeyLen,pData,nDataLen); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_append_fmt()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_append_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...) -{ - unqlite_kv_engine *pEngine; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - if( pEngine->pIo->pMethods->xAppend == 0 ){ - /* Storage engine does not implement such method */ - unqliteGenError(pDb,"xAppend() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - SyBlob sWorker; /* Working buffer */ - va_list ap; - SyBlobInit(&sWorker,&pDb->sMem); - /* Format the data */ - va_start(ap,zFormat); - SyBlobFormatAp(&sWorker,zFormat,ap); - va_end(ap); - /* Perform the requested operation */ - rc = pEngine->pIo->pMethods->xAppend(pEngine,pKey,nKeyLen,SyBlobData(&sWorker),SyBlobLength(&sWorker)); - /* Clean up */ - SyBlobRelease(&sWorker); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_fetch()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_fetch(unqlite *pDb,const void *pKey,int nKeyLen,void *pBuf,unqlite_int64 *pBufLen) -{ - unqlite_kv_methods *pMethods; - unqlite_kv_engine *pEngine; - unqlite_kv_cursor *pCur; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - pMethods = pEngine->pIo->pMethods; - pCur = pDb->sDB.pCursor; - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - /* Seek to the record position */ - rc = pMethods->xSeek(pCur,pKey,nKeyLen,UNQLITE_CURSOR_MATCH_EXACT); - } - if( rc == UNQLITE_OK ){ - if( pBuf == 0 ){ - /* Data length only */ - rc = pMethods->xDataLength(pCur,pBufLen); - }else{ - SyBlob sBlob; - /* Initialize the data consumer */ - SyBlobInitFromBuf(&sBlob,pBuf,(sxu32)*pBufLen); - /* Consume the data */ - rc = pMethods->xData(pCur,unqliteDataConsumer,&sBlob); - /* Data length */ - *pBufLen = (unqlite_int64)SyBlobLength(&sBlob); - /* Cleanup */ - SyBlobRelease(&sBlob); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_fetch_callback()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_fetch_callback(unqlite *pDb,const void *pKey,int nKeyLen,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData) -{ - unqlite_kv_methods *pMethods; - unqlite_kv_engine *pEngine; - unqlite_kv_cursor *pCur; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - pMethods = pEngine->pIo->pMethods; - pCur = pDb->sDB.pCursor; - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - /* Seek to the record position */ - rc = pMethods->xSeek(pCur,pKey,nKeyLen,UNQLITE_CURSOR_MATCH_EXACT); - } - if( rc == UNQLITE_OK && xConsumer ){ - /* Consume the data directly */ - rc = pMethods->xData(pCur,xConsumer,pUserData); - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_delete()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_delete(unqlite *pDb,const void *pKey,int nKeyLen) -{ - unqlite_kv_methods *pMethods; - unqlite_kv_engine *pEngine; - unqlite_kv_cursor *pCur; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - pMethods = pEngine->pIo->pMethods; - pCur = pDb->sDB.pCursor; - if( pMethods->xDelete == 0 ){ - /* Storage engine does not implement such method */ - unqliteGenError(pDb,"xDelete() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - unqliteGenError(pDb,"Empty key"); - rc = UNQLITE_EMPTY; - }else{ - /* Seek to the record position */ - rc = pMethods->xSeek(pCur,pKey,nKeyLen,UNQLITE_CURSOR_MATCH_EXACT); - } - if( rc == UNQLITE_OK ){ - /* Exact match found, delete the entry */ - rc = pMethods->xDelete(pCur); - } - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_config()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_config(unqlite *pDb,int iOp,...) -{ - unqlite_kv_engine *pEngine; - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Point to the underlying storage engine */ - pEngine = unqlitePagerGetKvEngine(pDb); - if( pEngine->pIo->pMethods->xConfig == 0 ){ - /* Storage engine does not implements such method */ - unqliteGenError(pDb,"xConfig() method not implemented in the underlying storage engine"); - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - va_list ap; - /* Configure the storage engine */ - va_start(ap,iOp); - rc = pEngine->pIo->pMethods->xConfig(pEngine,iOp,ap); - va_end(ap); - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_init()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_init(unqlite *pDb,unqlite_kv_cursor **ppOut) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) || ppOut == 0 /* Noop */){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Allocate a new cursor */ - rc = unqliteInitCursor(pDb,ppOut); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_release()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_release(unqlite *pDb,unqlite_kv_cursor *pCur) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) || pCur == 0 /* Noop */){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Release the cursor */ - rc = unqliteReleaseCursor(pDb,pCur); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_first_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_first_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xFirst == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Seek to the first entry */ - rc = pCursor->pStore->pIo->pMethods->xFirst(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_last_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_last_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xLast == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Seek to the last entry */ - rc = pCursor->pStore->pIo->pMethods->xLast(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_valid_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_valid_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xValid == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - rc = pCursor->pStore->pIo->pMethods->xValid(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_next_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_next_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xNext == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Seek to the next entry */ - rc = pCursor->pStore->pIo->pMethods->xNext(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_prev_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_prev_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xPrev == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Seek to the previous entry */ - rc = pCursor->pStore->pIo->pMethods->xPrev(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_delete_entry()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_delete_entry(unqlite_kv_cursor *pCursor) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xDelete == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Delete the entry */ - rc = pCursor->pStore->pIo->pMethods->xDelete(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_reset()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_reset(unqlite_kv_cursor *pCursor) -{ - int rc = UNQLITE_OK; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Check if the requested method is implemented by the underlying storage engine */ - if( pCursor->pStore->pIo->pMethods->xReset == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Reset */ - pCursor->pStore->pIo->pMethods->xReset(pCursor); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_seek()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_seek(unqlite_kv_cursor *pCursor,const void *pKey,int nKeyLen,int iPos) -{ - int rc = UNQLITE_OK; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - if( nKeyLen < 0 ){ - /* Assume a null terminated string and compute it's length */ - nKeyLen = SyStrlen((const char *)pKey); - } - if( !nKeyLen ){ - rc = UNQLITE_EMPTY; - }else{ - /* Seek to the desired location */ - rc = pCursor->pStore->pIo->pMethods->xSeek(pCursor,pKey,nKeyLen,iPos); - } - return rc; -} -/* - * Default data consumer callback. That is, all retrieved is redirected to this - * routine which store the output in an internal blob. - */ -UNQLITE_PRIVATE int unqliteDataConsumer( - const void *pOut, /* Data to consume */ - unsigned int nLen, /* Data length */ - void *pUserData /* User private data */ - ) -{ - sxi32 rc; - /* Store the output in an internal BLOB */ - rc = SyBlobAppend((SyBlob *)pUserData, pOut, nLen); - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_data_callback()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Consume the key directly */ - rc = pCursor->pStore->pIo->pMethods->xKey(pCursor,xConsumer,pUserData); - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_key()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_key(unqlite_kv_cursor *pCursor,void *pBuf,int *pnByte) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - if( pBuf == 0 ){ - /* Key length only */ - rc = pCursor->pStore->pIo->pMethods->xKeyLength(pCursor,pnByte); - }else{ - SyBlob sBlob; - if( (*pnByte) < 0 ){ - return UNQLITE_CORRUPT; - } - /* Initialize the data consumer */ - SyBlobInitFromBuf(&sBlob,pBuf,(sxu32)(*pnByte)); - /* Consume the key */ - rc = pCursor->pStore->pIo->pMethods->xKey(pCursor,unqliteDataConsumer,&sBlob); - /* Key length */ - *pnByte = SyBlobLength(&sBlob); - /* Cleanup */ - SyBlobRelease(&sBlob); - } - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_data_callback()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - /* Consume the data directly */ - rc = pCursor->pStore->pIo->pMethods->xData(pCursor,xConsumer,pUserData); - return rc; -} -/* - * [CAPIREF: unqlite_kv_cursor_data()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_kv_cursor_data(unqlite_kv_cursor *pCursor,void *pBuf,unqlite_int64 *pnByte) -{ - int rc; -#ifdef UNTRUST - if( pCursor == 0 ){ - return UNQLITE_CORRUPT; - } -#endif - if( pBuf == 0 ){ - /* Data length only */ - rc = pCursor->pStore->pIo->pMethods->xDataLength(pCursor,pnByte); - }else{ - SyBlob sBlob; - if( (*pnByte) < 0 ){ - return UNQLITE_CORRUPT; - } - /* Initialize the data consumer */ - SyBlobInitFromBuf(&sBlob,pBuf,(sxu32)(*pnByte)); - /* Consume the data */ - rc = pCursor->pStore->pIo->pMethods->xData(pCursor,unqliteDataConsumer,&sBlob); - /* Data length */ - *pnByte = SyBlobLength(&sBlob); - /* Cleanup */ - SyBlobRelease(&sBlob); - } - return rc; -} -/* - * [CAPIREF: unqlite_begin()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_begin(unqlite *pDb) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Begin the write transaction */ - rc = unqlitePagerBegin(pDb->sDB.pPager); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_commit()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_commit(unqlite *pDb) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Commit the transaction */ - rc = unqlitePagerCommit(pDb->sDB.pPager); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_rollback()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int unqlite_rollback(unqlite *pDb) -{ - int rc; - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Rollback the transaction */ - rc = unqlitePagerRollback(pDb->sDB.pPager,TRUE); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return rc; -} -/* - * [CAPIREF: unqlite_util_load_mmaped_file()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -UNQLITE_APIEXPORT int unqlite_util_load_mmaped_file(const char *zFile,void **ppMap,unqlite_int64 *pFileSize) -{ - const jx9_vfs *pVfs; - int rc; - if( SX_EMPTY_STR(zFile) || ppMap == 0 || pFileSize == 0){ - /* Sanity check */ - return UNQLITE_CORRUPT; - } - *ppMap = 0; - /* Extract the Jx9 Vfs */ - pVfs = jx9ExportBuiltinVfs(); - /* - * Check if the underlying vfs implement the memory map routines - * [i.e: mmap() under UNIX/MapViewOfFile() under windows]. - */ - if( pVfs == 0 || pVfs->xMmap == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - /* Try to get a read-only memory view of the whole file */ - rc = pVfs->xMmap(zFile,ppMap,pFileSize); - } - return rc; -} -/* - * [CAPIREF: unqlite_util_release_mmaped_file()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -UNQLITE_APIEXPORT int unqlite_util_release_mmaped_file(void *pMap,unqlite_int64 iFileSize) -{ - const jx9_vfs *pVfs; - int rc = UNQLITE_OK; - if( pMap == 0 ){ - return UNQLITE_OK; - } - /* Extract the Jx9 Vfs */ - pVfs = jx9ExportBuiltinVfs(); - if( pVfs == 0 || pVfs->xUnmap == 0 ){ - rc = UNQLITE_NOTIMPLEMENTED; - }else{ - pVfs->xUnmap(pMap,iFileSize); - } - return rc; -} -/* - * [CAPIREF: unqlite_util_random_string()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -UNQLITE_APIEXPORT int unqlite_util_random_string(unqlite *pDb,char *zBuf,unsigned int buf_size) -{ - if( UNQLITE_DB_MISUSE(pDb) ){ - return UNQLITE_CORRUPT; - } - if( zBuf == 0 || buf_size < 3 ){ - /* Buffer must be long enough to hold three bytes */ - return UNQLITE_INVALID; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return UNQLITE_ABORT; /* Another thread have released this instance */ - } -#endif - /* Generate the random string */ - unqlitePagerRandomString(pDb->sDB.pPager,zBuf,buf_size); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return UNQLITE_OK; -} -/* - * [CAPIREF: unqlite_util_random_num()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -UNQLITE_APIEXPORT unsigned int unqlite_util_random_num(unqlite *pDb) -{ - sxu32 iNum; - if( UNQLITE_DB_MISUSE(pDb) ){ - return 0; - } -#if defined(UNQLITE_ENABLE_THREADS) - /* Acquire DB mutex */ - SyMutexEnter(sUnqlMPGlobal.pMutexMethods, pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ - if( sUnqlMPGlobal.nThreadingLevel > UNQLITE_THREAD_LEVEL_SINGLE && - UNQLITE_THRD_DB_RELEASE(pDb) ){ - return 0; /* Another thread have released this instance */ - } -#endif - /* Generate the random number */ - iNum = unqlitePagerRandomNum(pDb->sDB.pPager); -#if defined(UNQLITE_ENABLE_THREADS) - /* Leave DB mutex */ - SyMutexLeave(sUnqlMPGlobal.pMutexMethods,pDb->pMutex); /* NO-OP if sUnqlMPGlobal.nThreadingLevel != UNQLITE_THREAD_LEVEL_MULTI */ -#endif - return iNum; -} -- cgit v1.2.3