package nl.sense_os.service.storage;
import java.util.ArrayList;
import nl.sense_os.service.constants.SensorData.DataPoint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;
/**
* Class that manages a store for sensor data points in a persistent SQLite database. Helper class
* for {@link LocalStorage}.
*
* @author Steven Mulder <steven@sense-os.nl>
*/
public class SQLiteStorage {
public static String TAG = "SQLiteStorage";
/**
* Limit for number of query results
*/
public static final int QUERY_RESULTS_LIMIT = 10000;
/**
* Limit for number of query results in epi-mode (very low because epi mode data points can be
* huge)
*/
public static final int QUERY_RESULTS_LIMIT_EPI_MODE = 60;
private Context context;
private DbHelper dbHelper;
public SQLiteStorage(Context context) {
this.context = context;
dbHelper = new DbHelper(context);
}
/**
* Efficiently inserts a collection of rows in the database
*
* @param c
* Cursor with rows of data points
* @return The number of data points that were inserted
*/
public int bulkInsert(Cursor c) {
// prepare SQL insert statement
StringBuilder sb = new StringBuilder("INSERT INTO " + DbHelper.TABLE + " ");
sb.append("(" + DataPoint.SENSOR_NAME);
sb.append(", " + DataPoint.DISPLAY_NAME);
sb.append(", " + DataPoint.SENSOR_DESCRIPTION);
sb.append(", " + DataPoint.VALUE_PATH);
sb.append(", " + DataPoint.DATA_TYPE);
sb.append(", " + DataPoint.TIMESTAMP);
sb.append(", " + DataPoint.VALUE);
sb.append(", " + DataPoint.DEVICE_UUID);
sb.append(", " + DataPoint.TRANSMIT_STATE + ")");
sb.append(" VALUES (?,?,?,?,?,?,?,?);");
// get database
SQLiteDatabase db = dbHelper.getWritableDatabase();
int insertCount = 0;
// do transaction
try {
db.beginTransaction();
// execute an insert statement for each row
c.moveToFirst();
SQLiteStatement statement = db.compileStatement(sb.toString());
while (!c.isAfterLast()) {
statement.bindString(1, c.getString(c.getColumnIndex(DataPoint.SENSOR_NAME)));
statement.bindString(2, c.getString(c.getColumnIndex(DataPoint.DISPLAY_NAME)));
statement.bindString(3, c.getString(c.getColumnIndex(DataPoint.SENSOR_DESCRIPTION)));
statement.bindString(4, c.getString(c.getColumnIndex(DataPoint.DATA_TYPE)));
statement.bindLong(5, c.getLong(c.getColumnIndex(DataPoint.TIMESTAMP)));
statement.bindString(6, c.getString(c.getColumnIndex(DataPoint.VALUE)));
statement.bindString(7, c.getString(c.getColumnIndex(DataPoint.DEVICE_UUID)));
statement.bindLong(8, c.getInt(c.getColumnIndex(DataPoint.TRANSMIT_STATE)));
statement.bindString(9, c.getString(c.getColumnIndex(DataPoint.VALUE_PATH)));
statement.execute();
insertCount++;
c.moveToNext();
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
return insertCount;
}
public int bulkInsert2(ArrayList<ContentValues> values){
// get database
SQLiteDatabase db = dbHelper.getWritableDatabase();
int insertCount = 0;
// do transaction
try {
db.beginTransaction();
if (null != values && values.size() > 0){
for (int i = values.size()-1; i >= 0 ; i --){
ContentValues val = values.remove(i);
if (null != val && val.size() > 0){
db.insert(DbHelper.TABLE, null, val);
insertCount++;
}
else
Log.d(TAG, "null or empty");
}
Log.d(TAG, "Transaction successful");
db.setTransactionSuccessful();
}
} finally {
db.endTransaction();
}
return insertCount;
}
/**
* Deletes rows from the database
*
* @param where
* @param selectionArgs
* @return The number of rows affected
*/
public int delete(String where, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int result = db.delete(DbHelper.TABLE, where, selectionArgs);
return result;
}
/**
* Inserts a row into the database.
*
* @param values
* @return
*/
public long insert(ContentValues values) {
// insert in database
SQLiteDatabase db = dbHelper.getWritableDatabase();
long rowId = db.insert(DbHelper.TABLE, DataPoint.SENSOR_NAME, values);
return rowId;
}
/**
* Query the database
*
* @param projection
* @param where
* @param selectionArgs
* @param orderBy
* How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY
* itself). Passing null will use the default sort order, which orders by descending
* timestamp.
* @return Cursor with the result set
*/
public Cursor query(String[] projection, String where, String[] selectionArgs, String orderBy) {
// limit parameter depends on epi mode preference
// SharedPreferences pref = context.getSharedPreferences(SensePrefs.MAIN_PREFS,
// Context.MODE_PRIVATE);
// String limitStr = "" + QUERY_RESULTS_LIMIT;
// if (pref.getBoolean(Motion.EPIMODE, false)) {
// limitStr = "" + QUERY_RESULTS_LIMIT_EPI_MODE;
// }
// set default ordering
if (null == orderBy) {
orderBy = DataPoint.TIMESTAMP + " ASC";
}
// do query
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query(DbHelper.TABLE, projection, where, selectionArgs, null, null,
orderBy, null /*limitStr*/);
return cursor;
}
/**
* Updates rows in the database
*
* @param newValues
* @param where
* @param selectionArgs
* @return the number of rows affected
*/
public int update(ContentValues newValues, String where, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
int result = db.update(DbHelper.TABLE, newValues, where, selectionArgs);
return result;
}
}