MowDownJoe
MowDownJoe

Reputation: 788

SQLite Database isn't being properly filled by insert() statements

So recently, I asked a question about a class I created that extended SQLiteOpenHelper in which the insert() statements were causing errors in Logcat. Recently, I decided to use ddms to pull the database that my app is supposed to act as an interface for then viewed it in a terminal. This was the result:

Pictured: Me viewing a recently pulled version of my app's database Surprisingly to me, I only see one insert statement (from my app, anyway). I have tried multiple inserts from within my app, and only the initial "Hello world!" makes it in.

I'm unsure what the problem is. Can anyone help me figure out why my database is just dead weight? My guess involves the primary key not being properly incremented, but I have no idea why that would be. Also, no errors pop up in Logcat anymore.

I've included the constructors from my class, in case they might be helpful. In addition, I've also included the changes I've made to getNewTaskId() since my previous question:

public NagTasksDatabaseHelper(Context context, String name,
        CursorFactory factory, int version) {
    super(context, name, factory, version);
    // TODO Auto-generated constructor stub
}

/*
public NagTasksDatabaseHelper(Context context, String name,
        CursorFactory factory, int version,
        DatabaseErrorHandler errorHandler) {
    super(context, name, factory, version, errorHandler);
    // TODO Auto-generated constructor stub
    // NOTE TO SELF: Do not use this constructor. DatabaseErrorHandler only exists in Honeycomb onward.
}
*/
public NagTasksDatabaseHelper(Context context, CursorFactory factory){
    super(context, "NagTasks", factory, 1);
}
public NagTasksDatabaseHelper(Context context) //Most frequently use constructor
{
    super(context, "NagTasks", null, 1);
}
public int getNewTaskId(SQLiteDatabase db)
{
    Cursor c = db.rawQuery("SELECT MAX(_id) FROM TASKS", null);
    c.moveToFirst();
    int columnID = c.getColumnIndex(ID);
    if (columnID == -1)
    {
        c.close();
        return 0;
    } else {
        int newTaskID = c.getInt(columnID) +1;
        c.close();
        return newTaskID;
    }
}
public void addTask(String title, String notes)
{
    SQLiteDatabase db = getWritableDatabase();
    int newestID = getNewTaskId(db);
    ContentValues values = new ContentValues();
    values.put("_id", newestID);
    values.put("TASK", title);
    values.put("NOTE", notes);
    values.put("ISCHECKED", 0);
    db.insert("TASKS", null, values);
    db.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE IF NOT EXISTS TASKS (_id INTEGER PRIMARY KEY, TASK TEXT, NOTE TEXT, ISCHECKED INTEGER);");
}

EDIT: I changed the getColumnIndex() lines to getColumnIndexorThrow() and got these errors in LogCat:

06-17 18:47:40.557: V/LoaderManager(329): onLoadComplete: LoaderInfo{44f2ac00 #854 : SQLiteCursorLoader{44f2b950}}
06-17 18:47:40.557: V/LoaderManager(329):   onLoadFinished in SQLiteCursorLoader{44f2b950 id=854}: SQLiteCursor{44ee0800}
06-17 18:47:51.887: D/AndroidRuntime(329): Shutting down VM
06-17 18:47:51.887: W/dalvikvm(329): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
06-17 18:47:51.907: E/AndroidRuntime(329): FATAL EXCEPTION: main
06-17 18:47:51.907: E/AndroidRuntime(329): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mowdownDevelopments.nagTasks/com.mowdownDevelopments.nagTasks.NagTasksAddTasksActivity}: java.lang.IllegalArgumentException: column '_id' does not exist
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.os.Looper.loop(Looper.java:123)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread.main(ActivityThread.java:4627)
06-17 18:47:51.907: E/AndroidRuntime(329):  at java.lang.reflect.Method.invokeNative(Native Method)
06-17 18:47:51.907: E/AndroidRuntime(329):  at java.lang.reflect.Method.invoke(Method.java:521)
06-17 18:47:51.907: E/AndroidRuntime(329):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
06-17 18:47:51.907: E/AndroidRuntime(329):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
06-17 18:47:51.907: E/AndroidRuntime(329):  at dalvik.system.NativeStart.main(Native Method)
06-17 18:47:51.907: E/AndroidRuntime(329): Caused by: java.lang.IllegalArgumentException: column '_id' does not exist
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:314)
06-17 18:47:51.907: E/AndroidRuntime(329):  at com.mowdownDevelopments.nagTasks.NagTasksDatabaseHelper.getNewTaskId(NagTasksDatabaseHelper.java:127)
06-17 18:47:51.907: E/AndroidRuntime(329):  at com.mowdownDevelopments.nagTasks.NagTasksDatabaseHelper.getNewTaskId(NagTasksDatabaseHelper.java:141)
06-17 18:47:51.907: E/AndroidRuntime(329):  at com.mowdownDevelopments.nagTasks.NagTasksAddTaskFragment.onActivityCreated(NagTasksAddTaskFragment.java:42)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:891)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1810)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:501)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.Activity.performStart(Activity.java:3781)
06-17 18:47:51.907: E/AndroidRuntime(329):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636)
06-17 18:47:51.907: E/AndroidRuntime(329):  ... 11 more
06-17 18:47:58.947: I/Process(329): Sending signal. PID: 329 SIG: 9

...So, how does "_id" not exist? It would explain how the old version was always passing 0.

Upvotes: 0

Views: 407

Answers (3)

MowDownJoe
MowDownJoe

Reputation: 788

So, it turns out the problem was actually that the column name being passed to getColumnIndex() was, in fact, non-existent. So, the easy fix is to assign an alias to MAX(_id)...

public int getNewTaskId(SQLiteDatabase db)
{
    Cursor c = db.rawQuery("SELECT MAX(_id) AS max FROM TASKS", null);
    c.moveToFirst();
    int columnID = c.getColumnIndex("max");
    if (columnID == -1)
    {
        c.close();
        return 0;
    } else {
        int newTaskID = c.getInt(columnID) +1;
        c.close();
        return newTaskID;
    }
}

This fixes the issue.

Upvotes: 0

Simon Dorociak
Simon Dorociak

Reputation: 33495

My guess involves the primary key not being properly incremented, but I have no idea why that would be.

So your _id is not automatic incremented because you didn't specify it's incrementing. So replace your onCreate method with this:

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE TASKS (_id INTEGER PRIMARY KEY AUTOINCREMENT, TASK TEXT, NOTE TEXT, ISCHECKED INTEGER);");
}

You have to specify AUTOINCREMENT for your _id.

You didn't add your code where you are inserting data but you should use for this approach insert() method of SQLiteDatabase combinated with ContentValues.

public boolean addNewData(String name, String address) {
   ContentValues data = new ContentValues();
   data.put("NameColumn", name);
   data.put("AddressColumn", address);
   db.insert("TASKS", "NameColumn", data);
}

Also you should call close() method of SQLite in onStop or onDestroy method. Just add here more fragments of code or whole implementation.


EDIT:

Example of getNewTask

public int getNewTask(SQLiteDatabase db) {
        String SELECT_QUERY = "SELECT MAX(_id) FROM TASKS";
        Cursor c = db.rawQuery(SELECT_QUERY, null);
        if (c.getCount() > 0) {
            c.moveToFirst();
            int i = c.getInt(0);
            if (i > 0) {
                return i;
            }   
            else {
                return 0;
            }
        }
        else {
            return 0;
        }
    }

Upvotes: 1

Doug Currie
Doug Currie

Reputation: 41170

Shouldn't that be

int columnID = c.getColumnIndex("_id"); // not ID

You're always getting 0 back from getNewTaskId

Upvotes: 0

Related Questions