/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.android;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
import org.h2.command.Prepared;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.expression.Parameter;
import org.h2.result.ResultInterface;
import org.h2.store.PageStore;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueString;
import android.content.ContentValues;
import android.database.Cursor;
/**
* This class represents a database connection.
*/
public class H2Database {
/**
* When a conflict occurs, abort the current statement, but don't roll back
* the transaction. This is the default value.
*/
public static final int CONFLICT_ABORT = 2;
/**
* When a conflict occurs, return SQLITE_CONSTRAINT, but don't roll back the
* transaction.
*/
public static final int CONFLICT_FAIL = 3;
/**
* When a conflict occurs, continue, but don't modify the conflicting row.
*/
public static final int CONFLICT_IGNORE = 4;
/**
* When a conflict occurs, do nothing.
*/
public static final int CONFLICT_NONE = 0;
/**
* When a conflict occurs, the existing rows are replaced.
*/
public static final int CONFLICT_REPLACE = 5;
/**
* When a conflict occurs, the transaction is rolled back.
*/
public static final int CONFLICT_ROLLBACK = 1;
/**
* Create a new database if it doesn't exist.
*/
public static final int CREATE_IF_NECESSARY = 0x10000000;
/**
* This flag has no effect.
*/
public static final int NO_LOCALIZED_COLLATORS = 0x10;
/**
* Open the database in read-only mode.
*/
public static final int OPEN_READONLY = 1;
/**
* Open the database in read-write mode (default).
*/
public static final int OPEN_READWRITE = 0;
private final Session session;
private final CursorFactory factory;
H2Database(Session session, CursorFactory factory) {
this.factory = factory;
this.session = session;
}
/**
* Create a new in-memory database.
*
* @param factory the cursor factory
* @return a connection to this database
*/
public static H2Database create(H2Database.CursorFactory factory) {
ConnectionInfo ci = new ConnectionInfo("mem:");
Database db = new Database(ci, null);
Session s = db.getSystemSession();
return new H2Database(s, factory);
}
/**
* Open a connection to the given database.
*
* @param path the database file name
* @param factory the cursor factory
* @param flags 0, or a combination of OPEN_READONLY and CREATE_IF_NECESSARY
* @return a connection to this database
*/
public static H2Database openDatabase(String path, H2Database.CursorFactory factory, int flags) {
ConnectionInfo ci = new ConnectionInfo(path);
if ((flags & OPEN_READWRITE) != 0) {
// TODO readonly connections
}
if ((flags & CREATE_IF_NECESSARY) == 0) {
ci.setProperty("IFEXISTS", "TRUE");
}
ci.setProperty("FILE_LOCK", "FS");
Database db = new Database(ci, null);
Session s = db.getSystemSession();
return new H2Database(s, factory);
}
/**
* Open a connection to the given database. The database is created if it
* doesn't exist yet.
*
* @param file the database file
* @param factory the cursor factory
* @return a connection to this database
*/
public static H2Database openOrCreateDatabase(File file, H2Database.CursorFactory factory) {
return openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY);
}
/**
* Open a connection to the given database. The database is created if it
* doesn't exist yet.
*
* @param path the database file name
* @param factory the cursor factory
* @return a connection to this database
*/
public static H2Database openOrCreateDatabase(String path, H2Database.CursorFactory factory) {
return openDatabase(path, factory, CREATE_IF_NECESSARY);
}
/**
* Start a transaction.
*/
public void beginTransaction() {
session.setAutoCommit(false);
}
/**
* Start a transaction.
*
* @param transactionListener the transaction listener to use
*/
public void beginTransactionWithListener(H2TransactionListener transactionListener) {
// TODO H2TransactionListener
session.setAutoCommit(false);
}
/**
* Close the connection.
*/
public void close() {
session.close();
}
/**
* Prepare a statement.
*
* @param sql the statement
* @return the prepared statement
*/
public H2Statement compileStatement(String sql) {
return new H2Statement(session.prepare(sql));
}
/**
* Delete a number of rows in this database.
*
* @param table the table
* @param whereClause the condition
* @param whereArgs the parameter values
* @return the number of rows deleted
*/
public int delete(String table, String whereClause, String[] whereArgs) {
return 0;
}
/**
* End the transaction.
*/
public void endTransaction() {
// TODO
}
/**
* Execute the given statement.
*
* @param sql the statement
* @param bindArgs the parameter values
*/
public void execSQL(String sql, Object[] bindArgs) {
prepare(sql, bindArgs).update();
}
/**
* Execute the given statement.
*
* @param sql the statement
*/
public void execSQL(String sql) {
session.prepare(sql).update();
}
/**
* TODO
*
* @param tables the list of tables
* @return TODO
*/
public static String findEditTable(String tables) {
// TODO
return null;
}
/**
* Get the maximum size of the database file in bytes.
*
* @return the maximum size
*/
public long getMaximumSize() {
return Long.MAX_VALUE;
}
/**
* Get the page size of the database in bytes.
*
* @return the page size
*/
public long getPageSize() {
PageStore store = session.getDatabase().getPageStore();
return store == null ? 0 : store.getPageSize();
}
/**
* Get the name of the database file.
*
* @return the database file name
*/
public String getPath() {
return null;
}
/**
* TODO
*
* @return TODO
*/
public Map<String, String> getSyncedTables() {
return null;
}
/**
* Get the database version.
*
* @return the database version
*/
public int getVersion() {
return 0;
}
/**
* Check if there is an open transaction.
*
* @return true if there is
*/
public boolean inTransaction() {
return false;
}
/**
* Insert a row.
*
* @param table the table
* @param nullColumnHack not used
* @param values the values
* @return TODO
*/
public long insert(String table, String nullColumnHack, ContentValues values) {
return 0;
}
/**
* Try to insert a row.
*
* @param table the table
* @param nullColumnHack not used
* @param values the values
* @return TODO
*/
public long insertOrThrow(String table, String nullColumnHack, ContentValues values) {
return 0;
}
/**
* Try to insert a row, using the given conflict resolution option.
*
* @param table the table
* @param nullColumnHack not used
* @param initialValues the values
* @param conflictAlgorithm what conflict resolution to use
* @return TODO
*/
public long insertWithOnConflict(String table, String nullColumnHack,
ContentValues initialValues, int conflictAlgorithm) {
return 0;
}
/**
* Check if the database is locked by the current thread.
*
* @return true if it is
*/
public boolean isDbLockedByCurrentThread() {
return false;
}
/**
* Check if the database is locked by a different thread.
*
* @return true if it is
*/
public boolean isDbLockedByOtherThreads() {
return false;
}
/**
* Check if the connection is open.
*
* @return true if it is
*/
public boolean isOpen() {
return false;
}
/**
* Check if the connection is read-only.
*
* @return true if it is
*/
public boolean isReadOnly() {
return false;
}
/**
* TODO
*
* @param table the table
* @param deletedTable TODO
*/
public void markTableSyncable(String table, String deletedTable) {
// TODO
}
/**
* TODO
*
* @param table the table
* @param foreignKey the foreign key
* @param updateTable TODO
*/
public void markTableSyncable(String table, String foreignKey, String updateTable) {
// TODO
}
/**
* Check if an upgrade is required.
*
* @param newVersion the new version
* @return true if the current version doesn't match
*/
public boolean needUpgrade(int newVersion) {
return false;
}
/**
* Execute the SELECT statement for the given parameters.
*
* @param distinct if only distinct rows should be returned
* @param table the table
* @param columns the list of columns
* @param selection TODO
* @param selectionArgs TODO
* @param groupBy the group by list or null
* @param having the having condition or null
* @param orderBy the order by list or null
* @param limit the limit or null
* @return the cursor
*/
public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs,
String groupBy, String having, String orderBy, String limit) {
return null;
}
/**
* Execute the SELECT statement for the given parameters.
*
* @param table the table
* @param columns the list of columns
* @param selection TODO
* @param selectionArgs TODO
* @param groupBy the group by list or null
* @param having the having condition or null
* @param orderBy the order by list or null
* @return the cursor
*/
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
String having, String orderBy) {
return null;
}
/**
* Execute the SELECT statement for the given parameters.
*
* @param table the table
* @param columns the list of columns
* @param selection TODO
* @param selectionArgs TODO
* @param groupBy the group by list or null
* @param having the having condition or null
* @param orderBy the order by list or null
* @param limit the limit or null
* @return the cursor
*/
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit) {
return null;
}
/**
* Execute the SELECT statement for the given parameters.
*
* @param cursorFactory the cursor factory to use
* @param distinct if only distinct rows should be returned
* @param table the table
* @param columns the list of columns
* @param selection TODO
* @param selectionArgs TODO
* @param groupBy the group by list or null
* @param having the having condition or null
* @param orderBy the order by list or null
* @param limit the limit or null
* @return the cursor
*/
public Cursor queryWithFactory(H2Database.CursorFactory cursorFactory, boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
return null;
}
/**
* Execute the query.
*
* @param sql the SQL statement
* @param selectionArgs the parameter values
* @return the cursor
*/
public Cursor rawQuery(String sql, String[] selectionArgs) {
Prepared prep = prepare(sql, selectionArgs);
ResultInterface result = prep.query(0);
return new H2Cursor(result);
}
/**
* Execute the query using the given cursor factory.
*
* @param cursorFactory the cursor factory
* @param sql the SQL statement
* @param selectionArgs the parameter values
* @param editTable TODO
* @return the cursor
*/
public Cursor rawQueryWithFactory(H2Database.CursorFactory cursorFactory, String sql, String[] selectionArgs,
String editTable) {
return null;
}
/**
* Try to release memory.
*
* @return TODO
*/
public static int releaseMemory() {
return 0;
}
/**
* Replace an existing row in the database.
*
* @param table the table
* @param nullColumnHack ignored
* @param initialValues the values
* @return TODO
*/
public long replace(String table, String nullColumnHack, ContentValues initialValues) {
return 0;
}
/**
* Try to replace an existing row in the database.
*
* @param table the table
* @param nullColumnHack ignored
* @param initialValues the values
* @return TODO
*/
public long replaceOrThrow(String table, String nullColumnHack, ContentValues initialValues) {
return 0;
}
/**
* Set the locale.
*
* @param locale the new locale
*/
public void setLocale(Locale locale) {
// TODO
}
/**
* Enable or disable thread safety.
*
* @param lockingEnabled the new value
*/
public void setLockingEnabled(boolean lockingEnabled) {
// TODO
}
/**
* Set the maximum database file size.
*
* @param numBytes the file size in bytes
* @return the effective maximum size
*/
public long setMaximumSize(long numBytes) {
return 0;
}
/**
* Set the database page size. The value can not be changed once the
* database exists.
*
* @param numBytes the page size
*/
public void setPageSize(long numBytes) {
// TODO
}
/**
* Mark the transaction as completed successfully.
*/
public void setTransactionSuccessful() {
// TODO
}
/**
* Update the database version.
*
* @param version the version
*/
public void setVersion(int version) {
// TODO
}
/**
* Update one or multiple rows.
*
* @param table the table
* @param values the values
* @param whereClause the where condition
* @param whereArgs the parameter values
* @return the number of rows updated
*/
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
return 0;
}
/**
* Update one or multiple rows.
*
* @param table the table
* @param values the values
* @param whereClause the where condition
* @param whereArgs the parameter values
* @param conflictAlgorithm the conflict resolution option
* @return the number of rows updated
*/
public int updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs,
int conflictAlgorithm) {
return 0;
}
/**
* TODO
*
* @deprecated
* @return TODO
*/
public boolean yieldIfContended() {
return false;
}
/**
* Temporarily pause the transaction.
*
* @param sleepAfterYieldDelay TODO
* @return TODO
*/
public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
return false;
}
/**
* Temporarily pause the transaction.
*
* @return TODO
*/
public boolean yieldIfContendedSafely() {
return false;
}
/**
* The cursor factory.
*/
public interface CursorFactory {
/**
* Create a new cursor.
*
* @param db the connection
* @param masterQuery TODO
* @param editTable TODO
* @param query TODO
* @return the cursor
*/
Cursor newCursor(H2Database db, H2CursorDriver masterQuery, String editTable, H2Query query);
}
private Prepared prepare(String sql, Object[] args) {
Prepared prep = session.prepare(sql);
int len = args.length;
if (len > 0) {
ArrayList<Parameter> params = prep.getParameters();
for (int i = 0; i < len; i++) {
Parameter p = params.get(i);
p.setValue(getValue(args[i]));
}
}
return prep;
}
private Value getValue(Object o) {
if (o == null) {
return ValueNull.INSTANCE;
} else if (o instanceof String) {
return ValueString.get((String) o);
} else if (o instanceof Integer) {
return ValueInt.get((Integer) o);
} else if (o instanceof Long) {
return ValueLong.get((Integer) o);
}
return ValueString.get(o.toString());
// TODO
}
/**
* Create a new RuntimeException that says this feature is not supported.
*
* @return the runtime exception
*/
public static RuntimeException unsupported() {
// TODO
return new RuntimeException("Feature not supported");
}
}