From 9ee8378d393778ac67314be7ea8d5bcbaeee9ee0 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Sun, 7 Dec 2014 10:08:07 +0100 Subject: try out unqlite --- common/unqlite/unqlite_jx9.c | 977 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 977 insertions(+) create mode 100644 common/unqlite/unqlite_jx9.c (limited to 'common/unqlite/unqlite_jx9.c') diff --git a/common/unqlite/unqlite_jx9.c b/common/unqlite/unqlite_jx9.c new file mode 100644 index 0000000..7362c58 --- /dev/null +++ b/common/unqlite/unqlite_jx9.c @@ -0,0 +1,977 @@ +/* + * 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: unql_jx9.c v1.2 FreeBSD 2013-01-24 22:45 stable $ */ +#ifndef UNQLITE_AMALGAMATION +#include "unqliteInt.h" +#endif +/* + * This file implements UnQLite functions (db_exists(), db_create(), db_put(), db_get(), etc.) for the + * underlying Jx9 Virtual Machine. + */ +/* + * string db_version(void) + * Return the current version of the unQLite database engine. + * Parameter + * None + * Return + * unQLite version number (string). + */ +static int unqliteBuiltin_db_version(jx9_context *pCtx,int argc,jx9_value **argv) +{ + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + jx9_result_string(pCtx,UNQLITE_VERSION,(int)sizeof(UNQLITE_VERSION)-1); + return JX9_OK; +} +/* + * string db_errlog(void) + * Return the database error log. + * Parameter + * None + * Return + * Database error log (string). + */ +static int unqliteBuiltin_db_errlog(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_vm *pVm; + SyBlob *pErr; + + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Point to the error log */ + pErr = &pVm->pDb->sErr; + /* Return the log */ + jx9_result_string(pCtx,(const char *)SyBlobData(pErr),(int)SyBlobLength(pErr)); + return JX9_OK; +} +/* + * string db_copyright(void) + * string db_credits(void) + * Return the unQLite database engine copyright notice. + * Parameter + * None + * Return + * Copyright notice. + */ +static int unqliteBuiltin_db_credits(jx9_context *pCtx,int argc,jx9_value **argv) +{ + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + jx9_result_string(pCtx,UNQLITE_COPYRIGHT,(int)sizeof(UNQLITE_COPYRIGHT)-1); + return JX9_OK; +} +/* + * string db_sig(void) + * Return the unQLite database engine unique signature. + * Parameter + * None + * Return + * unQLite signature. + */ +static int unqliteBuiltin_db_sig(jx9_context *pCtx,int argc,jx9_value **argv) +{ + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + jx9_result_string(pCtx,UNQLITE_IDENT,sizeof(UNQLITE_IDENT)-1); + return JX9_OK; +} +/* + * bool collection_exists(string $name) + * bool db_exits(string $name) + * Check if a given collection exists in the underlying database. + * Parameter + * name: Lookup name + * Return + * TRUE if the collection exits. FALSE otherwise. + */ +static int unqliteBuiltin_collection_exists(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Perform the lookup */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + /* Lookup result */ + jx9_result_bool(pCtx,pCol ? 1 : 0); + return JX9_OK; +} +/* + * bool collection_create(string $name) + * bool db_create(string $name) + * Create a new collection. + * Parameter + * name: Collection name + * Return + * TRUE if the collection was successfuly created. FALSE otherwise. + */ +static int unqliteBuiltin_collection_create(jx9_context *pCtx,int argc,jx9_value **argv) +{ + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Try to create the collection */ + rc = unqliteCreateCollection(pVm,&sName); + /* Return the result to the caller */ + jx9_result_bool(pCtx,rc == UNQLITE_OK ? 1 : 0); + return JX9_OK; +} +/* + * value db_fetch(string $col_name) + * value db_get(string $col_name) + * Fetch the current record from a given collection and advance + * the record cursor. + * Parameter + * col_name: Collection name + * Return + * Record content success. NULL on failure (No more records to retrieve). + */ +static int unqliteBuiltin_db_fetch_next(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return null */ + jx9_result_null(pCtx); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return null */ + jx9_result_null(pCtx); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + /* Fetch the current record */ + jx9_value *pValue; + pValue = jx9_context_new_scalar(pCtx); + if( pValue == 0 ){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory"); + jx9_result_null(pCtx); + return JX9_OK; + }else{ + rc = unqliteCollectionFetchNextRecord(pCol,pValue); + if( rc == UNQLITE_OK ){ + jx9_result_value(pCtx,pValue); + /* pValue will be automatically released as soon we return from this function */ + }else{ + /* Return null */ + jx9_result_null(pCtx); + } + } + }else{ + /* No such collection, return null */ + jx9_result_null(pCtx); + } + return JX9_OK; +} +/* + * value db_fetch_by_id(string $col_name,int64 $record_id) + * value db_get_by_id(string $col_name,int64 $record_id) + * Fetch a record using its unique ID from a given collection. + * Parameter + * col_name: Collection name + * record_id: Record number (__id field of a JSON object) + * Return + * Record content success. NULL on failure (No such record). + */ +static int unqliteBuiltin_db_fetch_by_id(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + jx9_int64 nId; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 2 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or record ID"); + /* Return NULL */ + jx9_result_null(pCtx); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return NULL */ + jx9_result_null(pCtx); + return JX9_OK; + } + /* Extract the record ID */ + nId = jx9_value_to_int(argv[1]); + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + /* Fetch the desired record */ + jx9_value *pValue; + pValue = jx9_context_new_scalar(pCtx); + if( pValue == 0 ){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory"); + jx9_result_null(pCtx); + return JX9_OK; + }else{ + rc = unqliteCollectionFetchRecordById(pCol,nId,pValue); + if( rc == UNQLITE_OK ){ + jx9_result_value(pCtx,pValue); + /* pValue will be automatically released as soon we return from this function */ + }else{ + /* No such record, return null */ + jx9_result_null(pCtx); + } + } + }else{ + /* No such collection, return null */ + jx9_result_null(pCtx); + } + return JX9_OK; +} +/* + * array db_fetch_all(string $col_name,[callback filter_callback]) + * array db_get_all(string $col_name,[callback filter_callback]) + * Retrieve all records of a given collection and apply the given + * callback if available to filter records. + * Parameter + * col_name: Collection name + * Return + * Contents of the collection (JSON array) on success. NULL on failure. + */ +static int unqliteBuiltin_db_fetch_all(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return NULL */ + jx9_result_null(pCtx); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return NULL */ + jx9_result_null(pCtx); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + jx9_value *pValue,*pArray,*pCallback = 0; + jx9_value sResult; /* Callback result */ + /* Allocate an empty scalar value and an empty JSON array */ + pArray = jx9_context_new_array(pCtx); + pValue = jx9_context_new_scalar(pCtx); + jx9MemObjInit(pCtx->pVm,&sResult); + if( pValue == 0 || pArray == 0 ){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory"); + jx9_result_null(pCtx); + return JX9_OK; + } + if( argc > 1 && jx9_value_is_callable(argv[1]) ){ + pCallback = argv[1]; + } + unqliteCollectionResetRecordCursor(pCol); + /* Fetch collection records one after one */ + while( UNQLITE_OK == unqliteCollectionFetchNextRecord(pCol,pValue) ){ + if( pCallback ){ + jx9_value *apArg[2]; + /* Invoke the filter callback */ + apArg[0] = pValue; + rc = jx9VmCallUserFunction(pCtx->pVm,pCallback,1,apArg,&sResult); + if( rc == JX9_OK ){ + int iResult; /* Callback result */ + /* Extract callback result */ + iResult = jx9_value_to_bool(&sResult); + if( !iResult ){ + /* Discard the result */ + unqliteCollectionCacheRemoveRecord(pCol,unqliteCollectionCurrentRecordId(pCol) - 1); + continue; + } + } + } + /* Put the value in the JSON array */ + jx9_array_add_elem(pArray,0,pValue); + /* Release the value */ + jx9_value_null(pValue); + } + jx9MemObjRelease(&sResult); + /* Finally, return our array */ + jx9_result_value(pCtx,pArray); + /* pValue will be automatically released as soon we return from + * this foreign function. + */ + }else{ + /* No such collection, return null */ + jx9_result_null(pCtx); + } + return JX9_OK; +} +/* + * int64 db_last_record_id(string $col_name) + * Return the ID of the last inserted record. + * Parameter + * col_name: Collection name + * Return + * Record ID (64-bit integer) on success. FALSE on failure. + */ +static int unqliteBuiltin_db_last_record_id(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + jx9_result_int64(pCtx,unqliteCollectionLastRecordId(pCol)); + }else{ + /* No such collection, return FALSE */ + jx9_result_bool(pCtx,0); + } + return JX9_OK; +} +/* + * inr64 db_current_record_id(string $col_name) + * Return the current record ID. + * Parameter + * col_name: Collection name + * Return + * Current record ID (64-bit integer) on success. FALSE on failure. + */ +static int unqliteBuiltin_db_current_record_id(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + jx9_result_int64(pCtx,unqliteCollectionCurrentRecordId(pCol)); + }else{ + /* No such collection, return FALSE */ + jx9_result_bool(pCtx,0); + } + return JX9_OK; +} +/* + * bool db_reset_record_cursor(string $col_name) + * Reset the record ID cursor. + * Parameter + * col_name: Collection name + * Return + * TRUE on success. FALSE on failure. + */ +static int unqliteBuiltin_db_reset_record_cursor(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + unqliteCollectionResetRecordCursor(pCol); + jx9_result_bool(pCtx,1); + }else{ + /* No such collection */ + jx9_result_bool(pCtx,0); + } + return JX9_OK; +} +/* + * int64 db_total_records(string $col_name) + * Return the total number of inserted records in the given collection. + * Parameter + * col_name: Collection name + * Return + * Total number of records on success. FALSE on failure. + */ +static int unqliteBuiltin_db_total_records(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + unqlite_int64 nRec; + nRec = unqliteCollectionTotalRecords(pCol); + jx9_result_int64(pCtx,nRec); + }else{ + /* No such collection */ + jx9_result_bool(pCtx,0); + } + return JX9_OK; +} +/* + * string db_creation_date(string $col_name) + * Return the creation date of the given collection. + * Parameter + * col_name: Collection name + * Return + * Creation date on success. FALSE on failure. + */ +static int unqliteBuiltin_db_creation_date(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + Sytm *pTm = &pCol->sCreation; + jx9_result_string_format(pCtx,"%d-%d-%d %02d:%02d:%02d", + pTm->tm_year,pTm->tm_mon,pTm->tm_mday, + pTm->tm_hour,pTm->tm_min,pTm->tm_sec + ); + }else{ + /* No such collection */ + jx9_result_bool(pCtx,0); + } + return JX9_OK; +} +/* + * bool db_store(string $col_name,...) + * bool db_put(string $col_name,...) + * Store one or more JSON values in a given collection. + * Parameter + * col_name: Collection name + * Return + * TRUE on success. FALSE on failure. + */ +static int unqliteBuiltin_db_store(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + int i; + /* Extract collection name */ + if( argc < 2 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or records"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol == 0 ){ + jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + /* Store the given values */ + for( i = 1 ; i < argc ; ++i ){ + rc = unqliteCollectionPut(pCol,argv[i],0); + if( rc != UNQLITE_OK){ + jx9_context_throw_error_format(pCtx,JX9_CTX_ERR, + "Error while storing record %d in collection '%z'",i,&sName + ); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + } + /* All done, return TRUE */ + jx9_result_bool(pCtx,1); + return JX9_OK; +} +/* + * bool db_drop_collection(string $col_name) + * bool collection_delete(string $col_name) + * Remove a given collection from the database. + * Parameter + * col_name: Collection name + * Return + * TRUE on success. FALSE on failure. + */ +static int unqliteBuiltin_db_drop_col(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol == 0 ){ + jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + /* Drop the collection */ + rc = unqliteDropCollection(pCol); + /* Processing result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK); + return JX9_OK; +} +/* + * bool db_drop_record(string $col_name,int64 record_id) + * Remove a given record from a collection. + * Parameter + * col_name: Collection name. + * record_id: ID of the record. + * Return + * TRUE on success. FALSE on failure. + */ +static int unqliteBuiltin_db_drop_record(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + jx9_int64 nId; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 2 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or records"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol == 0 ){ + jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + /* Extract the record ID */ + nId = jx9_value_to_int64(argv[1]); + /* Drop the record */ + rc = unqliteCollectionDropRecord(pCol,nId,1,1); + /* Processing result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK); + return JX9_OK; +} +/* + * bool db_set_schema(string $col_name, object $json_object) + * Set a schema for a given collection. + * Parameter + * col_name: Collection name. + * json_object: Collection schema (Must be a JSON object). + * Return + * TRUE on success. FALSE on failure. + */ +static int unqliteBuiltin_db_set_schema(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + int rc; + /* Extract collection name */ + if( argc < 2 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or db scheme"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + if( !jx9_value_is_json_object(argv[1]) ){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection scheme"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + rc = UNQLITE_NOOP; + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + /* Set the collection scheme */ + rc = unqliteCollectionSetSchema(pCol,argv[1]); + }else{ + jx9_context_throw_error_format(pCtx,JX9_CTX_WARNING, + "No such collection '%z'", + &sName + ); + } + /* Processing result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK); + return JX9_OK; +} +/* + * object db_get_schema(string $col_name) + * Return the schema associated with a given collection. + * Parameter + * col_name: Collection name + * Return + * Collection schema on success. null otherwise. + */ +static int unqliteBuiltin_db_get_schema(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_col *pCol; + const char *zName; + unqlite_vm *pVm; + SyString sName; + int nByte; + /* Extract collection name */ + if( argc < 1 ){ + /* Missing arguments */ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or db scheme"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + zName = jx9_value_to_string(argv[0],&nByte); + if( nByte < 1){ + jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name"); + /* Return false */ + jx9_result_bool(pCtx,0); + return JX9_OK; + } + SyStringInitFromBuf(&sName,zName,nByte); + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Fetch the collection */ + pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD); + if( pCol ){ + /* Return the collection schema */ + jx9_result_value(pCtx,&pCol->sSchema); + }else{ + jx9_context_throw_error_format(pCtx,JX9_CTX_WARNING, + "No such collection '%z'", + &sName + ); + jx9_result_null(pCtx); + } + return JX9_OK; +} +/* + * bool db_begin(void) + * Manually begin a write transaction. + * Parameter + * None + * Return + * TRUE on success. FALSE otherwise. + */ +static int unqliteBuiltin_db_begin(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_vm *pVm; + unqlite *pDb; + int rc; + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + /* Point to the unqlite Vm */ + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Point to the underlying database handle */ + pDb = pVm->pDb; + /* Begin the transaction */ + rc = unqlitePagerBegin(pDb->sDB.pPager); + /* result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK ); + return JX9_OK; +} +/* + * bool db_commit(void) + * Manually commit a transaction. + * Parameter + * None + * Return + * TRUE if the transaction was successfuly commited. FALSE otherwise. + */ +static int unqliteBuiltin_db_commit(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_vm *pVm; + unqlite *pDb; + int rc; + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + /* Point to the unqlite Vm */ + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Point to the underlying database handle */ + pDb = pVm->pDb; + /* Commit the transaction if any */ + rc = unqlitePagerCommit(pDb->sDB.pPager); + /* Commit result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK ); + return JX9_OK; +} +/* + * bool db_rollback(void) + * Manually rollback a transaction. + * Parameter + * None + * Return + * TRUE if the transaction was successfuly rolled back. FALSE otherwise + */ +static int unqliteBuiltin_db_rollback(jx9_context *pCtx,int argc,jx9_value **argv) +{ + unqlite_vm *pVm; + unqlite *pDb; + int rc; + SXUNUSED(argc); /* cc warning */ + SXUNUSED(argv); + /* Point to the unqlite Vm */ + pVm = (unqlite_vm *)jx9_context_user_data(pCtx); + /* Point to the underlying database handle */ + pDb = pVm->pDb; + /* Rollback the transaction if any */ + rc = unqlitePagerRollback(pDb->sDB.pPager,TRUE); + /* Rollback result */ + jx9_result_bool(pCtx,rc == UNQLITE_OK ); + return JX9_OK; +} +/* + * Register all the UnQLite foreign functions defined above. + */ +UNQLITE_PRIVATE int unqliteRegisterJx9Functions(unqlite_vm *pVm) +{ + static const jx9_builtin_func aBuiltin[] = { + { "db_version" , unqliteBuiltin_db_version }, + { "db_copyright", unqliteBuiltin_db_credits }, + { "db_credits" , unqliteBuiltin_db_credits }, + { "db_sig" , unqliteBuiltin_db_sig }, + { "db_errlog", unqliteBuiltin_db_errlog }, + { "collection_exists", unqliteBuiltin_collection_exists }, + { "db_exists", unqliteBuiltin_collection_exists }, + { "collection_create", unqliteBuiltin_collection_create }, + { "db_create", unqliteBuiltin_collection_create }, + { "db_fetch", unqliteBuiltin_db_fetch_next }, + { "db_get", unqliteBuiltin_db_fetch_next }, + { "db_fetch_by_id", unqliteBuiltin_db_fetch_by_id }, + { "db_get_by_id", unqliteBuiltin_db_fetch_by_id }, + { "db_fetch_all", unqliteBuiltin_db_fetch_all }, + { "db_get_all", unqliteBuiltin_db_fetch_all }, + { "db_last_record_id", unqliteBuiltin_db_last_record_id }, + { "db_current_record_id", unqliteBuiltin_db_current_record_id }, + { "db_reset_record_cursor", unqliteBuiltin_db_reset_record_cursor }, + { "db_total_records", unqliteBuiltin_db_total_records }, + { "db_creation_date", unqliteBuiltin_db_creation_date }, + { "db_store", unqliteBuiltin_db_store }, + { "db_put", unqliteBuiltin_db_store }, + { "db_drop_collection", unqliteBuiltin_db_drop_col }, + { "collection_delete", unqliteBuiltin_db_drop_col }, + { "db_drop_record", unqliteBuiltin_db_drop_record }, + { "db_set_schema", unqliteBuiltin_db_set_schema }, + { "db_get_schema", unqliteBuiltin_db_get_schema }, + { "db_begin", unqliteBuiltin_db_begin }, + { "db_commit", unqliteBuiltin_db_commit }, + { "db_rollback", unqliteBuiltin_db_rollback }, + }; + int rc = UNQLITE_OK; + sxu32 n; + /* Register the unQLite functions defined above in the Jx9 call table */ + for( n = 0 ; n < SX_ARRAYSIZE(aBuiltin) ; ++n ){ + rc = jx9_create_function(pVm->pJx9Vm,aBuiltin[n].zName,aBuiltin[n].xFunc,pVm); + } + return rc; +} -- cgit v1.2.3