Skip to content

Instantly share code, notes, and snippets.

@soeminnminn
Last active February 8, 2022 12:33
Show Gist options
  • Save soeminnminn/b0a648c528bd13b5b8f3 to your computer and use it in GitHub Desktop.
Save soeminnminn/b0a648c528bd13b5b8f3 to your computer and use it in GitHub Desktop.
SQLite table warpper for android
package com.s16.data;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.BaseColumns;
import android.text.TextUtils;
public abstract class AbstractDataProvider extends ContentProvider {
protected static final String TAG = AbstractDataProvider.class.getSimpleName();
public static final String METHOD_BACKUP = "backup";
public static final String METHOD_RESTORE = "restore";
public static final String METHOD_SAVE = "save";
public static final String METHOD_GETMAXID = "getMaxId";
public static final String RETURN_KEY = "result";
private static final String DEFAULT_DATABASE_NAME = "database";
private static final int DEFAULT_DATABASE_VERSION = 1;
protected static int LOWORD(int val) { return val & 0xffff; }
protected static int HIWORD(int val) { return (val >> 0x10) & 0xffff; }
protected static int MAKELPARAM(int low, int high) { return ((high << 0x10) | (low & 0xffff)); }
private SQLiteDatabase mDatabase;
private String mDatabasePath;
private class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, mDatabaseName, null, mDatabaseVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
if (mTables == null) return;
for(int i = 0; i < mTables.length; i++) {
mTables[i].create(db);
}
onCreateHelper(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (mTables == null) return;
for(int i = 0; i < mTables.length; i++) {
mTables[i].drop(db);
}
onUpdateHelper(db, oldVersion, newVersion);
onCreate(db);
}
}
private final String mDatabaseName;
private final int mDatabaseVersion;
private final DataTable[] mTables;
private DatabaseHelper mDbHelper;
public AbstractDataProvider() {
super();
mDatabaseName = getDatabaseName();
mDatabaseVersion = getDatabaseVersion();
mTables = getAllTables();
}
protected String getDatabaseName() {
return DEFAULT_DATABASE_NAME;
}
protected int getDatabaseVersion() {
return DEFAULT_DATABASE_VERSION;
}
protected abstract Uri getContentUri();
protected abstract DataTable[] getAllTables();
protected abstract DataTable getTable(Uri uri);
protected abstract boolean useDistinct(Uri uri);
@Override
public abstract String getType(Uri uri);
protected void onCreateHelper(SQLiteDatabase db) {
}
protected void onUpdateHelper(SQLiteDatabase db, int oldVersion, int newVersion) {
}
protected DataTable getTable(String tableName) {
if (mTables == null) return null;
for(int i = 0; i < mTables.length; i++) {
if (mTables[i].getTableName().equals(tableName)) {
return mTables[i];
}
}
return null;
}
protected SQLiteDatabase getDatabase() {
if (mDatabase == null) {
if(mDbHelper == null) return null;
try {
mDatabase = mDbHelper.getWritableDatabase();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
return mDatabase;
}
protected File getDatabasePath() {
if (!TextUtils.isEmpty(mDatabasePath)) {
return new File(mDatabasePath);
}
return null;
}
public boolean isOpen() {
SQLiteDatabase database = getDatabase();
return (database != null) && (database.isOpen());
}
public void close() {
if (mDbHelper != null) mDbHelper.close();
}
@Override
public boolean onCreate() {
if(mDbHelper == null) {
mDbHelper = new DatabaseHelper(getContext());
}
SQLiteDatabase database = getDatabase();
if (database != null) {
mDatabasePath = database.getPath();
}
return (database != null);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor result = null;
final SQLiteDatabase database = getDatabase();
if (database == null) return result;
boolean distinct = useDistinct(uri);
DataTable table = getTable(uri);
if (table != null) {
if (projection == null) {
result = table.from(database).where(selection, selectionArgs).query(distinct, sortOrder, null);
} else {
result = table.from(database).where(selection, selectionArgs).query(distinct, projection, sortOrder, null);
}
if (result != null) {
result.moveToFirst();
result.setNotificationUri(getContext().getContentResolver(), uri);
}
}
return result;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase database = getDatabase();
if (database == null) return null;
long rowID = 0;
DataTable table = getTable(uri);
if (table != null) {
DataTable.DataColumn idColunm = table.getPrimaryKey();
String idColunmName = idColunm != null ? idColunm.getName() : BaseColumns._ID;
if (values.containsKey(idColunmName)) {
long id = values.getAsLong(idColunmName);
if (id < 0) {
id = getMaxId(table.getTableName(), idColunmName);
values.put(idColunmName, id + 1);
}
}
rowID = table.from(database).insert(values);
}
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(uri, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final SQLiteDatabase database = getDatabase();
if (database == null) return 0;
int count = 0;
DataTable table = getTable(uri);
if (table != null) {
if (!TextUtils.isEmpty(selection))
count = table.from(database).where(selection, selectionArgs).delete();
else
count = table.from(database).delete();
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
final SQLiteDatabase database = getDatabase();
if (database == null) return 0;
int count = 0;
DataTable table = getTable(uri);
if (table != null) {
if (!TextUtils.isEmpty(selection))
count = table.from(database).where(selection, selectionArgs).update(values);
else
count = table.from(database).update(values);
}
getContext().getContentResolver().notifyChange(uri, null);
return (int)count;
}
public int save(String tableName, ContentValues values, String selection,
String[] selectionArgs) {
final SQLiteDatabase database = getDatabase();
if (database == null) return 0;
int count = 0;
long rowID = 0;
DataTable table = getTable(tableName);
if (table != null) {
DataTable.DataColumn idColunm = table.getPrimaryKey();
String idColunmName = idColunm != null ? idColunm.getName() : BaseColumns._ID;
count = table.from(database).where(selection, selectionArgs).update(values);
if (count == 0) {
if (values.containsKey(idColunmName)) {
long id = values.getAsLong(idColunmName);
if (id < 0) {
id = getMaxId(table.getTableName(), idColunmName);
values.put(idColunmName, id + 1);
}
}
rowID = table.from(database).insert(values);
} else {
getContext().getContentResolver().notifyChange(table.getUri(), null);
}
}
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(getContentUri(), rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return 1;
}
return count;
}
public long getMaxId(String tableName, String idColumn) {
final SQLiteDatabase database = getDatabase();
if (database == null) return 0L;
long id = 0L;
Cursor idCursor = database.rawQuery("SELECT MAX(" + idColumn + ") FROM " + tableName + " LIMIT 1;" , null);
if (idCursor != null) {
if (idCursor.moveToFirst()) {
id = idCursor.getInt(0);
}
idCursor.close();
}
return id;
}
@Override
public int bulkInsert(Uri uri, ContentValues[] insertValuesArray) {
final SQLiteDatabase database = getDatabase();
if (database == null) return -1;
if (insertValuesArray == null) return -1;
DataTable table = getTable(uri);
if (table != null) {
DataTable.DataColumn idColunm = table.getPrimaryKey();
String idColunmName = idColunm != null ? idColunm.getName() : BaseColumns._ID;
int count = insertValuesArray.length;
database.beginTransaction();
for (int i=0; i<count; i++) {
int resultCount = 0;
ContentValues values = insertValuesArray[i];
if (values.containsKey(idColunmName)) {
long id = values.getAsLong(idColunmName);
if (id > 0) {
String selection = "`" + idColunmName + "` IS ?";
resultCount = table.from(database).where(selection, new String[] { String.valueOf(id) }).update(values);
}
}
if (resultCount == 0) {
table.from(database).insert(values);
}
}
database.setTransactionSuccessful();
database.endTransaction();
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
return -1;
}
@Override
public Bundle call(String method, String arg, Bundle extras) {
Bundle resultBundle = new Bundle();
if (METHOD_BACKUP.equals(method)) {
File srcDb = getDatabasePath();
File destDb = new File(arg);
boolean result = copyFile(srcDb, destDb);
resultBundle.putBoolean(RETURN_KEY, result);
} else if (METHOD_RESTORE.equals(method)) {
File srcDb = new File(arg);
File destDb = getDatabasePath();
boolean result = copyFile(srcDb, destDb);
resultBundle.putBoolean(RETURN_KEY, result);
} else if (METHOD_SAVE.equals(method)) {
ContentValues values = new ContentValues();
String[] columns = extras.getStringArray("columns");
for(String col : columns) {
values.put(col, extras.getString(col));
}
String selection = extras.getString("selection", null);
String[] selectionArgs = extras.getStringArray("selectionArgs");
int result = save(arg, values, selection, selectionArgs);
resultBundle.putInt(RETURN_KEY, result);
} else if (METHOD_GETMAXID.equals(method)) {
long id = getMaxId(arg, BaseColumns._ID);
resultBundle.putLong(RETURN_KEY, id);
}
return resultBundle;
}
@SuppressWarnings("resource")
protected boolean copyFile(File srcFile, File destFile) {
try {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite() && sd.canRead()) {
FileChannel src = new FileInputStream(srcFile).getChannel();
FileChannel dst = new FileOutputStream(destFile).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
package com.s16.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
public class DataTable implements Iterable<DataTable.DataColumn> {
protected static final String VND_PREFIX = "vnd.datatable";
protected static final String NAME_QUOTES = "`";
protected static final String[] DATA_TYPES = new String[] {
"VARCHAR", "NVARCHAR", "TEXT", "INTEGER", "REAL", "FLOAT",
"BOOLEAN", "CLOB", "BLOB", "TIMESTAMP", "NUMERIC",
"VARYING CHARACTER", "NATIONAL VARYING CHARACTER", "NONE"
};
private final Uri mBaseContentUri;
private final String mTableName;
private int mId;
private final ArrayList<DataColumn> mColumns = new ArrayList<DataColumn>();
private SQLiteDatabase mDatabase;
private Executor mExecutor;
private List<TableJoiner> mJoinerList;
public static DataTable newInstance(Uri baseContentUri, String tableName) {
return new DataTable(baseContentUri, tableName);
}
public static DataTable newInstance(Uri baseContentUri, int id, String tableName) {
return new DataTable(baseContentUri, id, tableName);
}
private DataTable(Uri baseContentUri, String tableName) {
this(baseContentUri, tableName.hashCode(), tableName);
}
private DataTable(Uri baseContentUri, int id, String tableName) {
if (baseContentUri == null) {
throw new NullPointerException();
}
mBaseContentUri = baseContentUri;
mTableName = tableName;
mExecutor = new Executor(getTableName(), false);
mJoinerList = new ArrayList<TableJoiner>();
mId = id;
}
public int getId() {
return mId;
}
public DataTable setId(int id) {
mId = id;
return this;
}
protected void assertTable() {
if (mTableName == null) {
throw new IllegalStateException("Table not specified");
}
if (mColumns == null || mColumns.size() == 0) {
throw new IllegalStateException("Columns not specified");
}
}
protected void assertDatabase() {
if (mDatabase == null) {
throw new IllegalStateException("Databse not specified");
}
}
protected boolean checkHasPrimaryKey() {
if (mColumns == null || mColumns.size() == 0) {
return false;
}
int keyCount = 0;
for(int i = 0; i < mColumns.size(); i++) {
if (mColumns.get(i).isPrimaryKey()) {
keyCount++;
}
}
if (keyCount > 1) {
throw new IllegalStateException("Table does not allow more then one primary key.");
}
return (keyCount == 1);
}
@Override
public String toString() {
String value = mTableName;
value += " (";
for(int i = 0; i < mColumns.size(); i++) {
if (i == 0) value += ", ";
value += mColumns.toString();
}
value += ")";
return value;
}
@Override
public boolean equals(Object o) {
if (o instanceof DataTable) {
DataTable other = (DataTable)o;
return mTableName.equals(other.getTableName());
}
return super.equals(o);
}
/**
* Get the String of Uri.
*/
public String getUriString() {
return getUri().toString();
}
/**
* Get the Uri for this table.
*/
public Uri getUri() {
Uri.Builder builder = mBaseContentUri.buildUpon();
builder.appendPath(mTableName);
return builder.build();
}
/**
* Get the Uri for this table.
*/
public Uri getUri(String uriString) {
if (TextUtils.isEmpty(uriString)) return null;
Uri.Builder builder = Uri.parse(uriString).buildUpon();
builder.appendPath(mTableName);
return builder.build();
}
/**
* Get the name of table.
*/
public String getTableName() {
return mTableName;
}
/**
* Add primary key column to table.
*/
public DataTable addPrimaryKey(String columnName, String sqlDataType, boolean isAutoIncrement) {
return addColumn(columnName, sqlDataType, true, false, isAutoIncrement, null);
}
/**
* Add column to table.
*/
private DataTable addColumn(DataColumn column) {
column.mIndex = mColumns.size();
mExecutor.putColumn(column);
mColumns.add(column);
return this;
}
/**
* Add column to table.
*/
public DataTable addColumn(String columnName, String sqlDataType) {
return addColumn(columnName, sqlDataType, false, true, false, null);
}
/**
* Add column to table.
*/
public DataTable addColumn(String columnName, String sqlDataType, boolean isAllowNull) {
return addColumn(columnName, sqlDataType, false, isAllowNull, false, null);
}
/**
* Add column to table.
*/
public DataTable addColumn(String columnName, String sqlDataType, boolean isAllowNull, String defaultValue) {
return addColumn(columnName, sqlDataType, false, isAllowNull, false, defaultValue);
}
/**
* Add column to table.
*/
public DataTable addColumn(String columnName, String sqlDataType, boolean isPrimaryKey
, boolean isAllowNull, boolean isAutoIncrement, String defaultValue) {
if (isPrimaryKey && checkHasPrimaryKey()) {
throw new IllegalStateException("Table does not allow more then one primary key.");
}
DataColumn column = new DataColumn(this, columnName, sqlDataType);
column.mIsPrimaryKey = isPrimaryKey;
column.mIsAllowNull = isAllowNull;
column.mIsAutoIncrement = isAutoIncrement;
column.mDefaultValue = defaultValue;
return addColumn(column);
}
/**
* Get the column of given name from table.
*/
public DataColumn getColumn(String columnName) {
int colIndex = indexOf(columnName);
if (colIndex > -1) {
return mColumns.get(colIndex);
}
return null;
}
/**
* Get the primary key column from table.
*/
public DataColumn getPrimaryKey() {
assertTable();
if (!checkHasPrimaryKey()) return null;
DataColumn keyColumn = null;
for(int i = 0; i < mColumns.size(); i++) {
DataColumn column = mColumns.get(i);
if (column.isPrimaryKey()) {
keyColumn = column;
break;
}
}
return keyColumn;
}
/**
* Get the columns name array from table.
*/
public String[] getColumnNames() {
assertTable();
String[] columns = new String[mColumns.size()];
for(int i = 0; i < mColumns.size(); i++) {
columns[i] = mColumns.get(i).getName();
}
return columns;
}
/**
* Get the count of columns from table.
*/
public int getColumnCount() {
return mColumns.size();
}
@Override
public Iterator<DataColumn> iterator() {
return new DataColumnsIterator();
}
/**
* Get the URI pattern is for more than one row.
*/
public String getContentTypeDir() {
String name = getTableName().toLowerCase();
if (name.endsWith("y")) {
return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + VND_PREFIX + "." + name.substring(0, name.length() - 1) + "ies";
} else if (name.endsWith("s")) {
return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + VND_PREFIX + "." + name;
} else {
return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + VND_PREFIX + "." + name + "s";
}
}
/**
* Get the URI pattern is for a single row.
*/
public String getContentTypeItem() {
String name = getTableName().toLowerCase();
if (name.endsWith("s")) {
return ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + VND_PREFIX + "." + name.substring(0, name.length() - 1);
}
return ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + VND_PREFIX + "." + name;
}
/**
* Get the index of column from table.
*/
public int indexOf(String columnName) {
if (TextUtils.isEmpty(columnName)) return -1;
for(int i = 0; i < mColumns.size(); i++) {
if (mColumns.get(i).getName().equals(columnName)) {
return i;
}
}
return -1;
}
/**
* Get the index of column from table.
*/
public int indexOf(DataColumn column) {
if (column == null) return -1;
for(int i = 0; i < mColumns.size(); i++) {
if (mColumns.get(i).getName().equals(column.getName())) {
return i;
}
}
return -1;
}
protected String createStatement(boolean withIsNotExist) {
assertTable();
String sql = "";
sql += "CREATE TABLE ";
if (withIsNotExist) {
sql += "IF NOT EXISTS ";
}
sql += NAME_QUOTES + mTableName + NAME_QUOTES + " (";
for(int i = 0; i < mColumns.size(); i++) {
DataColumn column = mColumns.get(i);
if (i > 0) sql += ",";
sql += column.toString();
}
sql += ");";
Log.w("createStatement", sql);
return sql;
}
protected String dropStatement(boolean withIsExist) {
assertTable();
return "DROP TABLE " + (withIsExist ? "IF EXISTS " : "") + NAME_QUOTES + mTableName + NAME_QUOTES + ");";
}
/**
* Get Query Builder
*/
public SQLiteQueryBuilder getQueryBuilder() {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(mTableName);
builder.setProjectionMap(mExecutor.getProjectionMap());
return builder;
}
@SuppressWarnings("unchecked")
protected <T> T typeConvertOrDefault(Object value, T defVal) {
if (value == null) return defVal;
if (defVal.getClass().equals(value.getClass())) {
return (T)value;
}
return defVal;
}
/**
* Make ContentValues
*/
public ContentValues makeContentValues(Object... values)
throws IllegalArgumentException {
if (values == null || values.length != getColumnCount()) {
throw new IllegalArgumentException("Values not specified");
}
ContentValues contentValues = new ContentValues();
for(int i=0; i<mColumns.size(); i++) {
DataColumn column = mColumns.get(i);
Object val = values[i];
if (val == null) {
contentValues.putNull(column.getName());
} else if (val instanceof Short) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Short.MIN_VALUE));
} else if (val instanceof Integer) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Integer.MIN_VALUE));
} else if (val instanceof Long) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Long.MIN_VALUE));
} else if (val instanceof Float) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Float.MIN_VALUE));
} else if (val instanceof Double) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Double.MIN_VALUE));
} else if (val instanceof Boolean) {
contentValues.put(column.getName(), typeConvertOrDefault(val, Boolean.FALSE));
} else if (val instanceof String) {
contentValues.put(column.getName(), typeConvertOrDefault(val, (String)""));
} else if (val instanceof byte[]) {
contentValues.put(column.getName(), typeConvertOrDefault(val, (byte[])null));
}
}
return contentValues;
}
/**
* Make executable
*/
public Executor from(SQLiteDatabase db) {
if (db == null) {
throw new IllegalArgumentException("SQLiteDatabase not specified");
}
assertTable();
mExecutor.reset();
mDatabase = db;
return mExecutor;
}
/**
* Set Join Condition
*/
public TableJoiner join(DataTable other, DataColumn mainColumn, DataColumn otherColumn) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(other, mainColumn, otherColumn);
mJoinerList.add(joiner);
return joiner;
}
/**
* Set Join Condition
*/
public TableJoiner join(DataTable other, String condition) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(other, condition);
mJoinerList.add(joiner);
return joiner;
}
/**
* Set Join Condition
*/
public TableJoiner join(String joinWith, String condition) {
if (TextUtils.isEmpty(joinWith)) {
throw new IllegalArgumentException("joinWith not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(joinWith, condition);
mJoinerList.add(joiner);
return joiner;
}
/**
* Execute create table.
*/
public void create(SQLiteDatabase db) {
create(db, true);
}
/**
* Execute create table.
*/
public void create(SQLiteDatabase db, boolean checkIsNotExist) {
assertTable();
db.execSQL(createStatement(checkIsNotExist));
}
/**
* Execute drop table.
*/
public void drop(SQLiteDatabase db) {
drop(db, true);
}
/**
* Execute drop table.
*/
public void drop(SQLiteDatabase db, boolean checkIsExist) {
assertTable();
db.execSQL(dropStatement(checkIsExist));
}
public class DataColumn {
private int mIndex;
private String mName;
private String mDataType;
private boolean mIsPrimaryKey;
private boolean mIsAllowNull;
private boolean mIsAutoIncrement;
private String mDefaultValue;
private String mExtended;
private final DataTable mTable;
private String mActualType;
private DataColumn(DataTable table, String columnName, String sqlDataType) {
mTable = table;
mName = columnName;
mDataType = sqlDataType;
mIsAllowNull = true;
mIndex = -1;
if (!TextUtils.isEmpty(mDataType)) {
String type = mDataType.trim();
Pattern pattern = Pattern.compile("^([^\\s]+)([\\s]+\\(|\\()([\\d]+)\\)$");
Matcher m = pattern.matcher(type);
if (m.matches()) {
type = m.group(0);
}
mActualType = type.trim().toUpperCase();
}
}
public DataTable getTable() {
return mTable;
}
public int getIndex() {
return mIndex;
}
public String getName() {
return mName;
}
public String getDataType() {
return mDataType;
}
public String getActualDataType() {
return mActualType;
}
public Class<?> getJavaType() {
String dataType = getActualDataType();
if (!TextUtils.isEmpty(dataType)) {
if ("TEXT".equals(dataType) || "VARCHAR".equals(dataType) || "NVARCHAR".equals(dataType)) {
return String.class;
} else if ("INTEGER".equals(dataType)) {
return Long.class;
} else if ("FLOAT".equals(dataType)) {
return Float.class;
} else if ("REAL".equals(dataType) || "NUMERIC".equals(dataType)) {
return Double.class;
} else if ("BOOLEAN".equals(dataType)) {
return Boolean.class;
} else {
return String.class;
}
}
return Object.class;
}
public boolean isPrimaryKey() {
return mIsPrimaryKey;
}
public boolean isAllowNull() {
return mIsAllowNull;
}
public boolean isAutoIncrement() {
return mIsAutoIncrement;
}
public String getDefaultValue() {
return mDefaultValue;
}
public String getExtended() {
return mExtended;
}
@Override
public String toString() {
return NAME_QUOTES + mName + NAME_QUOTES
+ " " + mDataType
+ (mIsPrimaryKey ? " PRIMARY KEY" : "")
+ (mIsAutoIncrement ? " AUTOINCREMENT" : "")
+ (!mIsAllowNull ? " NOT NULL" : "")
+ (mDefaultValue != null ? " DEFAULT " + mDefaultValue : "")
+ (mExtended != null ? " " + mExtended : "");
}
}
public class DataColumnsIterator implements Iterator<DataColumn> {
private int mColumnIndex = -1;
@Override
public boolean hasNext() {
if (mColumns == null) return false;
int idx = mColumnIndex + 1;
return (idx < mColumns.size());
}
@Override
public DataColumn next() {
if (mColumns == null) return null;
mColumnIndex++;
if (mColumnIndex < mColumns.size()) {
return mColumns.get(mColumnIndex);
}
return null;
}
@Override
public void remove() {
mColumnIndex = -1;
}
}
public class TableJoiner {
private DataTable mOtherTable;
private String mJoinWith;
private String mCondition;
private TableJoiner(DataTable other, DataColumn mainColumn, DataColumn otherColumn) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
if (mainColumn == null) {
throw new IllegalArgumentException("Main column not specified");
}
if (otherColumn == null) {
throw new IllegalArgumentException("Other column not specified");
}
mOtherTable = other;
mCondition = "`" + mainColumn.getTable().getTableName() + "`";
mCondition += ".`" + mainColumn.getName() + "`";
mCondition += " = `" + otherColumn.getTable().getTableName() + "`";
mCondition += ".`" + otherColumn.getName() + "`";
}
private TableJoiner(DataTable other, String condition) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
if (TextUtils.isEmpty(condition)) {
throw new IllegalArgumentException("Condition not specified");
}
mOtherTable = other;
mCondition = condition;
}
private TableJoiner(String joinWith, String condition) {
if (TextUtils.isEmpty(joinWith)) {
throw new IllegalArgumentException("joinWith not specified");
}
if (TextUtils.isEmpty(condition)) {
throw new IllegalArgumentException("Condition not specified");
}
mJoinWith = joinWith;
mCondition = condition;
}
public DataTable getTable() {
return mOtherTable;
}
public String getJoinable() {
return mJoinWith;
}
public String getCondition() {
return mCondition;
}
public TableJoiner join(DataTable other, DataColumn mainColumn, DataColumn otherColumn) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(other, mainColumn, otherColumn);
mJoinerList.add(joiner);
return joiner;
}
public TableJoiner join(DataTable other, String condition) {
if (other == null) {
throw new IllegalArgumentException("Other table not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(other, condition);
mJoinerList.add(joiner);
return joiner;
}
public TableJoiner join(String joinWith, String condition) {
if (TextUtils.isEmpty(joinWith)) {
throw new IllegalArgumentException("joinWith not specified");
}
assertTable();
TableJoiner joiner = new TableJoiner(joinWith, condition);
mJoinerList.add(joiner);
return joiner;
}
public Executor from(SQLiteDatabase db) {
Executor executor = new Executor(true);
// put main table's columns
Iterator<DataColumn> iter = iterator();
while(iter.hasNext()) {
executor.putColumn(iter.next());
}
// put joined table's columns
for(TableJoiner joiner : mJoinerList) {
if (joiner.getTable() != null) {
iter = joiner.getTable().iterator();
while(iter.hasNext()) {
executor.putColumn(iter.next());
}
}
}
StringBuilder joinBuilder = new StringBuilder();
joinBuilder.append("`" + getTableName() + "`");
for(TableJoiner joiner : mJoinerList) {
joinBuilder.append(" JOIN ");
if (joiner.getTable() != null) {
joinBuilder.append("`" + joiner.getTable().getTableName() + "`");
} else {
joinBuilder.append(joiner.getJoinable());
}
joinBuilder.append(" ON ");
joinBuilder.append("(" + joiner.getCondition() + ")");
}
executor.setExecTableName(joinBuilder.toString());
return executor;
}
}
public class Executor {
private Map<String, String> mProjectionMap = new HashMap<String, String>();
private StringBuilder mSelection = new StringBuilder();
private List<String> mSelectionArgs = new ArrayList<String>();
private String mExecTableName;
private final boolean mIsReadOnly;
private Executor(boolean isReadOnly) {
mExecTableName = getTableName();
mIsReadOnly = isReadOnly;
}
private Executor(String tableName, boolean isReadOnly) {
mExecTableName = tableName;
mIsReadOnly = isReadOnly;
}
public Executor where(String id) {
assertTable();
mSelection.append("(").append(getPrimaryKey().getName() + "=?").append(")");
mSelectionArgs.add(id);
return this;
}
protected void mapColumns(String[] columns) {
for (int i = 0; i < columns.length; i++) {
final String target = mProjectionMap.get(columns[i]);
if (target != null) {
columns[i] = target;
}
}
}
/**
* Reset any internal state, allowing this builder to be recycled.
*/
protected void reset() {
mSelection.setLength(0);
mSelectionArgs.clear();
}
protected void setExecTableName(String tableName) {
mExecTableName = tableName;
}
protected String getExecTableName() {
return mExecTableName;
}
protected void putColumn(DataColumn column) {
mProjectionMap.put(column.getName(), "`" + column.getTable().getTableName() + "`.`" + column.getName() + "`");
}
protected Map<String, String> getProjectionMap() {
return mProjectionMap;
}
/**
* Return selection string for current internal state.
*
* @see #getSelectionArgs()
*/
protected String getSelection() {
return mSelection.toString();
}
/**
* Return selection arguments for current internal state.
*
* @see #getSelection()
*/
protected String[] getSelectionArgs() {
return mSelectionArgs.toArray(new String[mSelectionArgs.size()]);
}
/**
* Map a column.
*/
public Executor map(String fromColumn, String toClause) {
mProjectionMap.put(fromColumn, toClause + " AS " + fromColumn);
return this;
}
/**
* Append the given selection clause to the internal state. Each clause is
* surrounded with parenthesis and combined using {@code AND}.
*/
public Executor where(String selection, String... selectionArgs) {
assertTable();
if (TextUtils.isEmpty(selection)) {
if (selectionArgs != null && selectionArgs.length > 0) {
throw new IllegalArgumentException("Valid selection required when including arguments=");
}
// Shortcut when clause is empty
return this;
}
if (mSelection.length() > 0) {
mSelection.append(" AND ");
}
mSelection.append("(").append(selection).append(")");
if (selectionArgs != null) {
for(String arg : selectionArgs) {
mSelectionArgs.add(arg);
}
}
return this;
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(boolean distinct, String orderBy, String limit) {
return query(distinct, getColumnNames(), null, null, orderBy, limit);
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(String orderBy, String limit) {
return query(getColumnNames(), null, null, orderBy, limit);
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(String[] columns, String orderBy, String limit) {
return query(columns, null, null, orderBy, limit);
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(boolean distinct, String[] columns, String orderBy, String limit) {
return query(distinct, columns, null, null, orderBy, limit);
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(String[] columns, String groupBy,
String having, String orderBy, String limit) {
return query(false, columns, groupBy, having, orderBy, limit);
}
/**
* Execute query using the current internal state as {@code WHERE} clause.
*/
public Cursor query(boolean distinct, String[] columns, String groupBy,
String having, String orderBy, String limit) {
assertTable();
assertDatabase();
if (columns != null) mapColumns(columns);
Cursor cursor = mDatabase.query(distinct, mExecTableName, columns, getSelection(), getSelectionArgs(), groupBy, having,
orderBy, limit);
return cursor;
}
/**
* Execute update using the current internal state as {@code WHERE} clause.
*/
public long save(ContentValues values) {
if (values == null) {
throw new IllegalArgumentException("Values not specified");
}
assertTable();
if (mIsReadOnly) {
throw new IllegalStateException("Table is readonly");
}
assertDatabase();
long result = mDatabase.update(mExecTableName, values, getSelection(), getSelectionArgs());
if (result < 1) {
result = mDatabase.insert(mExecTableName, null, values);
}
return result;
}
/**
* Execute update using the current internal state as {@code WHERE} clause.
*/
public long insert(ContentValues values) {
if (values == null) {
throw new IllegalArgumentException("Values not specified");
}
assertTable();
if (mIsReadOnly) {
throw new IllegalStateException("Table is readonly");
}
assertDatabase();
return mDatabase.insert(mExecTableName, null, values);
}
/**
* Execute update using the current internal state as {@code WHERE} clause.
*/
public long insert(String nullColumnHack, ContentValues values) {
if (values == null) {
throw new IllegalArgumentException("Values not specified");
}
assertTable();
if (mIsReadOnly) {
throw new IllegalStateException("Table is readonly");
}
assertDatabase();
return mDatabase.insert(mExecTableName, nullColumnHack, values);
}
/**
* Execute update using the current internal state as {@code WHERE} clause.
*/
public int update(ContentValues values) {
if (values == null) {
throw new IllegalArgumentException("Values not specified");
}
assertTable();
if (mIsReadOnly) {
throw new IllegalStateException("Table is readonly");
}
assertDatabase();
return mDatabase.update(mExecTableName, values, getSelection(), getSelectionArgs());
}
/**
* Execute delete using the current internal state as {@code WHERE} clause.
*/
public int delete() {
assertTable();
if (mIsReadOnly) {
throw new IllegalStateException("Table is readonly");
}
assertDatabase();
return mDatabase.delete(mExecTableName, getSelection(), getSelectionArgs());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment