Home » Android » android – SQLite unable to open database file (code 14) on frequent "SELECT" query

android – SQLite unable to open database file (code 14) on frequent "SELECT" query

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have following class “Singleton” to handle SQLite connection and to make sure to have 1 instance of connection for whole process/app:

public class DBController {
  private static DBController instance = new DBController();
  private static DBHelper dbHelper;
  public static DBController getInstance()
  {
    return instance;
  }
  public SQLiteDatabase dbOpen(Context context)
  {
    if(dbHelper == null)
        dbHelper = new DBHelper(context);
    return dbHelper.getWritableDatabase();
  }
}

And DBHelper class itself:

public class DBHelper extends SQLiteOpenHelper {

  public DBHelper(Context context) {
    super(context, "database.db", null, 1);
  }
  @Override
  public void onCreate(SQLiteDatabase db) {
    final String position = "CREATE TABLE test (" +
            "test TEXT NOT NULL);";
    db.execSQL(position);
  }
}

When I frequently try to “SELECT” some info from database I am receiving following error:

SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
SQLiteLog: (14) os_unix.c:31278: (24) open(/data/user/0/uz.mycompany.myapp/databases/database.db-journal) - 
SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
SQLiteLog: (14) os_unix.c:31278: (24) open(/data/user/0/uz.mycompany.myapp/databases/database.db-journal) - 
SQLiteLog: (14) statement aborts at 29: [SELECT * FROM test WHERE test='testdata1'] unable to open database file
SQLiteQuery: exception: unable to open database file (code 14); query: SELECT * FROM test WHERE test='testdata1'
android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)

I am running following code to execute query:

public String getData(Context context)
{
    SQLiteDatabase _db = dbOpen(context);
    Cursor c = _db.rawQuery("SELECT * FROM test WHERE test='testdata1'", null);
    return getDataFromCursor(c).get(0); //gets data from cursor and returns first one
}

How can I manage/improve my database connection to overcome/avoid this problem?

How to&Answers:

before executing any query to this stuff (You should open your database). Close db after completion the task.

private DBHelper dbHelper = new DBHelper(context);

try {
    _db = dbHelper.getWritableDatabase();
} catch (SQLException s) {
    new Exception("Error with DB Open");
}

// Then write your query now…. and then close the db.

_db.close();

You can check out my git link1 git link2

Answer:

As an addition, I believe that having too many cursors, and thus open’s, can also result in the same “unable to open database file error”. (in the following code, there’s 507 rows in the shoplistcursor, so that was over 1500 cursors used/reused in total)

I was getting the same message. As per :-

10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) os_unix.c:30046: (24) open(/data/data/mjt.shopper/databases/Shopper-journal) - 
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) os_unix.c:30046: (24) open(/data/data/mjt.shopper/databases/Shopper-journal) - 
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) statement aborts at 24: [SELECT *  FROM productusage WHERE productailseref = 60 AND productproductref = 75 ;] unable to open database file
10-29 19:57:00.902 12845-12845/mjt.shopper E/SQLiteQuery: exception: unable to open database file (code 14); query: SELECT *  FROM productusage WHERE productailseref = 60 AND productproductref = 75 ;
10-29 19:57:00.902 12845-12845/mjt.shopper D/AndroidRuntime: Shutting down VM
10-29 19:57:00.903 12845-12845/mjt.shopper E/AndroidRuntime: FATAL EXCEPTION: main

The code, that was in error, was :-

 SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } 
            if(shoplistcursor.isLast()) {
                prdusecsr.close();
                aislecsr.close();
                productcsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
}

The cure was to close the cursors on each iteration. As per :-

 SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } else {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
    }

Answer:

Your code re-opens the database every time dbOpen() is called.

An SQLite database object is quite lightweight; it does not really make sense to keep closing and re-opening it.

You already have your singleton; just store a single SQLiteDatabase reference there.

Answer:

I am using cursor for a big query where cursor hit the DB more than 1350 times by three seperate ‘QUERY’ within 800 milliseconds. So I got the error (android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)). I solved it by closing the cursor before start a new query. That resolves my problem. Hope it will work the more big query than mine.

String data_query = "SELECT * FROM test WHERE id= " + c_id + " AND memberId = " + memberId;           
Cursor cu_cu = userHelper.getData(data_query);
float cu_cu_count = cu_cu.getCount();
System.out.println("ALL ANSWER COUNT : " + cu_cu_count);
cu_cu.close();

Answer:

In your Application class

public static SQLiteDatabase database;

@Override
public void onCreate() {
    super.onCreate();

    SQLiteOpenHelper helper = Database.getInstance(getApplicationContext());

    if (database == null) {
        database = helper.getWritableDatabase();
    } else {
        if (!database.isOpen()) {
            database = helper.getWritableDatabase();
        }
    }
}

In your queries class

 public DataSources() {
    database = ApplicationController.database;
 }

That way you create a writeable db object once