package no.java.schedule.provider.dbutil;
import android.content.ContentValues;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteStatement;
import android.provider.BaseColumns;
import no.java.schedule.provider.SessionsContract;
import no.java.schedule.provider.SessionsProvider;
/**
* Provide a lookup cache for {@link no.java.schedule.provider.SessionsContract.Tracks#_ID} and {@link no.java.schedule.provider.SessionsContract.Blocks#_ID},
* which is useful for speeding up doing bulk inserts.
*/
public class LookupCache {
private SQLiteStatement mTrackQuery;
private SQLiteStatement mBlockQuery;
private SQLiteStatement mTrackInsert;
private SQLiteStatement mBlockInsert;
private static final String TRACK_QUERY = ""+
" SELECT " + BaseColumns._ID +
" FROM " + SessionsProvider.TABLE_TRACKS +
" WHERE " + SessionsContract.TracksColumns.TRACK + "=?";
private static final String BLOCK_QUERY = ""+
" SELECT " + BaseColumns._ID +
" FROM " + SessionsProvider.TABLE_BLOCKS+
" WHERE " + SessionsContract.BlocksColumns.TIME_START + "=?" +
" AND " + SessionsContract.BlocksColumns.TIME_END + "=?";
private static final String TRACK_INSERT = ""+
" INSERT INTO " + SessionsProvider.TABLE_TRACKS +
" VALUES (NULL,?,10526880,1)";
private static final String BLOCK_INSERT = "" +
" INSERT INTO " + SessionsProvider.TABLE_BLOCKS +
" VALUES (NULL,?,?)";
public LookupCache(SQLiteDatabase db) {
// Prepare lookup query and insert statements
mTrackQuery = db.compileStatement(TRACK_QUERY);
mBlockQuery = db.compileStatement(BLOCK_QUERY);
mTrackInsert = db.compileStatement(TRACK_INSERT);
mBlockInsert = db.compileStatement(BLOCK_INSERT);
}
/**
* Fill a valid {@link no.java.schedule.provider.SessionsContract.Tracks#_ID} for the provided
* {@link android.content.ContentValues}, querying or creating as needed.
*/
public synchronized void fillTrackId(ContentValues incoming) {
if (!incoming.containsKey(SessionsContract.SessionsColumns.TRACK_ID)){
String[] values = new String[] { incoming.getAsString(SessionsContract.TracksColumns.TRACK)};
long trackId = geRecordId(mTrackQuery, mTrackInsert, values);
incoming.put(SessionsContract.SessionsColumns.TRACK_ID, trackId);
incoming.remove(SessionsContract.TracksColumns.TRACK);
}
}
/**
* Fill a valid {@link no.java.schedule.provider.SessionsContract.Blocks#_ID} for the provided
* {@link android.content.ContentValues}, querying or creating as needed.
*/
public synchronized void fillBlockId(ContentValues incoming) {
if (!incoming.containsKey(SessionsContract.SessionsColumns.BLOCK_ID)) {
final Long startTime = incoming.getAsLong(SessionsContract.BlocksColumns.TIME_START);
final Long endTime = incoming.getAsLong(SessionsContract.BlocksColumns.TIME_END);
Long[] values = new Long[]{ startTime, endTime };
//Log.d("javaBinSchedule", String.format("Looking up slot %s - %s", new Date(startTime), new Date(endTime)));
long blockId = geRecordId(mBlockQuery, mBlockInsert, values);
incoming.put(SessionsContract.SessionsColumns.BLOCK_ID, blockId);
incoming.remove(SessionsContract.BlocksColumns.TIME_START);
incoming.remove(SessionsContract.BlocksColumns.TIME_END);
}
}
private synchronized long geRecordId(SQLiteStatement query, SQLiteStatement insert, Object[] values) {
try {
// Try searching database for mapping
bindValues(query, values);
return query.simpleQueryForLong();
} catch (SQLiteDoneException e) {
// Nothing found, so try inserting new mapping
bindValues(insert, values);
final long result = insert.executeInsert();
if (result != -1){
return result;
} else {
throw new IllegalStateException("Couldn't find or create internal mapping");
}
}
}
private void bindValues(SQLiteStatement query, Object[] values) {
for (int i = 0; i < values.length; i++){
DatabaseUtils.bindObjectToProgram(query, i + 1, values[i]);
}
}
}