Sample client application for BangDB Server

This is just a sample client application for BangDB server. This sample client application for BangDB server covers few basic features in simple sense, but would help user understand and build their own application. There are follow 3 basic steps to write application:

  1. Get BangDB Environment and database
  2. Create tables, indexes, stream etc… and perform operations
  3. Close environment

The client for BangDB is written in C/C++ and it does lot more than simply sending and receiving data over the tcp.

C++
Java

Let's first create the env and db object

DBParam dpm;
dpm.setTransactionType(DB_TRANSACTION_NONE);
#ifdef _BANGDB_SSL_ dpm.setSecureConn(true);
#endif BangDBEnv *env = new BangDBEnv(&dpm);
BangDBDatabase *bdb = new BangDBDatabase("mydb", env, &dpm);

Now we need table to start the operations

TableEnv te;
te.setTableType(NORMAL_TABLE);
te.setKeySize(24);
// default key is string type, hence we can set the size of the key 
BangDBTable *t1 = bdb->getTable("normal_table", te, OPENCREATE);
// Open or create
if(!t1) { 
   printf("normal table creation failed\n"); return -1; 
}

Let's get the db description and print

const char *db_desc = NULL;
db_desc = bdb->getStats(true);
if(!db_desc) { 
   printf("getStats for db failed\n"); return -1; 
} else { 
   printf("getStats for db returns following:\n%s\n", db_desc);
   delete[] db_desc;
}

We may get the table description as well

const char *tbl_desc = t1->getStats(true); 
if(!tbl_desc) { 
   printf("table desc failed\n"); return -1;
} else { 
   printf("getStats for normal table returns following:\n%s\n", tbl_desc); delete[] tbl_desc;
}

Now let's put some data and read it

bool flag = true;
// let's put some key and value
FDT k("my_key1", 7), v("my_val1", 7);
if(t1->put(&k, &v, INSERT_UNIQUE) < 0) { 
   printf("put in the normal table failed\n"); flag = false; 
} 
FDT *ov = NULL;
if(t1->get(&k, &ov) < 0) { 
   printf("get in the normal table failed\n"); flag = false; 
} else { 
   printf("1. key = %s, val = %s\n", (char*)k.data, (char*)ov->data); ov->free();
}

Use the previous key with INSERT_UNIQUE flag and it should return 1, which means key already exists

v.data = (char*)"my_val1_update";
v.length = 14; if(t1->put(&k, &v, INSERT_UNIQUE) != 1)
// unique put should fail here as key exists
{ 
   printf("update in the normal table failed as it put unique data\n");
   flag = false;
} 
// we may call put with INSERT_UPDATE to update the existing key 
if(t1->put(&k, &v, INSERT_UPDATE) < 0) {
   printf("update in the normal table failed as it could not update the key\n"); 
   flag = false; 
} ov = NULL; 
if(t1->get(&k, &ov) < 0) { 
   printf("get in the normal table failed\n"); 
   flag = false; 
} else { 
   printf("2. key = %s, val = %s\n", (char*)k.data, (char*)ov->data); ov->free();
}

Delete the key now

if(t1->del(&k) < 0) { 
printf("del in normal table failed\n");
flag = false; 
}
// try to get the deleted key, you should get -1 else it's error
ov = NULL;
if(t1->get(&k, &ov) >= 0) { 
   printf("del error\n"); flag = false; 
} if(ov) { 
   printf("get in the normal table failed as it got the deleted key\n"); 
flag = false;
  } 

Scan the table now

ResultSet *rs = NULL; ScanFilter sf; int nc = 0;
// since there could be large amount of data and hence we may need to
// scan multiple times in order to get the data
// therefore we need to call scan recursively 
// BangDB simplifies this completely and allows user to call like following;
// Note; you may add other args as well as needed 
printf("Scanning for table t1\n");
while(true) { 
rs = t1->scan(rs, NULL, NULL, &sf);
if(!rs) break;
nc += rs->count();
while(rs->hasNext()) { 
   // since this table has key and val as string hence can call these to print
   printf("key = %s, val = %s\n", rs->getNextKeyStr(), rs->getNextValStr()); rs->moveNext();
 } 
} 
printf("num of scanned items for table t1 = %d\n", nc);

Create a normal table with long as key

te.reset();
te.setTableType(NORMAL_TABLE);
te.setKeyType(NORMAL_KEY_LONG);
// key is long now, not string, hence key_size is not needed 
BangDBTable *t2 = bdb->getTable("normal_table_long", &te, OPENCREATE);
if(!t2) { 
   printf("normal table creating failed\n"); return -1;
} 
// put key val 
long lv = 1;
FDT k2(lv, 8), v2("my_val_long1", 12);
if(t2->put(&k2, &v2, INSERT_UNIQUE) < 0) {
   printf("put in the normal table failed\n");
   flag = false;
}
// get the val for the given key 
ov = NULL;
if(t2->get(&k2, &ov) < 0) { 
   printf("get in the normal table failed\n"); flag = false;
} else { 
    printf("3. key = %ld, val = %s\n", (long)k2.data, (char*)ov->data); ov->free();
}

Drop a table now

There are two ways to do this

  1. Call dropTable() on BangDBDatabse
  2. Close the table and tell server to clean close it - I.e. delete everything for the table

Let's drop the table using 2

if(t1->closeTable(CLEANCLOSE_AT_SERVER) < 0) { 
printf("failed to drop the table t1\n"); flag = false; 
}
delete t1; 
// check if it exists 
if(bdb->doesTableExist("normal_table")) { 
  printf("table normal_table exists after dropping it\n"); flag = false; 
}

Let's create wide table now, table that deals with json doc, but it can also store simple text

te.reset();
te.setTableType(WIDE_TABLE);
te.setKeyType(NORMAL_KEY_LONG);
// let's use long key te.setAllowDuplicate(true);
// dupl key is allowed te.setVersionType(BANGDB_DATA_VERSION_VALID_INVALID);
// this will maintain versions, usually we should do this 
BangDBTable *t3 = bdb->getTable("my_wide_table1", &te, OPENCREATE);
if(!t3) { 
   printf("wide table could not be created\n"); return -1;
}

Put few keys and vals and get them

FDT wk1(111, 8), wk2(222, 8), wk3(333, 8); FDT wv1("wide val 1", 10), wv2("wide val 2", 10), wv3("wide val 3", 10);
if(t3->put(&wk1, &wv1, INSERT_UNIQUE) < 0) { 
   printf("put for widetable failed\n"); flag = false;
 } if(t3->put(&wk2, &wv2, INSERT_UNIQUE) < 0) { 
   printf("put for widetable failed\n"); flag = false;
 } if(t3->put(&wk3, &wv3, INSERT_UNIQUE) < 0) { 
   printf("put for widetable failed\n"); flag = false;
 } wv1.data = (char*)"wide_val_1_up"; wv1.length = 13;
if(t3->put(&wk1, &wv1, INSERT_UNIQUE) < 0) { 
   printf("put for widetable failed\n"); 
   flag = false;
 } 
FDT *wov = NULL; 
if(t3->get(&wk1, &wov) < 0) { 
  printf("get failed for wide table\n");
  flag = false; }
else { 
   printf("4. key = %d, val = %s\n", 111, (char*)wov->data);
   wov->
   free();
   delete wov; 
}

Scan for some key range - this will recursively scan until all keys and values are scanned

rs = NULL; sf.reset();
nc = 0;
printf("Scanning for table t3\n");
while(true) { 
   rs = t3->scan(rs, &wk1, &wk3, &sf);
   if(!rs) break; nc += rs->count();
   while(rs->hasNext()) {
      printf("key = %ld, val = %s\n", rs->getNextKeyLong(), rs->getNextValStr()); rs->moveNext(); 
   } 
} 
printf("num of scanned items for table t3 = %d\n", nc);

May count number of keys as well, with or without range

printf("total num of elements in t3 = %ld\n", t3->count());
printf("num of elements between wk2 and wk3 in t3 = %ld\n", t3->count(&wk2, &wk3));

Try now with json doc - usually we should only put docs or non-docs, mixing may not be very logical, hence let's create new wide table

te.reset();
te.setAllowDuplicate(true);
te.reset();
te.setTableType(WIDE_TABLE);
te.setKeyType(NORMAL_KEY_LONG);
te.setAllowDuplicate(true);
te.setVersionType(BANGDB_DATA_VERSION_VALID_INVALID);
BangDBTable *t4 = bdb->getTable("my_wide_table2", &te, OPENCREATE);
if(!t4) { 
   printf("wide table t4 could not be created\n"); return -1; 
}

Add few indexes

// this one creates an index on string type field where max size is 16 bytes
if(t4->addIndex_str("org", 16, true) < 0) { 
   printf("error in adding index org\n"); flag = false;
} 
// this one creates an index on string type field where max size is 24 bytes 
// note, it's a nested index 
if(t4->addIndex_str("family.favsport", 24, true) < 0) { 
   printf("error in adding index family.favsport\n"); 
flag = false; 
}

Now let's put some docs

const char *doc1 = "{\"name\":\"sachin sinha\", \"org\":\"iqlect\", \"likes\":[\"music\", \"sports\", \"movies\"], \"family\":{\"wife\":\"vijeta\", \"father\":\"k m n sinha\",\"favsport\":\"cricket\"}}";

const char *doc2 = "{\"name\":\"mukesh prasad singh\", \"org\":\"zopsmart\", \"likes\":[\"tech\", \"sports\", \"movies\"], \"family\":{\"wife\":\"julie\", \"father\":\"p prasad\",\"favsport\":\"football\"}}";

const char *doc3 = "{\"name\":\"aman thakur\", \"org\":\"google\", \"likes\":[\"investment\", \"ping pong\", \"movies\"], \"family\":{\"wife\":\"koyal\", \"father\":\"h thakur\",\"favsport\":\"cricket\"}}";

const char *doc4 = "{\"name\":\"arjun\", \"org\":\"nps\", \"likes\":[\"music\", \"video games\", \"movies\"], \"family\":{\"father\":\"Sachin Sinha\", \"mother\":\"vijeta\",\"favsport\":\"cricket\"}}";

if(t4->putDoc(doc1) < 0) 
// note we are not supplying any key, in this case db will pick timestamp (in microsec) as the key 
{ 
   printf("put failed for doc1\n"); flag = false; 
} 
if(t4->putDoc(doc2) < 0) { 
   printf("put failed for doc2\n"); 
   flag = false; 
} 
if(t4->putDoc(doc3) < 0) { 
   printf("put failed for doc3\n");
   flag = false;
} 
if(t4->putDoc(doc4) < 0) { 
   printf("put failed for doc4\n");
   flag = false;
}

Let's define some query for which we wish to scan the data, query selects data where “org=iqlect”

DataQuery dq;
const char *idx_query; dq.addQuery("org", EQ, "iqlect", JO_INVALID);
// select all where org = Iqlect idx_query = dq.getQuery();
rs = NULL; // must set it to null sf.reset(); nc = 0;
printf("Scan query : select * from t4 where org = iqlect\n"); 
while(true) { 
   if((rs = t4->scanDoc(rs, NULL, NULL, idx_query, &sf)) == NULL)
   // note scanDoc() here and not scan() break;
   nc += rs->count();
   while(rs->hasNext()) { 
      printf("key = %ld, val = %s\n", rs->getNextKeyLong(), rs->getNextValStr());  
      rs->moveNext();   
   }   
}   
printf("num of scanned items for table t4 (select * from t4 where org = iqlect) = %d\n", nc);

Now select all where family favsports = cricket

dq.reset(); dq.addQuery("family.favsport", EQ, "cricket", JO_INVALID);
idx_query = dq.getQuery();
rs = NULL;
// must set it to null sf.reset(); nc = 0;
printf("Scanning query : select * from t4 where family.favsport = cricket\n");
while(true) { 
if((rs = t4->scanDoc(rs, NULL, NULL, idx_query, &sf)) == NULL) break;
nc += rs->count();
while(rs->hasNext()) { 
printf("key = %ld, val = %s\n", rs->getNextKeyLong(), rs->getNextValStr()); rs->moveNext(); 
} } 
printf("num of scanned items for table t4 (select * from t4 where family.favsport = cricket) = %d\n", nc);

We can simply count with filter/query as well

printf("t4 count for filter based scan = %ld with total count = %ld\n", t4-gt;
count(NULL, NULL, idx_query, amp;sf), t4->count());

Let's check number of tables in the DB

printf("num of tables in the db = %ld\n", bdb->getNumTables());
printf("does table t3 exist? ans = %s\n", bdb->doesTableExist("my_wide_table1") ? "yes" : "no");
printf("does table t1 exist? ans = %s\n", bdb->doesTableExist("normal_table") ? "yes" : "no");

Get all table list and print - note you will get these tables in describe database or describe table api calls as well

const char *tbl_list = bdb-gt;
getTableList();
if(!tbl_list) { 
printf("tbl list is NULL\n"); flag = false;
 } else { 
printf("table list = \n%s\n", tbl_list); delete[] tbl_list;
 }

Drop the “org” index and put some value and then scan using index

if(t4->dropIndex("org") lt; 0) { 
printf("drop index failed for index org\n");
flag = false;
}

Now we can still put docs and query for index “org”, even though it's not there, db would still fetch the results for the query. Index helps the performance of query however it's not needed for the query

const char *doc5 = "{\"name\":\"raj\", \"org\":\"iqlect\", \"likes\":[\"music\", \"sprots\", \"movies\"], \"family\":{\"wife\":\"richa pandey\", \"father\":\"kevin\", \"mother\":\"latika\"}}";
if(t4->putDoc(doc5) < 0) { 
printf("put failed for doc5\n"); flag = false;
 } 
printf("........ scan again for org index = iqlect .......\n");
dq.reset();
dq.addQuery("org", EQ, "iqlect", JO_INVALID); idx_query = dq.getQuery();
rs = NULL;
// must set it to null sf.reset();
nc = 0;
printf("Scan query - select * from t4 where org = iqlect\n");
while(true) { if((rs = t4->
scanDoc(rs, NULL, NULL, idx_query, &sf)) == NULL) break;
nc += rs->count();
while(rs->hasNext()) { 
printf("key = %ld, val = %s\n", rs->getNextKeyLong(), rs->getNextValStr()); rs->moveNext();
 } } 
printf("num of scanned items for table t4 (select * from t4 where org = iqlect) = %d\n", nc);

You may close the table when done or in the end when you close database, all tables get closed as well

if(t2->closeTable() < 0) { 
printf("normal closeTable failed\n");
flag = false; }
delete t2;
// even if you don't close the table, it's a good practice to delete the table object, db won't clean this object, will just close the table

Close the db, it will close all other db resources as well

env->closeDatabase(bdb, CLEANCLOSE_AT_SERVER);
delete bdb;
delete env;
printf("test %s\n", flag ? "passed" : "failed"); return flag ? 0 : -1;

You can download the sample test file for BangDB and run.

Load the lib and create the env and db

System.loadLibrary("bangdb-client-java");
DBParam dbp = new DBParam(); dbp.set_port("10101");
dbp.set_host("127.0.0.1");
dbp.setTransactionType(TransactionType.DB_MULTIOPS_TRANSACTION_NONE);
BangDBEnv dbenv = new BangDBEnv(dbp);
BangDBDatabase bdb = new BangDBDatabase("mydb", dbenv, dbp);

Let's create a normal table, note for normal table val is opaque

TableEnv te = new TableEnv();
te.setTableType(TableType.NORMAL_TABLE);
te.setKeySize(24);
// default key is String type, hence we can set the size of the key
BangDBTable t1 = bdb.getTable("normal_table", te, OpenType.OPENCREATE);
// Open or create if(t1 == null) { System.out.print("normal table creating failed\n"); return -1; }

Let's get the db description and print

String db_desc = null;
db_desc = bdb.getStats(true);
if(db_desc == null) { 
   System.out.print("getStats for db failed\n");
   return -1; 
} else {
   System.out.print("getStats for db returns following:\n" + db_desc);
}
// we may get the table description as well 
String tbl_desc = t1.getStats(true);
if(tbl_desc == null) { 
   System.out.print("table desc failed\n"); return -1;
} else { 
   System.out.print("getStats for normal table returns following:\n" + tbl_desc);
}

Let's put some key and value

String key = "my_key1";
String val = "my_val1";
if(t1.put(key, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) < 0) { 
   System.out.print("put in the normal table failed\n");
   flag = false;
} 
byte[]
ov = null;
if((ov = t1.get(key, null)) == null) { 
   System.out.print("get in the normal table failed\n");
   flag = false; 
}
else { 
   System.out.println("1. key = " + key + " val = " + new String(ov));
}

Use the previous key to INSERT_UNIQUE, it should return 1, which means key already exists, also when called get(), it will return the updated data

val = "my_val1_update";
if(t1.put(key, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) != 1) 
// unique put should fail here as key exists { 
   System.out.print("update in the normal table failed as it put unique data\n"); 
   flag = false; 
} 
// we may call put with INSERT_UPDATE to update the existing key 
if(t1.put(key, val.getBytes(), InsertOptions.INSERT_UPDATE, null) < 0) { 
   System.out.print("update in the normal table failed as it could not update the key\n"); 
   flag = false;
}
ov = null;
if((ov = t1.get(key, null)) == null) { 
   System.out.print("get in the normal table failed\n");
   flag = false; 
} else { 
   System.out.println("1. key = " + key + " val = " + new String(ov));
}

Delete the key now

if(t1.del(key, null) < 0) {
System.out.print("del in normal table failed\n");
flag = false; 
} // try to get the deleted key, you should get -1 else it's error
ov = null;
if((ov = t1.get(key, null)) != null) { 
  System.out.print("del error\n"); flag = false;
} 
if(ov != null) {
  System.out.print("get in the normal table failed as it got the deleted key\n"); 
  flag = false;
}

Scan the table now

ResultSet rs = null;
ScanFilter sf = new ScanFilter();
String sk = null; int nc = 0;
// since there could be large amount of data and hence we may need to
// scan multiple times in order to get the data
// therefore we need to call scan recursively
// BangDB simplifies this completely and allows user to call like following;
// Note; you may add other args as well as needed System.out.print("Scanning for table t1\n");
while(true) { 
   rs = t1.scan(rs, sk, null, sf, null);
   if(rs == null) break; nc += rs.count();
   while(rs.hasNext()) { 
      System.out.println("key = " + new String(rs.getNextKey()) + "val = " + new String(rs.getNextVal())); 
   rs.moveNext(); 
   } 
} 
System.out.println("num of scanned items for table t1 = "+ nc);

Create a normal table with long as key

te.reset();
te.setTableType(TableType.NORMAL_TABLE);
te.setKeyType(KeyType.NORMAL_KEY_LONG);
// key is long now, not String, hence key_size is not needed
BangDBTable t2 = bdb.getTable("normal_table_long", te, OpenType.OPENCREATE);
if(t2 == null) { 
   System.out.print("normal table creating failed\n");
   return -1;
}

Put key val

long lk = 1;
val = "my_val_long1";
if(t2.put(lk, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) < 0) { 
   System.out.print("put in the normal table failed\n"); 
   flag = false;
}
// get the val for the given key 
ov = null;
if((ov = t2.get(lk, null)) == null) { 
   System.out.print("get in the normal table failed\n");
   flag = false;
}
else { 
   System.out.println("3. key = " + lk + " val = " + new String(ov));
}

Drop a table now

There are two ways to do this:

  1. Call dropTable() on BangDBDatabse
  2. Close the table and tell server to clean close it - I.e. delete everything for the table

Let's drop the table using 2

if(t1.closeTable(CloseType.CLEANCLOSE_AT_SERVER, true) < 0) { 
  System.out.print("failed to drop the table t1\n");
  flag = false;
}
// check if it exists
if(bdb.doesTableExist("normal_table", 0)) {
  System.out.print("table normal_table exists after dropping it\n");
  flag = false; 
}

Let's create wide table now, table that deals with json doc, but it can also store simple text

te.reset();
te.setTableType(TableType.WIDE_TABLE);
te.setKeyType(KeyType.NORMAL_KEY_LONG);
// let's use long key te.setAllowDuplicate(1);
// dupl key is allowed te.setVersionType(VersionType.BANGDB_DATA_VERSION_VALID);
// this will maintain versions, usually we should do this
BangDBTable t3 = bdb.getTable("my_wide_table1", te, OpenType.OPENCREATE);
if(t3 == null) { 
   System.out.print("wide table could not be created\n");
   return -1;
}

Put few keys and vals

lk = 111;
val = "wide val 1";
if (t3.put(lk, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) & lt; 0) {
   System.out.print("put for widetable failed\n");
   flag = false;
}
lk = 222;
val = "wide val 2";
if (t3.put(lk, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) & lt; 0) {
   System.out.print("put for widetable failed\n");
   flag = false;
}
lk = 333;
val = "wide val 3";
if (t3.put(lk, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) & lt; 0) {
   System.out.print("put for widetable failed\n");
   flag = false;
}
lk = 111;
val = "wide_val_1_up";
if (t3.put(lk, val.getBytes(), InsertOptions.INSERT_UNIQUE, null) & lt; 0) {
   System.out.print("put for widetable failed\n");
   flag = false;
}
ov = null;
if ((ov = t3.get(lk, null)) == null) {
   System.out.print("get failed for wide table\n");
   flag = false;
} else {
   System.out.println("4. key = " + lk + " val = " + new String(ov));
}

Scan for some key range - this will recursively scan until all keys and values are scanned

rs = null;
sf.reset();
nc = 0;
long lk1 = 111, lk3 = 333;
System.out.print("Scanning for table t3\n");
while (true) {
   rs = t3.scan(rs, lk1, lk3, sf, null);
   if (rs == null) break;
   nc += rs.count();
   while (rs.hasNext()) {
      System.out.println("key = " + rs.getNextKeyLong() + " val = " + new String(rs.getNextVal()));
      rs.moveNext();
   }
}
System.out.println("num of scanned items for table t3 = " + nc);
// may count number of keys as well, with or without range
System.out.println("total num of elements in t3 = " + t3.count());
long lk2 = 222;
sf.reset();
System.out.println("num of elements between lk2 and lk3 in t3 = " + t3.count(lk2, lk3, null, sf));

Try now json doc - usually we should only put docs or non-docs, mixing may not be very logical

Hence let's create new wide table

te.reset();
te.setAllowDuplicate(1);
te.reset();
te.setTableType(TableType.WIDE_TABLE);
te.setKeyType(KeyType.NORMAL_KEY_LONG);
te.setAllowDuplicate(1);
te.setVersionType(VersionType.BANGDB_DATA_VERSION_VALID);
BangDBTable t4 = bdb.getTable("my_wide_table2", te, OpenType.OPENCREATE);
if (t4 == null) {
   System.out.print("wide table t4 could not be created\n");
   return -1;
}

Let's add few indexes as well

This one creates an index on String type field where max size is 16

if (t4.addIndex_str("org", 16, true) & lt; 0) {
  System.out.print("error in adding index org\n");
  flag = false;
}
// this one creates an index on String type field where max size is 24 bytes
// note, it's a nested index
if (t4.addIndex_str("family.favsport", 24, true) & lt; 0) {
  System.out.print("error in adding index family.favsport\n");
  flag = false;
}

Let's add some data

String doc1 = "{\"name\":\"sachin sinha\", \"org\":\"iqlect\", \"likes\":[\"music\", \"sports\", \"movies\"], \"family\":{\"wife\":\"vijeta\", \"father\":\"k m n sinha\",\"favsport\":\"cricket\"}}";
String doc2 = "{\"name\":\"mukesh prasad singh\", \"org\":\"zopsmart\", \"likes\":[\"tech\", \"sports\", \"movies\"], \"family\":{\"wife\":\"julie\", \"father\":\"p prasad\",\"favsport\":\"football\"}}";
String doc3 = "{\"name\":\"aman thakur\", \"org\":\"google\", \"likes\":[\"investment\", \"ping pong\", \"movies\"], \"family\":{\"wife\":\"koyal\", \"father\":\"h thakur\",\"favsport\":\"cricket\"}}";
String doc4 = "{\"name\":\"arjun\", \"org\":\"nps\", \"likes\":[\"music\", \"video games\", \"movies\"], \"family\":{\"father\":\"Sachin Sinha\", \"mother\":\"vijeta\",\"favsport\":\"cricket\"}}";
if (t4.putDoc(doc1, 0, null, InsertOptions.INSERT_UNIQUE) & lt; 0)
// note we are not supplying any key, in this case db will pick timestamp (in microsec) as the key
{
   System.out.print("put failed for doc1\n");
   flag = false;
}
if (t4.putDoc(doc2, 0, null, InsertOptions.INSERT_UNIQUE) & lt; 0) {
   System.out.print("put failed for doc2\n");
   flag = false;
}
if (t4.putDoc(doc3, 0, null, InsertOptions.INSERT_UNIQUE) & lt; 0) {
   System.out.print("put failed for doc3\n");
   flag = false;
}
if (t4.putDoc(doc4, 0, null, InsertOptions.INSERT_UNIQUE) & lt; 0) {
   System.out.print("put failed for doc4\n");
   flag = false;
}

Let's define some query for which we wish to scan the data. Let's use the query select * from t4 where “org” = “iqlect”

DataQuery dq = new DataQuery();
String idx_query = null;
dq.addQuery("org", ScanOperator.EQ, "iqlect", JoinType.JO_INVALID);
// select all where org = Iqlect idx_query = dq.getQuery(); rs = null;
// must set it to null sf.reset(); nc = 0;
System.out.print("Scan query : select * from t4 where org = iqlect\n");
while (true) {
   if ((rs = t4.scanDoc(rs, 0, 0, idx_query, sf)) == null)
      // note scanDoc() here and not scan() break;
      nc += rs.count();
   while (rs.hasNext()) {
      System.out.println("key = " + rs.getNextKeyLong() + " val = " + new String(rs.getNextVal()));
      rs.moveNext();
   }
}
System.out.println("num of scanned items for table t4 (select * from t4 where org = iqlect) = " + nc);

Now select all where family favsports = cricket

dq.reset();
dq.addQuery("family.favsport", ScanOperator.EQ, "cricket", JoinType.JO_INVALID);
idx_query = dq.getQuery();
rs = null;
// must set it to null sf.reset();
nc = 0; System.out.print("Scanning query : select * from t4 where family.favsport = cricket\n");
while(true) { if((rs = t4.scanDoc(rs, 0, 0, idx_query, sf)) == null)
// note scanDoc() here and not scan() break;
nc += rs.count();
while(rs.hasNext()) { 
System.out.println("key = " + rs.getNextKeyLong() + " val = " + new String(rs.getNextVal())); rs.moveNext(); 
} }
System.out.println("num of scanned items for table t4 (select * from t4 where family.favsport = cricket) = " + nc); 

We can also count for the given query

System.out.println("t4 count for filter based scan = " + t4.count(null, null, idx_query, sf) + " with total count = " + t4.count());

Now, let's just check the tables

System.out.println("num of tables in the db = " + bdb.getNumTables(3));
System.out.println("does table t3 exist? ans = " + bdb.doesTableExist("my_wide_table1", 0));
System.out.println("does table t1 exist? ans = " + bdb.doesTableExist("normal_table", 0));

Get all table list and print - note you will get these tables in describe database or describe table api calls as well

String tbl_list = bdb.getTableList();
if(tbl_list == null) { 
   System.out.print("tbl list is null\n");
   flag = false;
} else {
   System.out.println("table list = \n"+ tbl_list);
} 

Drop the “org” index and put some value and then scan using index

if(t4.dropIndex("org") < 0) {
   System.out.print("drop index failed for index org\n");
   flag = false;
}

Now we put the doc again, and search using same index and even though the index is deleted, db will still fetch the data for query that involves the index.

System.out.print("........ scan again for org index = iqlect .......\n");
dq.reset();
dq.addQuery("org", ScanOperator.EQ, "iqlect", JoinType.JO_INVALID); idx_query = dq.getQuery();
rs = null;
// must set it to null sf.reset();
nc = 0; System.out.print("Scan query - select * from t4 where org = iqlect\n");
while(true) { if((rs = t4.scanDoc(rs, 0, 0, idx_query, sf)) == null) 
// note scanDoc() here and not scan() break;
nc += rs.count(); while(rs.hasNext()) {
   System.out.println("key = " + rs.getNextKeyLong() + " val = " + new String(rs.getNextVal())); 
   rs.moveNext(); 
} } 
System.out.println("num of scanned items for table t4 (select * from t4 where org = iqlect) = " + nc);

You may close the table when done or in the end when you close database, all tables get closed as well

if(t2.closeTable(CloseType.DEFAULT_AT_SERVER, false) < 0) { 
  System.out.print("normal closeTable failed\n"); flag = false;
}

To close the db, simply call the closeDatabase(), this clears every other resources in the db

dbenv.closeDatabase(CloseType.CLEANCLOSE_AT_SERVER);
if(flag) System.out.println("test passed");
else {
  System.out.println("test failed"); return flag ? 0 : -1;
}

You can download the sample test file for BangDB and run.