Put Operation

In the previous section we reviewed the BnagDB objects and dealing with them. Now using the objects we will perform some operations. This section will review the *put* operation

put

connection (for Normal Table)

API - without transaction

FILEOFF_T put(const char *key, int keylen, DATA_VAR *val, insert_options flag);

FILEOFF_T put(const char *key, const char *val, insert_options flag);

FILEOFF_T put(FDT *key, FDT *val, insert_options flag);

FILEOFF_T put(LONG_T key, FDT *val, insert_options flag);

FILEOFF_T put(LONG_T key, const char *val, insert_options flag);

API -with transaction

FILEOFF_T put(const char *key, int keylen, DATA_VAR *val, insert_options flag, bangdb_txn *txn_handle);

FILEOFF_T put(const char *key, const char *val, insert_options flag, bangdb_txn *txn_handle);

FILEOFF_T put(FDT *key, FDT *val, insert_options flag, bangdb_txn *txn_handle);

FILEOFF_T put(LONG_T key, FDT *val, insert_options flag, bangdb_txn *txn_handle);

FILEOFF_T is long long. FDT is data type which is defiened as below. And the insert_options is enum which guides the put operation. The inser_options values are also given below

	struct FDT
	{
		void *data;
		DATALEN_T len;	//DATALEN_T is unsigned int
		FDT();
		FDT(void *_data, DATLEN_T _len);
		void copy(FDT *v);
		void free();
		~FDT();
	};
	
	//the data is assigned by the user for put and by db for get. 
	//For get always call free() for releasing the buffer. 
	//For put if data assigned by the user was created on heap 
	//then must call this. Releasing memory is user's responsibilty
	

When we deal with opaque or binary data then it's good to use FDT //type as we can specify the data and its length here. If the data assigned here has been created on heap (dynamically) then we should either release //that data separately or call free() on FDT type. //Copy() method is to copy a FDT type (more like copy contr)

When we deal with null terminated char strings then we can simple use the char* based API

The insert_options defines how the put operation is going to be done, here are the various values of inser_options

	enum insert_options
	{
		//if non-existing then insert and returns 0 
		//else returns 1 if already exists else -1 for error
		INSERT_UNIQUE,	
		
		//if existing then update and returns 0 
		//else returns 1 if does not exist else -1 for error
		UPDATE_EXISTING,	
	
		//insert if non-existing else update, should 
		//always return 0 for success else -1 for error
		INSERT_UPDATE,	
		
		//delete if existing(for future usage)
		DELETE_EXISTING,	
	};
	

DATA_VAR is for a scenario where user wishes to allocate buffer //and use it for all operations. It also helps in reading or writing from a particular offset. The structure of DATA_VAR is as follows;

	struct DATA_VAR
	{
		//the pointer to pre allocated buffer. for write db will read from
		//it and for read db would write to it. User should clear the buffer
		
		void *data_buf;							
						
		//the allocated buffer length (db doesn't touch this)
		
		int data_buf_len;	
		
		//length of the read data (returned by db) or length of data to write
		
		int data_len;		
		
		//for write db takes the bytes from data_buf from the data_offt and
		//for read db reads data in db from data_offt
		//data_offt + data_len <= data_buf_len, else data will be curtailed
		
		int data_offt; 						
					
		//db sets if more data is to come for read(MORE_DATA_TO_READ)
		
		int flag;		
	}
	

Now we will insert some values using the put APIs

	//assume that we have connection object (please see prev section)
	
	char *k1 = "atricle_key_101";
	char *v1 = "product description for key 101";
	char *v2 = "updated value for key_101";
	
	if(conn->put(k1, v1, INSERT_UNIQUE) < 0)
		bangdb_logger("error in put");
	
	FDT *fk1 = new FDT("article_key_102", 15);
	void *bv1 = (void*)"artbirary binary data";
	FDT *fv1 = new FDT(bv1, 39);
	
	if(conn->put(fk1, fv1, INSERT_UNIQUE) < 0)
	 	bangdb_logger("error in put");
	 	
	//update the k1
	int retval = 0;
	
	if((retval = conn->put(k1, v2, INSERT_EXISTING)) < 0)
	 	bangdb_logger("error in put\n");
	 else if(retval == 1)
	  	bangdb_logger("key k1 does not exist\n");
	  	
	//when you don't care if value exists or not and want to always 
	//update/insert the value then simple use INSERT_UPDATE type
	
	//finally clean up , if any
	
	delete fk1;		
	delete fv1;
	
	//no need to call free() on fk1 or fk2 as data assigned to FDT was not created on heap
	
	

Next we will do put operations useing transaction

	FDT *fk = new FDT("dummy key", 10);
	FDT *fv = new FDT("test data for table1", 20;
	FDT *fv2 = new FDT("test data for table2", 20);
	
	bangdb_txn txn;
	
	db.begin_transaction(&txn);
	
	//conn1 is connection for table1
	conn1->put(fk, fv INSERT_UNIQUE, &txn);
	
	//conn2 is connection for table2
	conn1->put(fk, fv2 INSERT_UPDATE, &txn);
	
	db->commit_transaction(&txn);
	
	//note we have left out the error condition check for put and commit
	

primConnection (for Primitive Table)

FILEOFF_T put(LONG_T key, LONG_T val, insert_options flag);

FILEOFF_T put(int key, int val, insert_options flag);

FILEOFF_T put(const char *key, LONG_T val, insert_options flag);

FILEOFF_T put(FDT *key, LONG_T val, insert_options flag);

Note that for primitive table, the key and value will be of fixed size. Though key could be int, long and char* (of fixed size) type but the value would always be either int or long. Hence all the put API mentioned above has value as long or int

simple example could be as follows;

	table *ptbl = db->getPrimitiveTable("prim_table");	//default creates for PRIMITIVE_LONG data type
	primConnection *pconn = ptbl->getPrimConnection();
	if(pconn->put(10, 20, INSERT_UNIQUE) < 0)
		bangdb_logger("error in put");
		
	//note that primitive table type should not be spcified explicitly, 
	//rather through the bangdb_primitive_data_type passed
	//to the getPrimitiveTable API exposed by db
	
	//also primConnection should be used for primitive table
	

wideConnection (for wide Table)

The wideConnection has similar API as of connection (Normal Table) API. Except that it has few more APIs suitable for dealing with structured data(json). Here are extra API that wideConnection exposed

int put(FDT *key, FDT *val, const char* index_name, FDT *index_val);

int put(LONG_T key, FDT *val, const char* index_name, FDT *index_val);

int put_doc(const char *key, const char *json_str, insert_options flag);

int put_doc(LONG_T key, const char *json_str, insert_options flag);

LONG_T put_doc(const char *json_str);

The first two APIs are for storing opaque data but allow user to index on certain text. For example if someone is storing value = "The high performance 1TB SSD", then user can index on various words in this text by doing following for ex;

	FDT k, v, ival;
	k.data = "item1"; k.length = 5;
	v.data = "The high performance 1TB SSD"; v.length = 28;
	char *idxName = "product";
	ival.data = "SSD"; ival.length = 3;
	
	if(wconn->put(&k, &v, idxName, &ival) < 0)
		bangdb_logger("put error");
		
	//This creates a index name Product and adds index for SSD into it mapping to the inserted value
	
	//note that currently for opaque data type only single index can be created, 
	//this will soon be supplemented with dynamic multiple index options
	

The last three APIs are for structured data and currently it supports json data. The 3rd and 4th API allows user to explicitly define the key whereas the last, 5th one implicitly creates the key and returns it upon success. Here user can create as many index as required before calling these APIs. Indexes can be created using createIndex API

	char *jstr = (char*)"{\"fields\": [\"Mathematics\", \"Computer Science\",\"cryptanalysis\",\"Biology\"],"
				 \"name\": { \"first\": \"Alan\", \"last\": \"Turing\" }, "
				 \"birth\": \"Jun 23, 1912\", \"death\": \"Jun 07, 1954\", "
				 \"school\": [ \"Princeton University\", \"Cambridge\", \"King's College\" ],"
				 \"country\" : \"England\"}";
				 
	//assume that we have already created index on fields, name.last, school and country
	//once we put, db would implicitly write the indexes as well
	
	//we can put with explicit key or without any key in which case db would create one
	
	if(wconn->put_doc("key1", jstr, INSERT_UNIQUE) < 0)
		bangdb_logger("error in put");
	
	//or
	
	LONG_T pk = put_doc(jstr);
	if(pk < 0)
		bangdb_logger("error in put");
	else
		bangdb_logger("the pk is %ld for put", pk);
	

Connection (for Normal Table)

API - without transaction

long Put(long key, string val, InsertOptions flag)

long Put(long key, byte[] val, InsertOptions flag)

long Put(string key, ref DataVar dv, InsertOptions flag)

long Put(byte[] key, ref DataVar dv, InsertOptions flag)

long Put(byte[] key, byte[] val, InsertOptions flag)

long Put(string key, string val, InsertOptions flag)

long Put(string key, byte[] val, InsertOptions flag)

long Put(byte[] key, string val, InsertOptions flag)

API -with transaction

public long Put(long key, string val, InsertOptions flag, Transaction txn)

public long Put(long key, byte[] val, InsertOptions flag, Transaction txn)

long Put(string key, ref DataVar dv, InsertOptions flag, Transaction txn)

long Put(byte[] key, ref DataVar dv, InsertOptions flag, Transaction txn)

long Put(byte[] key, byte[] val, InsertOptions flag, Transaction txn)

long Put(string key, string val, InsertOptions flag, Transaction txn)

long Put(string key, byte[] val, InsertOptions flag, Transaction txn)

long Put(byte[] key, string val, InsertOptions flag, Transaction txn)

The InsertOptions is enum which guides the put operation. The inser_options values are given below

The insert_options defines how the put operation is going to be done, here are the various values of inser_options

	public enum InsertOptions
	{
		//if non-existing then insert and returns 0 else returns 1 if already exists else -1 for error
		InsertUnique,		
		
		//if existing then update and returns 0 else returns 1 if does not exist else -1 for error 
		UpdateExisting,	  
          
		//insert if non-existing else update, should always return 0 for success else -1 for error 
		InsertUpdate,	
        	
		//delete if existing(for future usage) 
		DeleteExisting,	    
	};
	

DataVar is defined as folllows;

	//constructor, The sizeInBytes tells how much buffer to pre allocate
	DataVar(int sizeInBytes)

	//Copying of buffer as following APIs
	void Copy(string _buf, int len)

	void Copy(byte[] _buf, int len)

	//Reading of the buffer
	string Read()

	string Read(int len)

	//Compare or equal
	bool Equals(string _buf, int len)

	bool Equals(byte[] _buf, int len)

	bool Equals(byte[] buffer1, int offset1, byte[] buffer2, int offset2, int count)

	There are others getters and setters exposed by the DataVar type
	

Now we will insert some values using the put APIs

	//assume that we have connection object (please see prev section)
	
	string k1 = "atricle_key_101"; 
	string v1 = "product description for key 101"; 
	string v2 = "updated value";
	
	if(conn.Put(k1, v1, InsertOptions.InsertUnique) < 0)
		Common.BangDBLogger("error in put");
	
	byte[] fk1 = Encoding.UTF8.getBytes("article_key_102");
	byte[] fv1 = Encoding.UTF8.getBytes("artbirary binary data");
	
	if(conn.Put(fk1, fv1, InsertOptions.InsertUnique) < 0)
	 	Common.BangDBLogger("error in put");
	 	
	//update the k1
	int retval = 0;
	
	if((retval = conn.Put(k1, v2, InsertOptions.InsertExisting)) < 0)
	 	Common.BangDBLogger("error in put");
	 else if(retval == 1)
	  	Common.BangDBLogger("key k1 does not exist");
	  	
	//when you don't care if value exists or not and want to always update/insert 
	//the value then simple use InsertUpdate type
	
	

Next we will do put operations using transaction

	byte[] k = Encoding.UTF8.GetBytes("dummy key");
	byte[] v = Encoding.UTF8.GetBytes("test data for table1");
	byte[] v2 = Encoding.UTF8.GetBytes("test data for table2");
	
	Transaction txn = new Transaction();
	db.BeginTransaction(txn);
	
	//conn1 is connection for table1
	conn1.Put(k, v, InertOptions.InsertUnique, txn);

	//conn2 is connection for table1
	conn2.Put(k, v2, InertOptions.InsertUpdate, txn);
	
	db.CommitTransaction(ref txn);
	
	//note we have left out the error condition check for put and commit
	

PrimConnection (for primitive table)

public long Put(long key, long val, InsertOptions flag);

public long Put(int key, int val, InsertOptions flag);

public long Put(string key, long val, InsertOptions flag);

public long Put(byte[] key, long val, InsertOptions flag);

Note that for primitive table, the key and value will be of fixed size. Though key could be int, long and string (of fixed size) type but the value would always be either int or long. Hence all the put API mentioned above has value as long or int simple example could be as follows;

	Table ptbl = db.GetPrimitiveTable("prim_table"); //default will be PrimitiveTableLong type
	PrimConnection pconn = ptbl.GetPrimConnection();
	if(pconn.Put(10, 20, InsertOptions.InsertUnique) < 0)
		Common.BangDBLogger("error in put");
		
	//note that primitive table type should not be spcified explicitly, rather through the BangDBPrimitiveDataType 
	//passed to the getPrimitiveTable API exposed by db
	
	//also PrimConnection should be used for primitive table 
	

Wide Connection (for wide table)

The wideConnection has similar API as of connection (Normal Table) API. Except that it has few more APIs suitable for dealing with structured data(json). Here are extra API that wideConnection exposed

public long Put(byte[] key, string val, string idxName, string idxVal);

public long Put(string key, byte[] val, string idxName, string idxVal);

public long Put(string key, string val, string idxName, string idxVal);

public long Put(long key, string val, string idxName, string idxVal);

public long Put(long key, byte[] val, string idxName, string idxVal);

public long PutDoc(string key, string jsonStr, InsertOptions flag);

public long PutDoc(long key, string jsonStr, InsertOptions flag);

public long PutDoc(string jsonStr);

The first two APIs are for storing opaque data but allow user to index on certain text. For example if someone is storing value = "The high performance 1TB SSD", then user can index on various words in this text by doing following for ex;

	  string k = "item 1", v = "The high performance 1TB SSD";
	  string idxName = "product", idxVal = "SSD";
	  if(wconn.Put(k, v, idxName, idxVal) < 0)
	  	Common.BangDBLogger("error in put");
	  
	  //This creates a index name Product and adds index for SSD into it mapping to the inserted value
	  
	  //note that currently for opaque data type only single index can be created, this will soon be supplemented with dynamic multiple index options
	  

The last three APIs (the ones which end with Doc) are for structured data and currently it supports json data. The 3rd and 4th API allows user to explicitly define the key whereas the last, 5th one implicitly creates the key and returns it upon success. Here user can create as many index as required before calling these APIs. Indexes can be created using createIndex API

	string jstr = "{\"fields\": [\"Mathematics\", \"Computer Science\",\"cryptanalysis\",\"Biology\"],"+
				 \"name\": { \"first\": \"Alan\", \"last\": \"Turing\" }, "+
				 \"birth\": \"Jun 23, 1912\", \"death\": \"Jun 07, 1954\", "+
				 \"school\": [ \"Princeton University\", \"Cambridge\", \"King's College\" ],"+
				 \"country\" : \"England\"}";
				 
	//assume that we have already created index on fields, name.last, school and country
	//once we put, db would implicitly write the indexes as well
	
	//we can put with explicit key or without any key in which case db would create one
	
	if(wconn.PutDoc("key1", jstr, InsertOptions.InsertUnique) < 0)
		Common.BangDBLogger("error in put");
	
	//or
	
	long pk = PutDoc(jstr);
	if(pk < 0)
		Common.BangDBLogger("error in put");
	else
		Common.BangDBLogger("the pk is " + pk + " for put");
	

Connection (for Normal Table)

API - without transaction

public long put(long key, String val, InsertOptions flag);

public long put(long key, byte[] val, InsertOptions flag);

public long put(String key, DataVar val, InsertOptions flag);

public long put(byte[] key, DataVar val, InsertOptions flag);

public long put(byte[] key, byte[] val, InsertOptions flag);

public long put(String key, String val, InsertOptions flag);

API -with transaction

public long put(String key, DataVar val, InsertOptions flag, Transaction txn);

public long put(byte[] key, DataVar val, InsertOptions flag, Transaction txn);

public long put(String key, String val, InsertOptions flag, Transaction txn);

public long put(byte[] key, byte[] val, InsertOptions flag, Transaction txn);

public long put(long key, byte[] val, InsertOptions flag, Transaction txn);

The InsertOptions is enum which guides the put operation. The InsertOptions values are given below

The InsertOptions defines how the put operation is going to be done, here are the various values of InsertOptions

	
		//if non-existing then insert and returns 0 
		//else returns 1 if already exists else -1 for error
		
		INSERT_UNIQUE,		
		
		//if existing then update and returns 0 else 
		//returns 1 if does not exist else -1 for error 
		
		UPDATE_EXISTING,	  
          
		//insert if non-existing else update, should always 
		//return 0 for success else -1 for error 
		
		INSERT_UPDATE,	
        	
		//delete if existing(for transaction internal usage) 
		
		DELETE_EXISTING,	    

	

DataVar is for a scenario where user wishes to allocate buffer and use it for all operations. It also helps in reading or writing from a particular offset. The structure of DATA_VAR is as follows;

	//constructor, sizeInBytes in amount of buffer to be created in bytes
	DataVar(int sizeInBytes);
	
	//copy buffer
	void setBuffer(byte[] _buf);
	
	//reading buffer
	byte[] getBuffer();
	

Now we will insert some values using the put APIs

	//assume that we have connection object (please see prev section)
	
	String k1 = "atricle_key_101";
	String v1 = "product description for key 101";
	String v2 = "updated value";
	
	if(conn.put(k1, v1, InsertOptions.INSERT_UNIQUE) < 0)
		BangDBCommon.bangdb_logger("error in put");
	
	byte[] fk1 = "article_key_102".getBytes();
	byte[] fv1 = "artbirary binary data".getBytes();
	
	if(conn.put(fk1, fv1, InsertOptions.INSERT_UNIQUE) < 0)
	 	BangDBCommon.bangdb_logger("error in put");
	 	
	//update the k1
	int retval = 0;
	
	if((retval = conn.put(k1, v2, InsertOptions.UPDATE_EXISTING)) < 0)
	 	BangDBCommon.bangdb_logger("error in put");
	 else if(retval == 1)
	  	BangDBCommon.bangdb_logger("key k1 does not exist");
	  	
	//when you don't care if value exists or not and want to always update/insert 
	//the value then simple use INSERT_UPDATE type
	
	

Next we will do put operations using transaction

	byte[] k = "dummy key".getBytes();
	byte[] v = "test data for table1".getBytes();
	byte[] v2 = "test data for table2".getBytes();
	
	Transaction txn = new Transaction();
	db.beginTransaction();
	
	//conn1 is connection for table1
	conn1.put(k, v, InsertOptions.INSERT_UNIQUE, txn);

	//conn2 is connection for table1
	conn2.put(k, v2, InsertOptions.INSERT_UPDATE, txn);
	
	db.commitTransaction(txn);
	
	//note we have left out the error condition check for put and commit
	

PrimConnection (for Primitive table)

public long put(int key, int val, InsertOptions flag);

public long put(long key, long val, InsertOptions flag);

public long put(String key, long val, InsertOptions flag);

public long put(byte[] key, long val, InsertOptions flag);

Note that for primitive table, the key and value will be of fixed size. Though key could be int, long and String (of fixed size) type but the value would always be either int or long. Hence all the put API mentioned above has value as long or int

simple example could be as follows;

	TableEnv tenv = new TableEnv();
	Table ptbl = db.getPrimitiveTable("prim_table", BangDBPrimitiveDataType.PrimitiveLong, DBAccess.OPENCREATE, tenv);
	PrimConnection pconn = ptbl.getPrimConnection();
	if(pconn->put(10, 20, InsertOptions.INSERT_UNIQUE) < 0)
		BangDBCommon.bangdb_logger("error in put");
		
	//note that primitive table type should not be spcified explicitly, rather through the BangDBPrimitiveDataType passed
	//to the getPrimitiveTable API exposed by db
	
	//also PrimConnection should be used for primitive table
	

WideConnection (for Wide table)

The wideConnection has similar API as of connection (Normal Table) API. Except that it has few more APIs suitable for dealing with structured data(json). Here are extra API that wideConnection exposed

public long put(String key, String val, String idxName, String idxVal);

public long put(String key, byte[] val, String idxName, String idxVal);

public long put(byte[] key, String val, String idxName, String idxVal);

public long put(long key, String val, String idxName, String idxVal);

public long put(long key, byte[] val, String idxName, String idxVal);

public long put(byte[] key, byte[] val, String index_name, byte[] index_val);

public long putDoc(String key, String jsonStr, InsertOptions flag);

public long putDoc(long key, String jsonStr, InsertOptions flag);

public long putDoc(String jsonStr);

The first six APIs are for storing opaque data but allow user to index on certain text. For example if someone is storing value = "The high performance 1TB SSD", then user can index on various words in this text by doing following for ex;

	 String k = "item 1", v = "The high performance 1TB SSD";
	 String idxName = "product", idxVal = "SSD";
	 if(wconn.put(k, v, idxName, idxVal) < 0)
	  	BangDBCommon.bangdb_logger("error in put");
	  
	 //This creates a index name Product and adds index for SSD into it mapping to the inserted value
	  
	 //note that currently for opaque data type only single index can be created, this will soon be supplemented with dynamic multiple index options
	

The last three APIs are for structured data and currently it supports json data. The 3rd and 4th API allows user to explicitly define the key whereas the last, 5th one implicitly creates the key and returns it upon success. Here user can create as many index as required before calling these APIs. Indexes can be created using createIndex API"

	 String jstr = "{\"fields\": [\"Mathematics\", \"Computer Science\",\"cryptanalysis\",\"Biology\"], "+
				 "\"name\": { \"first\": \"Alan\", \"last\": \"Turing\" }, "+
				 "\"birth\": \"Jun 23, 1912\", \"death\": \"Jun 07, 1954\", "+ 
				 "\"school\": [ \"Princeton University\", \"Cambridge\", \"King's College\" ], "+ 
				 "\"country\" : \"England\"}";
				 
	//assume that we have already created index on fields, name.last, school and country
	//once we put, db would implicitly write the indexes as well
	
	//we can put with explicit key or without any key in which case db would create one
	
	if(wconn.putDoc("key1", jstr, InsertOptions.INSERT_UNIQUE) < 0)
		BangDBCommon.bangdb_logger("error in put");
	
	//or
	
	long pk = putDoc(jstr);
	if(pk < 0)
		BangDBCommon.bangdb_logger("error in put");
	else
		BangDBCommon.bangdb_logger("the pk is " + pk + " for put");