Symisc UnQLite

An Embeddable NoSQL Database Engine



UnQLite C/C++ API Reference - Using Database Cursors.

Syntax

Using database cursors.


Opening Database Cursors


int unqlite_kv_cursor_init(unqlite *pDb,unqlite_kv_cursor **ppOut);

int unqlite_kv_cursor_release(unqlite *pDb,unqlite_kv_cursor *pCur);

int unqlite_kv_cursor_reset(unqlite_kv_cursor *pCursor);


Positioning Database Cursors


int unqlite_kv_cursor_seek(unqlite_kv_cursor *pCursor,const void *pKey,int nKeyLen,int iPos);

int unqlite_kv_cursor_first_entry(unqlite_kv_cursor *pCursor);

int unqlite_kv_cursor_last_entry(unqlite_kv_cursor *pCursor);

int unqlite_kv_cursor_valid_entry(unqlite_kv_cursor *pCursor);

int unqlite_kv_cursor_next_entry(unqlite_kv_cursor *pCursor);

int unqlite_kv_cursor_prev_entry(unqlite_kv_cursor *pCursor);


Extracting Data from Database Cursors


int unqlite_kv_cursor_key(unqlite_kv_cursor *pCursor,void *pBuf,int *pnByte);

int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);

int unqlite_kv_cursor_data(unqlite_kv_cursor *pCursor,void *pBuf,unqlite_int64 *pnData);

int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);


Deleting Records using Database Cursors


int unqlite_kv_cursor_delete_entry(unqlite_kv_cursor *pCursor);


Description


Cursors provide a mechanism by which you can iterate over the records in a database. Using cursors, you can seek, fetch, move, and delete database records.

Before playing with cursors, you must first allocate a new cursor handle using unqlite_kv_cursor_init(). This is often the first UnQLite cursor API call that an application makes and is a prerequisite in order to use cursors. When done, you must call unqlite_kv_cursor_release() to release any allocated resource by the cursor and thus to avoid memory leaks.


To iterate over database records, from the first record to the last, simply call unqlite_kv_cursor_first_entry() with successive call to unqlite_kv_cursor_next_entry() until it return a value other than UNQLITE_OK (See example below). Note that you can call unqlite_kv_cursor_valid_entry() to check if the cursor is pointing to a valid record (This will return 1 when valid. 0 otherwise).


To iterate over database records, from the last record to the first, simply call unqlite_kv_cursor_last_entry() with successive call to unqlite_kv_cursor_prev_entry() until it return a value other than UNQLITE_OK (See example below). Note that you can call unqlite_kv_cursor_valid_entry() to check if the cursor is pointing to a valid record (This will return 1 when valid. 0 otherwise).


You can also use cursors to search for records and start the iteration process from there. To do that, simply call unqlite_kv_cursor_seek() with the target record key and the seek direction (Last argument). The seek direction can take the following value:


UNQLITE_CURSOR_MATCH_EXACT or 0 (default)

Default search method supported by all key/value storage subsystem. An exact match is performed. If the record exists, the cursor is left pointing to it. Otherwise it is left pointing to EOF and UNQLITE_NOTFOUND is returned.


UNQLITE_CURSOR_MATCH_LE

The cursor is left pointing to the largest key in the database that is smaller than (pKey/nKey). If the database contains no keys smaller than (pKey/nKey), the cursor is left at EOF.

This option have sense only if the underlying key/value storage subsystem support range search (i.e: B+Tree, R+Tree, etc.). Otherwise this option is ignored and an exact match is performed.


UNQLITE_CURSOR_MATCH_GE

The cursor is left pointing to the smallest key in the database that is larger than (pKey/nKey). If the database contains no keys larger than (pKey/nKey), the cursor is left at EOF.

This option have sense only if the underlying key/value storage subsystem support range search (i.e: B+Tree, R+Tree, etc.). Otherwise this option is ignored and an exact match is performed.


To retrieve record key/data from a valid cursor (Tip: call unqlite_kv_cursor_valid_entry() to test cursor validity ) simply use the following interface:


unqlite_kv_cursor_key();

unqlite_kv_cursor_key_callback();

unqlite_kv_cursor_data();

unqlite_kv_cursor_data_callback();


These interfaces works exactly like their high-level thread-safe client: unqlite_kv_fetch() and unqlite_kv_fetch_callback(). See below for an usage or example or refer to the high-level client API description for additional information.


To delete a record from the database using the cursor interface, simply point to the target record using unqlite_kv_cursor_seek() and call unqlite_kv_cursor_delete_entry() after successful seek (See below for an usage example).


unqlite_kv_cursor_init() and unqlite_kv_cursor_release() are thread-safe while the other interfaces are not. Caller must ensure that no other thread can access the same cursor handle. Otherwise the result is undefined.


Parameters


pCursor

A pointer to a correctly initialized database cursor.


Return value


UNQLITE_OK is returned on successfull seek. Any other return value typically UNQLITE_EOF, UNQLITE_NOTFOUND indicates invalid seek (i.e. No more records to fetch).


Example

Compile this C file for a smart introduction to these interface.


#include <unqlite.h>

int rc;
unqlite *pDb;
unqlite_kv_cursor *pCursor;
unqlite_int64 iData;

// Open our database;
rc = unqlite_open(&pDb,"test.db",UNQLITE_OPEN_CREATE);
if( rc != UNQLITE_OK ){ return; }

//Store some records unqlite_kv_store(), unqlite_kv_append()...

/* Allocate a new cursor instance */

rc = unqlite_kv_cursor_init(pDb,&pCursor);

if( rc != UNQLITE_OK ){ return; }


/* Point to the first record */

for( unqlite_kv_cursor_first_entry(pCursor) ; unqlite_kv_cursor_valid_entry(pCursor) ; unqlite_kv_cursor_next_entry(pCursor) ){

    

     /* Consume the key */

     printf("\nKey ==>\n\t");

     unqlite_kv_cursor_key_callback(pCursor,DataConsumerCallback,0);


     /* Extract data length */

     unqlite_kv_cursor_data(pCursor,NULL,&iData);

     printf("\nData length ==> %lld\n\t",iData);

      

     /* Consume the data */

     unqlite_kv_cursor_data_callback(pCursor,DataConsumerCallback,0);

  }


/* Delete a record */

rc = unqlite_kv_cursor_seek(pCursor,"MyRecord",-1 /* Key length */,UNQLITE_CURSOR_MATCH_EXACT);

if( rc == UNQLITE_OK ){

    rc = unqlite_kv_cursor_delete_entry(pCursor);

  if( rc != UNQLITE_OK ){ return; }

}


/* Point to the last record */
rc = unqlite_kv_cursor_last_entry(pCursor);
if( rc != UNQLITE_OK ){ return; }

/* Iterate over the records */

while( unqlite_kv_cursor_valid_entry(pCursor) ){

      /* Consume the key */

   printf("\nKey ==>\n\t");

   unqlite_kv_cursor_key_callback(pCursor,DataConsumerCallback,0);


   /* Extract data length */

   unqlite_kv_cursor_data(pCursor,NULL,&iData);

   printf("\nData length ==> %lld\n\t",iData);

      

   /* Consume the data */

   unqlite_kv_cursor_data_callback(pCursor,DataConsumerCallback,0);

 

   /* Point to the previous record */

   unqlite_kv_cursor_prev_entry(pCursor);

}


/* Finally, Release our cursor */

unqlite_kv_cursor_release(pDb,pCursor);


//Auto-commit the transaction and close our handle
unqlite_close(pDb);


See also


unqlite_kv_fetch, unqlite_kv_fetch_callback, unqlite_kv_append, unqlite_kv_store, unqlite_open, unqlite_close.



Symisc Systems
Copyright © Symisc Systems