how open cerod database using sqlite-jdbc drivers

782 views
Skip to first unread message

Raj Kamal

unread,
Oct 23, 2013, 5:55:39 AM10/23/13
to xer...@googlegroups.com
Hi,

I am able to use sqlite jdbc 3.1.15 version driver to connect to sqlite db using below command.

connection = DriverManager.getConnection("jdbc:sqlite:sample_cerod.db");

Could some one point me to how I should frame the connection string to open a connection to a "sample.db.cerod" file which is compressed and encrypted by a password.
How and where should I pass the parameter for "cerod" and "password" parameters?

Regards,
Kamal.

Grace B

unread,
Oct 27, 2013, 10:21:57 PM10/27/13
to xer...@googlegroups.com
The driver doesn't support SQLite cerod.
To add support, you will need to build the SQLite library with the CEROD extension. 

I think you will then be able open the db with
connection = DriverManager.getConnection("jdbc:sqlite::cerod:passwd:sample_cerod.db")
 

Regards,
Kamal.

Raj Kamal

unread,
Nov 20, 2013, 5:26:15 AM11/20/13
to xer...@googlegroups.com

Hi Grace,

With your suggestion I was able to successfully connect to a CEROD database using java code below:
when I try to fetch data through the driver from sqlite_master, I get 0 results as shown below

                    expDBPath = "abc.cerod";
    SQLiteConnection con = (SQLiteConnection)DriverManager.getConnection("jdbc:sqlite::cerod:"+expDBPath);
    
    System.out.println("Successfully connected to CEROD db ["+expDBPath+"] using Bitbucket sqlite JDBC Drivers version 3.7.2: ");
       
  String sqliteSelectQuery = "select count(*) from sqlite_master;";
  
  Statement statement = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
  statement.setQueryTimeout(DBExportConstants.CEROD_DB_QUERY_TIMEOUT);  // set timeout to 30 sec.
  statement.setFetchSize(DBExportConstants.CEROD_DB_FETCH_SIZE);
  
  System.out.println("Select query of sqlite is: "+sqliteSelectQuery);
  
  ResultSet cerodRS = statement.executeQuery(sqliteSelectQuery);// limit 10000");//sim_event_content
  
  ResultSetMetaData rsmd = cerodRS.getMetaData();
  
  System.out.println("Number of columns returned is ["+rsmd.getColumnCount()+"] for query: "+sqliteSelectQuery);
  System.out.println("cerodRS, isFirst(): "+cerodRS.isFirst());
  
  while(cerodRS.next()){
  System.out.println("row count is: "+cerodRS.getInt(1));
  }
  System.out.println("Done with result set");

and its output...

Creating connection to export catalog db...........: abc.cerod
Successfully connected to CEROD db [abc.cerod] using Bitbucket sqlite JDBC Drivers version 3.7.2:
Select query of sqlite is: select count(*) from sqlite_master;
Number of columns returned is [1] for query: select count(*) from sqlite_master;
rs isFirst(): false
row count is: 0
Done with result set

but, the same CEROD file(abc.cerod) when queried from sqlite command line is fetching proper results as listed below:

[root@ELM125SP3P iTechnology]# ./sqlite3 :cerod::abc.cerod "select count(*) from sqlite_master"
21
[root@ELM125SP3P iTechnology]# ./sqlite3 :cerod::abc.cerod "select count(*) from sim_event_content"
50003

when I try to fetch data through the driver from a table other than sqlite_master, I get below error :
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such table: sim_event_content)


Could you please let me know where I am going wrong.

Thank you,
Murali.

Raj Kamal

unread,
Nov 25, 2013, 11:30:47 AM11/25/13
to xer...@googlegroups.com
Hi Grace,

I tried using load_extension

 boolean loadedExtn = statement.execute("SELECT load_extension('libcalm-sqlite3.so','sqlite3CalmFtsInit')");
 
but, JVM crashed !!; here is a snippet of core dump

#5  0xf78bf0bc in JVM_handle_linux_signal () from /usr/java/jdk1.6.0_25/jre/lib/i386/server/libjvm.so
#6  0xf78bada4 in signalHandler(int, siginfo*, void*) () from /usr/java/jdk1.6.0_25/jre/lib/i386/server/libjvm.so
#7  <signal handler called>
#8  0x0034bc6d in pthread_mutex_lock () from /lib/libpthread.so.0
#9  0xaf0f4162 in sqlite3_mutex_enter (p=0x0) at ../src/mutex_unix.c:186
#10 0xaf08f408 in sqlite3_create_function (db=0xaf3a3970, zFunctionName=0xaf0fcb3e "calmfts_tokenizer", nArg=1, enc=5, p=0xaf3a4488, xFunc=0xaf0defa0 <scalar
    xStep=0, xFinal=0) at ../src/main.c:544
#11 0xaf0def2d in sqlite3Fts3InitHashTable (db=0xaf3a3970, pHash=0xaf3a4488, zName=0xaf0fcb3e "calmfts_tokenizer") at ../src/fts3/fts3_tokenizer.c:356
#12 0xaf0e2694 in sqlite3CalmFtsInit (db=0xaf3a3970) at ../src/calmfts3/calmfts.c:7069
#13 0xaf28605f in ?? () from /tmp/sqlite-3.7.151-i386-libsqlitejdbc.so
#14 0xaf3a3970 in ?? ()
#15 0xf72d97d8 in ?? ()
#16 0xaf2e8c40 in geteuid () from /tmp/sqlite-3.7.151-i386-libsqlitejdbc.so


while the console quit gracefully as mentioned below:

[root@ELM125SP3P iTechnology]# ./sqlite3 :cerod::abc.cerod "SELECT load_extension('libcalm-sqlite3.so');"
SQL error: libcalm-sqlite3.so: undefined symbol: sqlite3_extension_init

[root@ELM125SP3P iTechnology]# ./sqlite3 :cerod::abc.cerod "SELECT load_extension('libcalm-sqlite3.so','sqlite3CalmFtsInit');"
SQL error: error during initialization:

Grace B

unread,
Nov 27, 2013, 2:46:26 PM11/27/13
to xer...@googlegroups.com
Hey Kamal,
I apologize for the late response.

There seems to be a bug in the connection opening logic (https://bitbucket.org/xerial/sqlite-jdbc/src/tip/src/main/java/org/sqlite/SQLiteConnection.java?at=default#cl-125). It will either open/create a file called '::cerod:filepath' in the current working directory.
That explains whey sqlite3_master returns no records.

Apply the following patch and rebuilding the driver. Let me know if this works.

diff --git a/src/main/java/org/sqlite/SQLiteConnection.java b/src/main/java/org/sqlite/SQLiteConnection.java
--- a/src/main/java/org/sqlite/SQLiteConnection.java
+++ b/src/main/java/org/sqlite/SQLiteConnection.java
@@ -122,7 +122,7 @@
      */
     private void open(int openModeFlags, int busyTimeout) throws SQLException {
         // check the path to the file exists
-        if (!":memory:".equals(fileName) && !fileName.startsWith("file:") && !fileName.contains("mode=memory")) {
+        if (!":memory:".equals(fileName) && !fileName.startsWith(":cerod:") && !fileName.startsWith("file:") && !fileName.contains("mode=memory")) {
             if (fileName.startsWith(RESOURCE_NAME_PREFIX)) {
                 String resourceName = fileName.substring(RESOURCE_NAME_PREFIX.length());

Raj Kamal

unread,
Nov 28, 2013, 5:56:24 AM11/28/13
to xer...@googlegroups.com
Thank you for your inputs Grace.

I will try to build the code and let you know the behaviour.

Regards,
Murali.

Raj Kamal

unread,
Dec 1, 2013, 12:24:34 AM12/1/13
to xer...@googlegroups.com

Hi Grace,

 

I tried to build the JAR file with your change  and also had to change below code in JDBC.java:

    static String extractAddress(String url) {

        // if no file name is given use a memory database

        if( PREFIX.equalsIgnoreCase(url) )

            return ":memory:" ;

         else if(url.contains(PREFIX_CEROD))

            return url.substring(PREFIX_CEROD.length());

         else

            return url.substring(PREFIX.length());

    }

 

And used above modified SNAPSHOT.jar to test below code                

 

            try{

                         Properties sqliteProps = new Properties();

                    //PRAGMA activate_extensions='see-7bb07b8d471d642e';

                        sqliteProps.setProperty("activate_extensions", "7bb07b8d471d642e");

                        sqliteProps.setProperty("enable_load_extension", "7bb07b8d471d642e");

                       

                        SQLiteConfig sqliteConfig = new SQLiteConfig(sqliteProps);

                            //sqliteConfig.setPragma("enable_load_extension", "true");

                            sqliteConfig.enableLoadExtension(true);

                       

                            SQLiteDataSource sds = new SQLiteDataSource(sqliteConfig);

                            sds.setLoadExtension(true);

                            sds.setUrl( "jdbc:sqlite:cerod::abc.db.cerod");

                            con =  (SQLiteConnection) sds.getConnection();

                            

                            System.out.println("Successfully connected to CEROD db ["+sds.getUrl()+"] using Bitbucket sqlite JDBC Drivers version 3.7.15: ");

                    Statement statement = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);

                      boolean loadedExtn = statement.execute("SELECT load_extension('libcalm-sqlite3.so','sqlite3CalmFtsInit')");

                                      System.out.println("loadExtn returned: "+loadedExtn);    

                        }catch(SQLException sqle){ 

                     System.out.println("found error: "+sqle);

              }

 

It gave below output:

 

 

[root@ca-elm2 iTechnology]# java -cp ".:testSQLiteCEROD.jar:sqlite-jdbc-3.7.15-M1.jar " testSQLiteCEROD

 

KAMMU02: the props are: {open_mode=70, date_precision=MILLISECONDS, date_string_format=yyyy-MM-dd HH:mm:ss.SSS, date_class=INTEGER, transaction_mode=DEFFERED, enable_load_extension=true}

Successfully connected to CEROD db [jdbc:sqlite:cerod::abc.db.cerod] using Bitbucket sqlite JDBC Drivers version 3.7.15:

Select query of sqlite is: select * from sqlite_master;

found error: java.sql.SQLException: [SQLITE_NOTADB]  File opened that is not a database file (file is encrypted or is not a database)

 

basically the extension loading mechanism seems to be working after the connection is established, but in my case, the extension should be already available in JAR/JNI environment to query the connection itself.

 

Could you please point me on how I can overcome this challenge ?

 

When I try to load the extension before querying sqlite_master table using below code: 

                            SQLiteDataSource sds = new SQLiteDataSource(sqliteConfig);

                            sds.setLoadExtension(true);

                            sds.setUrl( "jdbc:sqlite:cerod::abc.db.cerod");

                            con =  (SQLiteConnection) sds.getConnection();

                         boolean loadedExtn = statement.execute("SELECT load_extension('libcalm-sqlite3.so','sqlite3CalmFtsInit')");


the JVM crashes with below crash log(/hs_err_pid27383.log)!!


Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)

C  [libpthread.so.0+0x7c6d]  pthread_mutex_lock+0x1d

C  [libcalm-sqlite3.so+0x8ef22]  short+0x1d

C  [libcalm-sqlite3.so+0x2d4ee]  short+0x20

C  [libcalm-sqlite3.so+0x7c93d]  short+0x80

C  [libcalm-sqlite3.so+0x8e862]  short+0x139

C  [sqlite-3.7.15-i386-libsqlitejdbc.so+0x473b2]  Java_org_sqlite_NativeDB_shared_1cache+0x41662

C  [sqlite-3.7.15-i386-libsqlitejdbc.so+0x4759e]  Java_org_sqlite_NativeDB_shared_1cache+0x4184e

C  [sqlite-3.7.15-i386-libsqlitejdbc.so+0x6f492]  Java_org_sqlite_NativeDB_shared_1cache+0x69742

C  [sqlite-3.7.15-i386-libsqlitejdbc.so+0x5b524]  Java_org_sqlite_NativeDB_shared_1cache+0x557d4

C  [sqlite-3.7.15-i386-libsqlitejdbc.so+0x58e5]  Java_org_sqlite_NativeDB_step+0x25

j  org.sqlite.NativeDB.step(J)I+0

j  org.sqlite.DB.execute(Lorg/sqlite/Stmt;[Ljava/lang/Object;)Z+102

j  org.sqlite.Stmt.exec()Z+45

j  org.sqlite.Stmt.execute(Ljava/lang/String;)Z+39

j  testSQLiteCEROD.getCERODConnection()V+122

j  testSQLiteCEROD.main([Ljava/lang/String;)V+0


looks like, creation of statement was not completely successful and executing a query with an invalid Statement reference is leading to this crash !



Below are some details of the CEROD extension that we use: 

 

[root@ca-elm2 iTechnology]# nm -g libcalm-sqlite3.so  |grep sqlite3CalmFtsInit

000000000007f5a0 T sqlite3CalmFtsInit

 

Our libcalm-sqlite3.so is compiled with following options:

gcc  -DNDEBUG -Wall -pthread -fPIC -O3 -ggdb -m32 -D_IGLINUX -D_LINUX -DSQLITE_CORE -DSQLITE_DLL -DSQLITE_THREADSAFE=1 -DSQLITE_THREAD_OVERRIDE_LOCK=0 -DSQLITE_HAS_CODEC=1 -DSQLITE_USE_RC4 -DTEMP_STORE=1 -DSQLITE_ENABLE_CEROD -DSQLITE_ENABLE_FTS3 -I/root /thirdparty/zlib/1.2.3/include -I../include -I../src/fts3 -I../src/calmfts3

our binary is created with following compiler arguments:

g++ -shared -z defs -z combreloc -fPIC -rdynamic  -m32 *.o  lib/release.linux_x86.gnu-4.1.2/libcalm-sqlite3.so

And it is statically loaded as done in main.c

  /* Statically load calmfts2 module */

  if( !db->mallocFailed && rc==SQLITE_OK ){

    rc = sqlite3CalmFtsInit(db);

  }

 

Our working CPP code opens a CEROD using

extern "C" void sqlite3_activate_cerod(const char*);

    // Initialize the cerod extensions to Sqlite

    sqlite3_activate_cerod("7bb07b8d471d642e");

    rc = sqlite3_open(“:cerod::”+dbName.c_str(), &ppdb);


Please me know if you need more information about our CEROD extension.

Regards,
Murali.

Grace B

unread,
Jan 5, 2014, 1:17:00 AM1/5/14
to xer...@googlegroups.com
Hey Kamal,
I apologize for the late reply.

Here is another patch for you. The following will statically load as in C.

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,8 @@
  perl -p -e "s/sqlite3_api;/sqlite3_api = 0;/g" \
     $(SQLITE_AMAL_DIR)/sqlite3ext.h > $(SQLITE_OUT)/sqlite3ext.h
 # insert a code for loading extension functions
- perl -p -e "s/^opendb_out:/  if(!db->mallocFailed && rc==SQLITE_OK){ rc = RegisterExtensionFunctions(db); }\nopendb_out:/;" \
+ perl -p -e "s/^opendb_out:/  if(!db->mallocFailed && rc==SQLITE_OK){ rc = RegisterExtensionFunctions(db); }\n \
+ if(!db->mallocFailed && rc==SQLITE_OK){ rc = sqlite3CalmFtsInit(db); }\nopendb_out:/;" \
     $(SQLITE_AMAL_DIR)/sqlite3.c > $(SQLITE_OUT)/sqlite3.c
  cat src/main/ext/*.c >> $(SQLITE_OUT)/sqlite3.c
  $(CC) -o $@ -c $(CFLAGS) \
Reply all
Reply to author
Forward
0 new messages