Mates i m getting this error message while using sqlite3 native c library (JNI) through NDK
Please suggest me where i m doing wrong
01-29 11:04:19.532: E/Error(2023): SQLite3.Exception: database disk image is malformed
01-29 11:04:19.544: E/dalvikvm(2023): JNI ERROR (app bug): accessed stale local reference 0x7f00001d (index 7 in a table of size 7)
01-29 11:04:19.544: E/dalvikvm(2023): VM aborting
01-29 11:04:19.544: A/libc(2023): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 2023 (abdkosh.android)
Here is my block of code which is generating this error
public ArrayList<String> getDefinations(String query, int column_index)
{
ArrayList<String> words = new ArrayList<String>();
MatrixCursor mcursor = null;
try {
Stmt stmt = getDB2().prepare(query);
if (stmt.step()) {
stmt.get_cursor().moveToFirst();
mcursor = stmt.get_cursor();
try {
mcursor.moveToFirst();
do {
words.add(mcursor.getString(column_index));
} while (mcursor.moveToNext());
} catch (IndexOutOfBoundsException e) {
if (MainActivity.logcat_status) {
Log.e("Error", e + "");
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
if (MainActivity.logcat_status) {
Log.e("Error", e + "");
}
}
Here is the query i m trying to execute
"select pos, definition, sample FROM word INNER JOIN sense ON word.wordid = sense.wordid INNER JOIN synset ON sense.synsetid = synset.synsetid LEFT JOIN sample ON sample.synsetid = synset.synsetid WHERE lemma = 'life'"
Actually that word "life" is not in the dictionary so
stmt.get_cursor().moveToFirst();
goes to first record set (1st row) which actually doesn't exits and after this line through the exception and app is closed by dalvikvm.
This is was exactly happening in this case.
So my question is how "stmt" will know that there is no record set with specific word.
Here is the link where i have downloaded and using the jni(c) wrapper classses http://www.sqlite.org/snapshot/sqlite-amalgamation-201401290146.zip and then created "libsqlite3_jni.so" file via NDK
link of handler class i m using http://code.google.com/p/sqlite3-android/ for interacting to c code.
IMO stmt.step() method is doing the problem only when there is no record set.
Here is my complete Stmt.java
package SQLite3;
import com.shabdkosh.android.MainActivity;
import android.util.Log;
/**
* Class to represent compiled SQLite3 statement.
*
* Note, that all native methods of this class are not synchronized, i.e. it is
* up to the caller to ensure that only one thread is in these methods at any
* one time.
*/
public class Stmt {
/**
* Internal handle for the SQLite3 statement.
*/
private long handle = 0;
/**
* Internal last error code for prepare()/step() methods.
*/
protected int error_code = 0;
/**
* Prepare the next SQL statement for the Stmt instance.
*
* @return true when the next piece of the SQL statement sequence has been
* prepared, false on end of statement sequence.
*/
public native boolean prepare() throws SQLite3.Exception;
/**
* Perform one step of compiled SQLite3 statement.
*
* Example:<BR>
*
* <PRE>
* ...
* try {
* Stmt s = db.prepare("select * from x; select * from y;");
* s.bind(...);
* ...
* s.bind(...);
* while (s.step(cb)) {
* Object o = s.value(...);
* ...
* }
* // s.reset() for re-execution or
* // s.prepare() for the next piece of SQL
* while (s.prepare()) {
* s.bind(...);
* ...
* s.bind(...);
* while (s.step(cb)) {
* Object o = s.value(...);
* ...
* }
* }
* } catch (SQLite.Exception e) {
* s.close();
* }
* </PRE>
*
* @return true when row data is available, false on end of result set.
*/
public native boolean step() throws SQLite3.Exception;
/**
* Close the compiled SQLite3 statement.
*/
public native void close() throws SQLite3.Exception;
/**
* Reset the compiled SQLite3 statement without clearing parameter bindings.
*/
public native void reset() throws SQLite3.Exception;
/**
* Clear all bound parameters of the compiled SQLite3 statement.
*/
public native void clear_bindings() throws SQLite3.Exception;
/**
* Bind positional integer value to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param value
* value of parameter
*/
public native void bind(int pos, int value) throws SQLite3.Exception;
/**
* Bind positional long value to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param value
* value of parameter
*/
public native void bind(int pos, long value) throws SQLite3.Exception;
/**
* Bind positional double value to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param value
* value of parameter
*/
public native void bind(int pos, double value) throws SQLite3.Exception;
/**
* Bind positional byte array to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param value
* value of parameter, may be null
*/
public native void bind(int pos, byte[] value) throws SQLite3.Exception;
/**
* Bind positional String to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param value
* value of parameter, may be null
*/
public native void bind(int pos, String value) throws SQLite3.Exception;
/**
* Bind positional SQL null to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
*/
public native void bind(int pos) throws SQLite3.Exception;
/**
* Bind positional zero'ed blob to compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @param length
* byte size of zero blob
*/
public native void bind_zeroblob(int pos, int length)
throws SQLite3.Exception;
/**
* Return number of parameters in compiled SQLite3 statement.
*
* @return int number of parameters
*/
public native int bind_parameter_count() throws SQLite3.Exception;
/**
* Return name of parameter in compiled SQLite3 statement.
*
* @param pos
* parameter index, 1-based
* @return String parameter name
*/
public native String bind_parameter_name(int pos) throws SQLite3.Exception;
/**
* Return index of named parameter in compiled SQLite3 statement.
*
* @param name
* of parameter
* @return int index of parameter, 1-based
*/
public native int bind_parameter_index(String name)
throws SQLite3.Exception;
/**
* Retrieve integer column from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return int column value
*/
public native int column_int(int col) throws SQLite3.Exception;
/**
* Retrieve long column from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return long column value
*/
public native long column_long(int col) throws SQLite3.Exception;
/**
* Retrieve double column from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return double column value
*/
public native double column_double(int col) throws SQLite3.Exception;
/**
* Retrieve blob column from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return byte[] column value
*/
public native byte[] column_bytes(int col) throws SQLite3.Exception;
/**
* Retrieve string column from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String column value
*/
public native String column_string(int col) throws SQLite3.Exception;
/**
* Retrieve column type from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return column type code, e.g. SQLite.Constants.SQLITE_INTEGER
*/
public native int column_type(int col) throws SQLite3.Exception;
/**
* Retrieve number of columns of exec'ed SQLite3 statement.
*
* @return int number of columns
*/
public native int column_count() throws SQLite3.Exception;
/**
* Retrieve column data as object from exec'ed SQLite3 statement.
*
* @param col
* column number, 0-based
* @return Object or null
*/
public Object column(int col) throws SQLite3.Exception {
switch (column_type(col)) {
case Constants.SQLITE_INTEGER:
return new Long(column_long(col));
case Constants.SQLITE_FLOAT:
return new Double(column_double(col));
case Constants.SQLITE_BLOB:
return column_bytes(col);
case Constants.SQLITE3_TEXT:
return column_string(col);
}
return null;
}
/**
* Return name of column of SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String or null
*/
public native String column_name(int col) throws SQLite3.Exception;
/**
* Return table name of column of SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String or null
*/
public native String column_table_name(int col) throws SQLite3.Exception;
/**
* Return database name of column of SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String or null
*/
public native String column_database_name(int col) throws SQLite3.Exception;
/**
* Return declared column type of SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String or null
*/
public native String column_decltype(int col) throws SQLite3.Exception;
/**
* Return origin column name of column of SQLite3 statement.
*
* @param col
* column number, 0-based
* @return String or null
*/
public native String column_origin_name(int col) throws SQLite3.Exception;
/**
* Return statement status information.
*
* @param op
* which counter to report
* @param flg
* reset flag
* @return counter
*/
public native int status(int op, boolean flg);
/**
* Destructor for object.
*/
protected native void finalize();
/**
* Internal native initializer.
*/
private static native void internal_init();
static {
internal_init();
}
protected String[] mColumns = null;
public String[] column_names(){
if(mColumns == null){
int colCount = 0;
try {
colCount = column_count();
} catch (Exception e1) {
// TODO Auto-generated catch block
if(MainActivity.logcat_status){
Log.e("Error", e1+"");}
}
mColumns = new String[colCount];
for(int i=0; i<colCount;i++){
try {
mColumns[i] = column_name(i);
} catch (Exception e) {
// TODO Auto-generated catch block
if(MainActivity.logcat_status){
Log.e("Error", e+"");}
}
}
}
return mColumns;
}
public int column_index(String col_name){
String[] names = column_names();
int col_count = names.length;
int i;
for(i=0; i < col_count; i++){
if(col_name.equals(names[i])) return i;
}
return -1;
}
public MatrixCursor get_cursor(){
return get_cursor(20);
}
public MatrixCursor get_cursor(int capacity){
MatrixCursor cursor = new MatrixCursor(column_names(), capacity);
try {
int colCount = column_count();
while(step()){
Object[] rowObject = new Object[colCount];
for(int i=0; i < colCount; i++){
rowObject[i] = column_string(i);
}
cursor.addRow(rowObject);
}
} catch (Exception e) {
// TODO Auto-generated catch block
if(MainActivity.logcat_status){
Log.e("Error", e+"");}
}
return cursor;
}
}
Thanks in advance
@Manish. I have edited your sample code. Please use cursor.getCount() like this. Thankyou