diff --git a/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider2_Provider.java b/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider2_Provider.java index 3f85427f3d6e9fff94939f375c9664a9bdd5b50e..f5be6864b11d9dc73c9adc628c85f3835ba25833 100644 --- a/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider2_Provider.java +++ b/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider2_Provider.java @@ -6,7 +6,7 @@ import com.dbflow5.adapter.ModelAdapter; import com.dbflow5.annotation.ConflictAction; import com.dbflow5.config.DatabaseHolder; import com.dbflow5.config.FlowManager; -import net.sqlcipher.DatabaseUtils; +import com.dbflow5.sqlcipher.utils.DatabaseUtils; import ohos.aafwk.ability.DataAbilityHelper; import ohos.aafwk.content.Intent; import ohos.data.dataability.DataAbilityPredicates; diff --git a/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider_Provider.java b/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider_Provider.java index c14d41327148534173accc74a8b3d840f50553df..20d349ff234bc91ce1fce10b06e3f4fbc6a5ac0a 100644 --- a/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider_Provider.java +++ b/entry/src/ohosTest/java/com/dbflow5/provider/TestContentProvider_Provider.java @@ -6,7 +6,7 @@ import com.dbflow5.adapter.ModelAdapter; import com.dbflow5.annotation.ConflictAction; import com.dbflow5.config.DatabaseHolder; import com.dbflow5.config.FlowManager; -import net.sqlcipher.DatabaseUtils; +import com.dbflow5.sqlcipher.utils.DatabaseUtils; import ohos.aafwk.ability.DataAbilityHelper; import ohos.aafwk.ability.DataAbilityRemoteException; import ohos.aafwk.content.Intent; diff --git a/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherDatabase.java b/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherDatabase.java index 97da6a8a76a47741db6582330e05fb22894312e9..8f8efd815f318a11ce39474330ccab9ee76231cf 100644 --- a/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherDatabase.java +++ b/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherDatabase.java @@ -3,12 +3,6 @@ package com.dbflow5.sqlcipher; import com.dbflow5.annotation.Database; import com.dbflow5.config.DBFlowDatabase; -/** - * CipherDatabase - * - * @author wangyin - * @since 2021/06/21 - */ @Database(version = 1) public abstract class CipherDatabase extends DBFlowDatabase { } diff --git a/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherTestObjects.java b/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherTestObjects.java index 9b8741d27a9976a703a09384488f67b2fed00d6c..ed5997c93546a41d1bfe247620a453598a9645c2 100644 --- a/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherTestObjects.java +++ b/entry/src/ohosTest/java/com/dbflow5/sqlcipher/CipherTestObjects.java @@ -8,12 +8,6 @@ import com.dbflow5.database.DatabaseCallback; import com.dbflow5.structure.BaseModel; import ohos.app.Context; -/** - * CipherTestObjects - * - * @author wangyin - * @since 2021/06/21 - */ public class CipherTestObjects { public static class SQLCipherOpenHelperImpl extends SQLCipherOpenHelper { @@ -26,9 +20,14 @@ public class CipherTestObjects { this.context = context1; this.databaseDefinition = databaseDefinition1; this.callback = callback; - cipherSecret = "dbflow-rules"; + } + + @Override + protected String cipherSecret() { + return "dbflow-rules"; } } + @Table(database = CipherDatabase.class) public static class CipherModel extends BaseModel { @PrimaryKey diff --git a/sqlcipher/build.gradle b/sqlcipher/build.gradle index 7155915f389137e990511c8bcaa5fa8e11bf89c9..6af2f6dca2e9ba7f399b8b73dd171a822f4a4f9e 100644 --- a/sqlcipher/build.gradle +++ b/sqlcipher/build.gradle @@ -20,5 +20,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar','*.so']) testImplementation 'junit:junit:4.13' + api 'io.openharmony.tpc.thirdlib:ohos-database-sqlcipher:1.0.2' + api(project(":lib")) } diff --git a/sqlcipher/libs/arm64-v8a/libsqlcipher.so b/sqlcipher/libs/arm64-v8a/libsqlcipher.so deleted file mode 100644 index 4f45ec9f14140331382cbe2ffc65fe2a0212f5d7..0000000000000000000000000000000000000000 Binary files a/sqlcipher/libs/arm64-v8a/libsqlcipher.so and /dev/null differ diff --git a/sqlcipher/libs/armeabi-v7a/libsqlcipher.so b/sqlcipher/libs/armeabi-v7a/libsqlcipher.so deleted file mode 100644 index 70103ac3385a92b13d0c19f1bbc2dd1a7037741c..0000000000000000000000000000000000000000 Binary files a/sqlcipher/libs/armeabi-v7a/libsqlcipher.so and /dev/null differ diff --git a/sqlcipher/libs/x86/libsqlcipher.so b/sqlcipher/libs/x86/libsqlcipher.so deleted file mode 100644 index 052459888f63cb4adf023d998711f0e58b4543b8..0000000000000000000000000000000000000000 Binary files a/sqlcipher/libs/x86/libsqlcipher.so and /dev/null differ diff --git a/sqlcipher/libs/x86_64/libsqlcipher.so b/sqlcipher/libs/x86_64/libsqlcipher.so deleted file mode 100644 index 9ffada875d96a3b2dd49c5208fdea20536e72480..0000000000000000000000000000000000000000 Binary files a/sqlcipher/libs/x86_64/libsqlcipher.so and /dev/null differ diff --git a/sqlcipher/src/main/java/com/dbflow5/sqlcipher/SQLCipherOpenHelper.java b/sqlcipher/src/main/java/com/dbflow5/sqlcipher/SQLCipherOpenHelper.java index b510674d4c9f9643b9ee46d156a43db42d37eab3..e8467a112bb2b2f80e68a51fde84008b49d1ec71 100644 --- a/sqlcipher/src/main/java/com/dbflow5/sqlcipher/SQLCipherOpenHelper.java +++ b/sqlcipher/src/main/java/com/dbflow5/sqlcipher/SQLCipherOpenHelper.java @@ -12,24 +12,24 @@ import ohos.app.Context; * Description: The replacement [OpenHelper] for SQLCipher. Specify a subclass of this is [DatabaseConfig.getDatabaseClass] * of your database to get it to work with specifying the secret you use for the databaseForTable. */ -public class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper { +public abstract class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper { private final Context context; public LocalDatabaseHelperDelegate delegate; private SQLCipherDatabase cipherDatabase = null; - private String _databaseName; + private final String _databaseName; public SQLCipherOpenHelper(Context context, DBFlowDatabase databaseDefinition, DatabaseCallback listener) { - super(context, databaseDefinition.isInMemory()? null : databaseDefinition.getDatabaseFileName(), null, databaseDefinition.databaseVersion()); + super(context, databaseDefinition.isInMemory()? null : context.getExternalCacheDir() + "/" + databaseDefinition.getDatabaseFileName(), null, databaseDefinition.databaseVersion()); this.context = context; _databaseName = databaseDefinition.getDatabaseFileName(); SQLiteDatabase.loadLibs(context); if(delegate == null) { delegate = new LocalDatabaseHelperDelegate(context, listener, databaseDefinition, databaseDefinition.backupEnabled()? - // Temp database mirrors existing - new BackupHelper(context, LocalDatabaseHelperDelegate.getTempDbFileName(databaseDefinition), databaseDefinition.databaseVersion(), databaseDefinition) : null); + // Temp database mirrors existing + new BackupHelper(context, LocalDatabaseHelperDelegate.getTempDbFileName(databaseDefinition), databaseDefinition.databaseVersion(), databaseDefinition) : null); } } @@ -45,12 +45,12 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper @Override public DatabaseWrapper database() { if (cipherDatabase == null || !cipherDatabase.database.isOpen()) { - cipherDatabase = SQLCipherDatabase.from(getWritableDatabase(cipherSecret)); + cipherDatabase = SQLCipherDatabase.from(getWritableDatabase(cipherSecret())); } return cipherDatabase; } - protected String cipherSecret; + protected abstract String cipherSecret(); @Override public void performRestoreFromBackup() { @@ -130,7 +130,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper @Override public DatabaseWrapper database() { if (sqlCipherDatabase == null) { - sqlCipherDatabase = SQLCipherDatabase.from(getWritableDatabase(cipherSecret)); + sqlCipherDatabase = SQLCipherDatabase.from(getWritableDatabase(cipherSecret())); } return sqlCipherDatabase; } @@ -192,6 +192,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper } public static DatabaseConfig.OpenHelperCreator createHelperCreator(Context context, String secret) { - return OhosSQLiteOpenHelper.createHelperCreator(context); + return (db, callback) -> new SQLCipherOpenHelper(context, db, callback){ + @Override + protected String cipherSecret() { + return secret; + } + }; } } diff --git a/sqlcipher/src/main/java/net/sqlcipher/DatabaseUtils.java b/sqlcipher/src/main/java/com/dbflow5/sqlcipher/utils/DatabaseUtils.java similarity index 98% rename from sqlcipher/src/main/java/net/sqlcipher/DatabaseUtils.java rename to sqlcipher/src/main/java/com/dbflow5/sqlcipher/utils/DatabaseUtils.java index fc22ead337a64b389a18097534a5c8280412e6e5..c35d9ff49f9abd5e8b371f92d9a22d1d0bdda1e3 100644 --- a/sqlcipher/src/main/java/net/sqlcipher/DatabaseUtils.java +++ b/sqlcipher/src/main/java/com/dbflow5/sqlcipher/utils/DatabaseUtils.java @@ -14,17 +14,18 @@ * limitations under the License. */ -package net.sqlcipher; - -import net.sqlcipher.database.SQLiteAbortException; -import net.sqlcipher.database.SQLiteConstraintException; -import net.sqlcipher.database.SQLiteDatabase; -import net.sqlcipher.database.SQLiteDatabaseCorruptException; -import net.sqlcipher.database.SQLiteDiskIOException; -import net.sqlcipher.database.SQLiteException; -import net.sqlcipher.database.SQLiteFullException; -import net.sqlcipher.database.SQLiteProgram; -import net.sqlcipher.database.SQLiteStatement; +package com.dbflow5.sqlcipher.utils; + +import net.sqlcipher.AbstractWindowedCursor; +import net.sqlcipher.SQLException; +import net.sqlcipher.database.*; +import net.sqlcipher.utils.TextUtils; +import ohos.data.rdb.ValuesBucket; +import ohos.data.resultset.ResultSet; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; +import ohos.rpc.MessageParcel; +import ohos.utils.Parcel; import java.io.FileNotFoundException; import java.io.PrintStream; @@ -32,16 +33,6 @@ import java.text.Collator; import java.util.HashMap; import java.util.Map; -import ohos.data.rdb.ValuesBucket; - -import ohos.rpc.MessageParcel; -import ohos.utils.Parcel; -import net.sqlcipher.utils.TextUtils; - -import ohos.data.resultset.ResultSet; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - /** * Static utility methods for dealing with databases and {@link }s. */ @@ -318,7 +309,7 @@ public class DatabaseUtils { /** * return the collation key - * @param name + * @param name name * @return the collation key */ public static String getCollationKey(String name) { @@ -332,7 +323,7 @@ public class DatabaseUtils { /** * return the collation key in hex format - * @param name + * @param name name * @return the collation key in hex format */ public static String getHexCollationKey(String name) { diff --git a/sqlcipher/src/main/java/net/sqlcipher/AbstractCursor.java b/sqlcipher/src/main/java/net/sqlcipher/AbstractCursor.java deleted file mode 100644 index 7592656738214c59f2324667cf73c0c3c3e189ff..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/AbstractCursor.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ohos.aafwk.ability.DataAbilityHelper; -import ohos.data.rdb.DataObservable; -import ohos.data.rdb.DataObserver; -import ohos.data.resultset.ResultSet; -import ohos.data.resultset.SharedBlock; -import ohos.aafwk.ability.IDataAbilityObserver; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import ohos.utils.PacMap; -import ohos.utils.net.Uri; - - -/** - * This is an abstract cursor class that handles a lot of the common code - * that all cursors need to deal with and is provided for convenience reasons. - */ -public abstract class AbstractCursor implements ohos.data.resultset.SharedResultSet, ResultSet { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x002E,"AbstractCursor"); - - DataObservable mDataSetObservable = new DataObservable(); - // ContentObservable mContentObservable = new ContentObservable(); - - private PacMap mExtras = PacMap.EMPTY_PAC_MAP; - - /* -------------------------------------------------------- */ - /* These need to be implemented by subclasses */ - abstract public int getRowCount(); - - abstract public String[] getAllColumnNames(); - - abstract public String getString(int column); - abstract public short getShort(int column); - abstract public int getInt(int column); - abstract public long getLong(int column); - abstract public float getFloat(int column); - abstract public double getDouble(int column); - abstract public boolean isColumnNull(int column); - - abstract public ColumnType getColumnTypeForIndex(int column); - - // TODO implement getBlob in all cursor types - public byte[] getBlob(int column) { - throw new UnsupportedOperationException("getBlob is not supported"); - } - /* -------------------------------------------------------- */ - /* Methods that may optionally be implemented by subclasses */ - - /** - * returns a pre-filled window, return NULL if no such window - * @return SharedBlock - */ - public SharedBlock getBlock() { - return null; - } - - public int getColumnCount() { - return getAllColumnNames().length; - } - - public void deactivate() { - deactivateInternal(); - } - - /** - * deactivateInternal - * @hide - */ - public void deactivateInternal() { - if (mSelfObserver != null) { - mContentResolver.unregisterObserver(mNotifyUri, mSelfObserver); - mSelfObserverRegistered = false; - } - mDataSetObservable.notifyObservers(); //notifyInvalidated not available - } - - public boolean requery() { - if (mSelfObserver != null && mSelfObserverRegistered == false) { - - mContentResolver.registerObserver(mNotifyUri, mSelfObserver); - mSelfObserverRegistered = true; - } - mDataSetObservable.notifyObservers(); - return true; - } - - public boolean isClosed() { - return mClosed; - } - - public void close() { - mClosed = true; - // mContentObservable.unregisterAll(); //todo - deactivateInternal(); - } - - /** - * commitUpdates - * @hide - * @deprecated - * @param values value - * @return true/false - */ - public boolean commitUpdates(Map> values) { - return false; - } - - /** - * deleteRow - * @hide - * @deprecated - * @return true/false - */ - public boolean deleteRow() { - return false; - } - - /** - * This function is called every time the cursor is successfully scrolled - * to a new position, giving the subclass a chance to update any state it - * may have. If it returns false the move function will also do so and the - * cursor will scroll to the beforeFirst position. - * - * @param oldPosition the position that we're moving from - * @param newPosition the position that we're moving to - * @return true if the move is successful, false otherwise - */ - public boolean onGo(int oldPosition, int newPosition) { - return true; - } - - - public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) { - // Default implementation, uses getString - String result = getString(columnIndex); - if (result != null) { - char[] data = buffer.data; - if (data == null || data.length < result.length()) { - buffer.data = result.toCharArray(); - } else { - for (int i = 0; i < result.length(); i++) { - data[i] = result.charAt(i); - } -// try { -// result.getChars(0, result.length(), data, 0); -// }catch (Exception e) { -// e.printStackTrace(); -// } - } - buffer.sizeCopied = result.length(); - } else { - buffer.sizeCopied = 0; - } - } - - /* -------------------------------------------------------- */ - /* Implementation */ - public AbstractCursor() { - mPos = -1; - mRowIdColumnIndex = -1; - mCurrentRowID = null; - mUpdatedRows = new HashMap>(); - } - - public final int getRowIndex() { - return mPos; - } - - public final boolean goToRow(int position) { - // Make sure position isn't past the end of the cursor - final int count = getRowCount(); - if (position >= count) { - mPos = count; - return false; - } - - // Make sure position isn't before the beginning of the cursor - if (position < 0) { - mPos = -1; - return false; - } - - // Check for no-op moves, and skip the rest of the work for them - if (position == mPos) { - return true; - } - - boolean result = onGo(mPos, position); - if (result == false) { - mPos = -1; - } else { - mPos = position; - if (mRowIdColumnIndex != -1) { - mCurrentRowID = Long.valueOf(getLong(mRowIdColumnIndex)); - } - } - - return result; - } - - /** - * Copy data from cursor to CursorWindow - * @param position start position of data - * @param window - */ - public void fillBlock(int position, SharedBlock window) { - DatabaseUtils.cursorFillWindow(this, position, window); - } - - public final boolean goTo(int offset) { - return goToRow(mPos + offset); - } - - public final boolean goToFirstRow() { - return goToRow(0); - } - - public final boolean goToLastRow() { - return goToRow(getRowCount() - 1); - } - - public final boolean goToNextRow() { - return goToRow(mPos + 1); - } - - public final boolean goToPreviousRow() { - return goToRow(mPos - 1); - } - - public final boolean isAtFirstRow() { - return mPos == 0 && getRowCount() != 0; - } - - public final boolean isAtLastRow() { - int cnt = getRowCount(); - return mPos == (cnt - 1) && cnt != 0; - } - - public final boolean isStarted() { - if (getRowCount() == 0) { - return true; - } - return mPos == -1; - } - - public final boolean isEnded() { - if (getRowCount() == 0) { - return true; - } - return mPos == getRowCount(); - } - - public int getColumnIndexForName(String columnName) { - // Hack according to bug 903852 - final int periodIndex = columnName.lastIndexOf('.'); - if (periodIndex != -1) { - Exception e = new Exception(); - HiLog.error(label, "requesting column name with table name -- " + columnName, e); - columnName = columnName.substring(periodIndex + 1); - } - - String columnNames[] = getAllColumnNames(); - int length = columnNames.length; - for (int i = 0; i < length; i++) { - if (columnNames[i].equalsIgnoreCase(columnName)) { - return i; - } - } - - /*if (Config.LOGV) {*/ //todo - if (getRowCount() > 0) { - HiLog.warn(label,"AbstractCursor", "Unknown column " + columnName); - } - // - return -1; - } - - public String getColumnNameForIndex(int columnIndex) { - return getAllColumnNames()[columnIndex]; - } - - /** - * updateBlob - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateBlob(int columnIndex, byte[] value) { - return update(columnIndex, value); - } - - /** - * updateString - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateString(int columnIndex, String value) { - return update(columnIndex, value); - } - - /** - * updateShort - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateShort(int columnIndex, short value) { - return update(columnIndex, Short.valueOf(value)); - } - - /** - * updateInt - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateInt(int columnIndex, int value) { - return update(columnIndex, Integer.valueOf(value)); - } - - /** - * updateLong - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateLong(int columnIndex, long value) { - return update(columnIndex, Long.valueOf(value)); - } - - /** - * updateFloat - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateFloat(int columnIndex, float value) { - return update(columnIndex, Float.valueOf(value)); - } - - /** - * updateDouble - * @hide - * @deprecated - * @param columnIndex index - * @param value value - * @return true/false - */ - public boolean updateDouble(int columnIndex, double value) { - return update(columnIndex, Double.valueOf(value)); - } - - /** - * updateToNull - * @hide - * @deprecated - * @param columnIndex index - * @return true/false - */ - public boolean updateToNull(int columnIndex) { - return update(columnIndex, null); - } - - /** - * update - * @hide - * @deprecated - * @param columnIndex index - * @param obj object - * @return true/false - */ - public boolean update(int columnIndex, Object obj) { - if (!supportsUpdates()) { - return false; - } - - // Long.valueOf() returns null sometimes! -// Long rowid = Long.valueOf(getLong(mRowIdColumnIndex)); - Long rowid = Long.valueOf(getLong(mRowIdColumnIndex)); - if (rowid == null) { - throw new IllegalStateException("null rowid. mRowIdColumnIndex = " + mRowIdColumnIndex); - } - - synchronized(mUpdatedRows) { - Map row = mUpdatedRows.get(rowid); - if (row == null) { - row = new HashMap(); - mUpdatedRows.put(rowid, row); - } - row.put(getAllColumnNames()[columnIndex], obj); - } - - return true; - } - - /** - * Returns true if there are pending updates that have not yet been committed. - * - * @return true if there are pending updates that have not yet been committed. - * @hide - * @deprecated - */ - public boolean hasUpdates() { - synchronized(mUpdatedRows) { - return mUpdatedRows.size() > 0; - } - } - - /** - * abortUpdates - * @hide - * @deprecated - */ - public void abortUpdates() { - synchronized(mUpdatedRows) { - mUpdatedRows.clear(); - } - } - - /** - * commitUpdates - * @hide - * @deprecated - * @return true/false - */ - public boolean commitUpdates() { - return commitUpdates(null); - } - - /** - * supportsUpdates - * @hide - * @deprecated - * @return true/false - */ - public boolean supportsUpdates() { - return mRowIdColumnIndex != -1; - } - - public void registerObserver(DataObserver observer) { - // mContentObservable.registerObserver(observer); //todo contentobservable not available - } - - public void unregisterObserver(DataObserver observer) { - // cursor will unregister all observers when it close - if (!mClosed) { - // mContentObservable.unregisterObserver(observer);//todo - } - } - - /** - * This is hidden until the data set change model has been re-evaluated. - * @hide - */ - protected void notifyDataSetChange() { - mDataSetObservable.notifyObservers(); - } - - /** - * This is hidden until the data set change model has been re-evaluated. - * @hide - * @return DataObservable - */ - protected DataObservable getDataSetObservable() { - return mDataSetObservable; - - } - /*public void registerObserver(DataObserver observer) { //added instead of datasetobserver - // mDataSetObservable.registerObserver(observer); //todo - } - - public void unregisterObserver(DataObserver observer) { - // mDataSetObservable.unregisterObserver(observer);//todo - }*/ - - /** - * Subclasses must call this method when they finish committing updates to notify all - * observers. - * - * @param selfChange - */ - protected void onChange(boolean selfChange) { - synchronized (mSelfObserverLock) { - // mContentObservable.dispatchChange(selfChange); //todo - if (mNotifyUri != null && selfChange) { - mContentResolver.notifyChange(mNotifyUri); - } - } - } - - /** - * Specifies a content URI to watch for changes. - * - * @param cr The content resolver from the caller's context. - * @param notifyUri The URI to watch for changes. This can be a - * specific row URI, or a base URI for a whole class of content. - */ - @Override - public void setAffectedByUris(Object cr, List notifyUri) { - if (cr instanceof DataAbilityHelper) { - synchronized (mSelfObserverLock) { - mNotifyUriList = notifyUri; - for(Uri uri:notifyUri) { - mContentResolver = (DataAbilityHelper) cr; - if (mSelfObserver != null) { - mContentResolver.unregisterObserver(uri, mSelfObserver); - } - mSelfObserver = new SelfContentObserver(this); - mContentResolver.registerObserver(mNotifyUri, mSelfObserver); - mSelfObserverRegistered = true; - } - } - } - } - - public List getAffectedByUris() { - return mNotifyUriList; - } - - public boolean getWantsAllOnMoveCalls() { - return false; - } - - public void setExtensions(PacMap extras) { - mExtras = (extras == null) ? PacMap.EMPTY_PAC_MAP : extras; - } - - public PacMap getExtensions() { - return mExtras; - } //todo - - public PacMap respond(PacMap extras) { - return PacMap.EMPTY_PAC_MAP; - } // no such method in hmos - - /** - * This function returns true if the field has been updated and is - * used in conjunction with {@link #getUpdatedField} to allow subclasses to - * support reading uncommitted updates. NOTE: This function and - * {@link #getUpdatedField} should be called together inside of a - * block synchronized on mUpdatedRows. - * - * @param columnIndex the column index of the field to check - * @return true if the field has been updated, false otherwise - */ - protected boolean isFieldUpdated(int columnIndex) { - if (mRowIdColumnIndex != -1 && mUpdatedRows.size() > 0) { - Map updates = mUpdatedRows.get(mCurrentRowID); - if (updates != null && updates.containsKey(getAllColumnNames()[columnIndex])) { - return true; - } - } - return false; - } - - /** - * This function returns the uncommitted updated value for the field - * at columnIndex. NOTE: This function and {@link #isFieldUpdated} should - * be called together inside of a block synchronized on mUpdatedRows. - * - * @param columnIndex the column index of the field to retrieve - * @return the updated value - */ - protected Object getUpdatedField(int columnIndex) { - Map updates = mUpdatedRows.get(mCurrentRowID); - return updates.get(getAllColumnNames()[columnIndex]); - } - - /** - * This function throws CursorIndexOutOfBoundsException if - * the cursor position is out of bounds. Subclass implementations of - * the get functions should call this before attempting - * to retrieve data. - * - * @throws CursorIndexOutOfBoundsException - */ - protected void checkPosition() { - if (-1 == mPos || getRowCount() == mPos) { - throw new CursorIndexOutOfBoundsException(mPos, getRowCount()); - } - } - - @Override - protected void finalize() { - if (mSelfObserver != null && mSelfObserverRegistered == true) { - mContentResolver.unregisterObserver(mNotifyUri, mSelfObserver); - } - } - - /** - * Cursors use this class to track changes others make to their URI. - */ - protected static class SelfContentObserver implements IDataAbilityObserver { - WeakReference mCursor; - - public SelfContentObserver(AbstractCursor cursor) { - // super(null); //no superclass - mCursor = new WeakReference(cursor); - } - - /*@Override - public boolean deliverSelfNotifications() { - return false; - }*/ - - @Override - public void onChange() { - AbstractCursor cursor = mCursor.get(); - if (cursor != null) { - cursor.onChange(false); - } - } - - } - - /** - * This HashMap contains a mapping from Long rowIDs to another Map - * that maps from String column names to new values. A NULL value means to - * remove an existing value, and all numeric values are in their class - * forms, i.e. Integer, Long, Float, etc. - */ - protected HashMap> mUpdatedRows; - - /** - * This must be set to the index of the row ID column by any - * subclass that wishes to support updates. - */ - protected int mRowIdColumnIndex; - - protected int mPos; - - /** - * If {@link #mRowIdColumnIndex} is not -1 this contains contains the value of - * the column at {@link #mRowIdColumnIndex} for the current row this cursor is - * pointing at. - */ - protected Long mCurrentRowID; - protected DataAbilityHelper mContentResolver; - protected boolean mClosed = false; - private Uri mNotifyUri; - private List mNotifyUriList; - private IDataAbilityObserver mSelfObserver; - final private Object mSelfObserverLock = new Object(); - private boolean mSelfObserverRegistered; -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/AbstractWindowedCursor.java b/sqlcipher/src/main/java/net/sqlcipher/AbstractWindowedCursor.java deleted file mode 100644 index f6150a02cfd45b36998998de3eb97085e9ee6848..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/AbstractWindowedCursor.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import ohos.data.resultset.ResultSet; - -/** - * A base class for Cursors that store their data in {@link CursorWindow}s. - */ -public abstract class AbstractWindowedCursor extends AbstractCursor { - @Override - public byte[] getBlob(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - return (byte[])getUpdatedField(columnIndex); - } - } - return mWindow.getBlob(mPos, columnIndex); - } - - @Override - public String getString(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - return (String)getUpdatedField(columnIndex); - } - } - return mWindow.getString(mPos, columnIndex); - } - - @Override - public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - super.copyStringToBuffer(columnIndex, buffer); - } - } - mWindow.copyStringToBuffer(mPos, columnIndex, buffer); - } - - @Override - public short getShort(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Number value = (Number)getUpdatedField(columnIndex); - return value.shortValue(); - } - } - return mWindow.getShort(mPos, columnIndex); - } - - @Override - public int getInt(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Number value = (Number)getUpdatedField(columnIndex); - return value.intValue(); - } - } - return mWindow.getInt(mPos, columnIndex); - } - - @Override - public long getLong(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Number value = (Number)getUpdatedField(columnIndex); - return value.longValue(); - } - } - return mWindow.getLong(mPos, columnIndex); - } - - @Override - public float getFloat(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Number value = (Number)getUpdatedField(columnIndex); - return value.floatValue(); - } - } - return mWindow.getFloat(mPos, columnIndex); - } - - @Override - public double getDouble(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Number value = (Number)getUpdatedField(columnIndex); - return value.doubleValue(); - } - } - return mWindow.getDouble(mPos, columnIndex); - } - - @Override - public boolean isColumnNull(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - return getUpdatedField(columnIndex) == null; - } - } - return mWindow.isNull(mPos, columnIndex); - } - - public boolean isBlob(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object == null || object instanceof byte[]; - } - } - return mWindow.isBlob(mPos, columnIndex); - } - - public boolean isString(int columnIndex) - { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object == null || object instanceof String; - } - } - return mWindow.isString(mPos, columnIndex); - } - - public boolean isLong(int columnIndex) { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object != null && (object instanceof Integer || object instanceof Long); - } - } - return mWindow.isLong(mPos, columnIndex); - } - - public boolean isFloat(int columnIndex) - { - checkPosition(); - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object != null && (object instanceof Float || object instanceof Double); - } - } - return mWindow.isFloat(mPos, columnIndex); - } - - @Override - public ColumnType getColumnTypeForIndex(int columnIndex) { - checkPosition(); - return mWindow.getType(mPos, columnIndex); - } - - @Override - protected void checkPosition() { - super.checkPosition(); - if (mWindow == null) { - throw new StaleDataException("Access closed cursor"); - } - } - - @Override - public CursorWindow getBlock() { - return mWindow; - } - - /** - * Set a new cursor window to cursor, usually set a remote cursor window - * @param window cursor window - */ - public void setWindow(CursorWindow window) { - if (mWindow != null) { - mWindow.close(); - } - mWindow = window; - } - - public boolean hasWindow() { - return mWindow != null; - } - - /** - * This needs be updated in {@link #onMove} by subclasses, and - * needs to be set to NULL when the contents of the cursor change. - */ - protected CursorWindow mWindow; -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/BulkCursorNative.java b/sqlcipher/src/main/java/net/sqlcipher/BulkCursorNative.java deleted file mode 100644 index 1c80ce22f8c990e6911c901a25910b41601b3f46..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/BulkCursorNative.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import ohos.rpc.IRemoteObject; -import ohos.rpc.MessageOption; -import ohos.rpc.MessageParcel; -import ohos.rpc.RemoteObject; -import ohos.utils.BasePacMap; -import ohos.utils.PacMap; - -import ohos.rpc.RemoteException; -import ohos.utils.Parcel; - -import java.util.HashMap; -import java.util.Map; - -/** - * Native implementation of the bulk cursor. This is only for use in implementing - * IPC, application code should use the Cursor interface. - * - * {@hide} - */ -public abstract class BulkCursorNative extends RemoteObject implements IBulkCursor -{ - public BulkCursorNative() - { - super(null); - attachLocalInterface(this, descriptor); - } - - /** - * Cast a Binder object into a content resolver interface, generating - * a proxy if needed. - * @param obj IRemoteObject - * @return IBulkCursor - */ - static public IBulkCursor asInterface(IRemoteObject obj) - { - if (obj == null) { - return null; - } - IBulkCursor in = (IBulkCursor)obj.queryLocalInterface(descriptor); - if (in != null) { - return in; - } - - return new BulkCursorProxy(obj); - } - - @Override - public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption flags) - throws RemoteException { - try { - switch (code) { - case GET_CURSOR_WINDOW_TRANSACTION: { - data.readInterfaceToken(); - int startPos = data.readInt(); - CursorWindow window = getWindow(startPos); - if (window == null) { - reply.writeInt(0); - return true; - } - reply.writeNoException(); - reply.writeInt(1); - window.marshalling(reply, 0); - return true; - } - - case COUNT_TRANSACTION: { - data.readInterfaceToken(); - int count = count(); - reply.writeNoException(); - reply.writeInt(count); - return true; - } - - case GET_COLUMN_NAMES_TRANSACTION: { - data.readInterfaceToken(); - String[] columnNames = getColumnNames(); - reply.writeNoException(); - reply.writeInt(columnNames.length); - int length = columnNames.length; - for (int i = 0; i < length; i++) { - reply.writeString(columnNames[i]); - } - return true; - } - - case DEACTIVATE_TRANSACTION: { - data.readInterfaceToken(); - deactivate(); - reply.writeNoException(); - return true; - } - - case CLOSE_TRANSACTION: { - data.readInterfaceToken(); - close(); - reply.writeNoException(); - return true; - } - - case REQUERY_TRANSACTION: { - data.readInterfaceToken(); - /* IContentObserver observer = - IContentObserver.Stub.asInterface(data.readRemoteObject()); - CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); - int count = requery(observer, window); - reply.writeNoException(); - reply.writeInt(count); // TODO AIDL - reply.writeParcelable(getExtras());*/ - return true; - } - - case UPDATE_ROWS_TRANSACTION: { - data.readInterfaceToken(); - // TODO - what ClassLoader should be passed to readHashMap? - // TODO - switch to Bundle - HashMap> values = (HashMap>)data.readMap(); - boolean result = updateRows(values); - reply.writeNoException(); - reply.writeInt((result == true ? 1 : 0)); - return true; - } - - case DELETE_ROW_TRANSACTION: { - data.readInterfaceToken(); - int position = data.readInt(); - boolean result = deleteRow(position); - reply.writeNoException(); - reply.writeInt((result == true ? 1 : 0)); - return true; - } - - case ON_MOVE_TRANSACTION: { - data.readInterfaceToken(); - int position = data.readInt(); - onMove(position); - reply.writeNoException(); - return true; - } - - case WANTS_ON_MOVE_TRANSACTION: { - data.readInterfaceToken(); - boolean result = getWantsAllOnMoveCalls(); - reply.writeNoException(); - reply.writeInt(result ? 1 : 0); - return true; - } - - case GET_EXTRAS_TRANSACTION: { - data.readInterfaceToken(); - PacMap extras = getExtras(); - reply.writeNoException(); - reply.writeSequenceable(extras); - return true; - } - - case RESPOND_TRANSACTION: { - data.readInterfaceToken(); - PacMap extras = data.createSequenceable(getClass().getClassLoader()); - PacMap returnExtras = respond(extras); - reply.writeNoException(); - reply.writeSequenceable(returnExtras); - return true; - } - /*default: - throw new IllegalStateException("Unexpected value: " + code);*/ - } - } catch (Exception e) { - DatabaseUtils.writeExceptionToParcel(reply, e); - return true; - } - return super.onRemoteRequest(code, data, reply, flags); //TODO today - } - - public IRemoteObject asObject() - { - return this; - } -} - -final class BulkCursorProxy implements IBulkCursor { - private IRemoteObject mRemote; - private PacMap mExtras; - - public BulkCursorProxy(IRemoteObject remote) - { - mRemote = remote; - mExtras = null; - } - - public IRemoteObject asObject() - { - return mRemote; - } - - public CursorWindow getWindow(int startPos) throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - data.writeInt(startPos); - - mRemote.sendRequest(GET_CURSOR_WINDOW_TRANSACTION, (MessageParcel) data, (MessageParcel)reply, new MessageOption(0));//todo - - DatabaseUtils.readExceptionFromParcel(reply); //todo - - CursorWindow window = null; - if (reply.readInt() == 1) { - window = CursorWindow.createFromParcel(reply); - } - - data.reclaim(); - reply.reclaim(); - - return window; - } - - public void onMove(int position) throws RemoteException { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - data.writeInt(position); - - mRemote.sendRequest(ON_MOVE_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - data.reclaim(); - reply.reclaim(); - } - - public int count() throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - boolean result = mRemote.sendRequest(COUNT_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - int count; - if (result == false) { - count = -1; - } else { - count = reply.readInt(); - } - data.reclaim(); - reply.reclaim(); - return count; - } - - public String[] getColumnNames() throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - mRemote.sendRequest(GET_COLUMN_NAMES_TRANSACTION, (MessageParcel)data,(MessageParcel) reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - String[] columnNames = null; - int numColumns = reply.readInt(); - columnNames = new String[numColumns]; - for (int i = 0; i < numColumns; i++) { - columnNames[i] = reply.readString(); - } - - data.reclaim(); - reply.reclaim(); - return columnNames; - } - - public void deactivate() throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - mRemote.sendRequest(DEACTIVATE_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - DatabaseUtils.readExceptionFromParcel(reply); - - data.reclaim(); - reply.reclaim(); - } - - public void close() throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - mRemote.sendRequest(CLOSE_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - DatabaseUtils.readExceptionFromParcel(reply); - - data.reclaim(); - reply.reclaim(); - } - - /*public int requery(IContentObserver observer, CursorWindow window) throws RemoteException { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - // ((MessageParcel)data).writeRemoteObject(observer);//todo AIDL - window.marshalling(data, 0); - - boolean result = mRemote.sendRequest(REQUERY_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - int count; - if (!result) { - count = -1; - } else { - count = reply.readInt(); - mExtras = reply.createSequenceable(getClass().getClassLoader()); - } - - data.reclaim(); - reply.reclaim(); - - return count; - }*/ - - public boolean updateRows(Map values) throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - data.writeMap(values); - - mRemote.sendRequest(UPDATE_ROWS_TRANSACTION, (MessageParcel)data,(MessageParcel) reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - boolean result = (reply.readInt() == 1); - - data.reclaim(); - reply.reclaim(); - - return result; - } - - public boolean deleteRow(int position) throws RemoteException - { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - data.writeInt(position); - - mRemote.sendRequest(DELETE_ROW_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - boolean result = (reply.readInt() == 1 ? true : false); - - data.reclaim(); - reply.reclaim(); - - return result; - } - - public boolean getWantsAllOnMoveCalls() throws RemoteException { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - mRemote.sendRequest(WANTS_ON_MOVE_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - int result = reply.readInt(); - data.reclaim(); - reply.reclaim(); - return result != 0; - } - - public PacMap getExtras() throws RemoteException { - if (mExtras == null) { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - mRemote.sendRequest(GET_EXTRAS_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - reply.addAppClassLoader(ClassLoader.getSystemClassLoader()); - mExtras = reply.createSequenceable(getClass().getClassLoader()); - data.reclaim(); - reply.reclaim(); - } - return mExtras; - } - - public PacMap respond(PacMap extras) throws RemoteException { - Parcel data = Parcel.create(); - Parcel reply = Parcel.create(); - - ((MessageParcel)data).writeInterfaceToken(descriptor); - - data.writeSequenceable(extras); - - mRemote.sendRequest(RESPOND_TRANSACTION, (MessageParcel)data, (MessageParcel)reply, new MessageOption(0)); - - DatabaseUtils.readExceptionFromParcel(reply); - - PacMap returnExtras = reply.createSequenceable(getClass().getClassLoader()); - data.reclaim(); - reply.reclaim(); - return returnExtras; - } -} - - diff --git a/sqlcipher/src/main/java/net/sqlcipher/BulkCursorToCursorAdaptor.java b/sqlcipher/src/main/java/net/sqlcipher/BulkCursorToCursorAdaptor.java deleted file mode 100644 index 874e040ba76748053ac142b2b41385109d3ef309..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/BulkCursorToCursorAdaptor.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import java.util.Map; - -import ohos.data.rdb.DataObserver; -import ohos.hiviewdfx.HiLogLabel; -import ohos.utils.PacMap; -import ohos.rpc.RemoteException; -import ohos.hiviewdfx.HiLog; - -/** - * Adapts an {@link IBulkCursor} to a {@link Cursor} for use in the local - * process. - * - * {@hide} - */ -public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor { - static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00203, "BulkCursorToCursorAdaptor"); - - private SelfContentObserver mObserverBridge; - private IBulkCursor mBulkCursor; - private int mCount; - private String[] mColumns; - private boolean mWantsAllOnMoveCalls; - - public void set(IBulkCursor bulkCursor) { - mBulkCursor = bulkCursor; - - try { - mCount = mBulkCursor.count(); - mWantsAllOnMoveCalls = mBulkCursor.getWantsAllOnMoveCalls(); - - // Search for the rowID column index and set it for our parent - mColumns = mBulkCursor.getColumnNames(); - mRowIdColumnIndex = findRowIdColumnIndex(mColumns); - } catch (RemoteException ex) { - HiLog.error(label, "Setup failed because the remote process is dead"); - } - } - - /** - * Version of set() that does fewer Binder calls if the caller - * already knows BulkCursorToCursorAdaptor's properties. - * @param bulkCursor bulkCursor - * @param count count - * @param idIndex index - */ - public void set(IBulkCursor bulkCursor, int count, int idIndex) { - mBulkCursor = bulkCursor; - mColumns = null; // lazily retrieved - mCount = count; - mRowIdColumnIndex = idIndex; - } - - /** - * Returns column index of "_id" column, or -1 if not found. - * @param columnNames columnNames - * @return index - */ - public static int findRowIdColumnIndex(String[] columnNames) { - int length = columnNames.length; - for (int i = 0; i < length; i++) { - if (columnNames[i].equals("_id")) { - return i; - } - } - return -1; - } - - /** - * Gets a SelfDataChangeOberserver that can be sent to a remote - * process to receive change notifications over IPC. - * - * @return A SelfContentObserver hooked up to this Cursor - */ - /* public synchronized IContentObserver getObserver() { - if (mObserverBridge == null) { - mObserverBridge = new SelfContentObserver(this); - } - return null;//mObserverBridge.getContentObserver(); //TODO nf fix this - }*/ - - @Override - public int getRowCount() { - return mCount; - } - - @Override - public boolean onGo(int oldPosition, int newPosition) { - try { - // Make sure we have the proper window - if (mWindow != null) { - if (newPosition < mWindow.getStartRowIndex() || - newPosition >= (mWindow.getStartRowIndex() + mWindow.getRowCount())) { - mWindow = mBulkCursor.getWindow(newPosition); - } else if (mWantsAllOnMoveCalls) { - mBulkCursor.onMove(newPosition); - } - } else { - mWindow = mBulkCursor.getWindow(newPosition); - } - } catch (RemoteException ex) { - // We tried to get a window and failed - HiLog.error(label, "Unable to get window because the remote process is dead"); - return false; - } - - // Couldn't obtain a window, something is wrong - if (mWindow == null) { - return false; - } - - return true; - } - - @Override - public void deactivate() { - // This will call onInvalidated(), so make sure to do it before calling release, - // which is what actually makes the data set invalid. - super.deactivate(); - - try { - mBulkCursor.deactivate(); - } catch (RemoteException ex) { - HiLog.warn(label, "Remote process exception when deactivating"); - } - mWindow = null; - } - - @Override - public void close() { - super.close(); - try { - mBulkCursor.close(); - } catch (RemoteException ex) { - HiLog.warn(label, "Remote process exception when closing"); - } - mWindow = null; - } - - @Override - public boolean requery() { - try { - int oldCount = mCount; - //TODO get the window from a pool somewhere to avoid creating the memory dealer - /*mCount = mBulkCursor.requery(getObserver(), new CursorWindow( - false *//* the window will be accessed across processes *//*));*/ //todo - if (mCount != -1) { - mPos = -1; - mWindow = null; - - // super.requery() will call onChanged. Do it here instead of relying on the - // observer from the far side so that observers can see a correct value for mCount - // when responding to onChanged. - super.requery(); - return true; - } else { - deactivate(); - return false; - } - } catch (Exception ex) { - HiLog.error(label, "Unable to requery because the remote process exception ",ex.getMessage()); - deactivate(); - return false; - } - } - - /** - * deleteRow - * @hide - * @deprecated - * @return true/false - */ - @Override - public boolean deleteRow() { - try { - boolean result = mBulkCursor.deleteRow(mPos); - if (result != false) { - // The window contains the old value, discard it - mWindow = null; - - // Fix up the position - mCount = mBulkCursor.count(); - if (mPos < mCount) { - int oldPos = mPos; - mPos = -1; - goToRow(oldPos); - } else { - mPos = mCount; - } - - // Send the change notification - onChange(true); - } - return result; - } catch (RemoteException ex) { - HiLog.error(label, "Unable to delete row because the remote process is dead"); - return false; - } - } - - @Override - public String[] getAllColumnNames() { - if (mColumns == null) { - try { - mColumns = mBulkCursor.getColumnNames(); - } catch (RemoteException ex) { - HiLog.error(label, "Unable to fetch column names because the remote process is dead"); - return null; - } - } - return mColumns; - } - - /** - * commitUpdates - * @hide - * @deprecated - * @param additionalValues additionalValues - * @return true/false - */ - @Override - public boolean commitUpdates(Map> additionalValues) { - if (!supportsUpdates()) { - HiLog.error(label, "commitUpdates not supported on this cursor, did you include the _id column?"); - return false; - } - - synchronized(mUpdatedRows) { - if (additionalValues != null) { - mUpdatedRows.putAll(additionalValues); - } - - if (mUpdatedRows.size() <= 0) { - return false; - } - - try { - boolean result = mBulkCursor.updateRows(mUpdatedRows); - - if (result == true) { - mUpdatedRows.clear(); - - // Send the change notification - onChange(true); - } - return result; - } catch (RemoteException ex) { - HiLog.error(label, "Unable to commit updates because the remote process is dead"); - return false; - } - } - } - - @Override - public PacMap getExtensions() { - try { - return mBulkCursor.getExtras(); - } catch (RemoteException e) { - // This should never happen because the system kills processes that are using remote - // cursors when the provider process is killed. - throw new RuntimeException(e); - } - } - - @Override - public PacMap respond(PacMap extras) { - try { - return mBulkCursor.respond(extras); - } catch (RemoteException e) { - // the system kills processes that are using remote cursors when the provider process - // is killed, but this can still happen if this is being called from the system process, - // so, better to log and return an empty bundle. - HiLog.warn(label, "respond() threw RemoteException, returning an empty bundle.", e); - return PacMap.EMPTY_PAC_MAP; - } - } - - @Override - public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) { - // TODO Auto-generated method stub - - } - - @Override - public void registerObserver(DataObserver observer) { - // TODO Auto-generated method stub - - } - -/* @Override - public void registerdataSetObserver(DataSetObserver observer) { { //todo no such method in hmos abstractcursor - // TODO Auto-generated method stub - - }*/ - - @Override - public void unregisterObserver(DataObserver observer) { - // TODO Auto-generated method stub - - } - -/*// @Override - public void unregisterDataSetObserver(DataSetObserver observer) { //todo no such method in hmos abstractcursor - // TODO Auto-generated method stub - - }*/ - - - - -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/CharArrayBuffer.java b/sqlcipher/src/main/java/net/sqlcipher/CharArrayBuffer.java deleted file mode 100644 index f5a2359ceef2127961db2a7be48bc235542f0b55..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CharArrayBuffer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -/** - * This is used for {@link Cursor#copyStringToBuffer} - */ -public final class CharArrayBuffer { - public CharArrayBuffer(int size) { - data = new char[size]; - } - - public CharArrayBuffer(char[] buf) { - data = buf; - } - - public char[] data; // In and out parameter - public int sizeCopied; // Out parameter -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/CrossProcessCursorWrapper.java b/sqlcipher/src/main/java/net/sqlcipher/CrossProcessCursorWrapper.java deleted file mode 100644 index 7e439e278ea034f82982c30982710101d4b8e369..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CrossProcessCursorWrapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.sqlcipher; - -import ohos.data.resultset.ResultSet; -import ohos.data.resultset.SharedBlock; -import ohos.data.resultset.SharedResultSet; - -public class CrossProcessCursorWrapper extends CursorWrapper implements SharedResultSet { - - public CrossProcessCursorWrapper(ResultSet cursor) { - super(cursor); - } - - @Override - public SharedBlock getBlock() { - return null; - } - - @Override - public void fillBlock(int position, SharedBlock window) { - DatabaseUtils.cursorFillWindow(this, position, window); - } - - @Override - public boolean onGo(int oldPosition, int newPosition) { - return true; - } -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/CursorIndexOutOfBoundsException.java b/sqlcipher/src/main/java/net/sqlcipher/CursorIndexOutOfBoundsException.java deleted file mode 100644 index 71bc8a3195c8f9cc0b004f544f785e4ff03f6def..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CursorIndexOutOfBoundsException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -/** - * An exception indicating that a cursor is out of bounds. - */ -public class CursorIndexOutOfBoundsException extends IndexOutOfBoundsException { - - public CursorIndexOutOfBoundsException(int index, int size) { - super("Index " + index + " requested, with a size of " + size); - } - - public CursorIndexOutOfBoundsException(String message) { - super(message); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/CursorWindow.java b/sqlcipher/src/main/java/net/sqlcipher/CursorWindow.java deleted file mode 100644 index 3a813e26bf137dca65616e7f6471a4fa649bc6cd..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CursorWindow.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import net.sqlcipher.CharArrayBuffer; -import ohos.data.resultset.ResultSet; -import ohos.rpc.IRemoteObject; -import ohos.rpc.MessageParcel; -import ohos.utils.Parcel; -import ohos.utils.Sequenceable; - -/** - * A buffer containing multiple cursor rows. - */ -public class CursorWindow extends ohos.data.resultset.SharedBlock implements Sequenceable { - private long nWindow; - private int mStartPos; - private int mRequiredPos; - CursorWindowHelper cursorWindowHelper = new CursorWindowHelper(); - private static CursorWindowAllocation allocation = new DefaultCursorWindowAllocation(); - - public static void setCursorWindowAllocation(CursorWindowAllocation value){ - allocation = value; - } - public static CursorWindowAllocation getCursorWindowAllocation() { - return allocation; - } - - /** - * Creates a new empty window. - * - * @param localWindow true if this window will be used in this process only - */ - public CursorWindow(boolean localWindow) { - super(""); // todo no super constructor taking in boolean value - mStartPos = 0; - if(allocation == null){ - allocation = new DefaultCursorWindowAllocation(); - } - cursorWindowHelper = new CursorWindowHelper(); - native_init(localWindow, - allocation.getInitialAllocationSize(), - allocation.getGrowthPaddingSize(), - allocation.getMaxAllocationSize()); - } - /** - * Returns the starting position of this window within the entire - * Cursor's result set. - * - * @return the starting position of this window within the entire - * Cursor's result set. - */ - public int getStartRowIndex() { - return mStartPos; - } - - /** - * Set the start position of cursor window - * @param pos - */ - public void setStartRowIndex(int pos) { - mStartPos = pos; - } - - public int getRequiredPosition(){ - return mRequiredPos; - } - - public void setRequiredPosition(int pos) { - mRequiredPos = pos; - } - - /** - * Returns the number of rows in this window. - * - * @return the number of rows in this window. - */ - public int getRowCount() { - cursorWindowHelper.acquireReference(); - try { - return getNumRows_native(); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native int getNumRows_native(); - /** - * Set number of Columns - * @param columnNum - * @return true if success - */ - public boolean setColumnCount(int columnNum) { - cursorWindowHelper.acquireReference(); - try { - return setNumColumns_native(columnNum); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean setNumColumns_native(int columnNum); - - /** - * Allocate a row in cursor window - * @return false if cursor window is out of memory - */ - public boolean allocateRow(){ - cursorWindowHelper.acquireReference(); - try { - return allocRow_native(); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean allocRow_native(); - - /** - * Free the last row - */ - public void freeLastRow(){ - cursorWindowHelper.acquireReference(); - try { - freeLastRow_native(); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native void freeLastRow_native(); - - /** - * copy byte array to cursor window - * @param value - * @param row - * @param col - * @return false if fail to copy - */ - public boolean putBlob(int row, int col, byte[] value) { - cursorWindowHelper.acquireReference(); - try { - return putBlob_native(value, row - mStartPos, col); // todo native methods needs to check format - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean putBlob_native(byte[] value, int row, int col); - - /** - * Copy String to cursor window - * @param value - * @param row - * @param col - * @return false if fail to copy - */ - public boolean putString(int row, int col, String value) { - cursorWindowHelper.acquireReference(); - try { - return putString_native(value, row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean putString_native(String value, int row, int col); - - /** - * Copy integer to cursor window - * @param value - * @param row - * @param col - * @return false if fail to copy - */ - public boolean putLong(int row, int col, long value) { - cursorWindowHelper.acquireReference(); - try { - return putLong_native(value, row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean putLong_native(long value, int row, int col); - - - /** - * Copy double to cursor window - * @param value - * @param row - * @param col - * @return false if fail to copy - */ - public boolean putDouble(int row, int col, double value) { - cursorWindowHelper.acquireReference(); - try { - return putDouble_native(value, row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean putDouble_native(double value, int row, int col); - - /** - * Set the [row, col] value to NULL - * @param row - * @param col - * @return false if fail to copy - */ - public boolean putNull(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return putNull_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean putNull_native(int row, int col); - - - /** - * Returns {@code true} if given field is {@code NULL}. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return {@code true} if given field is {@code NULL} - */ - public boolean isNull(int row, int col) { //deprecated - cursorWindowHelper.acquireReference(); - try { - return isNull_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean isNull_native(int row, int col); - - /** - * Returns a byte array for the given field. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a String value for the given field - */ - public byte[] getBlob(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return getBlob_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns the value at (row, col) as a byte array. - * - *

If the value is null, then null is returned. If the - * type of column col is a string type, then the result - * is the array of bytes that make up the internal representation of the - * string value. If the type of column col is integral or floating-point, - * then an {@link SQLiteException} is thrown. - * - * @param row row - * @param col column - * @return byte[] - */ - private native byte[] getBlob_native(int row, int col); - - /** - * Returns data type of the given column's value. - *

- * Returned column types are - *

    - *
  • {@link Cursor#FIELD_TYPE_NULL}
  • - *
  • {@link Cursor#FIELD_TYPE_INTEGER}
  • - *
  • {@link Cursor#FIELD_TYPE_FLOAT}
  • - *
  • {@link Cursor#FIELD_TYPE_STRING}
  • - *
  • {@link Cursor#FIELD_TYPE_BLOB}
  • - *
- *

- * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return the value type - */ - public ResultSet.ColumnType getType(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - int value = getType_native(row - mStartPos, col); - return getColumnTypefromNative(value); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - public ResultSet.ColumnType getColumnTypefromNative(int value) { - if (value == 0) { - return ResultSet.ColumnType.TYPE_NULL; - } else if (value == 1) { - return ResultSet.ColumnType.TYPE_INTEGER; - } else if (value == 2) { - return ResultSet.ColumnType.TYPE_FLOAT; - } else if (value == 3) { - return ResultSet.ColumnType.TYPE_STRING; - } else { - return ResultSet.ColumnType.TYPE_BLOB; - } - } - - /** - * Checks if a field contains either a blob or is null. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return {@code true} if given field is {@code NULL} or a blob - * @deprecated use {@link #getType(int, int)} instead - */ - public boolean isBlob(int row, int col) { //deprecated - cursorWindowHelper.acquireReference(); - try { - return isBlob_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Checks if a field contains a long - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return {@code true} if given field is a long - * @deprecated use {@link #getType(int, int)} instead - */ - public boolean isLong(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return isInteger_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Checks if a field contains a float. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return {@code true} if given field is a float - * @deprecated use {@link #getType(int, int)} instead - */ - public boolean isFloat(int row, int col) { //deprecated - cursorWindowHelper.acquireReference(); - try { - return isFloat_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Checks if a field contains either a String or is null. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return {@code true} if given field is {@code NULL} or a String - * @deprecated use {@link #getType(int, int)} instead - */ - public boolean isString(int row, int col) { //deprecated - cursorWindowHelper.acquireReference(); - try { - return isString_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native boolean isBlob_native(int row, int col); - private native boolean isString_native(int row, int col); - private native boolean isInteger_native(int row, int col); - private native boolean isFloat_native(int row, int col); - - private native int getType_native(int row, int col); - - /** - * Returns a String for the given field. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a String value for the given field - */ - public String getString(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return getString_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns the value at (row, col) as a String. - * - *

If the value is null, then null is returned. If the - * type of column col is integral, then the result is the string - * that is obtained by formatting the integer value with the printf - * family of functions using format specifier %lld. If the - * type of column col is floating-point, then the result is the string - * that is obtained by formatting the floating-point value with the - * printf family of functions using format specifier %g. - * If the type of column col is a blob type, then an - * {@link SQLiteException} is thrown. - * - * @param row row - * @param col column - * @return string - */ - private native String getString_native(int row, int col); - //private native byte[] getString_native(int row, int col); - - /** - * copy the text for the given field in the provided char array. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @param buffer the CharArrayBuffer to copy the text into, - * If the requested string is larger than the buffer - * a new char buffer will be created to hold the string. and assigne to - * CharArrayBuffer.data - */ - public void copyStringToBuffer(int row, int col, CharArrayBuffer buffer) { - if (buffer == null) { - throw new IllegalArgumentException("CharArrayBuffer should not be null"); - } - if (buffer.data == null) { - buffer.data = new char[64]; - } - cursorWindowHelper.acquireReference(); - try { - char[] newbuf = copyStringToBuffer_native( - row - mStartPos, col, buffer.data.length, buffer); //todo hos native api is required - if (newbuf != null) { - buffer.data = newbuf; - } - } finally { - cursorWindowHelper.releaseReference(); - } - } - - private native char[] copyStringToBuffer_native( - int row, int col, int bufferSize, CharArrayBuffer buffer); - - /** - * Returns a long for the given field. - * row is 0 based - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a long value for the given field - */ - public long getLong(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return getLong_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns the value at (row, col) as a long. - * - *

If the value is null, then 0L is returned. If the - * type of column col is a string type, then the result - * is the long that is obtained by parsing the string value with - * strtoll. If the type of column col is - * floating-point, then the result is the floating-point value casted to a long. - * If the type of column col is a blob type, then an - * {@link SQLiteException} is thrown. - * - * @param row row - * @param col column - * @return value - */ - private native long getLong_native(int row, int col); - - /** - * Returns a double for the given field. - * row is 0 based - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a double value for the given field - */ - public double getDouble(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return getDouble_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns the value at (row, col) as a double. - * - *

If the value is null, then 0.0 is returned. If the - * type of column col is a string type, then the result - * is the double that is obtained by parsing the string value with - * strtod. If the type of column col is - * integral, then the result is the integer value casted to a double. - * If the type of column col is a blob type, then an - * {@link SQLiteException} is thrown. - * - * @param row row - * @param col column - * @return value - */ - private native double getDouble_native(int row, int col); - - /** - * Returns a short for the given field. - * row is 0 based - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a short value for the given field - */ - public short getShort(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return (short) getLong_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns an int for the given field. - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return an int value for the given field - */ - public int getInt(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return (int) getLong_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Returns a float for the given field. - * row is 0 based - * - * @param row the row to read from, row - getStartPosition() being the actual row in the window - * @param col the column to read from - * @return a float value for the given field - */ - public float getFloat(int row, int col) { - cursorWindowHelper.acquireReference(); - try { - return (float) getDouble_native(row - mStartPos, col); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** - * Clears out the existing contents of the window, making it safe to reuse - * for new data. Note that the number of columns in the window may NOT - * change across a call to clear(). - */ - public void clear() { - cursorWindowHelper.acquireReference(); - try { - mStartPos = 0; - native_clear(); - } finally { - cursorWindowHelper.releaseReference(); - } - } - - /** Clears out the native side of things */ - private native void native_clear(); - - /** - * Cleans up the native resources associated with the window. - */ - public void close() { - cursorWindowHelper.releaseReference(); - } - - private native void close_native(); - - @Override - protected void finalize() { - // Just in case someone forgot to call close... - if (nWindow == 0) { - return; - } - close_native(); - } - - public static final Producer CREATOR - = new Producer() { - public CursorWindow createFromParcel(Parcel source) { - return new CursorWindow(source,0); - } - public CursorWindow[] newArray(int size) { - return new CursorWindow[size]; - } - }; - - public boolean unmarshalling(Parcel p) { - return false; //not used - } - - public static CursorWindow createFromParcel(Parcel parcel) { - return CREATOR.createFromParcel(parcel); - } - - public int describeContents() { - return 0; - } - - public boolean marshalling(Parcel dest, int flags) { - ((MessageParcel) dest).writeRemoteObject(native_getBinder()); - return dest.writeInt(mStartPos); - } - - public CursorWindow(Parcel source,int foo) { - super(""); - IRemoteObject nativeBinder = ((MessageParcel) source).readRemoteObject(); - mStartPos = source.readInt(); - - native_init(nativeBinder); - } - - public void acquireRef() { - cursorWindowHelper.acquireReference(); - } - - public void releaseRef() { - cursorWindowHelper.releaseReference(); - } - - /** Get the binder for the native side of the window - * @return IRemoteObject - */ - private native IRemoteObject native_getBinder(); - - /** Does the native side initialization for an empty window - * @param localOnly flag - * @param initialSize initialSize - * @param growthPaddingSize growthPaddingSize - * @param maxSize max size - */ - private native void native_init(boolean localOnly, long initialSize, - long growthPaddingSize, long maxSize); - - /** Does the native side initialization with an existing binder from another process - * @param nativeBinder IRemoteObject - */ - private native void native_init(IRemoteObject nativeBinder); - - protected void onAllReferencesReleased() { - close_native(); - // super.onAllReferencesReleased(); //todo no such method in superclass - } -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/CursorWindowAllocation.java b/sqlcipher/src/main/java/net/sqlcipher/CursorWindowAllocation.java deleted file mode 100644 index 6b4c47f25f42f3c319e29bf8bc8442becf394d74..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CursorWindowAllocation.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.sqlcipher; - -public interface CursorWindowAllocation { - long getInitialAllocationSize(); - long getGrowthPaddingSize(); - long getMaxAllocationSize(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/CursorWindowHelper.java b/sqlcipher/src/main/java/net/sqlcipher/CursorWindowHelper.java deleted file mode 100644 index 496c22913eba4101a2c82a6459084c1745d10c15..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CursorWindowHelper.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.sqlcipher; - -import net.sqlcipher.database.SQLiteClosableHos; - -public class CursorWindowHelper extends SQLiteClosableHos { - - @Override - protected void onAllReferencesReleased() { - //no implementation can be provided now , native dependency on dispose(); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/CursorWrapper.java b/sqlcipher/src/main/java/net/sqlcipher/CursorWrapper.java deleted file mode 100644 index fa2b49275a78dfcc527da83ad958c74ed8944b76..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CursorWrapper.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import ohos.data.resultset.ResultSet; - -/** - * Extension of ohos.data.resultset.ResultSetWrapper to support getColumnTypeForIndex(). - */ -public class CursorWrapper extends ohos.data.resultset.ResultSetWrapper implements ResultSet { - - private final ResultSet mCursor; - - public CursorWrapper(ResultSet cursor) { - super(cursor); - mCursor = cursor; - } - - public ColumnType getColumnTypeForIndex(int columnIndex) { - return mCursor.getColumnTypeForIndex(columnIndex); - } - - public ResultSet getResultSet() { - return mCursor; - } -} - - diff --git a/sqlcipher/src/main/java/net/sqlcipher/CustomCursorWindowAllocation.java b/sqlcipher/src/main/java/net/sqlcipher/CustomCursorWindowAllocation.java deleted file mode 100644 index 9575dafe768300430eea4550f7655bd07645ed15..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/CustomCursorWindowAllocation.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.sqlcipher; - -import net.sqlcipher.CursorWindowAllocation; - -public class CustomCursorWindowAllocation implements CursorWindowAllocation { - - private long initialAllocationSize = 0L; - private long growthPaddingSize = 0L; - private long maxAllocationSize = 0L; - - public CustomCursorWindowAllocation(long initialSize, - long growthPaddingSize, - long maxAllocationSize){ - this.initialAllocationSize = initialSize; - this.growthPaddingSize = growthPaddingSize; - this.maxAllocationSize = maxAllocationSize; - } - - public long getInitialAllocationSize() { - return initialAllocationSize; - } - - public long getGrowthPaddingSize() { - return growthPaddingSize; - } - - public long getMaxAllocationSize() { - return maxAllocationSize; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/DatabaseErrorHandler.java b/sqlcipher/src/main/java/net/sqlcipher/DatabaseErrorHandler.java deleted file mode 100644 index 58096f1d8947f1cf08b03adc3e093636eb04bcdc..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/DatabaseErrorHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import net.sqlcipher.database.SQLiteDatabase; - -/** - * An interface to let the apps define the actions to take when the following errors are detected - * database corruption - */ -public interface DatabaseErrorHandler { - - /** - * defines the method to be invoked when database corruption is detected. - * @param dbObj the {@link SQLiteDatabase} object representing the database on which corruption - * is detected. - */ - void onCorruption(SQLiteDatabase dbObj); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/DefaultCursorWindowAllocation.java b/sqlcipher/src/main/java/net/sqlcipher/DefaultCursorWindowAllocation.java deleted file mode 100644 index 47b5f5480e103395b39cd7e92fbfe66baaba4407..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/DefaultCursorWindowAllocation.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.sqlcipher; - -import net.sqlcipher.CursorWindowAllocation; - -public class DefaultCursorWindowAllocation implements CursorWindowAllocation { - - private long initialAllocationSize = 1024 * 1024; - private long WindowAllocationUnbounded = 0; - - public long getInitialAllocationSize() { - return initialAllocationSize; - } - - public long getGrowthPaddingSize() { - return initialAllocationSize; - } - - public long getMaxAllocationSize() { - return WindowAllocationUnbounded; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/DefaultDatabaseErrorHandler.java b/sqlcipher/src/main/java/net/sqlcipher/DefaultDatabaseErrorHandler.java deleted file mode 100644 index 155d91fa3a2cbd4010c1bf199a2931aeb1c0d090..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/DefaultDatabaseErrorHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import java.io.File; -import java.util.List; - -import net.sqlcipher.database.SQLiteDatabase; - -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -/** - * Default class used to define the actions to take when the database corruption is reported - * by sqlite. - *

- * If null is specified for DatabaeErrorHandler param in the above calls, then this class is used - * as the default {@link DatabaseErrorHandler}. - */ -public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler { - - private final String TAG = getClass().getSimpleName(); - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00209, "DefaultDatabaseErrorHandler"); - - /** - * defines the default method to be invoked when database corruption is detected. - * @param dbObj the {@link SQLiteDatabase} object representing the database on which corruption - * is detected. - */ - - public void onCorruption(SQLiteDatabase dbObj) { - // NOTE: Unlike the AOSP, this version does NOT attempt to delete any attached databases. - // TBD: Are we really certain that the attached databases would really be corrupt? - HiLog.error(label, "Corruption reported by sqlite on database, deleting: " + dbObj.getPath()); - - if (dbObj.isOpen()) { - HiLog.error(label, "Database object for corrupted database is already open, closing"); - - try { - dbObj.close(); - } catch (Exception e) { - /* ignored */ - HiLog.error(label, "Exception closing Database object for corrupted database, ignored", e); - } - } - - deleteDatabaseFile(dbObj.getPath()); - } - - private void deleteDatabaseFile(String fileName) { - if (fileName.equalsIgnoreCase(":memory:") || fileName.trim().length() == 0) { - return; - } - HiLog.error(label, "deleting the database file: " + fileName); - try { - boolean isDelete = new File(fileName).delete(); - } catch (Exception e) { - /* print warning and ignore exception */ - HiLog.warn(label, "delete failed: " + e.getMessage()); - } - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/IBulkCursor.java b/sqlcipher/src/main/java/net/sqlcipher/IBulkCursor.java deleted file mode 100644 index f5f399d7526e33a5b378c2290f521d86d2736831..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/IBulkCursor.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import ohos.rpc.RemoteException; -import ohos.rpc.IRemoteBroker; -import ohos.rpc.IRemoteObject; -import ohos.utils.PacMap; - -import java.util.Map; - -/** - * This interface provides a low-level way to pass bulk cursor data across - * both process and language boundries. Application code should use the Cursor - * interface directly. - * - * {@hide} - */ -public interface IBulkCursor extends IRemoteBroker { - /** - * Returns a BulkCursorWindow, which either has a reference to a shared - * memory segment with the rows, or an array of JSON strings. - * @param startPos startPos - * @return CursorWindow - * @throws RemoteException RemoteException - */ - public CursorWindow getWindow(int startPos) throws RemoteException; - - public void onMove(int position) throws RemoteException; - - /** - * Returns the number of rows in the cursor. - * - * @return the number of rows in the cursor. - * @throws RemoteException RemoteException - */ - public int count() throws RemoteException; - - /** - * Returns a string array holding the names of all of the columns in the - * cursor in the order in which they were listed in the result. - * - * @return the names of the columns returned in this query. - * @throws RemoteException RemoteException - */ - public String[] getColumnNames() throws RemoteException; - - public boolean updateRows(Map> values) throws RemoteException; - - public boolean deleteRow(int position) throws RemoteException; - - public void deactivate() throws RemoteException; - - public void close() throws RemoteException; - - // public int requery(IContentObserver observer, CursorWindow window) throws RemoteException; - - boolean getWantsAllOnMoveCalls() throws RemoteException; - - PacMap getExtras() throws RemoteException; - - PacMap respond(PacMap extras) throws RemoteException; - - /* IPC constants */ - static final String descriptor = "IBulkCursor"; - - static final int GET_CURSOR_WINDOW_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID; - static final int COUNT_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 1; - static final int GET_COLUMN_NAMES_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 2; - static final int UPDATE_ROWS_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 3; - static final int DELETE_ROW_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 4; - static final int DEACTIVATE_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 5; - static final int REQUERY_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 6; - static final int ON_MOVE_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 7; - static final int WANTS_ON_MOVE_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 8; - static final int GET_EXTRAS_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 9; - static final int RESPOND_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 10; - static final int CLOSE_TRANSACTION = IRemoteObject.MIN_TRANSACTION_ID + 11; -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/InvalidRowColumnException.java b/sqlcipher/src/main/java/net/sqlcipher/InvalidRowColumnException.java deleted file mode 100644 index 275b28d9fc1ff2fbbbec2e28b450d7eb04a07303..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/InvalidRowColumnException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.sqlcipher; - -/** - * An exception that indicates there was an error accessing a specific row/column. - */ -public class InvalidRowColumnException extends RuntimeException -{ - public InvalidRowColumnException() {} - - public InvalidRowColumnException(String error) - { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/MatrixCursor.java b/sqlcipher/src/main/java/net/sqlcipher/MatrixCursor.java deleted file mode 100644 index 996bd4c9eb69a59a2f0e9dcd557c8dc015bef043..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/MatrixCursor.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -import java.util.ArrayList; -import ohos.data.resultset.ResultSet; - -/** - * A mutable cursor implementation backed by an array of {@code Object}s. Use - * {@link #newRow()} to add rows. Automatically expands internal capacity - * as needed. - */ -public class MatrixCursor extends AbstractCursor { - - private final String[] columnNames; - private Object[] data; - private int rowCount = 0; - private final int columnCount; - - /** - * Constructs a new cursor with the given initial capacity. - * - * @param columnNames names of the columns, the ordering of which - * determines column ordering elsewhere in this cursor - * @param initialCapacity in rows - */ - public MatrixCursor(String[] columnNames, int initialCapacity) { - this.columnNames = columnNames; - this.columnCount = columnNames.length; - - if (initialCapacity < 1) { - initialCapacity = 1; - } - - this.data = new Object[columnCount * initialCapacity]; - } - - /** - * Constructs a new cursor. - * - * @param columnNames names of the columns, the ordering of which - * determines column ordering elsewhere in this cursor - */ - public MatrixCursor(String[] columnNames) { - this(columnNames, 16); - } - - /** - * Gets value at the given column for the current row. - * @param column column - * @return value - */ - private Object get(int column) { - if (column < 0 || column >= columnCount) { - throw new CursorIndexOutOfBoundsException("Requested column: " - + column + ", # of columns: " + columnCount); - } - if (mPos < 0) { - throw new CursorIndexOutOfBoundsException("Before first row."); - } - if (mPos >= rowCount) { - throw new CursorIndexOutOfBoundsException("After last row."); - } - return data[mPos * columnCount + column]; - } - - /** - * Adds a new row to the end and returns a builder for that row. Not safe - * for concurrent use. - * - * @return builder which can be used to set the column values for the new - * row - */ - public RowBuilder addRowByBuilder() { - rowCount++; - int endIndex = rowCount * columnCount; - ensureCapacity(endIndex); - int start = endIndex - columnCount; - return new RowBuilder(start, endIndex); - } - - /** - * Adds a new row to the end with the given column values. Not safe - * for concurrent use. - * - * @throws IllegalArgumentException if {@code columnValues.length != - * columnNames.length} - * @param columnValues in the same order as the the column names specified - * at cursor construction time - */ - public void addRow(Object[] columnValues) { - if (columnValues.length != columnCount) { - throw new IllegalArgumentException("columnNames.length = " - + columnCount + ", columnValues.length = " - + columnValues.length); - } - - int start = rowCount++ * columnCount; - ensureCapacity(start + columnCount); - System.arraycopy(columnValues, 0, data, start, columnCount); - } - - /** - * Adds a new row to the end with the given column values. Not safe - * for concurrent use. - * - * @throws IllegalArgumentException if {@code columnValues.size() != - * columnNames.length} - * @param columnValues in the same order as the the column names specified - * at cursor construction time - */ - public void addRow(Iterable columnValues) { - int start = rowCount * columnCount; - int end = start + columnCount; - ensureCapacity(end); - - if (columnValues instanceof ArrayList) { - addRow((ArrayList) columnValues, start); - return; - } - - int current = start; - Object[] localData = data; - for (Object columnValue : columnValues) { - if (current == end) { - // TODO: null out row? - throw new IllegalArgumentException( - "columnValues.size() > columnNames.length"); - } - localData[current++] = columnValue; - } - - if (current != end) { - // TODO: null out row? - throw new IllegalArgumentException( - "columnValues.size() < columnNames.length"); - } - - // Increase row count here in case we encounter an exception. - rowCount++; - } - - /** Optimization for {@link ArrayList}. - * @param columnValues columnValues - * @param start start - */ - private void addRow(ArrayList columnValues, int start) { - int size = columnValues.size(); - if (size != columnCount) { - throw new IllegalArgumentException("columnNames.length = " - + columnCount + ", columnValues.size() = " + size); - } - - rowCount++; - Object[] localData = data; - for (int i = 0; i < size; i++) { - localData[start + i] = columnValues.get(i); - } - } - - /** Ensures that this cursor has enough capacity. - * @param size size - */ - private void ensureCapacity(int size) { - if (size > data.length) { - Object[] oldData = this.data; - int newSize = data.length * 2; - if (newSize < size) { - newSize = size; - } - this.data = new Object[newSize]; - System.arraycopy(oldData, 0, this.data, 0, oldData.length); - } - } - - /** - * Builds a row, starting from the left-most column and adding one column - * value at a time. Follows the same ordering as the column names specified - * at cursor construction time. - */ - public class RowBuilder { - - private int index; - private final int endIndex; - - RowBuilder(int index, int endIndex) { - this.index = index; - this.endIndex = endIndex; - } - - /** - * Sets the next column value in this row. - * - * @param columnValue columnValue - * @throws CursorIndexOutOfBoundsException if you try to add too many - * values - * @return this builder to support chaining - */ - public RowBuilder add(Object columnValue) { - if (index == endIndex) { - throw new CursorIndexOutOfBoundsException( - "No more columns left."); - } - - data[index++] = columnValue; - return this; - } - } - - // AbstractCursor implementation. - - @Override - public int getRowCount() { - return rowCount; - } - - @Override - public String[] getAllColumnNames() { - return columnNames; - } - - @Override - public String getString(int column) { - Object value = get(column); - if (value == null) return null; - return value.toString(); - } - - @Override - public short getShort(int column) { - Object value = get(column); - if (value == null) return 0; - if (value instanceof Number) return ((Number) value).shortValue(); - return Short.parseShort(value.toString()); - } - - @Override - public int getInt(int column) { - Object value = get(column); - if (value == null) return 0; - if (value instanceof Number) return ((Number) value).intValue(); - return Integer.parseInt(value.toString()); - } - - @Override - public long getLong(int column) { - Object value = get(column); - if (value == null) return 0; - if (value instanceof Number) return ((Number) value).longValue(); - return Long.parseLong(value.toString()); - } - - @Override - public float getFloat(int column) { - Object value = get(column); - if (value == null) return 0.0f; - if (value instanceof Number) return ((Number) value).floatValue(); - return Float.parseFloat(value.toString()); - } - - @Override - public double getDouble(int column) { - Object value = get(column); - if (value == null) return 0.0d; - if (value instanceof Number) return ((Number) value).doubleValue(); - return Double.parseDouble(value.toString()); - } - - @Override - public ColumnType getColumnTypeForIndex(int column) { - return DatabaseUtils.getTypeOfObject(get(column)); - } - - @Override - public boolean isColumnNull(int column) { - return get(column) == null; - } - -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/RowAllocationException.java b/sqlcipher/src/main/java/net/sqlcipher/RowAllocationException.java deleted file mode 100644 index a468056818c17887de8f842400ae78e27851fa8f..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/RowAllocationException.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.sqlcipher; - -/** - * An exception that indicates there was an error attempting to allocate a row - * for the CursorWindow. - */ -public class RowAllocationException extends RuntimeException -{ - public RowAllocationException() {} - - public RowAllocationException(String error) - { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/SQLException.java b/sqlcipher/src/main/java/net/sqlcipher/SQLException.java deleted file mode 100644 index 28481288bec3cde919fd2d40c58f6a0b16db828d..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/SQLException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -/** - * An exception that indicates there was an error with SQL parsing or execution. - */ -public class SQLException extends RuntimeException { - public SQLException() {} - - public SQLException(String error) - { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/StaleDataException.java b/sqlcipher/src/main/java/net/sqlcipher/StaleDataException.java deleted file mode 100644 index 02692828d4a186b7b37ea23bf9642bb4bac3bda1..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/StaleDataException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher; - -/** - * This exception is thrown when a Cursor contains stale data and must be - * requeried before being used again. - */ -public class StaleDataException extends RuntimeException -{ - public StaleDataException() - { - super(); - } - - public StaleDataException(String description) - { - super(description); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/UnknownTypeException.java b/sqlcipher/src/main/java/net/sqlcipher/UnknownTypeException.java deleted file mode 100644 index 4da359ff9e7c16ff2294c38369134b6a44ed0a7a..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/UnknownTypeException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.sqlcipher; - -/** - * An exception that indicates an unknown type was returned. - */ -public class UnknownTypeException extends RuntimeException -{ - public UnknownTypeException() {} - - public UnknownTypeException(String error) - { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/DatabaseObjectNotClosedException.java b/sqlcipher/src/main/java/net/sqlcipher/database/DatabaseObjectNotClosedException.java deleted file mode 100644 index 89f2adf7c5bd98f91febcd6d74b937b557e924c3..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/DatabaseObjectNotClosedException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that garbage-collector is finalizing a database object - * that is not explicitly closed - * @hide - */ -public class DatabaseObjectNotClosedException extends RuntimeException -{ - private static final String s = "Application did not close the cursor or database object " + - "that was opened here"; - - public DatabaseObjectNotClosedException() - { - super(s); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteAbortException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteAbortException.java deleted file mode 100644 index 89b066ceca697684d6b70f743f9064074ead4eed..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteAbortException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that the SQLite program was aborted. - * This can happen either through a call to ABORT in a trigger, - * or as the result of using the ABORT conflict clause. - */ -public class SQLiteAbortException extends SQLiteException { - public SQLiteAbortException() {} - - public SQLiteAbortException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosable.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosable.java deleted file mode 100644 index 93c50db2ab64c46e3be0292d71db977fb3df1a7d..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosable.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.*; - -/** - * An object created from a SQLiteDatabase that can be closed. - */ -public abstract class SQLiteClosable { - private int mReferenceCount = 1; - private Object mLock = new Object(); - - protected abstract void onAllReferencesReleased(); - protected void onAllReferencesReleasedFromContainer() {} - - public void acquireReference() { - synchronized(mLock) { - if (mReferenceCount <= 0) { - throw new IllegalStateException( - "attempt to re-open an already-closed object: " + getObjInfo()); - } - mReferenceCount++; - } - } - - public void releaseReference() { - synchronized(mLock) { - mReferenceCount--; - if (mReferenceCount == 0) { - onAllReferencesReleased(); - } - } - } - - public void releaseReferenceFromContainer() { - synchronized(mLock) { - mReferenceCount--; - if (mReferenceCount == 0) { - onAllReferencesReleasedFromContainer(); - } - } - } - - private String getObjInfo() { - StringBuilder buff = new StringBuilder(); - buff.append(this.getClass().getName()); - buff.append(" ("); - if (this instanceof SQLiteDatabase) { - buff.append("database = "); - buff.append(((SQLiteDatabase)this).getPath()); - } else if (this instanceof SQLiteProgram || this instanceof SQLiteStatement || - this instanceof SQLiteQuery) { - buff.append("mSql = "); - buff.append(((SQLiteProgram)this).mSql); - } - /*else if (this instanceof CursorWindow) { - buff.append("mStartPos = "); - buff.append(((CursorWindow)this).getStartPosition()); - }*/ - buff.append(") "); - return buff.toString(); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosableHos.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosableHos.java deleted file mode 100644 index 0ed49ce7ebc7fd9b8d0d0ad11692f25733af9455..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteClosableHos.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import java.io.Closeable; - -/** - * An object created from a SQLiteDatabase that can be closed. - * - * This class implements a primitive reference counting scheme for database objects. - */ -public abstract class SQLiteClosableHos implements Closeable { - private int mReferenceCount = 1; - - /** - * Called when the last reference to the object was released by - * a call to {@link #releaseReference()} or {@link #close()}. - */ - protected abstract void onAllReferencesReleased(); - - /** - * Called when the last reference to the object was released by - * a call to {@link #releaseReferenceFromContainer()}. - * - * @deprecated Do not use. - */ - @Deprecated - protected void onAllReferencesReleasedFromContainer() { - onAllReferencesReleased(); - } - - /** - * Acquires a reference to the object. - * - * @throws IllegalStateException if the last reference to the object has already - * been released. - */ - public void acquireReference() { - synchronized(this) { - if (mReferenceCount <= 0) { - throw new IllegalStateException( - "attempt to re-open an already-closed object: " + this); - } - mReferenceCount++; - } - } - - /** - * Releases a reference to the object, closing the object if the last reference - * was released. - * - * @see #onAllReferencesReleased() - */ - public void releaseReference() { - boolean refCountIsZero = false; - synchronized(this) { - refCountIsZero = --mReferenceCount == 0; - } - if (refCountIsZero) { - onAllReferencesReleased(); - } - } - - /** - * Releases a reference to the object that was owned by the container of the object, - * closing the object if the last reference was released. - * - * @see #onAllReferencesReleasedFromContainer() - * @deprecated Do not use. - */ - @Deprecated - public void releaseReferenceFromContainer() { - boolean refCountIsZero = false; - synchronized(this) { - refCountIsZero = --mReferenceCount == 0; - } - if (refCountIsZero) { - onAllReferencesReleasedFromContainer(); - } - } - - /** - * Releases a reference to the object, closing the object if the last reference - * was released. - * - * Calling this method is equivalent to calling {@link #releaseReference}. - * - * @see #releaseReference() - * @see #onAllReferencesReleased() - */ - public void close() { - releaseReference(); - } -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCompiledSql.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCompiledSql.java deleted file mode 100644 index 8443ca3621e01288f71100b98847d2f78ed815cd..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCompiledSql.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -/** - * This class encapsulates compilation of sql statement and release of the compiled statement obj. - * Once a sql statement is compiled, it is cached in {@link SQLiteDatabase} - * and it is released in one of the 2 following ways - * 1. when {@link SQLiteDatabase} object is closed. - * 2. if this is not cached in {@link SQLiteDatabase} - * releaases this obj. - */ -/* package */ class SQLiteCompiledSql { - - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00205, "SQLiteCompiledSql"); - - /** The database this program is compiled against. */ - /* package */ SQLiteDatabase mDatabase; - - /** - * Native linkage, do not modify. This comes from the database. - */ - /* package */ long nHandle = 0; - - /** - * Native linkage, do not modify. When non-0 this holds a reference to a valid - * sqlite3_statement object. It is only updated by the native code, but may be - * checked in this class when the database lock is held to determine if there - * is a valid native-side program or not. - */ - /* package */ long nStatement = 0; - - /** the following are for debugging purposes */ - private String mSqlStmt = null; - - /** when in cache and is in use, this member is set */ - private boolean mInUse = false; - - /* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) { - if (!db.isOpen()) { - throw new IllegalStateException("database " + db.getPath() + " already closed"); - } - mDatabase = db; - mSqlStmt = sql; - this.nHandle = db.mNativeHandle; - compile(sql, true); - } - - /** - * Compiles the given SQL into a SQLite byte code program using sqlite3_prepare_v2(). If - * this method has been called previously without a call to close and forCompilation is set - * to false the previous compilation will be used. Setting forceCompilation to true will - * always re-compile the program and should be done if you pass differing SQL strings to this - * method. - * - *

Note: this method acquires the database lock.

- * - * @param sql the SQL string to compile - * @param forceCompilation forces the SQL to be recompiled in the event that there is an - * existing compiled SQL program already around - */ - private void compile(String sql, boolean forceCompilation) { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - // Only compile if we don't have a valid statement already or the caller has - // explicitly requested a recompile. - if (forceCompilation) { - mDatabase.lock(); - try { - // Note that the native_compile() takes care of destroying any previously - // existing programs before it compiles. - native_compile(sql); - } finally { - mDatabase.unlock(); - } - } - } - - /* package */ void releaseSqlStatement() { - // Note that native_finalize() checks to make sure that nStatement is - // non-null before destroying it. - if (nStatement != 0) { - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "closed and deallocated DbObj (id#" + nStatement +")"); - } - try { - mDatabase.lock(); - native_finalize(); - nStatement = 0; - } finally { - mDatabase.unlock(); - } - } - } - - /** - * returns true if acquire() succeeds. false otherwise. - * @return true/false - */ - /* package */ synchronized boolean acquire() { - if (mInUse) { - // someone already has acquired it. - return false; - } - mInUse = true; - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "Acquired DbObj (id#" + nStatement + ") from DB cache"); - } - return true; - } - - /* package */ synchronized void release() { - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "Released DbObj (id#" + nStatement + ") back to DB cache"); - } - mInUse = false; - } - - /** - * Make sure that the native resource is cleaned up. - * @throws Throwable Throwable - */ - @Override - protected void finalize() throws Throwable { - try { - if (nStatement == 0) return; - // finalizer should NEVER get called - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "** warning ** Finalized DbObj (id#" + nStatement + ")"); - } - releaseSqlStatement(); - } finally { - super.finalize(); - } - } - - /** - * Compiles SQL into a SQLite program. - * - *

The database lock must be held when calling this method. - * @param sql The SQL to compile. - */ - private final native void native_compile(String sql); - private final native void native_finalize(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteConstraintException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteConstraintException.java deleted file mode 100644 index d9d548f6760e7936eaa4d71fdba7069f08b633c2..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteConstraintException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that an integrity constraint was violated. - */ -public class SQLiteConstraintException extends SQLiteException { - public SQLiteConstraintException() {} - - public SQLiteConstraintException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteContentHelper.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteContentHelper.java deleted file mode 100644 index 7c9a56c5a2b1a159940d7c397dbf88c29485255d..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteContentHelper.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import ohos.app.Context; -import ohos.global.resource.RawFileDescriptor; -import ohos.data.resultset.ResultSet; -import ohos.global.resource.RawFileEntry; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import ohos.rpc.MessageParcel; -import ohos.rpc.ReliableFileDescriptor; -import ohos.security.asset.AssetOperator; - -import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Some helper functions for using SQLite database to implement content providers. - * - * @hide - */ -public class SQLiteContentHelper { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x002A, "SQLiteContentHelper"); - private static ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); - - /** - * Runs an SQLite query and returns an AssetFileDescriptor for the - * blob in column 0 of the first row. If the first column does - * not contain a blob, an unspecified exception is thrown. - * - * @param db Handle to a readable database. - * @param sql SQL query, possibly with query arguments. - * @param selectionArgs Query argument values, or {@code null} for no argument. - * @return If no exception is thrown, a non-null AssetFileDescriptor is returned. - * @throws FileNotFoundException If the query returns no results or the - * value of column 0 is NULL, or if there is an error creating the - * asset file descriptor. - */ -/* public static RawFileDescriptor getBlobColumnAsAssetFile(Context context, SQLiteDatabase db, String sql, - String[] selectionArgs) throws FileNotFoundException { - FileDescriptor fd = null; - - try { - final MessageParcel file = simpleQueryForBlobMemoryFile(db, sql, selectionArgs); - if (file == null) { - throw new FileNotFoundException("No results."); - } - fd = file.readFileDescriptor(); - RawFileEntry assetManager = context.getResourceManager().getRawFileEntry(file); - RawFileDescriptor afd = assetManager.openRawFileDescriptor(); - return afd; - } catch (IOException ex) { - throw new FileNotFoundException(ex.toString()); - } - }*/ - - /** - * Runs an SQLite query and returns a MemoryFile for the - * blob in column 0 of the first row. If the first column does - * not contain a blob, an unspecified exception is thrown. - * - * @param db database - * @param sql string - * @param selectionArgs arguments - * @return A memory file, or {@code null} if the query returns no results - * or the value column 0 is NULL. - * @throws IOException If there is an error creating the memory file. - */ - // TODO: make this native and use the SQLite blob API to reduce copying - private static MessageParcel simpleQueryForBlobMemoryFile(SQLiteDatabase db, String sql, - String[] selectionArgs) throws IOException { - ResultSet cursor = db.rawQuery(sql, selectionArgs); - if (cursor == null) { - return null; - } - try { - if (!cursor.goToFirstRow()) { - return null; - } - byte[] bytes = cursor.getBlob(0); - if (bytes == null) { - return null; - } - buffer.put(bytes, 0, bytes.length); - buffer.flip(); - MessageParcel file = MessageParcel.obtain(); - file.writeRawData(bytes, bytes.length); - - // file.deactivate(); - return file; - } finally { - cursor.close(); - } - } - -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursor.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursor.java deleted file mode 100644 index f9eeb86f201f214e811fee60c029b75e3b2900c3..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursor.java +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.AbstractWindowedCursor; -import net.sqlcipher.CursorWindow; -import net.sqlcipher.SQLException; - -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.locks.ReentrantLock; - -import ohos.data.rdb.DataObserver; -import ohos.eventhandler.EventHandler; -import ohos.eventhandler.EventRunner; -import ohos.eventhandler.InnerEvent; -import ohos.os.ProcessManager; -import net.sqlcipher.utils.TextUtils; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -/** - * A Cursor implementation that exposes results from a query on a - * {@link SQLiteDatabase}. - * - * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple - * threads should perform its own synchronization when using the SQLiteCursor. - */ -public class SQLiteCursor extends AbstractWindowedCursor { - static final String TAG = "Cursor"; - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x002A, "SQLiteCursor"); - static final int NO_COUNT = -1; - - /** The name of the table to edit */ - private String mEditTable; - - /** The names of the columns in the rows */ - private String[] mColumns; - - /** The query object for the cursor */ - private SQLiteQuery mQuery; - - /** The database the cursor was created from */ - private SQLiteDatabase mDatabase; - - /** The compiled query this cursor came from */ - private SQLiteCursorDriver mDriver; - - /** The number of rows in the cursor */ - private int mCount = NO_COUNT; - - private int mCursorWindowCapacity = 0; - - private boolean fillWindowForwardOnly = false; - - /** A mapping of column names to column indices, to speed up lookups */ - private Map mColumnNameMap; - - /** Used to find out where a cursor was allocated in case it never got released. */ - private Throwable mStackTrace; - - /** - * mMaxRead is the max items that each cursor window reads - * default to a very high value - */ - private int mMaxRead = Integer.MAX_VALUE; - private int mInitialRead = Integer.MAX_VALUE; - private int mCursorState = 0; - private ReentrantLock mLock = null; - private boolean mPendingData = false; - - public void setFillWindowForwardOnly(boolean value) { - fillWindowForwardOnly = value; - } - - /** - * support for a cursor variant that doesn't always read all results - * initialRead is the initial number of items that cursor window reads - * if query contains more than this number of items, a thread will be - * created and handle the left over items so that caller can show - * results as soon as possible - * @param initialRead initial number of items that cursor read - * @param maxRead leftover items read at maxRead items per time - * @hide - */ - public void setLoadStyle(int initialRead, int maxRead) { - mMaxRead = maxRead; - mInitialRead = initialRead; - mLock = new ReentrantLock(true); - } - - private void queryThreadLock() { - if (mLock != null) { - mLock.lock(); - } - } - - private void queryThreadUnlock() { - if (mLock != null) { - mLock.unlock(); - } - } - - - /** - * @hide - */ - final private class QueryThread implements Runnable { - private final int mThreadState; - QueryThread(int version) { - mThreadState = version; - } - private void sendMessage() { - if (mNotificationHandler != null) { - mNotificationHandler.sendEvent(1); - mPendingData = false; - } else { - mPendingData = true; - } - - } - public void run() { - // use cached mWindow, to avoid get null mWindow - CursorWindow cw = mWindow; - ProcessManager.setThreadPriority(ProcessManager.getTid(), 10); - // the cursor's state doesn't change - while (true) { - if(mLock == null){ - mLock = new ReentrantLock(true); - } - mLock.lock(); - if (mCursorState != mThreadState) { - mLock.unlock(); - break; - } - try { - int count = mQuery.fillWindow(cw, mMaxRead, mCount); - // return -1 means not finished - if (count != 0) { - if (count == NO_COUNT){ - mCount += mMaxRead; - sendMessage(); - } else { - mCount = count; - sendMessage(); - break; - } - } else { - break; - } - } catch (Exception e) { - // end the tread when the cursor is close - break; - } finally { - mLock.unlock(); - } - } - } - } - - - /** - * @hide - */ - protected static class MainThreadNotificationHandler extends EventHandler { - private final WeakReference wrappedCursor; - - MainThreadNotificationHandler(SQLiteCursor cursor,EventRunner runner) { - super(runner); - wrappedCursor = new WeakReference(cursor); - } - - public void processEvent(InnerEvent event) { - SQLiteCursor cursor = wrappedCursor.get(); - if (cursor != null) { - cursor.notifyDataSetChange(); - } - } - } - - /** - * @hide - */ - protected MainThreadNotificationHandler mNotificationHandler; - - public void registerObserver(DataObserver observer) { //todo - super.registerObserver(observer); - if ((Integer.MAX_VALUE != mMaxRead || Integer.MAX_VALUE != mInitialRead) && - mNotificationHandler == null) { - queryThreadLock(); - try { - EventRunner runner = EventRunner.create(true); - mNotificationHandler = new MainThreadNotificationHandler(this, runner); - if (mPendingData) { - notifyDataSetChange(); - mPendingData = false; - } - } finally { - queryThreadUnlock(); - } - } - } - - /** - * Execute a query and provide access to its result set through a Cursor - * interface. For a query such as: {@code SELECT name, birth, phone FROM - * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth, - * phone) would be in the projection argument and everything from - * {@code FROM} onward would be in the params argument. This constructor - * has package scope. - * - * @param db a reference to a Database object that is already constructed - * and opened - * @param editTable the name of the table used for this query - * @param query the rest of the query terms - * cursor is finalized - */ - public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver, - String editTable, SQLiteQuery query) { - // The AbstractCursor constructor needs to do some setup. - super(); - mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace(); - mDatabase = db; - mDriver = driver; - mEditTable = editTable; - mColumnNameMap = null; - mQuery = query; - - try { - db.lock(); - - // Setup the list of columns - int columnCount = mQuery.columnCountLocked(); - mColumns = new String[columnCount]; - - // Read in all column names - for (int i = 0; i < columnCount; i++) { - String columnName = mQuery.columnNameLocked(i); - mColumns[i] = columnName; - HiLog.debug(label,"DatabaseWindow", "mColumns[" + i + "] is " - + mColumns[i]); - - // Make note of the row ID column index for quick access to it - if ("_id".equals(columnName)) { - mRowIdColumnIndex = i; - } - } - } finally { - db.unlock(); - } - } - - /** - * getDatabase - * @return the SQLiteDatabase that this cursor is associated with. - */ - public SQLiteDatabase getDatabase() { - return mDatabase; - } - - @Override - public boolean onGo(int oldPosition, int newPosition) { - // Make sure the row at newPosition is present in the window - if (mWindow == null || newPosition < mWindow.getStartRowIndex() || - newPosition >= (mWindow.getStartRowIndex() + mWindow.getRowCount())) { - fillWindow(newPosition); - } - return true; - } - - @Override - public int getRowCount() { - if (mCount == NO_COUNT) { - fillWindow(0); - } - return mCount; - } - - private void fillWindow (int requiredPos) { - int startPos = 0; - if (mWindow == null) { - // If there isn't a window set already it will only be accessed locally - mWindow = new CursorWindow(true /* the window is local only */); - } else { - mCursorState++; - queryThreadLock(); - try { - mWindow.clear(); - } finally { - queryThreadUnlock(); - } - } - if(fillWindowForwardOnly) { - startPos = requiredPos; - } else { - startPos = mCount == NO_COUNT - ? cursorPickFillWindowStartPosition(requiredPos, 0) - : cursorPickFillWindowStartPosition(requiredPos, mCursorWindowCapacity); - } - mWindow.setStartRowIndex(startPos); - mWindow.setRequiredPosition(requiredPos); - HiLog.debug(label, String.format("Filling cursor window with start position:%d required position:%d", - startPos, requiredPos)); - mCount = mQuery.fillWindow(mWindow, mInitialRead, 0); - if(mCursorWindowCapacity == 0) { - mCursorWindowCapacity = mWindow.getRowCount(); - } - // return -1 means not finished - if (mCount == NO_COUNT){ - mCount = startPos + mInitialRead; - Thread t = new Thread(new QueryThread(mCursorState), "query thread"); - t.start(); - } - } - - @Override - public int getColumnIndexForName(String columnName) { - // Create mColumnNameMap on demand - if (mColumnNameMap == null) { - String[] columns = mColumns; - int columnCount = columns.length; - HashMap map = new HashMap(columnCount, 1); - for (int i = 0; i < columnCount; i++) { - map.put(columns[i], i); - } - mColumnNameMap = map; - } - - // Hack according to bug 903852 - final int periodIndex = columnName.lastIndexOf('.'); - if (periodIndex != -1) { - Exception e = new Exception(); - HiLog.error(label, "requesting column name with table name -- " + columnName, e); - columnName = columnName.substring(periodIndex + 1); - } - - Integer i = mColumnNameMap.get(columnName); - if (i != null) { - return i.intValue(); - } else { - return -1; - } - } - - /** - * deleteRow - * @hide - * @deprecated - * @return true/false - */ - public boolean deleteRow() { - checkPosition(); - - // Only allow deletes if there is an ID column, and the ID has been read from it - if (mRowIdColumnIndex == -1 || mCurrentRowID == null) { - HiLog.error(label, "Could not delete row because either the row ID column is not available or it" + - "has not been read."); - return false; - } - boolean success; - - /* - * Ensure we don't change the state of the database when another - * thread is holding the database lock. requery() and moveTo() are also - * synchronized here to make sure they get the state of the database - * immediately following the DELETE. - */ - mDatabase.lock(); - try { - try { - mDatabase.delete(mEditTable, mColumns[mRowIdColumnIndex] + "=?", - new String[] {mCurrentRowID.toString()}); - success = true; - } catch (SQLException e) { - success = false; - } - - int pos = mPos; - requery(); - - /* - * Ensure proper cursor state. Note that mCurrentRowID changes - * in this call. - */ - goToRow(pos); - } finally { - mDatabase.unlock(); - } - if (success) { - onChange(true); - return true; - } else { - return false; - } - } - - @Override - public String[] getAllColumnNames() { - return mColumns; - } - - /** - * supportsUpdates - * @hide - * @deprecated - * @return true/false - */ - public boolean supportsUpdates() { - // return super.supportsUpdates() && !TextUtils.isEmpty(mEditTable); - return !TextUtils.isEmpty(mEditTable); - } - - /** - * commitUpdates - * @hide - * @deprecated - * @param additionalValues additionalValues - * @return true/false - */ - // @Override - public boolean commitUpdates(Map> additionalValues) { - if (!supportsUpdates()) { - HiLog.error(label, "commitUpdates not supported on this cursor, did you " - + "include the _id column?"); - return false; - } - - /* - * Prevent other threads from changing the updated rows while they're - * being processed here. - */ - synchronized (mUpdatedRows) { - if (additionalValues != null) { - mUpdatedRows.putAll(additionalValues); - } - - if (mUpdatedRows.size() == 0) { - return true; - } - - /* - * Prevent other threads from changing the database state while - * we process the updated rows, and prevents us from changing the - * database behind the back of another thread. - */ - mDatabase.beginTransaction(); - try { - StringBuilder sql = new StringBuilder(128); - - // For each row that has been updated - for (Map.Entry> rowEntry : - mUpdatedRows.entrySet()) { - Map values = rowEntry.getValue(); - Long rowIdObj = rowEntry.getKey(); - - if (rowIdObj == null || values == null) { - throw new IllegalStateException("null rowId or values found! rowId = " - + rowIdObj + ", values = " + values); - } - - if (values.size() == 0) { - continue; - } - - long rowId = rowIdObj.longValue(); - - Iterator> valuesIter = - values.entrySet().iterator(); - - sql.setLength(0); - sql.append("UPDATE " + mEditTable + " SET "); - - // For each column value that has been updated - Object[] bindings = new Object[values.size()]; - int i = 0; - while (valuesIter.hasNext()) { - Map.Entry entry = valuesIter.next(); - sql.append(entry.getKey()); - sql.append("=?"); - bindings[i] = entry.getValue(); - if (valuesIter.hasNext()) { - sql.append(", "); - } - i++; - } - - sql.append(" WHERE " + mColumns[mRowIdColumnIndex] - + '=' + rowId); - sql.append(';'); - mDatabase.execSQL(sql.toString(), bindings); - mDatabase.rowUpdated(mEditTable, rowId); - } - mDatabase.setTransactionSuccessful(); - } finally { - mDatabase.endTransaction(); - } - - mUpdatedRows.clear(); - } - - // Let any change observers know about the update - onChange(true); - - return true; - } - - private void deactivateCommon() { - HiLog.debug(label, "<<< Releasing cursor " + this); - mCursorState = 0; - if (mWindow != null) { - mWindow.close(); - mWindow = null; - } - HiLog.debug(label,"DatabaseWindow", "closing window in release()"); - } - - @Override - public void deactivate() { - super.deactivate(); - deactivateCommon(); - mDriver.cursorDeactivated(); - } - - @Override - public void close() { - super.close(); - deactivateCommon(); - mQuery.close(); - mDriver.cursorClosed(); - } - - @Override - public boolean requery() { - if (isClosed()) { - return false; - } - long timeStart = 0; - timeStart = System.currentTimeMillis(); - - /* - * Synchronize on the database lock to ensure that mCount matches the - * results of mQuery.requery(). - */ - mDatabase.lock(); - try { - if (mWindow != null) { - mWindow.clear(); - } - mPos = -1; - // This one will recreate the temp table, and get its count - mDriver.cursorRequeried(this); - mCount = NO_COUNT; - mCursorState++; - queryThreadLock(); - try { - mQuery.requery(); - } finally { - queryThreadUnlock(); - } - } finally { - mDatabase.unlock(); - } - - HiLog.debug(label,"DatabaseWindow", "closing window in requery()"); - HiLog.debug(label, "--- Requery()ed cursor " + this + ": " + mQuery); - - boolean result = super.requery(); - long timeEnd = System.currentTimeMillis(); - HiLog.debug(label, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString()); - return result; - } - - @Override - public void setWindow(CursorWindow window) { - if (mWindow != null) { - mCursorState++; - queryThreadLock(); - try { - mWindow.close(); - } finally { - queryThreadUnlock(); - } - mCount = NO_COUNT; - } - mWindow = window; - } - - /** - * Changes the selection arguments. The new values take effect after a call to requery(). - * @param selectionArgs arguments - */ - public void setSelectionArguments(String[] selectionArgs) { - mDriver.setBindArguments(selectionArgs); - } - - /** - * Release the native resources, if they haven't been released yet. - */ - @Override - protected void finalize() { - try { - // if the cursor hasn't been closed yet, close it first - if (mWindow != null) { - int len = mQuery.mSql.length(); - HiLog.error(label, "Finalizing a Cursor that has not been deactivated or closed. " + - "database = " + mDatabase.getPath() + ", table = " + mEditTable + - ", query = " + mQuery.mSql.substring(0, (len > 100) ? 100 : len), - mStackTrace); - close(); - SQLiteDebug.notifyActiveCursorFinalized(); - } else { - HiLog.error(label, "Finalizing cursor on database = " + mDatabase.getPath() + - ", table = " + mEditTable + ", query = " + mQuery.mSql); - } - } finally { - super.finalize(); - } - } - - - - @Override - public void fillBlock(int requiredPos, ohos.data.resultset.SharedBlock window) { - int startPos = 0; - if (mWindow == null) { - // If there isn't a window set already it will only be accessed locally - mWindow = new CursorWindow(true /* the window is local only */); - } else { - mCursorState++; - queryThreadLock(); - try { - mWindow.clear(); - } finally { - queryThreadUnlock(); - } - } - if(fillWindowForwardOnly) { - startPos = requiredPos; - } else { - startPos = mCount == NO_COUNT - ? cursorPickFillWindowStartPosition(requiredPos, 0) - : cursorPickFillWindowStartPosition(requiredPos, mCursorWindowCapacity); - } - mWindow.setStartRowIndex(startPos); - mWindow.setRequiredPosition(requiredPos); - HiLog.error(label, String.format("Filling cursor window with start position:%d required position:%d", - startPos, requiredPos)); - mCount = mQuery.fillWindow(mWindow, mInitialRead, 0); - if(mCursorWindowCapacity == 0) { - mCursorWindowCapacity = mWindow.getRowCount(); - } - // return -1 means not finished - if (mCount == NO_COUNT){ - mCount = startPos + mInitialRead; - Thread t = new Thread(new QueryThread(mCursorState), "query thread"); - t.start(); - } - } - - public int cursorPickFillWindowStartPosition( - int cursorPosition, int cursorWindowCapacity) { - return Math.max(cursorPosition - cursorWindowCapacity / 3, 0); - } - -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursorDriver.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursorDriver.java deleted file mode 100644 index d261a6ce4e59e8de6cea46d26358f29a555fb972..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteCursorDriver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import ohos.data.resultset.ResultSet; - -/** - * A driver for SQLiteCursors that is used to create them and gets notified - * by the cursors it creates on significant events in their lifetimes. - */ -public interface SQLiteCursorDriver { - /** - * Executes the query returning a Cursor over the result set. - * - * @param factory The CursorFactory to use when creating the Cursors, or - * null if standard SQLiteCursors should be returned. - * @param bindArgs arguments - * @return a Cursor over the result set - */ - ResultSet query(SQLiteDatabase.CursorFactory factory, String[] bindArgs); // for HOS - - /** - * Called by a SQLiteCursor when it is released. - */ - void cursorDeactivated(); - - /** - * Called by a SQLiteCursor when it is requeryed. - * - * @param cursor ResultSet - * @return The new count value. - */ - void cursorRequeried(ResultSet cursor); - - /** - * Called by a SQLiteCursor when it it closed to destroy this object as well. - */ - void cursorClosed(); - - /** - * Set new bind arguments. These will take effect in cursorRequeried(). - * @param bindArgs the new arguments - */ - public void setBindArguments(String[] bindArgs); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabase.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabase.java deleted file mode 100644 index d1bca8b75ed34d4e042b11807b97a1c53e77ea71..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabase.java +++ /dev/null @@ -1,3322 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.CrossProcessCursorWrapper; -import net.sqlcipher.DatabaseErrorHandler; -import net.sqlcipher.DatabaseUtils; -import net.sqlcipher.DefaultDatabaseErrorHandler; -import net.sqlcipher.SQLException; -import net.sqlcipher.database.SQLiteDebug.DbStats; -import net.sqlcipher.database.SQLiteQueryStats; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.locks.ReentrantLock; -import java.util.regex.Pattern; -import java.util.zip.ZipInputStream; - -import ohos.app.Context; -import ohos.data.rdb.ValuesBucket; -import ohos.data.resultset.ResultSet; -import ohos.hiviewdfx.Debug; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import net.sqlcipher.utils.TextUtils; -import ohos.utils.Pair; -import ohos.miscservices.timeutility.Time; - -import net.sqlcipher.harmonyx.SupportSQLiteDatabase; -import net.sqlcipher.harmonyx.SupportSQLiteQuery; - -/** - * Exposes methods to manage a SQLCipher database. - *

SQLiteDatabase has methods to create, delete, execute SQL commands, and - * perform other common database management tasks. - *

A call to loadLibs(…) should occur before attempting to - * create or open a database connection. - *

Database names must be unique within an application, not across all - * applications. - * - */ -public class SQLiteDatabase extends SQLiteClosable implements - SupportSQLiteDatabase { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00204, "SQLiteDatabase"); - private static final int EVENT_DB_OPERATION = 52000; - private static final int EVENT_DB_CORRUPT = 75004; - private static final String KEY_ENCODING = "UTF-8"; - - private enum SQLiteDatabaseTransactionType { - Deferred, - Immediate, - Exclusive, - } - - // Stores reference to all databases opened in the current process. - // (The referent Object is not used at this time.) - // INVARIANT: Guarded by sActiveDatabases. - private static WeakHashMap sActiveDatabases = - new WeakHashMap(); - - public int status(int operation, boolean reset){ - return native_status(operation, reset); - } //native calls todo - - /** - * Change the password of the open database using sqlite3_rekey(). - * - * @param password new database password - * - * @throws SQLiteException if there is an issue changing the password internally - * OR if the database is not open - * - * FUTURE @todo throw IllegalStateException if the database is not open and - * update the test suite - */ - public void changePassword(String password) throws SQLiteException { - /* safeguard: */ - if (!isOpen()) { - throw new SQLiteException("database not open"); - } - if (password != null) { - byte[] keyMaterial = getBytes(password.toCharArray()); - rekey(keyMaterial); - Arrays.fill(keyMaterial, (byte) 0); - } - } - - /** - * Change the password of the open database using sqlite3_rekey(). - * - * @param password new database password (char array) - * - * @throws SQLiteException if there is an issue changing the password internally - * OR if the database is not open - * - * FUTURE @todo throw IllegalStateException if the database is not open and - * update the test suite - */ - public void changePassword(char[] password) throws SQLiteException { - /* safeguard: */ - if (!isOpen()) { - throw new SQLiteException("database not open"); - } - if (password != null) { - byte[] keyMaterial = getBytes(password); - rekey(keyMaterial); - Arrays.fill(keyMaterial, (byte) 0); - } - } - - private static void loadICUData(Context context, File workingDir) { - OutputStream out = null; - ZipInputStream in = null; - File icuDir = new File(workingDir, "icu"); - File icuDataFile = new File(icuDir, "icudt46l.dat"); - try { - if(!icuDir.exists()) { - boolean mkdirs = icuDir.mkdirs(); - } - if(!icuDataFile.exists()) { - in = new ZipInputStream(context.getResourceManager().getRawFileEntry("icudt46l.zip").openRawFile()); - in.getNextEntry(); - out = new FileOutputStream(icuDataFile); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } - } - catch (Exception ex) { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error copying icu dat file", ex); - //} - if(icuDataFile.exists()){ - boolean delete = icuDataFile.delete(); - } - throw new RuntimeException(ex); - } - finally { - try { - if(in != null){ - in.close(); - } - if(out != null){ - out.flush(); - out.close(); - } - } catch (IOException ioe){ - /* if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error in closing streams IO streams after expanding ICU dat file", ioe); - //} - throw new RuntimeException(ioe); - } - } - } - - /** - * Implement this interface to provide custom strategy for loading jni libraries. - */ - public interface LibraryLoader { - /** - * Load jni libraries by given names. - * Straightforward implementation will be calling {@link System#loadLibrary(String name)} - * for every provided library name. - * - * @param libNames library names that sqlcipher need to load - */ - void loadLibraries(String... libNames); - } - - /** - * Loads the native SQLCipher library into the application process. - * @param context context - */ - public static synchronized void loadLibs (Context context) { - loadLibs(context, context.getFilesDir()); - } - - /** - * Loads the native SQLCipher library into the application process. - * @param context context - * @param workingDir file - */ - public static synchronized void loadLibs (Context context, File workingDir) { - loadLibs(context, workingDir, new LibraryLoader() { - @Override - public void loadLibraries(String... libNames) { - for (String libName : libNames) { - System.loadLibrary(libName); - } - } - }); - } - - /** - * Loads the native SQLCipher library into the application process. - * @param context context - * @param libraryLoader LibraryLoader - */ - public static synchronized void loadLibs(Context context, LibraryLoader libraryLoader) { - loadLibs(context, context.getFilesDir(), libraryLoader); - } - - /** - * Loads the native SQLCipher library into the application process. - * @param context context - * @param workingDir file - * @param libraryLoader LibraryLoader - */ - public static synchronized void loadLibs (Context context, File workingDir, LibraryLoader libraryLoader) { - libraryLoader.loadLibraries("sqlcipher"); - } - - /** - * Algorithms used in ON CONFLICT clause - * http://www.sqlite.org/lang_conflict.html - */ - /** - * When a constraint violation occurs, an immediate ROLLBACK occurs, - * thus ending the current transaction, and the command aborts with a - * return code of SQLITE_CONSTRAINT. If no transaction is active - * (other than the implied transaction that is created on every command) - * then this algorithm works the same as ABORT. - */ - public static final int CONFLICT_ROLLBACK = 1; - - /** - * When a constraint violation occurs,no ROLLBACK is executed - * so changes from prior commands within the same transaction - * are preserved. This is the default behavior. - */ - public static final int CONFLICT_ABORT = 2; - - /** - * When a constraint violation occurs, the command aborts with a return - * code SQLITE_CONSTRAINT. But any changes to the database that - * the command made prior to encountering the constraint violation - * are preserved and are not backed out. - */ - public static final int CONFLICT_FAIL = 3; - - /** - * When a constraint violation occurs, the one row that contains - * the constraint violation is not inserted or changed. - * But the command continues executing normally. Other rows before and - * after the row that contained the constraint violation continue to be - * inserted or updated normally. No error is returned. - */ - public static final int CONFLICT_IGNORE = 4; - - /** - * When a UNIQUE constraint violation occurs, the pre-existing rows that - * are causing the constraint violation are removed prior to inserting - * or updating the current row. Thus the insert or update always occurs. - * The command continues executing normally. No error is returned. - * If a NOT NULL constraint violation occurs, the NULL value is replaced - * by the default value for that column. If the column has no default - * value, then the ABORT algorithm is used. If a CHECK constraint - * violation occurs then the IGNORE algorithm is used. When this conflict - * resolution strategy deletes rows in order to satisfy a constraint, - * it does not invoke delete triggers on those rows. - * This behavior might change in a future release. - */ - public static final int CONFLICT_REPLACE = 5; - - /** - * use the following when no conflict action is specified. - */ - public static final int CONFLICT_NONE = 0; - private static final String[] CONFLICT_VALUES = new String[] - {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; - - /** - * Maximum Length Of A LIKE Or GLOB Pattern - * The pattern matching algorithm used in the default LIKE and GLOB implementation - * of SQLite can exhibit O(N^2) performance (where N is the number of characters in - * the pattern) for certain pathological cases. To avoid denial-of-service attacks - * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes. - * The default value of this limit is 50000. A modern workstation can evaluate - * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly. - * The denial of service problem only comes into play when the pattern length gets - * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns - * are at most a few dozen bytes in length, paranoid application developers may - * want to reduce this parameter to something in the range of a few hundred - * if they know that external users are able to generate arbitrary patterns. - */ - public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000; - - /** - * Flag for {@link #openDatabase} to open the database for reading and writing. - * If the disk is full, this may fail even before you actually write anything. - * - * {@more} Note that the value of this flag is 0, so it is the default. - */ - public static final int OPEN_READWRITE = 0x00000000; // update native code if changing - - /** - * Flag for {@link #openDatabase} to open the database for reading only. - * This is the only reliable way to open a database if the disk may be full. - */ - public static final int OPEN_READONLY = 0x00000001; // update native code if changing - - private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing - - /** - * Flag for {@link #openDatabase} to open the database without support for localized collators. - * - * {@more} This causes the collator LOCALIZED not to be created. - * You must be consistent when using this flag to use the setting the database was - * created with. If this is set, {@link #setLocale} will do nothing. - */ - public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing - - /** - * Flag for {@link #openDatabase} to create the database file if it does not already exist. - */ - public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing - - /** - * SQLite memory database name - */ - public static final String MEMORY = ":memory:"; - - /** - * Indicates whether the most-recently started transaction has been marked as successful. - */ - private boolean mInnerTransactionIsSuccessful; - - /** - * Valid during the life of a transaction, and indicates whether the entire transaction (the - * outer one and all of the inner ones) so far has been successful. - */ - private boolean mTransactionIsSuccessful; - - /** - * Valid during the life of a transaction. - */ - private SQLiteTransactionListener mTransactionListener; //todo - - /** Synchronize on this when accessing the database */ - private final ReentrantLock mLock = new ReentrantLock(true); - - private long mLockAcquiredWallTime = 0L; - private long mLockAcquiredThreadTime = 0L; - - // limit the frequency of complaints about each database to one within 20 sec - // unless run command adb shell setprop log.tag.Database VERBOSE - private static final int LOCK_WARNING_WINDOW_IN_MS = 20000; - /** If the lock is held this long then a warning will be printed when it is released. */ - private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300; - private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100; - private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000; - - private static final int SLEEP_AFTER_YIELD_QUANTUM = 1000; - - // The pattern we remove from database filenames before - // potentially logging them. - private static final Pattern EMAIL_IN_DB_PATTERN = Pattern.compile("[\\w\\.\\-]+@[\\w\\.\\-]+"); - - private long mLastLockMessageTime = 0L; - - // Things related to query logging/sampling for debugging - // slow/frequent queries during development. Always log queries - // which take (by default) 500ms+; shorter queries are sampled - // accordingly. Commit statements, which are typically slow, are - // logged together with the most recently executed SQL statement, - // for disambiguation. The 500ms value is configurable via a - // SystemProperty, but developers actively debugging database I/O - // should probably use the regular log tunable, - // LOG_SLOW_QUERIES_PROPERTY, defined below. - private static int sQueryLogTimeInMillis = 0; // lazily initialized - private static final int QUERY_LOG_SQL_LENGTH = 64; - private static final String COMMIT_SQL = "COMMIT;"; - private String mLastSqlStatement = null; - - // String prefix for slow database query EventLog records that show - // lock acquistions of the database. - /* package */ static final String GET_LOCK_LOG_PREFIX = "GETLOCK:"; - - /** Used by native code, do not rename */ - /* package */ long mNativeHandle = 0; - - /** Used to make temp table names unique */ - /* package */ int mTempTableSequence = 0; - - /** The path for the database file */ - private String mPath; - - /** The anonymized path for the database file for logging purposes */ - private String mPathForLogs = null; // lazily populated - - /** The flags passed to open/create */ - private int mFlags; - - /** The optional factory to use when creating new Cursors */ - private CursorFactory mFactory; - - private WeakHashMap mPrograms; //todo - - /** - * for each instance of this class, a cache is maintained to store - * the compiled query statement ids returned by sqlite database. - * key = sql statement with "?" for bind args - * value = {@link SQLiteCompiledSql} - * If an application opens the database and keeps it open during its entire life, then - * there will not be an overhead of compilation of sql statements by sqlite. - * - * why is this cache NOT static? because sqlite attaches compiledsql statements to the - * struct created when {@link SQLiteDatabase#(String, CursorFactory, int)} is - * invoked. - * - * this cache has an upper limit of mMaxSqlCacheSize (settable by calling the method - * (@link setMaxCacheSize(int)}). its default is 0 - i.e., no caching by default because - * most of the apps don't use "?" syntax in their sql, caching is not useful for them. - */ - /* package */ Map mCompiledQueries = new HashMap(); - /** - * @hide - */ - public static final int MAX_SQL_CACHE_SIZE = 250; - private int mMaxSqlCacheSize = MAX_SQL_CACHE_SIZE; // max cache size per Database instance - private int mCacheFullWarnings; - private static final int MAX_WARNINGS_ON_CACHESIZE_CONDITION = 1; - - /** {@link DatabaseErrorHandler} to be used when SQLite returns any of the following errors - * Corruption - * */ - private final DatabaseErrorHandler mErrorHandler; - - /** maintain stats about number of cache hits and misses */ - private int mNumCacheHits; - private int mNumCacheMisses; - - /** the following 2 members maintain the time when a database is opened and closed */ - private String mTimeOpened = null; - private String mTimeClosed = null; - - /** Used to find out where this object was created in case it never got closed. */ - private Throwable mStackTrace = null; - - // System property that enables logging of slow queries. Specify the threshold in ms. - private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold"; - private final int mSlowQueryThreshold; - - /** - * addSQLiteClosable - * @param closable SQLiteClosable - */ - void addSQLiteClosable(SQLiteClosable closable) { - lock(); - try { - mPrograms.put(closable, null); - } finally { - unlock(); - } - } - - void removeSQLiteClosable(SQLiteClosable closable) { - lock(); - try { - mPrograms.remove(closable); - } finally { - unlock(); - } - } - - @Override - protected void onAllReferencesReleased() { - if (isOpen()) { - if (SQLiteDebug.DEBUG_SQL_CACHE) { - mTimeClosed = getTime(); - } - try{ - dbclose(); - }catch (Exception e){ - e.printStackTrace(); - } - - synchronized (sActiveDatabases) { - sActiveDatabases.remove(this); - } - } - } - - /** - * Attempts to release memory that SQLite holds but does not require to - * operate properly. Typically this memory will come from the page cache. - * - * @return the number of bytes actually released - */ - static public native int releaseMemory(); - - /** - * Control whether or not the SQLiteDatabase is made thread-safe by using locks - * around critical sections. This is pretty expensive, so if you know that your - * DB will only be used by a single thread then you should set this to false. - * The default is true. - * @param lockingEnabled set to true to enable locks, false otherwise - */ - public void setLockingEnabled(boolean lockingEnabled) { - mLockingEnabled = lockingEnabled; - } - - /** - * If set then the SQLiteDatabase is made thread-safe by using locks - * around critical sections - */ - private boolean mLockingEnabled = true; - - /* package */ - void onCorruption() { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Calling error handler for corrupt database (detected) ",mPath); - // } - - // NOTE: DefaultDatabaseErrorHandler deletes the corrupt file, EXCEPT for memory database - mErrorHandler.onCorruption(this); - } - - /** - * Locks the database for exclusive access. The database lock must be held when - * touch the native sqlite3* object since it is single threaded and uses - * a polling lock contention algorithm. The lock is recursive, and may be acquired - * multiple times by the same thread. This is a no-op if mLockingEnabled is false. - * - * @see #unlock() - */ - /* package */ void lock() { - if (!mLockingEnabled) return; - mLock.lock(); - if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { - if (mLock.getHoldCount() == 1) { - // Use elapsed real-time since the CPU may sleep when waiting for IO - mLockAcquiredWallTime = Time.getRealTime(); - mLockAcquiredThreadTime = Debug.getCpuTime(); - } - } - } - - /** - * Locks the database for exclusive access. The database lock must be held when - * touch the native sqlite3* object since it is single threaded and uses - * a polling lock contention algorithm. The lock is recursive, and may be acquired - * multiple times by the same thread. - * - * @see #unlockForced() - */ - private void lockForced() { - mLock.lock(); - if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { - if (mLock.getHoldCount() == 1) { - // Use elapsed real-time since the CPU may sleep when waiting for IO - mLockAcquiredWallTime = Time.getRealTime(); - mLockAcquiredThreadTime = Debug.getCpuTime(); - } - } - } - - /** - * Releases the database lock. This is a no-op if mLockingEnabled is false. - * - * @see #unlock() - */ - /* package */ void unlock() { - if (!mLockingEnabled) return; - if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { - if (mLock.getHoldCount() == 1) { - checkLockHoldTime(); - } - } - mLock.unlock(); - } - - /** - * Releases the database lock. - * - * @see #unlockForced() - */ - private void unlockForced() { - if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) { - if (mLock.getHoldCount() == 1) { - checkLockHoldTime(); - } - } - mLock.unlock(); - } - - private void checkLockHoldTime() { - // Use elapsed real-time since the CPU may sleep when waiting for IO - long elapsedTime = Time.getRealTime(); - long lockedTime = elapsedTime - mLockAcquiredWallTime; - if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT && - !HiLog.isLoggable(0x00204,"SQLitedatabase", HiLog.LOG_APP) && - (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) { //todo, kept LOGapp istead of verbose - return; - } - if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) { - int threadTime = (int) - ((Debug.getCpuTime() - mLockAcquiredThreadTime) / 1000000); - if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS || - lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) { - mLastLockMessageTime = elapsedTime; - String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was " - + threadTime + "ms"; - if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) { - /*if(BuildConfig.DEBUG){*/ - HiLog.debug(label, msg, new Exception()); - //} - } else { - /*if(BuildConfig.DEBUG){*/ - HiLog.debug(label, msg); - // } - } - } - } - } - - /** - * Performs a PRAGMA integrity_check; command against the database. - * @return true if the integrity check is ok, otherwise false - */ - public boolean isDatabaseIntegrityOk() { - Pair result = getResultFromPragma("PRAGMA integrity_check;"); - return result.f ? result.s.equals("ok") : result.f; - } - - /** - * Returns a list of attached databases including the main database - * by executing PRAGMA database_list - * @return a list of pairs of database name and filename - */ - public List> getAttachedDbs() { - return getAttachedDbs(this); - } - - /** - * Sets the journal mode of the database to WAL - * @return true if successful, false otherwise - */ - public boolean enableWriteAheadLogging() { - if(inTransaction()) { - String message = "Write Ahead Logging cannot be enabled while in a transaction"; - throw new IllegalStateException(message); - } - List> attachedDbs = getAttachedDbs(this); - if(attachedDbs != null && attachedDbs.size() > 1) return false; - if(isReadOnly() || getPath().equals(MEMORY)) return false; - String command = "PRAGMA journal_mode = WAL;"; - rawExecSQL(command); - return true; - } - - /** - * Sets the journal mode of the database to DELETE (the default mode) - */ - public void disableWriteAheadLogging() { - if(inTransaction()) { - String message = "Write Ahead Logging cannot be disabled while in a transaction"; - throw new IllegalStateException(message); - } - String command = "PRAGMA journal_mode = DELETE;"; - rawExecSQL(command); - } - - /** - * return true if the journal mode is set to WAL, otherwise false - * @return true if the journal mode is set to WAL, otherwise false - */ - public boolean isWriteAheadLoggingEnabled() { - Pair result = getResultFromPragma("PRAGMA journal_mode;"); - return result.f ? result.s.equals("wal") : result.f; - } - - /** - * Enables or disables foreign key constraints - * @param enable used to determine whether or not foreign key constraints are on - */ - public void setForeignKeyConstraintsEnabled(boolean enable) { - if(inTransaction()) { - String message = "Foreign key constraints may not be changed while in a transaction"; - throw new IllegalStateException(message); - } - String command = String.format("PRAGMA foreign_keys = %s;", - enable ? "ON" : "OFF"); - execSQL(command); - } - - /** - * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of - * the work done in that transaction and all of the nested transactions will be committed or - * rolled back. The changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. - * - *

Here is the standard idiom for transactions: - * - *

-     *   db.beginTransaction();
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- * - * @throws IllegalStateException if the database is not open - */ - public void beginTransaction() { - beginTransactionWithListener((SQLiteTransactionListener)null /* transactionStatusCallback */); - } - - /** - * Begins a transaction in Exlcusive mode. Transactions can be nested. When - * the outer transaction is ended all of the work done in that transaction - * and all of the nested transactions will be committed or rolled back. The - * changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they - * will be committed. - * - *

Here is the standard idiom for transactions: - * - *

-     *   db.beginTransactionWithListener(listener);
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- * @param transactionListener listener that should be notified when the transaction begins, - * commits, or is rolled back, either explicitly or by a call to - * {@link #yieldIfContendedSafely}. - * - * @throws IllegalStateException if the database is not open - */ - public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) { - beginTransactionWithListenerInternal(transactionListener, - SQLiteDatabaseTransactionType.Exclusive); - } - - /** - * Begins a transaction in Immediate mode - */ - public void beginTransactionNonExclusive() { - beginTransactionWithListenerInternal(null, - SQLiteDatabaseTransactionType.Immediate); - } - - /** - * Begins a transaction in Immediate mode - * @param transactionListener is the listener used to report transaction events - */ - public void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener) { - beginTransactionWithListenerInternal(transactionListener, - SQLiteDatabaseTransactionType.Immediate); - } - - /** - * End a transaction. See beginTransaction for notes about how to use this and when transactions - * are committed and rolled back. - * - * @throws IllegalStateException if the database is not open or is not locked by the current thread - */ - public void endTransaction() { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - if (!mLock.isHeldByCurrentThread()) { - throw new IllegalStateException("no transaction pending"); - } - try { - if (mInnerTransactionIsSuccessful) { - mInnerTransactionIsSuccessful = false; - } else { - mTransactionIsSuccessful = false; - } - if (mLock.getHoldCount() != 1) { - return; - } - RuntimeException savedException = null; - if (mTransactionListener != null) { - try { - if (mTransactionIsSuccessful) { - mTransactionListener.onCommit(); - } else { - mTransactionListener.onRollback(); - } - } catch (RuntimeException e) { - savedException = e; - mTransactionIsSuccessful = false; - } - } - if (mTransactionIsSuccessful) { - execSQL(COMMIT_SQL); - } else { - try { - execSQL("ROLLBACK;"); - if (savedException != null) { - throw savedException; - } - } catch (SQLException e) { - /* if(BuildConfig.DEBUG){*/ - HiLog.debug(label, "exception during rollback, maybe the DB previously " - + "performed an auto-rollback"); - // } - } - } - } finally { - mTransactionListener = null; - unlockForced(); - /*if(BuildConfig.DEBUG){*/ - HiLog.debug(label, "unlocked " + Thread.currentThread() - + ", holdCount is " + mLock.getHoldCount()); - // } - } - } - - /** - * Marks the current transaction as successful. Do not do any more database work between - * calling this and calling endTransaction. Do as little non-database work as possible in that - * situation too. If any errors are encountered between this and endTransaction the transaction - * will still be committed. - * - * @throws IllegalStateException if the database is not open, the current thread is not in a transaction, - * or the transaction is already marked as successful. - */ - public void setTransactionSuccessful() { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - if (!mLock.isHeldByCurrentThread()) { - throw new IllegalStateException("no transaction pending"); - } - if (mInnerTransactionIsSuccessful) { - throw new IllegalStateException( - "setTransactionSuccessful may only be called once per call to beginTransaction"); - } - mInnerTransactionIsSuccessful = true; - } - - /** - * return true if there is a transaction pending - * @return true/falses - */ - public boolean inTransaction() { - return mLock.getHoldCount() > 0; - } - - /** - * Checks if the database lock is held by this thread. - * - * @return true, if this thread is holding the database lock. - */ - public boolean isDbLockedByCurrentThread() { - return mLock.isHeldByCurrentThread(); - } - - /** - * Checks if the database is locked by another thread. This is - * just an estimate, since this status can change at any time, - * including after the call is made but before the result has - * been acted upon. - * - * @return true if the transaction was yielded, false if queue was empty or database was not open - */ - public boolean isDbLockedByOtherThreads() { - return !mLock.isHeldByCurrentThread() && mLock.isLocked(); - } - - /** - * Temporarily end the transaction to let other threads run. The transaction is assumed to be - * successful so far. Do not call setTransactionSuccessful before calling this. When this - * returns a new transaction will have been created but not marked as successful. - * - * @return true if the transaction was yielded - * - * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock - * will not be yielded. Use yieldIfContendedSafely instead. - */ - @Deprecated - public boolean yieldIfContended() { - /* safeguard: */ - if (!isOpen()) return false; - - return yieldIfContendedHelper(false /* do not check yielding */, - -1 /* sleepAfterYieldDelay */); - } - - /** - * Temporarily end the transaction to let other threads run. The transaction is assumed to be - * successful so far. Do not call setTransactionSuccessful before calling this. When this - * returns a new transaction will have been created but not marked as successful. This assumes - * that there are no nested transactions (beginTransaction has only been called once) and will - * throw an exception if that is not the case. - * - * @return true if the transaction was yielded, false if queue was empty or database was not open - */ - public boolean yieldIfContendedSafely() { - /* safeguard: */ - if (!isOpen()) return false; - - return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/); - } - - /** - * Temporarily end the transaction to let other threads run. The transaction is assumed to be - * successful so far. Do not call setTransactionSuccessful before calling this. When this - * returns a new transaction will have been created but not marked as successful. This assumes - * that there are no nested transactions (beginTransaction has only been called once) and will - * throw an exception if that is not the case. - * - * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if - * the lock was actually yielded. This will allow other background threads to make some - * more progress than they would if we started the transaction immediately. - * - * @return true if the transaction was yielded, false if queue was empty or database was not open - * - * @throws IllegalStateException if the database is locked more than once by the current thread - * @throws InterruptedException if the thread was interrupted while sleeping - */ - public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) { - /* safeguard: */ - if (!isOpen()) return false; - - return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay); - } - - private boolean yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay) { - if (mLock.getQueueLength() == 0) { - // Reset the lock acquire time since we know that the thread was willing to yield - // the lock at this time. - mLockAcquiredWallTime = Time.getRealTime(); - mLockAcquiredThreadTime = Debug.getCpuTime(); - return false; - } - setTransactionSuccessful(); - SQLiteTransactionListener transactionListener = mTransactionListener; - endTransaction(); - if (checkFullyYielded) { - if (this.isDbLockedByCurrentThread()) { - throw new IllegalStateException( - "Db locked more than once. yielfIfContended cannot yield"); - } - } - if (sleepAfterYieldDelay > 0) { - // Sleep for up to sleepAfterYieldDelay milliseconds, waking up periodically to - // check if anyone is using the database. If the database is not contended, - // retake the lock and return. - long remainingDelay = sleepAfterYieldDelay; - while (remainingDelay > 0) { - try { - Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ? - remainingDelay : SLEEP_AFTER_YIELD_QUANTUM); - } catch (InterruptedException e) { - Thread.interrupted(); - } - remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM; - if (mLock.getQueueLength() == 0) { - break; - } - } - } - beginTransactionWithListener(transactionListener); - return true; - } - - /** Maps table names to info about what to which _sync_time column to set - * to NULL on an update. This is used to support syncing. */ - private final Map mSyncUpdateInfo = - new HashMap(); - - public Map getSyncedTables() { - synchronized(mSyncUpdateInfo) { - HashMap tables = new HashMap(); - for (String table : mSyncUpdateInfo.keySet()) { - SyncUpdateInfo info = mSyncUpdateInfo.get(table); - if (info.deletedTable != null) { - tables.put(table, info.deletedTable); - } - } - return tables; - } - } - - /** - * Internal class used to keep track what needs to be marked as changed - * when an update occurs. This is used for syncing, so the sync engine - * knows what data has been updated locally. - */ - static private class SyncUpdateInfo { - /** - * Creates the SyncUpdateInfo class. - * - * @param masterTable The table to set _sync_time to NULL in - * @param deletedTable The deleted table that corresponds to the - * master table - * @param foreignKey The key that refers to the primary key in table - */ - SyncUpdateInfo(String masterTable, String deletedTable, - String foreignKey) { - this.masterTable = masterTable; - this.deletedTable = deletedTable; - this.foreignKey = foreignKey; - } - - /** The table containing the _sync_time column */ - String masterTable; - - /** The deleted table that corresponds to the master table */ - String deletedTable; - - /** The key in the local table the row in table. It may be _id, if table - * is the local table. */ - String foreignKey; - } - - /** - * Used to allow returning sub-classes of {@link ResultSet} when calling query. - */ - public interface CursorFactory { - /** - * See - * {@link SQLiteCursor#SQLiteCursor(SQLiteDatabase, SQLiteCursorDriver, - * String, SQLiteQuery)}. - * @param db database - * @param masterQuery SQLiteCursorDriver - * @param editTable string - * @param query query - * @return Resultset - */ - ResultSet newCursor(SQLiteDatabase db, - SQLiteCursorDriver masterQuery, String editTable, - SQLiteQuery query); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, String password, CursorFactory factory, int flags) { - return openDatabase(path, password, factory, flags, null); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. - * - *

Sets the locale of the database to the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file (char array) - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, char[] password, CursorFactory factory, int flags) { - return openDatabase(path, password, factory, flags, null, null); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS} - * with optional hook to run on pre/post key events. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * @param hook to run on pre/post key events - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, String password, CursorFactory factory, int flags, SQLiteDatabaseHook hook) { - return openDatabase(path, password, factory, flags, hook, null); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS} - * with optional hook to run on pre/post key events. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file (char array) - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * @param hook to run on pre/post key events (may be null) - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, char[] password, CursorFactory factory, int flags, SQLiteDatabaseHook hook) { - return openDatabase(path, password, factory, flags, hook, null); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS} - * with optional hook to run on pre/post key events. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * @param hook to run on pre/post key events - * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption (or null for default). - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, String password, CursorFactory factory, int flags, - SQLiteDatabaseHook hook, DatabaseErrorHandler errorHandler) { - return openDatabase(path, password == null ? null : password.toCharArray(), factory, flags, hook, errorHandler); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS} - * with optional hook to run on pre/post key events. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file (char array) - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * @param hook to run on pre/post key events (may be null) - * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption (or null for default). - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, char[] password, CursorFactory factory, int flags, - SQLiteDatabaseHook hook, DatabaseErrorHandler errorHandler) { - byte[] keyMaterial = getBytes(password); - return openDatabase(path, keyMaterial, factory, flags, hook, errorHandler); - } - - /** - * Open the database according to the flags {@link #OPEN_READWRITE} - * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS} - * with optional hook to run on pre/post key events. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path to database file to open and/or create - * @param password to use to open and/or create database file (byte array) - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called, or null for default - * @param flags to control database access mode and other options - * @param hook to run on pre/post key events (may be null) - * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption (or null for default). - * - * @return the newly opened database - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public static SQLiteDatabase openDatabase(String path, byte[] password, CursorFactory factory, int flags, - SQLiteDatabaseHook hook, DatabaseErrorHandler errorHandler) { - SQLiteDatabase sqliteDatabase = null; - DatabaseErrorHandler myErrorHandler = (errorHandler != null) ? errorHandler : new DefaultDatabaseErrorHandler(); - - try { - // Open the database. - sqliteDatabase = new SQLiteDatabase(path, factory, flags, myErrorHandler); - sqliteDatabase.openDatabaseInternal(password, hook); - } catch (SQLiteDatabaseCorruptException e) { - // Try to recover from this, if possible. - // FUTURE TBD: should we consider this for other open failures? - - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Calling error handler for corrupt database " + path, e); - // } - - // NOTE: if this errorHandler.onCorruption() throws the exception _should_ - // bubble back to the original caller. - // DefaultDatabaseErrorHandler deletes the corrupt file, EXCEPT for memory database - myErrorHandler.onCorruption(sqliteDatabase); - - // try *once* again: - sqliteDatabase = new SQLiteDatabase(path, factory, flags, myErrorHandler); - sqliteDatabase.openDatabaseInternal(password, hook); - } - - if (SQLiteDebug.DEBUG_SQL_STATEMENTS) { - sqliteDatabase.enableSqlTracing(path); - } - if (SQLiteDebug.DEBUG_SQL_TIME) { - sqliteDatabase.enableSqlProfiling(path); - } - - synchronized (sActiveDatabases) { - sActiveDatabases.put(sqliteDatabase, null); - } - - return sqliteDatabase; - } - - /** - * Equivalent to openDatabase(file.getPath(), password, factory, CREATE_IF_NECESSARY, databaseHook). - * @param file path - * @param password password - * @param factory factory - * @param databaseHook SQLiteDatabaseHook - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(File file, String password, CursorFactory factory, SQLiteDatabaseHook databaseHook) { - return openOrCreateDatabase(file, password, factory, databaseHook, null); - } - - /** - * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook). - * @param file path - * @param password password - * @param factory factory - * @param databaseHook SQLiteDatabaseHook - * @param errorHandler DatabaseErrorHandler - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(File file, String password, CursorFactory factory, SQLiteDatabaseHook databaseHook, - DatabaseErrorHandler errorHandler) { - return openOrCreateDatabase(file == null ? null : file.getPath(), password, factory, databaseHook, errorHandler); - } - - /** - * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook). - * @param path path - * @param password password - * @param factory factory - * @param databaseHook SQLiteDatabaseHook - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(String path, String password, CursorFactory factory, SQLiteDatabaseHook databaseHook) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook); - } - - public static SQLiteDatabase openOrCreateDatabase(String path, String password, CursorFactory factory, SQLiteDatabaseHook databaseHook, - DatabaseErrorHandler errorHandler) { - return openDatabase(path, password == null ? null : password.toCharArray(), factory, CREATE_IF_NECESSARY, databaseHook, errorHandler); - } - - public static SQLiteDatabase openOrCreateDatabase(String path, char[] password, CursorFactory factory, SQLiteDatabaseHook databaseHook) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook); - } - - public static SQLiteDatabase openOrCreateDatabase(String path, char[] password, CursorFactory factory, SQLiteDatabaseHook databaseHook, - DatabaseErrorHandler errorHandler) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook, errorHandler); - } - - public static SQLiteDatabase openOrCreateDatabase(String path, byte[] password, CursorFactory factory, SQLiteDatabaseHook databaseHook) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook, null); - } - - public static SQLiteDatabase openOrCreateDatabase(String path, byte[] password, CursorFactory factory, SQLiteDatabaseHook databaseHook, - DatabaseErrorHandler errorHandler) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook, errorHandler); - } - - /** - * Equivalent to openDatabase(file.getPath(), password, factory, CREATE_IF_NECESSARY). - * @param file file - * @param password password - * @param factory factory - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(File file, String password, CursorFactory factory) { - return openOrCreateDatabase(file, password, factory, null); - } - - /** - * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY). - * @param path path - * @param password password - * @param factory factory - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(String path, String password, CursorFactory factory) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, null); - } - - /** - * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY). - * @param path path - * @param password password - * @param factory factory - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(String path, char[] password, CursorFactory factory) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, null); - } - - /** - * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY). - * @param path path - * @param password password - * @param factory CursorFactory - * @return SQLiteDatabase - */ - public static SQLiteDatabase openOrCreateDatabase(String path, byte[] password, CursorFactory factory) { - return openDatabase(path, password, factory, CREATE_IF_NECESSARY, null, null); - } - - /** - * Create a memory backed SQLite database. Its contents will be destroyed - * when the database is closed. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called - * @param password to use to open and/or create database file - * - * @return a SQLiteDatabase object, or null if the database can't be created - * - * @throws SQLiteException if the database cannot be opened - */ - public static SQLiteDatabase create(CursorFactory factory, String password) { - // This is a magic string with special meaning for SQLite. - return openDatabase(MEMORY, password == null ? null : password.toCharArray(), factory, CREATE_IF_NECESSARY); - } - - /** - * Create a memory backed SQLite database. Its contents will be destroyed - * when the database is closed. - * - *

Sets the locale of the database to the the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param factory an optional factory class that is called to instantiate a - * cursor when query is called - * @param password to use to open and/or create database file (char array) - * - * @return a SQLiteDatabase object, or null if the database can't be created - * - * @throws SQLiteException if the database cannot be opened - */ - public static SQLiteDatabase create(CursorFactory factory, char[] password) { - return openDatabase(MEMORY, password, factory, CREATE_IF_NECESSARY); - } - - - /** - * Close the database. - */ - public void close() { - - if (!isOpen()) { - return; // already closed - } - lock(); - try { - closeClosable(); - // close this database instance - regardless of its reference count value - onAllReferencesReleased(); - } finally { - unlock(); - } - } - - private void closeClosable() { - /* deallocate all compiled sql statement objects from mCompiledQueries cache. - * this should be done before de-referencing all {@link SQLiteClosable} objects - * from this database object because calling - * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database - * to be closed. sqlite doesn't let a database close if there are - * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries. - */ - deallocCachedSqlStatements(); - - Iterator> iter = mPrograms.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - SQLiteClosable program = entry.getKey(); - if (program != null) { - program.onAllReferencesReleasedFromContainer(); - } - } - } - - /** - * Native call to close the database. - */ - private native void dbclose(); - - /** - * Gets the database version. - * - * @return the database version - * - * @throws IllegalStateException if the database is not open - */ - public int getVersion() { - SQLiteStatement prog = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - prog = new SQLiteStatement(this, "PRAGMA user_version;"); - long version = prog.simpleQueryForLong(); - return (int) version; - } finally { - if (prog != null) prog.close(); - unlock(); - } - } - - /** - * Sets the database version. - * - * @param version the new database version - * - * @throws SQLiteException if there is an issue executing the sql internally - * @throws IllegalStateException if the database is not open - */ - public void setVersion(int version) { - execSQL("PRAGMA user_version = " + version); - } - - /** - * Returns the maximum size the database may grow to. - * - * @return the new maximum database size - */ - public long getMaximumSize() { - SQLiteStatement prog = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - prog = new SQLiteStatement(this, - "PRAGMA max_page_count;"); - long pageCount = prog.simpleQueryForLong(); - return pageCount * getPageSize(); - } finally { - if (prog != null) prog.close(); - unlock(); - } - } - - /** - * Sets the maximum size the database will grow to. The maximum size cannot - * be set below the current size. - * - * @param numBytes the maximum database size, in bytes - * @return the new maximum database size - */ - public long setMaximumSize(long numBytes) { - SQLiteStatement prog = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - long pageSize = getPageSize(); - long numPages = numBytes / pageSize; - // If numBytes isn't a multiple of pageSize, bump up a page - if ((numBytes % pageSize) != 0) { - numPages++; - } - prog = new SQLiteStatement(this, - "PRAGMA max_page_count = " + numPages); - long newPageCount = prog.simpleQueryForLong(); - return newPageCount * pageSize; - } finally { - if (prog != null) prog.close(); - unlock(); - } - } - - /** - * Returns the current database page size, in bytes. - * - * @return the database page size, in bytes - */ - public long getPageSize() { - SQLiteStatement prog = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - prog = new SQLiteStatement(this, - "PRAGMA page_size;"); - long size = prog.simpleQueryForLong(); - return size; - } finally { - if (prog != null) prog.close(); - unlock(); - } - } - - /** - * Sets the database page size. The page size must be a power of two. This - * method does not work if any data has been written to the database file, - * and must be called right after the database has been created. - * - * @param numBytes the database page size, in bytes - */ - public void setPageSize(long numBytes) { - execSQL("PRAGMA page_size = " + numBytes); - } - - /** - * Mark this table as syncable. When an update occurs in this table the - * _sync_dirty field will be set to ensure proper syncing operation. - * - * @param table the table to mark as syncable - * @param deletedTable The deleted table that corresponds to the - * syncable table - * - * @throws SQLiteException if there is an issue executing the sql to mark the table as syncable - * OR if the database is not open - * - * FUTURE @todo throw IllegalStateException if the database is not open and - * update the test suite - * - * NOTE: This method was deprecated. - */ - public void markTableSyncable(String table, String deletedTable) { - /* safeguard: */ - if (!isOpen()) { - throw new SQLiteException("database not open"); - } - - markTableSyncable(table, "_id", table, deletedTable); - } - - /** - * Mark this table as syncable, with the _sync_dirty residing in another - * table. When an update occurs in this table the _sync_dirty field of the - * row in updateTable with the _id in foreignKey will be set to - * ensure proper syncing operation. - * - * @param table an update on this table will trigger a sync time removal - * @param foreignKey this is the column in table whose value is an _id in - * updateTable - * @param updateTable this is the table that will have its _sync_dirty - * - * @throws SQLiteException if there is an issue executing the sql to mark the table as syncable - * - * FUTURE @todo throw IllegalStateException if the database is not open and - * update the test suite - * - * NOTE: This method was deprecated. - */ - public void markTableSyncable(String table, String foreignKey, - String updateTable) { - /* safeguard: */ - if (!isOpen()) { - throw new SQLiteException("database not open"); - } - - markTableSyncable(table, foreignKey, updateTable, null); - } - - /** - * Mark this table as syncable, with the _sync_dirty residing in another - * table. When an update occurs in this table the _sync_dirty field of the - * row in updateTable with the _id in foreignKey will be set to - * ensure proper syncing operation. - * - * @param table an update on this table will trigger a sync time removal - * @param foreignKey this is the column in table whose value is an _id in - * updateTable - * @param updateTable this is the table that will have its _sync_dirty - * @param deletedTable The deleted table that corresponds to the - * updateTable - * - * @throws SQLiteException if there is an issue executing the sql - */ - private void markTableSyncable(String table, String foreignKey, - String updateTable, String deletedTable) { - lock(); - try { - native_execSQL("SELECT _sync_dirty FROM " + updateTable - + " LIMIT 0"); - native_execSQL("SELECT " + foreignKey + " FROM " + table - + " LIMIT 0"); - } finally { - unlock(); - } - - SyncUpdateInfo info = new SyncUpdateInfo(updateTable, deletedTable, - foreignKey); - synchronized (mSyncUpdateInfo) { - mSyncUpdateInfo.put(table, info); - } - } - - /** - * Call for each row that is updated in a cursor. - * - * @param table the table the row is in - * @param rowId the row ID of the updated row - */ - /* package */ void rowUpdated(String table, long rowId) { - SyncUpdateInfo info; - synchronized (mSyncUpdateInfo) { - info = mSyncUpdateInfo.get(table); - } - if (info != null) { - execSQL("UPDATE " + info.masterTable - + " SET _sync_dirty=1 WHERE _id=(SELECT " + info.foreignKey - + " FROM " + table + " WHERE _id=" + rowId + ")"); - } - } - - /** - * Finds the name of the first table, which is editable. - * - * @param tables a list of tables - * @return the first table listed - */ - public static String findEditTable(String tables) { - if (!TextUtils.isEmpty(tables)) { - // find the first word terminated by either a space or a comma - int spacepos = tables.indexOf(' '); - int commapos = tables.indexOf(','); - - if (spacepos > 0 && (spacepos < commapos || commapos < 0)) { - return tables.substring(0, spacepos); - } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) { - return tables.substring(0, commapos); - } - return tables; - } else { - throw new IllegalStateException("Invalid tables"); - } - } - - /** - * Compiles an SQL statement into a reusable pre-compiled statement object. - * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the - * statement and fill in those values with {@link SQLiteProgram#bindString} - * and {@link SQLiteProgram#bindLong} each time you want to run the - * statement. Statements may not return result sets larger than 1x1. - * - * @param sql The raw SQL statement, may contain ? for unknown values to be - * bound later. - * - * @return A pre-compiled {@link SQLiteStatement} object. Note that - * {@link SQLiteStatement}s are not synchronized, see the documentation for more details. - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public SQLiteStatement compileStatement(String sql) throws SQLException { - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - return new SQLiteStatement(this, sql); - } finally { - unlock(); - } - } - - /** - * Query the result with the selection - * - * @param distinct true if you want each row to be unique, false otherwise. - * @param table The table name to compile the query against. - * @param columns A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading - * data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null - * will return all rows for the given table. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in order that they - * appear in the selection. The values will be bound as Strings. - * @param groupBy A filter declaring how to group rows, formatted as an SQL - * GROUP BY clause (excluding the GROUP BY itself). Passing null - * will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in the cursor, - * if row grouping is being used, formatted as an SQL HAVING - * clause (excluding the HAVING itself). Passing null will cause - * all row groups to be included, and is required when row - * grouping is not being used. - * @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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - * - * @see ResultSet - */ - public ResultSet query(boolean distinct, String table, String[] columns, - String selection, String[] selectionArgs, String groupBy, - String having, String orderBy, String limit) { - return queryWithFactory(null, distinct, table, columns, selection, selectionArgs, - groupBy, having, orderBy, limit); - } - - /** - * query the result with the cursor factory - * - * @param cursorFactory the cursor factory to use, or null for the default factory - * @param distinct true if you want each row to be unique, false otherwise. - * @param table The table name to compile the query against. - * @param columns A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading - * data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null - * will return all rows for the given table. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in order that they - * appear in the selection. The values will be bound as Strings. - * @param groupBy A filter declaring how to group rows, formatted as an SQL - * GROUP BY clause (excluding the GROUP BY itself). Passing null - * will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in the cursor, - * if row grouping is being used, formatted as an SQL HAVING - * clause (excluding the HAVING itself). Passing null will cause - * all row groups to be included, and is required when row - * grouping is not being used. - * @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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * - * @return object, which is positioned before the first entry. Note that - * {@link }s are not synchronized, see the documentation for more details. - * - */ - public ResultSet queryWithFactory(CursorFactory cursorFactory, - boolean distinct, String table, String[] columns, - String selection, String[] selectionArgs, String groupBy, - String having, String orderBy, String limit) { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - String sql = SQLiteQueryBuilder.buildQueryString( - distinct, table, columns, selection, groupBy, having, orderBy, limit); - - return rawQueryWithFactory( - cursorFactory, sql, selectionArgs, findEditTable(table)); - } - - /** - * Query the given table, returning a {@link ResultSet} over the result set. - * - * @param table The table name to compile the query against. - * @param columns A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading - * data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null - * will return all rows for the given table. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in order that they - * appear in the selection. The values will be bound as Strings. - * @param groupBy A filter declaring how to group rows, formatted as an SQL - * GROUP BY clause (excluding the GROUP BY itself). Passing null - * will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in the cursor, - * if row grouping is being used, formatted as an SQL HAVING - * clause (excluding the HAVING itself). Passing null will cause - * all row groups to be included, and is required when row - * grouping is not being used. - * @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 may be unordered. - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - * - * @see ResultSet - */ - public ResultSet query(String table, String[] columns, String selection, - String[] selectionArgs, String groupBy, String having, - String orderBy) { - - return query(false, table, columns, selection, selectionArgs, groupBy, - having, orderBy, null /* limit */); - } - - /** - * Query the given table, returning a {@link ResultSet} over the result set. - * - * @param table The table name to compile the query against. - * @param columns A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading - * data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null - * will return all rows for the given table. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in order that they - * appear in the selection. The values will be bound as Strings. - * @param groupBy A filter declaring how to group rows, formatted as an SQL - * GROUP BY clause (excluding the GROUP BY itself). Passing null - * will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in the cursor, - * if row grouping is being used, formatted as an SQL HAVING - * clause (excluding the HAVING itself). Passing null will cause - * all row groups to be included, and is required when row - * grouping is not being used. - * @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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - * - * @see ResultSet - */ - public ResultSet query(String table, String[] columns, String selection, - String[] selectionArgs, String groupBy, String having, - String orderBy, String limit) { - - return query(false, table, columns, selection, selectionArgs, groupBy, - having, orderBy, limit); - } - - /** - * Runs the provided SQL and returns a {@link ResultSet} over the result set. - * - * @param sql the SQL query. The SQL string must not be ; terminated - * @param selectionArgs You may include ?s in where clause in the query, - * which will be replaced by the values from selectionArgs. The - * values will be bound as Strings. - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - */ - public ResultSet rawQuery(String sql, String[] selectionArgs) { - return rawQueryWithFactory(null, sql, selectionArgs, null); - } - - /** - * Determines the total size in bytes of the query results, and the largest - * single row in bytes for the query. - * - * @param sql the SQL query. The SQL string must a SELECT statement - * @param args the argments to bind to the query - * - * @return A {@link SQLiteQueryStats} based the provided SQL query. - */ - public SQLiteQueryStats getQueryStats(String sql, Object[] args){ - long totalPayload = 0L; - long largestIndividualPayload = 0L; - try { - String query = String.format("CREATE TABLE tempstat AS %s", sql); - execSQL(query, args); - ResultSet cursor = rawQuery("SELECT sum(payload) FROM dbstat WHERE name = tempstat;", new Object[]{}); - if(cursor == null) return new SQLiteQueryStats(totalPayload, largestIndividualPayload); - cursor.goToFirstRow(); - totalPayload = cursor.getLong(0); - cursor.close(); - cursor = rawQuery("SELECT max(mx_payload) FROM dbstat WHERE name = tempstat;", new Object[]{}); - if(cursor == null) return new SQLiteQueryStats(totalPayload, largestIndividualPayload); - cursor.goToFirstRow(); - largestIndividualPayload = cursor.getLong(0); - cursor.close(); - execSQL("DROP TABLE tempstat;"); - } catch(SQLiteException ex) { - execSQL("DROP TABLE IF EXISTS tempstat;"); - throw ex; - } - return new SQLiteQueryStats(totalPayload, largestIndividualPayload); - } - - /** - * Runs the provided SQL and returns a {@link ResultSet} over the result set. - * - * @param sql the SQL query. The SQL string must not be ; terminated - * @param args You may include ?s in where clause in the query, - * which will be replaced by the values from args. The - * values will be bound by their type. - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - */ - public ResultSet rawQuery(String sql, Object[] args) { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - long timeStart = 0; - if (/*Config.LOGV || */mSlowQueryThreshold != -1) { - timeStart = System.currentTimeMillis(); - } - SQLiteDirectCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, null); - ResultSet cursor = null; - try { - cursor = driver.query(mFactory, args); - } finally { - if (/*Config.LOGV ||*/ mSlowQueryThreshold != -1) { - // Force query execution - int count = -1; - if (cursor != null) { - count = cursor.getRowCount(); - } - - long duration = System.currentTimeMillis() - timeStart; - - if (/*BuildConfig.DEBUG || */duration >= mSlowQueryThreshold) { - HiLog.error(label, - "query (" + duration + " ms): " + driver.toString() + - ", args are , count is " + count); - } - } - } - return new CrossProcessCursorWrapper(cursor); - } - - /** - * Runs the provided SQL and returns a cursor over the result set. - * - * @param cursorFactory the cursor factory to use, or null for the default factory - * @param sql the SQL query. The SQL string must not be ; terminated - * @param selectionArgs You may include ?s in where clause in the query, - * which will be replaced by the values from selectionArgs. The - * values will be bound as Strings. - * @param editTable the name of the first table, which is editable - * - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * - * @throws SQLiteException if there is an issue executing the sql or the SQL string is invalid - * @throws IllegalStateException if the database is not open - */ - public ResultSet rawQueryWithFactory( - CursorFactory cursorFactory, String sql, String[] selectionArgs, - String editTable) { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - long timeStart = 0; - - if (/*Config.LOGV || */mSlowQueryThreshold != -1) { - timeStart = System.currentTimeMillis(); - } - - SQLiteDirectCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable); - - ResultSet cursor = null; - try { - cursor = driver.query( - cursorFactory != null ? cursorFactory : mFactory, - selectionArgs); - } finally { - if (/*Config.LOGV||*/ mSlowQueryThreshold != -1) { - - // Force query execution - int count = -1; - if (cursor != null) { - count = cursor.getRowCount(); - } - - long duration = System.currentTimeMillis() - timeStart; - - if (/*BuildConfig.DEBUG || */duration >= mSlowQueryThreshold) { - HiLog.debug(label, - "query (" + duration + " ms): " + driver.toString() + - ", args are , count is " + count); - } - } - } - return new CrossProcessCursorWrapper(cursor); - } - - /** - * Runs the provided SQL and returns a cursor over the result set. - * The cursor will read an initial set of rows and the return to the caller. - * It will continue to read in batches and send data changed notifications - * when the later batches are ready. - * @param sql the SQL query. The SQL string must not be ; terminated - * @param selectionArgs You may include ?s in where clause in the query, - * which will be replaced by the values from selectionArgs. The - * values will be bound as Strings. - * @param initialRead set the initial count of items to read from the cursor - * @param maxRead set the count of items to read on each iteration after the first - * @return A {@link } object, which is positioned before the first entry. Note that - * {@link }s are not synchronized, see the documentation for more details. - * - * This work is incomplete and not fully tested or reviewed, so currently - * hidden. - * @hide - */ - public ResultSet rawQuery(String sql, String[] selectionArgs, - int initialRead, int maxRead) { - net.sqlcipher.CursorWrapper cursorWrapper = (net.sqlcipher.CursorWrapper)rawQueryWithFactory(null, sql, selectionArgs, null); - ((SQLiteCursor)cursorWrapper.getResultSet()).setLoadStyle(initialRead, maxRead); - return cursorWrapper; - } - - /** - * Convenience method for inserting a row into the database. - * - * @param table the table to insert the row into - * @param nullColumnHack SQL doesn't allow inserting a completely empty row, - * so if initialValues is empty this column will explicitly be - * assigned a NULL value - * @param values this map contains the initial column values for the - * row. The keys should be the column names and the values the - * column values - * @return the row ID of the newly inserted row, or -1 if an error occurred - */ - public long insert(String table, String nullColumnHack, ValuesBucket values) { - try { - return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); - } catch (SQLException e) { - /* if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error inserting into " + table, e); - // } - return -1; - } - } - - /** - * Convenience method for inserting a row into the database. - * - * @param table the table to insert the row into - * @param nullColumnHack SQL doesn't allow inserting a completely empty row, - * so if initialValues is empty this column will explicitly be - * assigned a NULL value - * @param values this map contains the initial column values for the - * row. The keys should be the column names and the values the - * column values - * @throws SQLException - * @return the row ID of the newly inserted row, or -1 if an error occurred - */ - public long insertOrThrow(String table, String nullColumnHack, ValuesBucket values) - throws SQLException { - return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); - } - - /** - * Convenience method for replacing a row in the database. - * - * @param table the table in which to replace the row - * @param nullColumnHack SQL doesn't allow inserting a completely empty row, - * so if initialValues is empty this row will explicitly be - * assigned a NULL value - * @param initialValues this map contains the initial column values for - * the row. The key - * @return the row ID of the newly inserted row, or -1 if an error occurred - */ - public long replace(String table, String nullColumnHack, ValuesBucket initialValues) { - try { - return insertWithOnConflict(table, nullColumnHack, initialValues, - CONFLICT_REPLACE); - } catch (SQLException e) { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error inserting into " + table, e); - //} - return -1; - } - } - - /** - * Convenience method for replacing a row in the database. - * - * @param table the table in which to replace the row - * @param nullColumnHack SQL doesn't allow inserting a completely empty row, - * so if initialValues is empty this row will explicitly be - * assigned a NULL value - * @param initialValues this map contains the initial column values for - * the row. The key - * @throws SQLException - * @return the row ID of the newly inserted row, or -1 if an error occurred - */ - public long replaceOrThrow(String table, String nullColumnHack, - ValuesBucket initialValues) throws SQLException { - return insertWithOnConflict(table, nullColumnHack, initialValues, - CONFLICT_REPLACE); - } - - /** - * General method for inserting a row into the database. - * - * @param table the table to insert the row into - * @param nullColumnHack SQL doesn't allow inserting a completely empty row, - * so if initialValues is empty this column will explicitly be - * assigned a NULL value - * @param initialValues this map contains the initial column values for the - * row. The keys should be the column names and the values the - * column values - * @param conflictAlgorithm for insert conflict resolver - * - * @return the row ID of the newly inserted row - * OR the primary key of the existing row if the input param 'conflictAlgorithm' = - * {@link #CONFLICT_IGNORE} - * OR -1 if any error - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public long insertWithOnConflict(String table, String nullColumnHack, - ValuesBucket initialValues, int conflictAlgorithm) { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - - // Measurements show most sql lengths <= 152 - StringBuilder sql = new StringBuilder(152); - sql.append("INSERT"); - sql.append(CONFLICT_VALUES[conflictAlgorithm]); - sql.append(" INTO "); - sql.append(table); - // Measurements show most values lengths < 40 - StringBuilder values = new StringBuilder(40); - - Set> entrySet = null; - if (initialValues != null && initialValues.size() > 0) { - entrySet = initialValues.getAll(); - Iterator> entriesIter = entrySet.iterator(); - sql.append('('); - - boolean needSeparator = false; - while (entriesIter.hasNext()) { - if (needSeparator) { - sql.append(", "); - values.append(", "); - } - needSeparator = true; - Map.Entry entry = entriesIter.next(); - sql.append(entry.getKey()); - values.append('?'); - } - - sql.append(')'); - } else { - sql.append("(" + nullColumnHack + ") "); - values.append("NULL"); - } - - sql.append(" VALUES("); - sql.append(values); - sql.append(");"); - - lock(); - SQLiteStatement statement = null; - try { - statement = compileStatement(sql.toString()); - - // Bind the values - if (entrySet != null) { - int size = entrySet.size(); - Iterator> entriesIter = entrySet.iterator(); - for (int i = 0; i < size; i++) { - Map.Entry entry = entriesIter.next(); - DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue()); - - } - } - - // Run the program and then cleanup - statement.execute(); - - long insertedRowId = lastChangeCount() > 0 ? lastInsertRow() : -1; - if (insertedRowId == -1) { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error inserting using into ", table); - //} - } else { -// if (/*BuildConfig.DEBUG &&*/ HiLog.isLoggable(0x00208, "SqliteDatabase", HiLog.DEBUG)) { //CHANGE - HiLog.debug(label, "Inserting row " + insertedRowId + - " from using into " + table); - // } - } - return insertedRowId; - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } finally { - if (statement != null) { - statement.close(); - } - unlock(); - } - } - - /** - * Convenience method for deleting rows in the database. - * - * @param table the table to delete from - * @param whereClause the optional WHERE clause to apply when deleting. - * Passing null will delete all rows. - * @param whereArgs arguments - * @return the number of rows affected if a whereClause is passed in, 0 - * otherwise. To remove all rows and get a count pass "1" as the - * whereClause. - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public int delete(String table, String whereClause, String[] whereArgs) { - return delete(table, whereClause, (Object[])whereArgs); - } - - /** - * Convenience method for deleting rows in the database. - * - * @param table the table to delete from - * @param whereClause the optional WHERE clause to apply when deleting. - * Passing null will delete all rows. - * @param whereArgs arguments - * @return the number of rows affected if a whereClause is passed in, 0 - * otherwise. To remove all rows and get a count pass "1" as the - * whereClause. - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public int delete(String table, String whereClause, Object[] whereArgs) { - SQLiteStatement statement = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - statement = compileStatement("DELETE FROM " + table - + (!TextUtils.isEmpty(whereClause) - ? " WHERE " + whereClause : "")); - if (whereArgs != null) { - int numArgs = whereArgs.length; - for (int i = 0; i < numArgs; i++) { - DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]); - } - } - statement.execute(); - return lastChangeCount(); - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } finally { - if (statement != null) { - statement.close(); - } - unlock(); - } - } - - /** - * Convenience method for updating rows in the database. - * - * @param table the table to update in - * @param values a map from column names to new column values. null is a - * valid value that will be translated to NULL. - * @param whereClause the optional WHERE clause to apply when updating. - * Passing null will update all rows. - * @param whereArgs arguments - * @return the number of rows affected - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public int update(String table, ValuesBucket values, String whereClause, String[] whereArgs) { - return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE); - } - - /** - * Convenience method for updating rows in the database. - * - * @param table the table to update in - * @param values a map from column names to new column values. null is a - * valid value that will be translated to NULL. - * @param whereClause the optional WHERE clause to apply when updating. - * Passing null will update all rows. - * @param whereArgs arguments - * @param conflictAlgorithm for update conflict resolver - * - * @return the number of rows affected - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public int updateWithOnConflict(String table, ValuesBucket values, - String whereClause, String[] whereArgs, int conflictAlgorithm) { - if (values == null || values.size() == 0) { - throw new IllegalArgumentException("Empty values"); - } - - StringBuilder sql = new StringBuilder(120); - sql.append("UPDATE "); - sql.append(CONFLICT_VALUES[conflictAlgorithm]); - sql.append(table); - sql.append(" SET "); - - Set> entrySet = values.getAll(); - Iterator> entriesIter = entrySet.iterator(); - - while (entriesIter.hasNext()) { - Map.Entry entry = entriesIter.next(); - sql.append(entry.getKey()); - sql.append("=?"); - if (entriesIter.hasNext()) { - sql.append(", "); - } - } - - if (!TextUtils.isEmpty(whereClause)) { - sql.append(" WHERE "); - sql.append(whereClause); - } - SQLiteStatement statement = null; - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - statement = compileStatement(sql.toString()); - - // Bind the values - int size = entrySet.size(); - entriesIter = entrySet.iterator(); - int bindArg = 1; - for (int i = 0; i < size; i++) { - Map.Entry entry = entriesIter.next(); - DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue()); - bindArg++; - } - - if (whereArgs != null) { - size = whereArgs.length; - for (int i = 0; i < size; i++) { - statement.bindString(bindArg, whereArgs[i]); - bindArg++; - } - } - - // Run the program and then cleanup - statement.execute(); - int numChangedRows = lastChangeCount(); - if (/*BuildConfig.DEBUG &&*/ HiLog.isLoggable(0x00201, "SQLiteDatabase", HiLog.LOG_APP)) { - HiLog.debug(label, "Updated " + numChangedRows + - " rows using and for " + table); - } - return numChangedRows; - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } catch (SQLException e) { - /* if(BuildConfig.DEBUG){*/ - HiLog.error(label, "Error updating using for ", table); - // } - throw e; - } finally { - if (statement != null) { - statement.close(); - } - unlock(); - } - } - - /** - * Execute a single SQL statement that is not a query. For example, CREATE - * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not - * supported. it takes a write lock - * - * @param sql string - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public void execSQL(String sql) throws SQLException { - long timeStart = Time.getRealActiveTime(); - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - native_execSQL(sql); - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } finally { - unlock(); - } - } - - public void rawExecSQL(String sql){ - long timeStart = Time.getRealActiveTime(); - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - native_rawExecSQL(sql); - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } finally { - unlock(); - } - } - - /** - * Execute a single SQL statement that is not a query. For example, CREATE - * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not - * supported. it takes a write lock, - * - * @param sql - * @param bindArgs only byte[], String, Long and Double are supported in bindArgs. - * - * @throws SQLException If the SQL string is invalid for some reason - * @throws IllegalStateException if the database is not open - */ - public void execSQL(String sql, Object[] bindArgs) throws SQLException { - SQLiteStatement statement = null; - if (bindArgs == null) { - throw new IllegalArgumentException("Empty bindArgs"); - } - long timeStart = Time.getRealActiveTime(); - lock(); - try { - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - statement = compileStatement(sql); - if (bindArgs != null) { - int numArgs = bindArgs.length; - for (int i = 0; i < numArgs; i++) { - DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]); - } - } - statement.execute(); - } catch (SQLiteDatabaseCorruptException e) { - onCorruption(); - throw e; - } finally { - if (statement != null) { - statement.close(); - } - unlock(); - } - } - - @Override - protected void finalize() { - if (isOpen()) { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "close() was never explicitly called on database '%{default}s ' %{default}s", - mPath, mStackTrace); - // } - closeClosable(); - onAllReferencesReleased(); - } - } - - /** - * Public constructor which attempts to open the database. See {@link #create} and {@link #openDatabase}. - * - *

Sets the locale of the database to the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path The full path to the database - * @param password to use to open and/or create a database file (char array) - * @param factory The factory to use when creating cursors, may be NULL. - * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already - * exists, mFlags will be updated appropriately. - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public SQLiteDatabase(String path, char[] password, CursorFactory factory, int flags) { - this(path, factory, flags, null); - this.openDatabaseInternal(password, null); - } - - /** - * Public constructor which attempts to open the database. See {@link #create} and {@link #openDatabase}. - * - *

Sets the locale of the database to the system's current locale. - * Call {@link #setLocale} if you would like something else.

- * - * @param path The full path to the database - * @param password to use to open and/or create a database file (char array) - * @param factory The factory to use when creating cursors, may be NULL. - * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already - * exists, mFlags will be updated appropriately. - * @param databaseHook to run on pre/post key events - * - * @throws SQLiteException if the database cannot be opened - * @throws IllegalArgumentException if the database path is null - */ - public SQLiteDatabase(String path, char[] password, CursorFactory factory, int flags, SQLiteDatabaseHook databaseHook) { - this(path, factory, flags, null); - this.openDatabaseInternal(password, databaseHook); - } - - public SQLiteDatabase(String path, byte[] password, CursorFactory factory, int flags, SQLiteDatabaseHook databaseHook) { - this(path, factory, flags, null); - this.openDatabaseInternal(password, databaseHook); - } - - /** - * Private constructor (without database password) which DOES NOT attempt to open the database. - * - * @param path The full path to the database - * @param factory The factory to use when creating cursors, may be NULL. - * @param flags to control database access mode and other options - * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption (or null for default). - * - * @throws IllegalArgumentException if the database path is null - */ - private SQLiteDatabase(String path, CursorFactory factory, int flags, DatabaseErrorHandler errorHandler) { - if (path == null) { - throw new IllegalArgumentException("path should not be null"); - } - - mFlags = flags; - mPath = path; - - mSlowQueryThreshold = -1;//SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1); - mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace(); - mFactory = factory; - mPrograms = new WeakHashMap(); - - mErrorHandler = errorHandler; - } - - private void openDatabaseInternal(final char[] password, SQLiteDatabaseHook hook) { - final byte[] keyMaterial = getBytes(password); - openDatabaseInternal(keyMaterial, hook); - } - - private void openDatabaseInternal(final byte[] password, SQLiteDatabaseHook hook) { - boolean shouldCloseConnection = true; - try { - dbopen(mPath, mFlags); - keyDatabase(hook, new Runnable() { - public void run() { - if(password != null && password.length > 0) { - key(password); - } - } - }); - shouldCloseConnection = false; - - } catch(Exception ex) { - final char[] keyMaterial = getChars(password); - if(containsNull(keyMaterial)) { - keyDatabase(hook, new Runnable() { - public void run() { - if(password != null) { - key_mutf8(keyMaterial); - } - } - }); - if(password != null && password.length > 0) { - rekey(password); - } - shouldCloseConnection = false; - } else { - throw ex; - } - if(keyMaterial != null && keyMaterial.length > 0) { - Arrays.fill(keyMaterial, (char)0); - } - - } finally { - if(shouldCloseConnection) { - try{ - dbclose(); - }catch (Exception e){ - e.printStackTrace(); - } - if (SQLiteDebug.DEBUG_SQL_CACHE) { - mTimeClosed = getTime(); - } - } - } - - } - - private boolean containsNull(char[] data) { - char defaultValue = '\u0000'; - boolean status = false; - if(data != null && data.length > 0) { - for(char datum : data) { - if(datum == defaultValue) { - status = true; - break; - } - } - } - return status; - } - - private void keyDatabase(SQLiteDatabaseHook databaseHook, Runnable keyOperation) { - if(databaseHook != null) { - databaseHook.preKey(this); - } - if(keyOperation != null){ - keyOperation.run(); - } - if(databaseHook != null){ - databaseHook.postKey(this); - } - if (SQLiteDebug.DEBUG_SQL_CACHE) { - mTimeOpened = getTime(); - } - try { - ResultSet cursor = rawQuery("select count(*) from sqlite_master;", new String[]{}); - if(cursor != null){ - cursor.goToFirstRow(); - int count = cursor.getInt(0); - cursor.close(); - } - } catch (RuntimeException e) { - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, e.getMessage(), e); - // } - throw e; - } - } - - private String getTime() { - return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ", Locale.US).format(System.currentTimeMillis()); - } - - /** - * return whether the DB is opened as read only. - * @return true if DB is opened as read only - */ - public boolean isReadOnly() { - return (mFlags & OPEN_READ_MASK) == OPEN_READONLY; - } - - /** - * return true if the DB is currently open - * @return true if the DB is currently open (has not been closed) - */ - public boolean isOpen() { - return mNativeHandle != 0; - } - - public boolean needUpgrade(int newVersion) { - /* NOTE: getVersion() will throw if database is not open. */ - return newVersion > getVersion(); - } - - /** - * Getter for the path to the database file. - * - * @return the path to our database file. - */ - public final String getPath() { - return mPath; - } - - /** - * Removes email addresses from database filenames before they're - * logged to the EventLog where otherwise apps could potentially - * read them. - * @return path for logs - */ - private String getPathForLogs() { - if (mPathForLogs != null) { - return mPathForLogs; - } - if (mPath == null) { - return null; - } - if (mPath.indexOf('@') == -1) { - mPathForLogs = mPath; - } else { - mPathForLogs = EMAIL_IN_DB_PATTERN.matcher(mPath).replaceAll("XX@YY"); - } - return mPathForLogs; - } - - /** - * Sets the locale for this database. Does nothing if this database has - * the NO_LOCALIZED_COLLATORS flag set or was opened read only. - * - * @param locale locale - * @throws SQLException if the locale could not be set. The most common reason - * for this is that there is no collator available for the locale you requested. - * In this case the database remains unchanged. - */ - public void setLocale(Locale locale) { - lock(); - try { - native_setLocale(locale.toString(), mFlags); - } finally { - unlock(); - } - } - - /* - * ============================================================================ - * - * The following methods deal with compiled-sql cache - * ============================================================================ - */ - /** - * adds the given sql and its compiled-statement-id-returned-by-sqlite to the - * cache of compiledQueries attached to 'this'. - * - * if there is already a {@link SQLiteCompiledSql} in compiledQueries for the given sql, - * the new {@link SQLiteCompiledSql} object is NOT inserted into the cache (i.e.,the current - * mapping is NOT replaced with the new mapping). - * @param sql string - * @param compiledStatement compiledStatement - */ - /* package */ void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) { - if (mMaxSqlCacheSize == 0) { - // for this database, there is no cache of compiled sql. - if (SQLiteDebug.DEBUG_SQL_CACHE/* && BuildConfig.DEBUG*/) { - HiLog.debug(label, "|NOT adding_sql_to_cache|" + getPath() + "|" + sql); - } - return; - } - - SQLiteCompiledSql compiledSql = null; - synchronized(mCompiledQueries) { - // don't insert the new mapping if a mapping already exists - compiledSql = mCompiledQueries.get(sql); - if (compiledSql != null) { - return; - } - // add this to the cache - if (mCompiledQueries.size() == mMaxSqlCacheSize) { - /* - * cache size of {@link #mMaxSqlCacheSize} is not enough for this app. - * log a warning MAX_WARNINGS_ON_CACHESIZE_CONDITION times - * chances are it is NOT using ? for bindargs - so caching is useless. - * TODO: either let the callers set max cchesize for their app, or intelligently - * figure out what should be cached for a given app. - */ - if (++mCacheFullWarnings == MAX_WARNINGS_ON_CACHESIZE_CONDITION /*&& BuildConfig.DEBUG*/) { - HiLog.warn(label, "Reached MAX size for compiled-sql statement cache for database " + - getPath() + "; i.e., NO space for this sql statement in cache: " + - sql + ". Please change your sql statements to use '?' for " + - "bindargs, instead of using actual values"); - } - // don't add this entry to cache - } else { - // cache is NOT full. add this to cache. - mCompiledQueries.put(sql, compiledStatement); - if (SQLiteDebug.DEBUG_SQL_CACHE/* && BuildConfig.DEBUG*/) { - HiLog.debug(label, "|adding_sql_to_cache|" + getPath() + "|" + - mCompiledQueries.size() + "|" + sql); - } - } - } - return; - } - - - private void deallocCachedSqlStatements() { - synchronized (mCompiledQueries) { - for (SQLiteCompiledSql compiledSql : mCompiledQueries.values()) { - compiledSql.releaseSqlStatement(); - } - mCompiledQueries.clear(); - } - } - - /** - * from the compiledQueries cache, returns the compiled-statement-id for the given sql. - * returns null, if not found in the cache. - * @param sql string - * @return compiled-statement-id - */ - /* package */ SQLiteCompiledSql getCompiledStatementForSql(String sql) { - SQLiteCompiledSql compiledStatement = null; - boolean cacheHit; - synchronized(mCompiledQueries) { - if (mMaxSqlCacheSize == 0) { - // for this database, there is no cache of compiled sql. - if (SQLiteDebug.DEBUG_SQL_CACHE)/* && BuildConfig.DEBUG)*/ { - HiLog.debug(label, "|cache NOT found|" + getPath()); - } - return null; - } - cacheHit = (compiledStatement = mCompiledQueries.get(sql)) != null; - } - if (cacheHit) { - mNumCacheHits++; - } else { - mNumCacheMisses++; - } - - if (SQLiteDebug.DEBUG_SQL_CACHE/* && BuildConfig.DEBUG*/) { - HiLog.debug(label, "|cache_stats|" + - getPath() + "|" + mCompiledQueries.size() + - "|" + mNumCacheHits + "|" + mNumCacheMisses + - "|" + cacheHit + "|" + mTimeOpened + "|" + mTimeClosed + "|" + sql); - } - return compiledStatement; - } - - /** - * returns true if the given sql is cached in compiled-sql cache. - * @hide - * @param sql string - * @return true/false - */ - public boolean isInCompiledSqlCache(String sql) { - synchronized(mCompiledQueries) { - return mCompiledQueries.containsKey(sql); - } - } - - /** - * purges the given sql from the compiled-sql cache. - * @hide - * @param sql string - */ - public void purgeFromCompiledSqlCache(String sql) { - synchronized(mCompiledQueries) { - mCompiledQueries.remove(sql); - } - } - - /** - * remove everything from the compiled sql cache - * @hide - */ - public void resetCompiledSqlCache() { - synchronized(mCompiledQueries) { - mCompiledQueries.clear(); - } - } - - /** - * return the current maxCacheSqlCacheSize - * @hide - * @return maxCacheSqlCacheSize - */ - public synchronized int getMaxSqlCacheSize() { - return mMaxSqlCacheSize; - } - - /** - * set the max size of the compiled sql cache for this database after purging the cache. - * (size of the cache = number of compiled-sql-statements stored in the cache). - * - * max cache size can ONLY be increased from its current size (default = 0). - * if this method is called with smaller size than the current value of mMaxSqlCacheSize, - * then IllegalStateException is thrown - * - * synchronized because we don't want t threads to change cache size at the same time. - * @param cacheSize the size of the cache. can be (0 to MAX_SQL_CACHE_SIZE) - * @throws IllegalStateException if input cacheSize > MAX_SQL_CACHE_SIZE or < 0 or - * < the value set with previous setMaxSqlCacheSize() call. - * - * @hide - */ - public synchronized void setMaxSqlCacheSize(int cacheSize) { - if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) { - throw new IllegalStateException("expected value between 0 and " + MAX_SQL_CACHE_SIZE); - } else if (cacheSize < mMaxSqlCacheSize) { - throw new IllegalStateException("cannot set cacheSize to a value less than the value " + - "set with previous setMaxSqlCacheSize() call."); - } - mMaxSqlCacheSize = cacheSize; - } - - public static byte[] getBytes(char[] data) { - if(data == null || data.length == 0) return null; - CharBuffer charBuffer = CharBuffer.wrap(data); - ByteBuffer byteBuffer = Charset.forName(KEY_ENCODING).encode(charBuffer); - byte[] result = new byte[byteBuffer.limit()]; - byteBuffer.get(result); - return result; - } - - public static char[] getChars(byte[] data){ - if(data == null || data.length == 0) return null; - ByteBuffer byteBuffer = ByteBuffer.wrap(data); - CharBuffer charBuffer = Charset.forName(KEY_ENCODING).decode(byteBuffer); - char[] result = new char[charBuffer.limit()]; - charBuffer.get(result); - return result; - } - - /* begin SQLiteSupportDatabase methods */ - - @Override - public ResultSet query(String query) { - return rawQuery(query, null); - } - - @Override - public ResultSet query(String query, Object[] bindArgs) { - return rawQuery(query, bindArgs); - } - - /* @Override // CancellationSignal not present in hmos - public ResultSet query(SupportSQLiteQuery query) { - return query(query, null); - }*/ - - @Override - public ResultSet query(final SupportSQLiteQuery supportQuery/*, CancellationSignal cancellationSignal*/) {//todo cancellationsignal - String sql = supportQuery.getSql(); - int argumentCount = supportQuery.getArgCount(); - Object[] args = new Object[argumentCount]; - SQLiteDirectCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, null); - SQLiteQuery query = new SQLiteQuery(this, sql, 0, args); - supportQuery.bindTo(query); - return new CrossProcessCursorWrapper(new SQLiteCursor(this, driver, null, query)); - } - - @Override - public long insert(String table, int conflictAlgorithm, - ValuesBucket values) - throws SQLException { - return insertWithOnConflict(table, null, values, conflictAlgorithm); - } - - @Override - public int update(String table, int conflictAlgorithm, ValuesBucket values, - String whereClause, Object[] whereArgs) { - String[] args = new String[whereArgs.length]; - - for (int i = 0; i < whereArgs.length; i++) { - args[i] = whereArgs[i].toString(); - } - - return updateWithOnConflict(table, values, whereClause, args, conflictAlgorithm); - } - - @Override - public void beginTransactionWithListener( - final ohos.data.rdb.TransactionObserver transactionListener) { - beginTransactionWithListener(new SQLiteTransactionListener() { - @Override - public void onBegin() { - transactionListener.onBegin(); - } - - @Override - public void onCommit() { - transactionListener.onCommit(); - } - - @Override - public void onRollback() { - transactionListener.onRollback(); - } - }); - } - - @Override - public void beginTransactionWithListenerNonExclusive( - final ohos.data.rdb.TransactionObserver transactionListener) { - beginTransactionWithListenerNonExclusive( - new SQLiteTransactionListener() { - @Override - public void onBegin() { - transactionListener.onBegin(); - } - - @Override - public void onCommit() { - transactionListener.onCommit(); - } - - @Override - public void onRollback() { - transactionListener.onRollback(); - } - }); - } - - /* end SQLiteSupportDatabase methods */ - - private void beginTransactionWithListenerInternal(SQLiteTransactionListener transactionListener, - SQLiteDatabaseTransactionType transactionType) { - lockForced(); - if (!isOpen()) { - throw new IllegalStateException("database not open"); - } - boolean ok = false; - try { - // If this thread already had the lock then get out - if (mLock.getHoldCount() > 1) { - if (mInnerTransactionIsSuccessful) { - String msg = "Cannot call beginTransaction between " - + "calling setTransactionSuccessful and endTransaction"; - IllegalStateException e = new IllegalStateException(msg); - /*if(BuildConfig.DEBUG){*/ - HiLog.error(label, "beginTransaction() failed", e); - // } - throw e; - } - ok = true; - return; - } - // This thread didn't already have the lock, so begin a database - // transaction now. - if(transactionType == SQLiteDatabaseTransactionType.Exclusive) { - execSQL("BEGIN EXCLUSIVE;"); - } else if(transactionType == SQLiteDatabaseTransactionType.Immediate) { - execSQL("BEGIN IMMEDIATE;"); - } else if(transactionType == SQLiteDatabaseTransactionType.Deferred) { - execSQL("BEGIN DEFERRED;"); - } else { - String message = String.format("%s is an unsupported transaction type", - transactionType); - throw new IllegalArgumentException(message); - } - mTransactionListener = transactionListener; - mTransactionIsSuccessful = true; - mInnerTransactionIsSuccessful = false; - if (transactionListener != null) { - try { - transactionListener.onBegin(); - } catch (RuntimeException e) { - execSQL("ROLLBACK;"); - throw e; - } - } - ok = true; - } finally { - if (!ok) { - // beginTransaction is called before the try block so we must release the lock in - // the case of failure. - unlockForced(); - } - } - } - - /** - * this method is used to collect data about ALL open databases in the current process. - * bugreport is a user of this data. - * @return DbStats list - */ - /* package */ static ArrayList getDbStats() { - ArrayList dbStatsList = new ArrayList(); - - for (SQLiteDatabase db : getActiveDatabases()) { - if (db == null || !db.isOpen()) { - continue; - } - - // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db - int lookasideUsed = db.native_getDbLookaside(); - - // get the lastnode of the dbname - String path = db.getPath(); - int indx = path.lastIndexOf("/"); - String lastnode = path.substring((indx != -1) ? ++indx : 0); - - // get list of attached dbs and for each db, get its size and pagesize - ArrayList> attachedDbs = getAttachedDbs(db); - if (attachedDbs == null) { - continue; - } - for (int i = 0; i < attachedDbs.size(); i++) { - Pair p = attachedDbs.get(i); - long pageCount = getPragmaVal(db, p.f + ".page_count;"); - - // first entry in the attached db list is always the main database - // don't worry about prefixing the dbname with "main" - String dbName; - if (i == 0) { - dbName = lastnode; - } else { - // lookaside is only relevant for the main db - lookasideUsed = 0; - dbName = " (attached) " + p.f; - // if the attached db has a path, attach the lastnode from the path to above - if (p.s.trim().length() > 0) { - int idx = p.s.lastIndexOf("/"); - dbName += " : " + p.s.substring((idx != -1) ? ++idx : 0); - } - } - if (pageCount > 0) { - dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(), - lookasideUsed)); - } - } - } - return dbStatsList; - } - - private static ArrayList getActiveDatabases() { - ArrayList databases = new ArrayList(); - synchronized (sActiveDatabases) { - databases.addAll(sActiveDatabases.keySet()); - } - return databases; - } - - /** - * get the specified pragma value from sqlite for the specified database. - * only handles pragma's that return int/long. - * NO JAVA locks are held in this method. - * @param db database - * @param pragma string - * @return pragma value - * TODO: use this to do all pragma's in this class - */ - private static long getPragmaVal(SQLiteDatabase db, String pragma) { - if (!db.isOpen()) { - return 0; - } - SQLiteStatement prog = null; - try { - prog = new SQLiteStatement(db, "PRAGMA " + pragma); - long val = prog.simpleQueryForLong(); - return val; - } finally { - if (prog != null) prog.close(); - } - } - - /** - * returns list of full pathnames of all attached databases - * including the main database - * @param dbObj database object - * @return path names list - * TODO: move this to {@link DatabaseUtils} - */ - private static ArrayList> getAttachedDbs(SQLiteDatabase dbObj) { - if (!dbObj.isOpen()) { - return null; - } - ArrayList> attachedDbs = new ArrayList>(); - ResultSet c = dbObj.rawQuery("pragma database_list;", null); - while (c.goToNextRow()) { - attachedDbs.add(new Pair(c.getString(1), c.getString(2))); - } - c.close(); - return attachedDbs; - } - - private Pair getResultFromPragma(String command) { - ResultSet cursor = rawQuery(command, new Object[]{}); - if(cursor == null) return new Pair(false, ""); - cursor.goToFirstRow(); - String value = cursor.getString(0); - cursor.close(); - return new Pair(true, value); - } - - - /** - * Sets the root directory to search for the ICU data file - * @param path path - */ - public static native void setICURoot(String path); - - /** - * Native call to open the database. - * - * @param path The full path to the database - * @param flags flags - */ - private native void dbopen(String path, int flags); - - /** - * Native call to setup tracing of all sql statements - * - * @param path the full path to the database - */ - private native void enableSqlTracing(String path); - - /** - * Native call to setup profiling of all sql statements. - * currently, sqlite's profiling = printing of execution-time - * (wall-clock time) of each of the sql statements, as they - * are executed. - * - * @param path the full path to the database - */ - private native void enableSqlProfiling(String path); - - /** - * Native call to execute a raw SQL statement. {@link #lock} must be held - * when calling this method. - * - * @param sql The raw SQL string - * - * @throws SQLException - */ - /* package */ native void native_execSQL(String sql) throws SQLException; - - /** - * Native call to set the locale. {@link #lock} must be held when calling - * this method. - * @param loc locale - * @param flags flags - * - * @throws SQLException - */ - /* package */ native void native_setLocale(String loc, int flags); - - /** - * Returns the row ID of the last row inserted into the database. - * - * @return the row ID of the last row inserted into the database. - */ - /* package */ native long lastInsertRow(); - - /** - * Returns the number of changes made in the last statement executed. - * - * @return the number of changes made in the last statement executed. - */ - /* package */ native int lastChangeCount(); - - /** - * return the SQLITE_DBSTATUS_LOOKASIDE_USED documented here - * http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html - * @return int value of SQLITE_DBSTATUS_LOOKASIDE_USED - */ - private native int native_getDbLookaside(); - - private native void native_rawExecSQL(String sql); - - private native int native_status(int operation, boolean reset); - - private native void key(byte[] key) throws SQLException; - private native void key_mutf8(char[] key) throws SQLException; - private native void rekey(byte[] key) throws SQLException; -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseCorruptException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseCorruptException.java deleted file mode 100644 index 2e7373ca02d97d1b3ccc170ea75a097d0902aaca..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseCorruptException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that the SQLite database file is corrupt. - */ -public class SQLiteDatabaseCorruptException extends SQLiteException { - public SQLiteDatabaseCorruptException() {} - - public SQLiteDatabaseCorruptException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseHook.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseHook.java deleted file mode 100644 index 70d00f6697caab2261dfcfcd5ef57a828ad1efc7..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabaseHook.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.sqlcipher.database; - -/** - * An interface to perform pre and post key operations against a database. - */ -public interface SQLiteDatabaseHook { - /** - * Called before opening the database for Hos. - * @param database database - */ - void preKey(SQLiteDatabase database); - /** - * Called immediately after opening the database for Hos. - * @param database database - */ - void postKey(SQLiteDatabase database); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDebug.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDebug.java deleted file mode 100644 index a17b2b7a47328dd2f4d7d41cc3e7c7767184cd69..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDebug.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import java.util.ArrayList; -import ohos.hiviewdfx.HiLog; - -/** - * Provides debugging info about all SQLite databases running in the current process. - * - * {@hide} - */ -public final class SQLiteDebug { - /** - * Controls the printing of SQL statements as they are executed. - */ - public static final boolean DEBUG_SQL_STATEMENTS = - HiLog.isLoggable(0x00201,"SQLiteStatements", HiLog.LOG_APP); - - /** - * Controls the printing of wall-clock time taken to execute SQL statements - * as they are executed. - */ - public static final boolean DEBUG_SQL_TIME = - HiLog.isLoggable(0x00201,"SQLiteTime", HiLog.LOG_APP); - - /** - * Controls the printing of compiled-sql-statement cache stats. - */ - public static final boolean DEBUG_SQL_CACHE = - HiLog.isLoggable(0x00201,"SQLiteCompiledSql", HiLog.LOG_APP); - - /** - * Controls the stack trace reporting of active cursors being - * finalized. - */ - public static final boolean DEBUG_ACTIVE_CURSOR_FINALIZATION = - HiLog.isLoggable(0x00201,"SQLiteCursorClosing", HiLog.LOG_APP); - - /** - * Controls the tracking of time spent holding the database lock. - */ - public static final boolean DEBUG_LOCK_TIME_TRACKING = - HiLog.isLoggable(0x00201,"SQLiteLockTime", HiLog.LOG_APP); - - /** - * Controls the printing of stack traces when tracking the time spent holding the database lock. - */ - public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE = - HiLog.isLoggable(0x00201,"SQLiteLockStackTrace", HiLog.LOG_APP); - - /** - * Contains statistics about the active pagers in the current process. - * - * @see #getPagerStats(PagerStats) - */ - public static class PagerStats { - /** The total number of bytes in all pagers in the current process - * @deprecated not used any longer - */ - @Deprecated - public long totalBytes; - /** The number of bytes in referenced pages in all pagers in the current process - * @deprecated not used any longer - * */ - @Deprecated - public long referencedBytes; - /** The number of bytes in all database files opened in the current process - * @deprecated not used any longer - */ - @Deprecated - public long databaseBytes; - /** The number of pagers opened in the current process - * @deprecated not used any longer - */ - @Deprecated - public int numPagers; - - /** the current amount of memory checked out by sqlite using sqlite3_malloc(). - * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html - */ - public int memoryUsed; - - /** the number of bytes of page cache allocation which could not be sattisfied by the - * SQLITE_CONFIG_PAGECACHE buffer and where forced to overflow to sqlite3_malloc(). - * The returned value includes allocations that overflowed because they where too large - * (they were larger than the "sz" parameter to SQLITE_CONFIG_PAGECACHE) and allocations - * that overflowed because no space was left in the page cache. - * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html - */ - public int pageCacheOverflo; - - /** records the largest memory allocation request handed to sqlite3. - * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html - */ - public int largestMemAlloc; - - /** a list of {@link DbStats} - one for each main database opened by the applications - * running on the device - */ - public ArrayList dbStats; - } - - /** - * contains statistics about a database - */ - public static class DbStats { - /** name of the database */ - public String dbName; - - /** the page size for the database */ - public long pageSize; - - /** the database size */ - public long dbSize; - - /** documented here http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html */ - public int lookaside; - - public DbStats(String dbName, long pageCount, long pageSize, int lookaside) { - this.dbName = dbName; - this.pageSize = pageSize; - dbSize = (pageCount * pageSize) / 1024; - this.lookaside = lookaside; - } - } - - /** - * return all pager and database stats for the current process. - * @return {@link PagerStats} - */ - public static PagerStats getDatabaseInfo() { - PagerStats stats = new PagerStats(); - getPagerStats(stats); - stats.dbStats = SQLiteDatabase.getDbStats(); - return stats; - } - - /** - * Gathers statistics about all pagers in the current process. - * @param stats PagerStats - */ - public static native void getPagerStats(PagerStats stats); - - /** - * Returns the size of the SQLite heap. - * @return The size of the SQLite heap in bytes. - */ - public static native long getHeapSize(); - - /** - * Returns the amount of allocated memory in the SQLite heap. - * @return The allocated size in bytes. - */ - public static native long getHeapAllocatedSize(); - - /** - * Returns the amount of free memory in the SQLite heap. - * @return The freed size in bytes. - */ - public static native long getHeapFreeSize(); - - /** - * Determines the number of dirty belonging to the SQLite - * heap segments of this process. pages[0] returns the number of - * shared pages, pages[1] returns the number of private pages - * @param pages pagess - */ - public static native void getHeapDirtyPages(int[] pages); - - private static int sNumActiveCursorsFinalized = 0; - - /** - * Returns the number of active cursors that have been finalized. This depends on the GC having - * run but is still useful for tests. - * @return Returns the number of active cursors that have been finalized - */ - public static int getNumActiveCursorsFinalized() { - return sNumActiveCursorsFinalized; - } - - static synchronized void notifyActiveCursorFinalized() { - sNumActiveCursorsFinalized++; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDirectCursorDriver.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDirectCursorDriver.java deleted file mode 100644 index 40c42e62212d7c168260b51251be430b884d7055..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDirectCursorDriver.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.database.SQLiteDatabase.CursorFactory; -import ohos.data.resultset.ResultSet; - -/** - * A cursor driver that uses the given query directly. - * - * @hide - */ -public class SQLiteDirectCursorDriver implements SQLiteCursorDriver { - private String mEditTable; - private SQLiteDatabase mDatabase; - private ResultSet mCursor; - private String mSql; - private SQLiteQuery mQuery; - - public SQLiteDirectCursorDriver(SQLiteDatabase db, String sql, String editTable) { - mDatabase = db; - mEditTable = editTable; - mSql = sql; - } - - public ResultSet query(CursorFactory factory, Object[] args) { - SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, args); - try { - query.bindArguments(args); - if (factory == null) { - mCursor = new SQLiteCursor(mDatabase, this, mEditTable, query); - } else { - mCursor = factory.newCursor(mDatabase, this, mEditTable, query); - } - mQuery = query; - query = null; - return mCursor; - } finally { - // Make sure this object is cleaned up if something happens - if (query != null) query.close(); - } - } - - public ResultSet query(CursorFactory factory, String[] selectionArgs) { - // Compile the query - SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs); - - try { - // Arg binding - int numArgs = selectionArgs == null ? 0 : selectionArgs.length; - for (int i = 0; i < numArgs; i++) { - query.bindString(i + 1, selectionArgs[i]); - } - - // Create the cursor - if (factory == null) { - mCursor = new SQLiteCursor(mDatabase, this, mEditTable, query); - - } else { - mCursor = factory.newCursor(mDatabase, this, mEditTable, query); - } - - mQuery = query; - query = null; - return mCursor; - } finally { - // Make sure this object is cleaned up if something happens - if (query != null) query.close(); - } - } - - public void cursorClosed() { - mCursor = null; - } - - public void setBindArguments(String[] bindArgs) { - final int numArgs = bindArgs.length; - for (int i = 0; i < numArgs; i++) { - mQuery.bindString(i + 1, bindArgs[i]); - } - } - - @Override - public void cursorDeactivated() { - // Do nothing - } - - @Override - public void cursorRequeried(ResultSet cursor) { - // Do nothing - } - - @Override - public String toString() { - return "SQLiteDirectCursorDriver: " + mSql; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDiskIOException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDiskIOException.java deleted file mode 100644 index de4b54319e749400104b37fe3b757414a2ac8a1a..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDiskIOException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that an IO error occured while accessing the - * SQLite database file. - */ -public class SQLiteDiskIOException extends SQLiteException { - public SQLiteDiskIOException() {} - - public SQLiteDiskIOException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDoneException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDoneException.java deleted file mode 100644 index f0f6f0dc7c18ad9e129294c213f980a28682e103..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDoneException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that the SQLite program is done. - * Thrown when an operation that expects a row (such as {@link - * SQLiteStatement#simpleQueryForString} or {@link - * SQLiteStatement#simpleQueryForLong}) does not get one. - */ -public class SQLiteDoneException extends SQLiteException { - public SQLiteDoneException() {} - - public SQLiteDoneException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteException.java deleted file mode 100644 index 2c7f11a37c35fb3c5ddf3110ca35bc2673ce0d43..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.*; - -/** - * A SQLite exception that indicates there was an error with SQL parsing or execution. - */ -public class SQLiteException extends SQLException { - public SQLiteException() {} - - public SQLiteException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteFullException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteFullException.java deleted file mode 100644 index 66af19fee72525681b661d40aae0bd220c1fca3b..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteFullException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * An exception that indicates that the SQLite database is full. - */ -public class SQLiteFullException extends SQLiteException { - public SQLiteFullException() {} - - public SQLiteFullException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteMisuseException.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteMisuseException.java deleted file mode 100644 index ef261fc75b176c7925fc1246b3b050cbc092adbc..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteMisuseException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -public class SQLiteMisuseException extends SQLiteException { - public SQLiteMisuseException() {} - - public SQLiteMisuseException(String error) { - super(error); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteOpenHelper.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteOpenHelper.java deleted file mode 100644 index c8fbefed6301da9b3cdb7429f143287aea3bf200..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteOpenHelper.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import java.io.File; -import ohos.app.Context; -import net.sqlcipher.DatabaseErrorHandler; -import net.sqlcipher.DefaultDatabaseErrorHandler; -import net.sqlcipher.database.SQLiteDatabase.CursorFactory; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -/** - * A helper class to manage database creation and version management. - * You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and - * optionally {@link #onOpen}, and this class takes care of opening the database - * if it exists, creating it if it does not, and upgrading it as necessary. - * Transactions are used to make sure the database is always in a sensible state. - *

For an example, see the NotePadProvider class in the NotePad sample application, - * in the samples/ directory of the SDK.

- */ -public abstract class SQLiteOpenHelper { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00208, "SQLiteOpenHelper"); - - private final Context mContext; - private final String mName; - private final CursorFactory mFactory; - private final int mNewVersion; - private final SQLiteDatabaseHook mHook; - private final DatabaseErrorHandler mErrorHandler; - private boolean mEnableWriteAheadLogging; - private boolean mDeferSetWriteAheadLoggingEnabled; - - private SQLiteDatabase mDatabase = null; - private boolean mIsInitializing = false; - - /** - * Create a helper object to create, open, and/or manage a database. - * This method always returns very quickly. The database is not actually - * created or opened until one of {@link #getWritableDatabase} or - * {@link #getReadableDatabase} is called. - * - * @param context to use to open or create the database - * @param name of the database file, or null for an in-memory database - * @param factory to use for creating cursor objects, or null for the default - * @param version number of the database (starting at 1); if the database is older, - * {@link #onUpgrade} will be used to upgrade the database - */ - public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { - this(context, name, factory, version, null, new DefaultDatabaseErrorHandler()); - } - - /** - * Create a helper object to create, open, and/or manage a database. - * The database is not actually created or opened until one of - * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called. - * - * @param context to use to open or create the database - * @param name of the database file, or null for an in-memory database - * @param factory to use for creating cursor objects, or null for the default - * @param version number of the database (starting at 1); if the database is older, - * {@link #onUpgrade} will be used to upgrade the database - * @param hook to run on pre/post key events - */ - public SQLiteOpenHelper(Context context, String name, CursorFactory factory, - int version, SQLiteDatabaseHook hook) { - this(context, name, factory, version, hook, new DefaultDatabaseErrorHandler()); - } - - /** - * Create a helper object to create, open, and/or manage a database. - * The database is not actually created or opened until one of - * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called. - * - *

Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be - * used to handle corruption when sqlite reports database corruption.

- * - * @param context to use to open or create the database - * @param name of the database file, or null for an in-memory database - * @param factory to use for creating cursor objects, or null for the default - * @param version number of the database (starting at 1); if the database is older, - * {@link #onUpgrade} will be used to upgrade the database - * @param hook to run on pre/post key events - * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption. - */ - public SQLiteOpenHelper(Context context, String name, CursorFactory factory, - int version, SQLiteDatabaseHook hook, DatabaseErrorHandler errorHandler) { - if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version); - if (errorHandler == null) { - throw new IllegalArgumentException("DatabaseErrorHandler param value can't be null."); - } - - mContext = context; - mName = name; - mFactory = factory; - mNewVersion = version; - mHook = hook; - mErrorHandler = errorHandler; - } - - /** - * Create and/or open a database that will be used for reading and writing. - * Once opened successfully, the database is cached, so you can call this - * method every time you need to write to the database. Make sure to call - * {@link #close} when you no longer need it. - * - *

Errors such as bad permissions or a full disk may cause this operation - * to fail, but future attempts may succeed if the problem is fixed.

- * - * @param password password - * @throws SQLiteException if the database cannot be opened for writing - * @return a read/write database object valid until {@link #close} is called - */ - - public synchronized SQLiteDatabase getWritableDatabase(String password) { - return getWritableDatabase(password == null ? null : password.toCharArray()); - } - - public synchronized SQLiteDatabase getWritableDatabase(char[] password) { - return getWritableDatabase(password == null ? null : SQLiteDatabase.getBytes(password)); - } - - public synchronized SQLiteDatabase getWritableDatabase(byte[] password) { - if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { - return mDatabase; // The database is already open for business - } - - if (mIsInitializing) { - throw new IllegalStateException("getWritableDatabase called recursively"); - } - - // If we have a read-only database open, someone could be using it - // (though they shouldn't), which would cause a lock to be held on - // the file, and our attempts to open the database read-write would - // fail waiting for the file lock. To prevent that, we acquire the - // lock on the read-only database, which shuts out other users. - - boolean success = false; - SQLiteDatabase db = null; - if (mDatabase != null) mDatabase.lock(); - try { - mIsInitializing = true; - if (mName == null) { - db = SQLiteDatabase.create(null, ""); - } else { - // String path = mContext.getDatabaseDir().getPath(); - File dbPathFile = new File (mName); - if (!dbPathFile.exists() && dbPathFile.getParentFile() != null) { - boolean mkdirs = dbPathFile.getParentFile().mkdirs(); - } - db = SQLiteDatabase.openOrCreateDatabase(mName, password, mFactory, mHook, mErrorHandler); - } - if(mDeferSetWriteAheadLoggingEnabled) { - mEnableWriteAheadLogging = db.enableWriteAheadLogging(); - } - onConfigure(db); - int version = db.getVersion(); - if (version != mNewVersion) { - db.beginTransaction(); - try { - if (version == 0) { - onCreate(db); - } else { - if(version > mNewVersion) { - onDowngrade(db, version, mNewVersion); - } else { - onUpgrade(db, version, mNewVersion); - } - } - db.setVersion(mNewVersion); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - onOpen(db); - success = true; - return db; - } finally { - mIsInitializing = false; - if (success) { - if (mDatabase != null) { - try { mDatabase.close(); } catch (Exception e) { } - mDatabase.unlock(); - } - mDatabase = db; - } else { - if (mDatabase != null) mDatabase.unlock(); - if (db != null) db.close(); - } - } - } - - /** - * Create and/or open a database. This will be the same object returned by - * {@link #getWritableDatabase} unless some problem, such as a full disk, - * requires the database to be opened read-only. In that case, a read-only - * database object will be returned. If the problem is fixed, a future call - * to {@link #getWritableDatabase} may succeed, in which case the read-only - * database object will be closed and the read/write object will be returned - * in the future. - * - * @param password password - * @throws SQLiteException if the database cannot be opened - * @return a database object valid until {@link #getWritableDatabase} - * or {@link #close} is called. - */ - public synchronized SQLiteDatabase getReadableDatabase(String password) { - return getReadableDatabase(password == null ? null : password.toCharArray()); - } - - public synchronized SQLiteDatabase getReadableDatabase(char[] password) { - return getReadableDatabase(password == null ? null : SQLiteDatabase.getBytes(password)); - } - - public synchronized SQLiteDatabase getReadableDatabase(byte[] password) { - if (mDatabase != null && mDatabase.isOpen()) { - return mDatabase; // The database is already open for business - } - - if (mIsInitializing) { - throw new IllegalStateException("getReadableDatabase called recursively"); - } - - try { - return getWritableDatabase(password); - } catch (SQLiteException e) { - if (mName == null) throw e; // Can't open a temp database read-only! - HiLog.error(label, "Couldn't open " + mName + " for writing (will try read-only):", e); - } - - SQLiteDatabase db = null; - try { - mIsInitializing = true; - String path = mContext.getDatabaseDir().getPath(); - File databasePath = new File(path); - File databasesDirectory = new File(mContext.getDatabaseDir().getParent()); - - if(!databasesDirectory.exists()){ - boolean mkdirs = databasesDirectory.mkdirs(); - } - if(!databasePath.exists()){ - mIsInitializing = false; - db = getWritableDatabase(password); - mIsInitializing = true; - db.close(); - } - db = SQLiteDatabase.openDatabase(path, password, mFactory, SQLiteDatabase.OPEN_READONLY, mHook, mErrorHandler); - if (db.getVersion() != mNewVersion) { - throw new SQLiteException("Can't upgrade read-only database from version " + - db.getVersion() + " to " + mNewVersion + ": " + path); - } - - onOpen(db); - HiLog.warn(label, "Opened " + mName + " in read-only mode"); - mDatabase = db; - return mDatabase; - } finally { - mIsInitializing = false; - if (db != null && db != mDatabase) db.close(); - } - } - - /** - * Close any open database object. - */ - public synchronized void close() { - if (mIsInitializing) throw new IllegalStateException("Closed during initialization"); - - if (mDatabase != null && mDatabase.isOpen()) { - mDatabase.close(); - mDatabase = null; - } - } - - /** - * Return the name of the SQLite database being opened, as given to - * the constructor. - * @return database name - */ - public String getDatabaseName() { - return mName; - } - - /** - * Enables or disables the use of write-ahead logging for the database. - * - * Write-ahead logging cannot be used with read-only databases so the value of - * this flag is ignored if the database is opened read-only. - * - * @param enabled True if write-ahead logging should be enabled, false if it - * should be disabled. - * - * @see SQLiteDatabase#enableWriteAheadLogging() - */ - public void setWriteAheadLoggingEnabled(boolean enabled) { - synchronized (this) { - if (mEnableWriteAheadLogging != enabled) { - if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { - if (enabled) { - mDatabase.enableWriteAheadLogging(); - } else { - mDatabase.disableWriteAheadLogging(); - } - mEnableWriteAheadLogging = enabled; - } else { - mDeferSetWriteAheadLoggingEnabled = enabled; - } - } - } - } - - /** - * Called when the database needs to be downgraded. This is strictly similar to - * {@link #onUpgrade} method, but is called whenever current version is newer than requested one. - * However, this method is not abstract, so it is not mandatory for a customer to - * implement it. If not overridden, default implementation will reject downgrade and - * throws SQLiteException - * - *

- * This method executes within a transaction. If an exception is thrown, all changes - * will automatically be rolled back. - *

- * - * @param db The database. - * @param oldVersion The old database version. - * @param newVersion The new database version. - */ - public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { - throw new SQLiteException("Can't downgrade database from version " + - oldVersion + " to " + newVersion); - } - - /** - * Called when the database connection is being configured, to enable features - * such as write-ahead logging or foreign key support. - *

- * This method is called before {@link #onCreate}, {@link #onUpgrade}, - * {@link #onDowngrade}, or {@link #onOpen} are called. It should not modify - * the database except to configure the database connection as required. - *

- * This method should only call methods that configure the parameters of the - * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging} - * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, - * {@link SQLiteDatabase#setLocale}, or executing PRAGMA statements. - *

- * - * @param db The database. - */ - public void onConfigure(SQLiteDatabase db) {} - - /** - * Called when the database is created for the first time. This is where the - * creation of tables and the initial population of the tables should happen. - * - * @param db The database. - */ - public abstract void onCreate(SQLiteDatabase db); - - /** - * Called when the database needs to be upgraded. The implementation - * should use this method to drop tables, add tables, or do anything else it - * needs to upgrade to the new schema version. - * - *

The SQLite ALTER TABLE documentation can be found - * here. If you add new columns - * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns - * you can use ALTER TABLE to rename the old table, then create the new table and then - * populate the new table with the contents of the old table. - * - * @param db The database. - * @param oldVersion The old database version. - * @param newVersion The new database version. - */ - public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); - - /** - * Called when the database has been opened. - * Override method should check {@link SQLiteDatabase#isReadOnly} before - * updating the database. - * - * @param db The database. - */ - public void onOpen(SQLiteDatabase db) {} -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteProgram.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteProgram.java deleted file mode 100644 index 61f4cbe7ac7f019993211410d0c08a7836f592a9..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteProgram.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import net.sqlcipher.harmonyx.SupportSQLiteProgram; - -/** - * A base class for compiled SQLite programs. - * - * SQLiteProgram is not internally synchronized so code using a SQLiteProgram from multiple - * threads should perform its own synchronization when using the SQLiteProgram. - */ -public abstract class SQLiteProgram extends SQLiteClosable implements - SupportSQLiteProgram { - - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00205, "SQLiteProgram"); - - /** The database this program is compiled against. - * @deprecated do not use this - */ - @Deprecated - protected SQLiteDatabase mDatabase; - - /** The SQL used to create this query */ - /* package */ final String mSql; - - /** - * Native linkage, do not modify. This comes from the database and should not be modified - * in here or in the native code. - * @deprecated do not use this - */ - @Deprecated - protected long nHandle = 0; - - /** - * the SQLiteCompiledSql object for the given sql statement. - */ - private SQLiteCompiledSql mCompiledSql; - - /** - * SQLiteCompiledSql statement id is populated with the corresponding object from the above - * member. This member is used by the native_bind_* methods - * @deprecated do not use this - */ - @Deprecated - protected long nStatement = 0; - - /** - * Indicates whether {@link #close()} has been called. - */ - boolean mClosed = false; - - /* package */ SQLiteProgram(SQLiteDatabase db, String sql) { - mDatabase = db; - mSql = sql.trim(); - db.acquireReference(); - db.addSQLiteClosable(this); - this.nHandle = db.mNativeHandle; - int crudPrefixLength = 6; - - // only cache CRUD statements - String prefixSql = mSql.length() >= crudPrefixLength ? mSql.substring(0, crudPrefixLength) : mSql; - if (!prefixSql.equalsIgnoreCase("INSERT") && !prefixSql.equalsIgnoreCase("UPDATE") && - !prefixSql.equalsIgnoreCase("REPLAC") && - !prefixSql.equalsIgnoreCase("DELETE") && !prefixSql.equalsIgnoreCase("SELECT")) { - mCompiledSql = new SQLiteCompiledSql(db, sql); - nStatement = mCompiledSql.nStatement; - // since it is not in the cache, no need to acquire() it. - return; - } - - // it is not pragma - mCompiledSql = db.getCompiledStatementForSql(sql); - if (mCompiledSql == null) { - // create a new compiled-sql obj - mCompiledSql = new SQLiteCompiledSql(db, sql); - - // add it to the cache of compiled-sqls - // but before adding it and thus making it available for anyone else to use it, - // make sure it is acquired by me. - mCompiledSql.acquire(); - db.addToCompiledQueries(sql, mCompiledSql); - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "Created DbObj (id#" + mCompiledSql.nStatement + - ") for sql: " + sql); - } - } else { - // it is already in compiled-sql cache. - // try to acquire the object. - if (!mCompiledSql.acquire()) { - long last = mCompiledSql.nStatement; - // the SQLiteCompiledSql in cache is in use by some other SQLiteProgram object. - // we can't have two different SQLiteProgam objects can't share the same - // CompiledSql object. create a new one. - // finalize it when I am done with it in "this" object. - mCompiledSql = new SQLiteCompiledSql(db, sql); - if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - HiLog.debug(label, "** possible bug ** Created NEW DbObj (id#" + - mCompiledSql.nStatement + - ") because the previously created DbObj (id#" + last + - ") was not released for sql:" + sql); - } - // since it is not in the cache, no need to acquire() it. - } - } - nStatement = mCompiledSql.nStatement; - } - - @Override - protected void onAllReferencesReleased() { - releaseCompiledSqlIfNotInCache(); - mDatabase.releaseReference(); - mDatabase.removeSQLiteClosable(this); - } - - @Override - protected void onAllReferencesReleasedFromContainer() { - releaseCompiledSqlIfNotInCache(); - mDatabase.releaseReference(); - } - - private void releaseCompiledSqlIfNotInCache() { - if (mCompiledSql == null) { - return; - } - synchronized(mDatabase.mCompiledQueries) { - if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) { - // it is NOT in compiled-sql cache. i.e., responsibility of - // releasing this statement is on me. - mCompiledSql.releaseSqlStatement(); - mCompiledSql = null; - nStatement = 0; - } else { - // it is in compiled-sql cache. reset its CompiledSql#mInUse flag - mCompiledSql.release(); - } - } - } - - /** - * Returns a unique identifier for this program. - * - * @return a unique identifier for this program - */ - public final long getUniqueId() { - return nStatement; - } - - /* package */ String getSqlString() { - return mSql; - } - - /** - * compile - * @deprecated This method is deprecated and must not be used. - * - * @param sql the SQL string to compile - * @param forceCompilation forces the SQL to be recompiled in the event that there is an - * existing compiled SQL program already around - */ - @Deprecated - protected void compile(String sql, boolean forceCompilation) { - // TODO is there a need for this? - } - - /** - * Bind a NULL value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind null to - */ - @Override - public void bindNull(int index) { - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_bind_null(index); - } finally { - releaseReference(); - } - } - - /** - * Bind a long value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - @Override - public void bindLong(int index, long value) { - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_bind_long(index, value); - } finally { - releaseReference(); - } - } - - /** - * Bind a double value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - @Override - public void bindDouble(int index, double value) { - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_bind_double(index, value); - } finally { - releaseReference(); - } - } - - /** - * Bind a String value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - @Override - public void bindString(int index, String value) { - if (value == null) { - throw new IllegalArgumentException("the bind value at index " + index + " is null"); - } - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_bind_string(index, value); - } finally { - releaseReference(); - } - } - - /** - * Bind a byte array value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - @Override - public void bindBlob(int index, byte[] value) { - if (value == null) { - throw new IllegalArgumentException("the bind value at index " + index + " is null"); - } - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_bind_blob(index, value); - } finally { - releaseReference(); - } - } - - /** - * Clears all existing bindings. Unset bindings are treated as NULL. - */ - @Override - public void clearBindings() { - if (mClosed) { - throw new IllegalStateException("program already closed"); - } - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - acquireReference(); - try { - native_clear_bindings(); - } finally { - releaseReference(); - } - } - - /** - * Release this program's resources, making it invalid. - */ - public void close() { - if (mClosed) { - return; - } - if (!mDatabase.isOpen()) { - return; - } - mDatabase.lock(); - try { - releaseReference(); - } finally { - mDatabase.unlock(); - } - mClosed = true; - } - - /** - * native_compile - * @deprecated This method is deprecated and must not be used. - * Compiles SQL into a SQLite program. - * - *

The database lock must be held when calling this method. - * @param sql The SQL to compile. - */ - @Deprecated - protected final native void native_compile(String sql); - - /** - * native_finalize - * @deprecated This method is deprecated and must not be used. - */ - @Deprecated - protected final native void native_finalize(); - - protected final native void native_bind_null(int index); - protected final native void native_bind_long(int index, long value); - protected final native void native_bind_double(int index, double value); - protected final native void native_bind_string(int index, String value); - protected final native void native_bind_blob(int index, byte[] value); - private final native void native_clear_bindings(); -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQuery.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQuery.java deleted file mode 100644 index 72471903dd58a3f3fee5c66f4fb702ac734b2604..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQuery.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.*; - -import ohos.miscservices.timeutility.Time; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -/** - * A SQLite program that represents a query that reads the resulting rows into a CursorWindow. - * This class is used by SQLiteCursor and isn't useful itself. - * - * SQLiteQuery is not internally synchronized so code using a SQLiteQuery from multiple - * threads should perform its own synchronization when using the SQLiteQuery. - */ -public class SQLiteQuery extends SQLiteProgram { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00206, "SQLiteQuery"); - - /** The index of the unbound OFFSET parameter */ - private int mOffsetIndex; - - /** Args to bind on requery */ - private String[] mBindArgs; - private Object[] mObjectBindArgs; - - /** - * Create a persistent query object. - * - * @param db The database that this query object is associated with - * @param query The SQL string for this query. - * @param offsetIndex The 1-based index to the OFFSET parameter, - */ - /* package */ SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs) { - super(db, query); - - mOffsetIndex = offsetIndex; - mBindArgs = bindArgs; - } - - SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, Object[] bindArgs) { - super(db, query); - mOffsetIndex = offsetIndex; - mObjectBindArgs = bindArgs; - int length = mObjectBindArgs != null ? mObjectBindArgs.length : 0; - mBindArgs = new String[length]; - } - - /** - * Reads rows into a buffer. This method acquires the database lock. - * - * @param window The window to fill into - * @return number of total rows in the query - */ - /* package */ - int fillWindow(CursorWindow window, - int maxRead, int lastPos) { - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - try { - acquireReference(); - try { - window.acquireRef(); - // if the start pos is not equal to 0, then most likely window is - // too small for the data set, loading by another thread - // is not safe in this situation. the native code will ignore maxRead - int numRows = native_fill_window(window, - window.getStartRowIndex(), - window.getRequiredPosition(), - mOffsetIndex, - maxRead, lastPos); //todo native porting - - // Logging - if (SQLiteDebug.DEBUG_SQL_STATEMENTS) { - HiLog.debug(label, "fillWindow(): " + mSql); - } - return numRows; - } catch (IllegalStateException e){ - // simply ignore it - return 0; - } catch (SQLiteDatabaseCorruptException e) { - mDatabase.onCorruption(); - throw e; - } finally { - window.releaseRef(); - } - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - /** - * Get the column count for the statement. Only valid on query based - * statements. The database must be locked - * when calling this method. - * - * @return The number of column in the statement's result set. - */ - /* package */ int columnCountLocked() { - acquireReference(); - try { - return native_column_count(); - } finally { - releaseReference(); - } - } - - /** - * Retrieves the column name for the given column index. The database must be locked - * when calling this method. - * - * @param columnIndex the index of the column to get the name for - * @return The requested column's name - */ - /* package */ String columnNameLocked(int columnIndex) { - acquireReference(); - try { - return native_column_name(columnIndex); - } finally { - releaseReference(); - } - } - - @Override - public String toString() { - return "SQLiteQuery: " + mSql; - } - - /** - * Called by SQLiteCursor when it is requeried. - */ - /* package */ void requery() { - if (mBindArgs != null) { - int len = mBindArgs.length; - try { - if(mObjectBindArgs != null) { - bindArguments(mObjectBindArgs); - } else { - for (int i = 0; i < len; i++) { - super.bindString(i + 1, mBindArgs[i]); - } - } - } catch (SQLiteMisuseException e) { - StringBuilder errMsg = new StringBuilder("mSql " + mSql); - for (int i = 0; i < len; i++) { - errMsg.append(" "); - errMsg.append(mBindArgs[i]); - } - errMsg.append(" "); - IllegalStateException leakProgram = new IllegalStateException( - errMsg.toString(), e); - throw leakProgram; - } - } - } - - @Override - public void bindNull(int index) { - mBindArgs[index - 1] = null; - if (!mClosed) super.bindNull(index); - } - - @Override - public void bindLong(int index, long value) { - mBindArgs[index - 1] = Long.toString(value); - if (!mClosed) super.bindLong(index, value); - } - - @Override - public void bindDouble(int index, double value) { - mBindArgs[index - 1] = Double.toString(value); - if (!mClosed) super.bindDouble(index, value); - } - - @Override - public void bindString(int index, String value) { - mBindArgs[index - 1] = value; - if (!mClosed) super.bindString(index, value); - } - - public void bindArguments(Object[] args){ - if(args != null && args.length > 0){ - for(int i = 0; i < args.length; i++){ - Object value = args[i]; - if(value == null){ - bindNull(i + 1); - } else if (value instanceof Double) { - bindDouble(i + 1, (Double)value); - } else if (value instanceof Float) { - float number = ((Number)value).floatValue(); - bindDouble(i + 1, Double.valueOf(number)); - } else if (value instanceof Long) { - bindLong(i + 1, (Long)value); - } else if(value instanceof Integer) { - int number = ((Number) value).intValue(); - bindLong(i + 1, Long.valueOf(number)); - } else if (value instanceof Boolean) { - bindLong(i + 1, (Boolean)value ? 1 : 0); - } else if (value instanceof byte[]) { - bindBlob(i + 1, (byte[])value); - } else { - bindString(i + 1, value.toString()); - } - } - } - } - - private final native int native_fill_window(CursorWindow window, - int startPos, int requiredPos, - int offsetParam, int maxRead, - int lastPos); - - private final native int native_column_count(); - - private final native String native_column_name(int columnIndex); -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryBuilder.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryBuilder.java deleted file mode 100644 index d004218b0409f739bd40a0c73d0d1d894fd41d0f..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryBuilder.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.*; -import net.sqlcipher.utils.TextUtils; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; -import java.util.regex.Pattern; - -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import ohos.data.resultset.ResultSet; - -/** - * This is a convience class that helps build SQL queries to be sent to - * {@link SQLiteDatabase} objects. - */ -public class SQLiteQueryBuilder -{ - private static final String TAG = "SQLiteQueryBuilder"; - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00207, "SQLiteQueryBuilder"); - private static final Pattern sLimitPattern = - Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?"); - - private Map mProjectionMap = null; - private String mTables = ""; - private StringBuilder mWhereClause = null; // lazily created - private boolean mDistinct; - private SQLiteDatabase.CursorFactory mFactory; - private boolean mStrictProjectionMap; - private static final String _COUNT = "_count"; - - public SQLiteQueryBuilder() { - mDistinct = false; - mFactory = null; - } - - /** - * Mark the query as DISTINCT. - * - * @param distinct if true the query is DISTINCT, otherwise it isn't - */ - public void setDistinct(boolean distinct) { - mDistinct = distinct; - } - - /** - * Returns the list of tables being queried - * - * @return the list of tables being queried - */ - public String getTables() { - return mTables; - } - - /** - * Sets the list of tables to query. Multiple tables can be specified to perform a join. - * For example: - * setTables("foo, bar") - * setTables("foo LEFT OUTER JOIN bar ON (foo.id = bar.foo_id)") - * - * @param inTables the list of tables to query on - */ - public void setTables(String inTables) { - mTables = inTables; - } - - /** - * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded - * by parenthesis and ANDed with the selection passed to {@link #query}. The final - * WHERE clause looks like: - * - * WHERE (<append chunk 1><append chunk2>) AND (<query() selection parameter>) - * - * @param inWhere the chunk of text to append to the WHERE clause. - */ - public void appendWhere(CharSequence inWhere) { - if (mWhereClause == null) { - mWhereClause = new StringBuilder(inWhere.length() + 16); - } - if (mWhereClause.length() == 0) { - mWhereClause.append('('); - } - mWhereClause.append(inWhere); - } - - /** - * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded - * by parenthesis and ANDed with the selection passed to {@link #query}. The final - * WHERE clause looks like: - * - * WHERE (<append chunk 1><append chunk2>) AND (<query() selection parameter>) - * - * @param inWhere the chunk of text to append to the WHERE clause. it will be escaped - * to avoid SQL injection attacks - */ - public void appendWhereEscapeString(String inWhere) { - if (mWhereClause == null) { - mWhereClause = new StringBuilder(inWhere.length() + 16); - } - if (mWhereClause.length() == 0) { - mWhereClause.append('('); - } - DatabaseUtils.appendEscapedSQLString(mWhereClause, inWhere); - } - - /** - * Sets the projection map for the query. The projection map maps - * from column names that the caller passes into query to database - * column names. This is useful for renaming columns as well as - * disambiguating column names when doing joins. For example you - * could map "name" to "people.name". If a projection map is set - * it must contain all column names the user may request, even if - * the key and value are the same. - * - * @param columnMap maps from the user column names to the database column names - */ - public void setProjectionMap(Map columnMap) { - mProjectionMap = columnMap; - } - - /** - * Sets the cursor factory to be used for the query. You can use - * one factory for all queries on a database but it is normally - * easier to specify the factory when doing this query. @param - * factory the factor to use - * @param factory CursorFactory - */ - public void setCursorFactory(SQLiteDatabase.CursorFactory factory) { - mFactory = factory; - } - - /** - * setStrictProjectionMap - * @hide hide - * @param flag flag - */ - public void setStrictProjectionMap(boolean flag) { - mStrictProjectionMap = flag; - } - - /** - * Build an SQL query string from the given clauses. - * - * @param distinct true if you want each row to be unique, false otherwise. - * @param tables The table names to compile the query against. - * @param columns A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading - * data from storage that isn't going to be used. - * @param where A filter declaring which rows to return, formatted as an SQL - * WHERE clause (excluding the WHERE itself). Passing null will - * return all rows for the given URL. - * @param groupBy A filter declaring how to group rows, formatted as an SQL - * GROUP BY clause (excluding the GROUP BY itself). Passing null - * will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in the cursor, - * if row grouping is being used, formatted as an SQL HAVING - * clause (excluding the HAVING itself). Passing null will cause - * all row groups to be included, and is required when row - * grouping is not being used. - * @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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return the SQL query string - */ - public static String buildQueryString( - boolean distinct, String tables, String[] columns, String where, - String groupBy, String having, String orderBy, String limit) { - if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) { - throw new IllegalArgumentException( - "HAVING clauses are only permitted when using a groupBy clause"); - } - if (!TextUtils.isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) { - throw new IllegalArgumentException("invalid LIMIT clauses:" + limit); - } - - StringBuilder query = new StringBuilder(120); - - query.append("SELECT "); - if (distinct) { - query.append("DISTINCT "); - } - if (columns != null && columns.length != 0) { - appendColumns(query, columns); - } else { - query.append("* "); - } - query.append("FROM "); - query.append(tables); - appendClause(query, " WHERE ", where); - appendClause(query, " GROUP BY ", groupBy); - appendClause(query, " HAVING ", having); - appendClause(query, " ORDER BY ", orderBy); - appendClause(query, " LIMIT ", limit); - - return query.toString(); - } - - private static void appendClause(StringBuilder s, String name, String clause) { - if (!TextUtils.isEmpty(clause)) { - s.append(name); - s.append(clause); - } - } - - private static void appendClauseEscapeClause(StringBuilder s, String name, String clause) { - if (!TextUtils.isEmpty(clause)) { - s.append(name); - DatabaseUtils.appendEscapedSQLString(s, clause); - } - } - - /** - * Add the names that are non-null in columns to s, separating - * them with commas. - * @param s string - * @param columns columns - */ - public static void appendColumns(StringBuilder s, String[] columns) { - int n = columns.length; - - for (int i = 0; i < n; i++) { - String column = columns[i]; - - if (column != null) { - if (i > 0) { - s.append(", "); - } - s.append(column); - } - } - s.append(' '); - } - - /** - * Perform a query by combining all current settings and the - * information passed into this method. - * - * @param db the database to query on - * @param projectionIn A list of which columns to return. Passing - * null will return all columns, which is discouraged to prevent - * reading data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE - * itself). Passing null will return all rows for the given URL. - * @param selectionArgs You may include ?s in selection, which - * will be replaced by the values from selectionArgs, in order - * that they appear in the selection. The values will be bound - * as Strings. - * @param groupBy A filter declaring how to group rows, formatted - * as an SQL GROUP BY clause (excluding the GROUP BY - * itself). Passing null will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in - * the cursor, if row grouping is being used, formatted as an - * SQL HAVING clause (excluding the HAVING itself). Passing - * null will cause all row groups to be included, and is - * required when row grouping is not being used. - * @param sortOrder 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 may be unordered. - * @return a cursor over the result set - * - */ - public ResultSet query(SQLiteDatabase db, String[] projectionIn, - String selection, String[] selectionArgs, String groupBy, - String having, String sortOrder) { - return query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder, - null /* limit */); - } - - /** - * Perform a query by combining all current settings and the - * information passed into this method. - * - * @param db the database to query on - * @param projectionIn A list of which columns to return. Passing - * null will return all columns, which is discouraged to prevent - * reading data from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE - * itself). Passing null will return all rows for the given URL. - * @param selectionArgs You may include ?s in selection, which - * will be replaced by the values from selectionArgs, in order - * that they appear in the selection. The values will be bound - * as Strings. - * @param groupBy A filter declaring how to group rows, formatted - * as an SQL GROUP BY clause (excluding the GROUP BY - * itself). Passing null will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in - * the cursor, if row grouping is being used, formatted as an - * SQL HAVING clause (excluding the HAVING itself). Passing - * null will cause all row groups to be included, and is - * required when row grouping is not being used. - * @param sortOrder 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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return a cursor over the result set - * - */ - public ResultSet query(SQLiteDatabase db, String[] projectionIn, - String selection, String[] selectionArgs, String groupBy, - String having, String sortOrder, String limit) { - if (mTables == null) { - return null; - } - - String sql = buildQuery( - projectionIn, selection, selectionArgs, groupBy, having, - sortOrder, limit); - - if (HiLog.isLoggable(0x00208, TAG, HiLog.DEBUG)) { - HiLog.debug(label, "Performing query: " + sql); - } - return db.rawQueryWithFactory( - mFactory, sql, selectionArgs, - SQLiteDatabase.findEditTable(mTables)); - } - - /** - * Construct a SELECT statement suitable for use in a group of - * SELECT statements that will be joined through UNION operators - * in buildUnionQuery. - * - * @param projectionIn A list of which columns to return. Passing - * null will return all columns, which is discouraged to - * prevent reading data from storage that isn't going to be - * used. - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE - * itself). Passing null will return all rows for the given - * URL. - * @param selectionArgs You may include ?s in selection, which - * will be replaced by the values from selectionArgs, in order - * that they appear in the selection. The values will be bound - * as Strings. - * @param groupBy A filter declaring how to group rows, formatted - * as an SQL GROUP BY clause (excluding the GROUP BY itself). - * Passing null will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in - * the cursor, if row grouping is being used, formatted as an - * SQL HAVING clause (excluding the HAVING itself). Passing - * null will cause all row groups to be included, and is - * required when row grouping is not being used. - * @param sortOrder 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 may be unordered. - * @param limit Limits the number of rows returned by the query, - * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return the resulting SQL SELECT statement - */ - public String buildQuery( - String[] projectionIn, String selection, String[] selectionArgs, - String groupBy, String having, String sortOrder, String limit) { - String[] projection = computeProjection(projectionIn); - - StringBuilder where = new StringBuilder(); - boolean hasBaseWhereClause = mWhereClause != null && mWhereClause.length() > 0; - - if (hasBaseWhereClause) { - where.append(mWhereClause.toString()); - where.append(')'); - } - - // Tack on the user's selection, if present. - if (selection != null && selection.length() > 0) { - if (hasBaseWhereClause) { - where.append(" AND "); - } - - where.append('('); - where.append(selection); - where.append(')'); - } - - return buildQueryString( - mDistinct, mTables, projection, where.toString(), - groupBy, having, sortOrder, limit); - } - - /** - * Construct a SELECT statement suitable for use in a group of - * SELECT statements that will be joined through UNION operators - * in buildUnionQuery. - * - * @param typeDiscriminatorColumn the name of the result column - * whose cells will contain the name of the table from which - * each row was drawn. - * @param unionColumns the names of the columns to appear in the - * result. This may include columns that do not appear in the - * table this SELECT is querying (i.e. mTables), but that do - * appear in one of the other tables in the UNION query that we - * are constructing. - * @param columnsPresentInTable a Set of the names of the columns - * that appear in this table (i.e. in the table whose name is - * mTables). Since columns in unionColumns include columns that - * appear only in other tables, we use this array to distinguish - * which ones actually are present. Other columns will have - * NULL values for results from this subquery. - * @param computedColumnsOffset all columns in unionColumns before - * this index are included under the assumption that they're - * computed and therefore won't appear in columnsPresentInTable, - * e.g. "date * 1000 as normalized_date" - * @param typeDiscriminatorValue the value used for the - * type-discriminator column in this subquery - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE - * itself). Passing null will return all rows for the given - * URL. - * @param selectionArgs You may include ?s in selection, which - * will be replaced by the values from selectionArgs, in order - * that they appear in the selection. The values will be bound - * as Strings. - * @param groupBy A filter declaring how to group rows, formatted - * as an SQL GROUP BY clause (excluding the GROUP BY itself). - * Passing null will cause the rows to not be grouped. - * @param having A filter declare which row groups to include in - * the cursor, if row grouping is being used, formatted as an - * SQL HAVING clause (excluding the HAVING itself). Passing - * null will cause all row groups to be included, and is - * required when row grouping is not being used. - * @return the resulting SQL SELECT statement - */ - public String buildUnionSubQuery( - String typeDiscriminatorColumn, - String[] unionColumns, - Set columnsPresentInTable, - int computedColumnsOffset, - String typeDiscriminatorValue, - String selection, - String[] selectionArgs, - String groupBy, - String having) { - int unionColumnsCount = unionColumns.length; - String[] projectionIn = new String[unionColumnsCount]; - - for (int i = 0; i < unionColumnsCount; i++) { - String unionColumn = unionColumns[i]; - - if (unionColumn.equals(typeDiscriminatorColumn)) { - projectionIn[i] = "'" + typeDiscriminatorValue + "' AS " - + typeDiscriminatorColumn; - } else if (i <= computedColumnsOffset - || columnsPresentInTable.contains(unionColumn)) { - projectionIn[i] = unionColumn; - } else { - projectionIn[i] = "NULL AS " + unionColumn; - } - } - return buildQuery( - projectionIn, selection, selectionArgs, groupBy, having, - null /* sortOrder */, - null /* limit */); - } - - /** - * Given a set of subqueries, all of which are SELECT statements, - * construct a query that returns the union of what those - * subqueries return. - * @param subQueries an array of SQL SELECT statements, all of - * which must have the same columns as the same positions in - * their results - * @param sortOrder 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 may be unordered. - * @param limit The limit clause, which applies to the entire union result set - * - * @return the resulting SQL SELECT statement - */ - public String buildUnionQuery(String[] subQueries, String sortOrder, String limit) { - StringBuilder query = new StringBuilder(128); - int subQueryCount = subQueries.length; - String unionOperator = mDistinct ? " UNION " : " UNION ALL "; - - for (int i = 0; i < subQueryCount; i++) { - if (i > 0) { - query.append(unionOperator); - } - query.append(subQueries[i]); - } - appendClause(query, " ORDER BY ", sortOrder); - appendClause(query, " LIMIT ", limit); - return query.toString(); - } - - private String[] computeProjection(String[] projectionIn) { - if (projectionIn != null && projectionIn.length > 0) { - if (mProjectionMap != null) { - String[] projection = new String[projectionIn.length]; - int length = projectionIn.length; - - for (int i = 0; i < length; i++) { - String userColumn = projectionIn[i]; - String column = mProjectionMap.get(userColumn); - - if (column != null) { - projection[i] = column; - continue; - } - - if (!mStrictProjectionMap && - ( userColumn.contains(" AS ") || userColumn.contains(" as "))) { - /* A column alias already exist */ - projection[i] = userColumn; - continue; - } - - throw new IllegalArgumentException("Invalid column " - + projectionIn[i]); - } - return projection; - } else { - return projectionIn; - } - } else if (mProjectionMap != null) { - // Return all columns in projection map. - Set> entrySet = mProjectionMap.entrySet(); - String[] projection = new String[entrySet.size()]; - Iterator> entryIter = entrySet.iterator(); - int i = 0; - - while (entryIter.hasNext()) { - Entry entry = entryIter.next(); - - // Don't include the _count column when people ask for no projection. - if (entry.getKey().equals(_COUNT)) { - continue; - } - projection[i++] = entry.getValue(); - } - return projection; - } - return null; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryStats.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryStats.java deleted file mode 100644 index 4b36c05f001759ab53aa991a9f4555a7dfe18151..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteQueryStats.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.sqlcipher.database; - -public class SQLiteQueryStats { - long totalQueryResultSize = 0L; - long largestIndividualRowSize = 0L; - - public SQLiteQueryStats(long totalQueryResultSize, - long largestIndividualRowSize) { - this.totalQueryResultSize = totalQueryResultSize; - this.largestIndividualRowSize = largestIndividualRowSize; - } - - public long getTotalQueryResultSize(){ - return totalQueryResultSize; - } - - public long getLargestIndividualRowSize(){ - return largestIndividualRowSize; - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteStatement.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteStatement.java deleted file mode 100644 index d2bc6442f0d309a3572ec9eca0e344d2a7f71893..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteStatement.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import ohos.miscservices.timeutility.Time; -import net.sqlcipher.harmonyx.SupportSQLiteStatement; - -/** - * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused. - * The statement cannot return multiple rows, but 1x1 result sets are allowed. - * Don't use SQLiteStatement constructor directly, please use - * {@link SQLiteDatabase#compileStatement(String)} - * - * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple - * threads should perform its own synchronization when using the SQLiteStatement. - */ -public class SQLiteStatement extends SQLiteProgram implements - SupportSQLiteStatement -{ - /** - * Don't use SQLiteStatement constructor directly, please use - * {@link SQLiteDatabase#compileStatement(String)} - * @param db - * @param sql - */ - /* package */ SQLiteStatement(SQLiteDatabase db, String sql) { - super(db, sql); - } - - /** - * Execute this SQL statement, if it is not a query. For example, - * CREATE TABLE, DELTE, INSERT, etc. - * - * @throws net.sqlcipher.SQLException If the SQL string is invalid for - * some reason - */ - @Override - public void execute() { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - - acquireReference(); - try { - native_execute(); - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - /** - * Execute this SQL statement and return the ID of the row inserted due to this call. - * The SQL statement should be an INSERT for this to be a useful call. - * - * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. - * - * @throws net.sqlcipher.SQLException If the SQL string is invalid for - * some reason - */ - @Override - public long executeInsert() { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - - acquireReference(); - try { - native_execute(); - return (mDatabase.lastChangeCount() > 0) ? mDatabase.lastInsertRow() : -1; - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - @Override - public int executeUpdateDelete() { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - - acquireReference(); - try { - native_execute(); - return mDatabase.lastChangeCount(); - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - /** - * Execute a statement that returns a 1 by 1 table with a numeric value. - * For example, SELECT COUNT(*) FROM table; - * - * @return The result of the query. - * - * @throws net.sqlcipher.sqlite.SQLiteDoneException if the query returns zero rows - */ - @Override - public long simpleQueryForLong() { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - - acquireReference(); - try { - long retValue = native_1x1_long(); - return retValue; - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - /** - * Execute a statement that returns a 1 by 1 table with a text value. - * For example, SELECT COUNT(*) FROM table; - * - * @return The result of the query. - * - * @throws net.sqlcipher.sqlite.SQLiteDoneException if the query returns zero rows - */ - @Override - public String simpleQueryForString() { - if (!mDatabase.isOpen()) { - throw new IllegalStateException("database " + mDatabase.getPath() + " already closed"); - } - long timeStart = Time.getRealActiveTime(); - mDatabase.lock(); - - acquireReference(); - try { - String retValue = native_1x1_string(); - return retValue; - } finally { - releaseReference(); - mDatabase.unlock(); - } - } - - private final native void native_execute(); - private final native long native_1x1_long(); - private final native String native_1x1_string(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteTransactionListener.java b/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteTransactionListener.java deleted file mode 100644 index 69680ee308ae66e54cd02ed5bf80c7905b8dcc53..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SQLiteTransactionListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -/** - * A listener for transaction events. - */ -public interface SQLiteTransactionListener { - /** - * Called immediately after the transaction begins. - */ - void onBegin(); - - /** - * Called immediately before commiting the transaction. - */ - void onCommit(); - - /** - * Called if the transaction is about to be rolled back. - */ - void onRollback(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SqliteWrapper.java b/sqlcipher/src/main/java/net/sqlcipher/database/SqliteWrapper.java deleted file mode 100644 index 8e74a26b03da2657ff7c2077a5cef457d0859846..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SqliteWrapper.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 Esmertec AG. - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import ohos.aafwk.ability.DataAbilityHelper; -import ohos.aafwk.ability.DataAbilityRemoteException; -import ohos.data.dataability.DataAbilityPredicates; -import ohos.data.rdb.ValuesBucket; -import ohos.app.Context; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; - -import ohos.data.resultset.ResultSet; -import ohos.utils.net.Uri; -import ohos.agp.window.dialog.ToastDialog; - -/** - * @hide - */ - -public final class SqliteWrapper { - private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00206, "SqliteWrapper"); - private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE - = "unable to open database file"; - - private SqliteWrapper() { - // Forbidden being instantiated. - } - - // FIXME: need to optimize this method. - private static boolean isLowMemory(SQLiteException e) { - return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE); - } - - public static void checkSQLiteException(Context context, SQLiteException e) { - if (isLowMemory(e)) { - ToastDialog toast = new ToastDialog(context); - toast.setText(e.getMessage()).show(); - } else { - throw e; - } - } - - public static ResultSet query(Context context, DataAbilityHelper resolver, Uri uri, - String[] projection, String selection, String[] selectionArgs, String sortOrder) { - try { - DataAbilityPredicates predicates = createPredicateFromSelection(selection, selectionArgs); - predicates.setOrder(sortOrder); - return (ResultSet) resolver.query(uri, projection, predicates); - } catch (SQLiteException e) { - HiLog.error(label, "Catch a SQLiteException when query: ", e); - checkSQLiteException(context, e); - return null; - } catch (DataAbilityRemoteException e) { - HiLog.error(label, "Catch a SQLiteException when query: ", e); - return null; - } - } - - private static DataAbilityPredicates createPredicateFromSelection(String selection, String[] selectionArgs) { - DataAbilityPredicates predicates = new DataAbilityPredicates(selection); - List args = new ArrayList<>(Arrays.asList(selectionArgs)); - predicates.setWhereArgs(args); - return predicates; - } - -/* public static boolean requery(Context context, ResultSet cursor) { //deprecated method, removed - try { - return cursor.requery(); - } catch (SQLiteException e) { - HiLog.error(label, "Catch a SQLiteException when requery: ", e); - checkSQLiteException(context, e); - return false; - } - }*/ - - public static int update(Context context, DataAbilityHelper resolver, Uri uri, - ValuesBucket values, String where, String[] selectionArgs) { - try { - DataAbilityPredicates predicates = createPredicateFromSelection(where,selectionArgs); - return resolver.update(uri, values, predicates); - } catch (SQLiteException e) { - HiLog.error(label, "Catch a SQLiteException when update: ", e); - checkSQLiteException(context, e); - return -1; - } catch (DataAbilityRemoteException e) { - HiLog.error(label, "Catch a SQLiteException when query: ", e); - return -1; - } - } - - public static int delete(Context context, DataAbilityHelper resolver, Uri uri, - String where, String[] selectionArgs) { - try { - DataAbilityPredicates predicates = createPredicateFromSelection(where,selectionArgs); - return resolver.delete(uri, predicates); - } catch (SQLiteException e) { - HiLog.error(label, "Catch a SQLiteException when delete: ", e); - checkSQLiteException(context, e); - return -1; - }catch (DataAbilityRemoteException e) { - HiLog.error(label, "Catch a SQLiteException when query: ", e); - return -1; - } - } - - public static int insert(Context context, DataAbilityHelper resolver, - Uri uri, ValuesBucket values) { - try { - return resolver.insert(uri, values); - } catch (DataAbilityRemoteException d) { - HiLog.error(label, "Catch a DataAbilityRemoteException when insert: ", d); - return -1; - } catch (SQLiteException e) { - HiLog.error(label, "Catch a SQLiteException when insert: ", e); - checkSQLiteException(context, e); - return -1; - } - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SupportFactory.java b/sqlcipher/src/main/java/net/sqlcipher/database/SupportFactory.java deleted file mode 100644 index 91d672539f7ab4a4e78aeea0e5d241aa46f45a7d..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SupportFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019 Mark L. Murphy - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.harmonyx.SupportSQLiteOpenHelper; - -public class SupportFactory implements SupportSQLiteOpenHelper.Factory { - private final byte[] passphrase; - private final SQLiteDatabaseHook hook; - private final boolean clearPassphrase; - - public SupportFactory(byte[] passphrase) { - this(passphrase, (SQLiteDatabaseHook)null); - } - - public SupportFactory(byte[] passphrase, SQLiteDatabaseHook hook) { - this(passphrase, hook, true); - } - - public SupportFactory(byte[] passphrase, SQLiteDatabaseHook hook, - boolean clearPassphrase) { - this.passphrase = passphrase; - this.hook = hook; - this.clearPassphrase = clearPassphrase; - } - - @Override - public SupportSQLiteOpenHelper create(SupportSQLiteOpenHelper.Configuration configuration) { - return new SupportHelper(configuration, passphrase, hook, clearPassphrase); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/database/SupportHelper.java b/sqlcipher/src/main/java/net/sqlcipher/database/SupportHelper.java deleted file mode 100644 index 230a7c65060dafeaa988be5362ca259ebfb91094..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/database/SupportHelper.java +++ /dev/null @@ -1,117 +0,0 @@ - /* - * Copyright (C) 2019 Mark L. Murphy - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.database; - -import net.sqlcipher.harmonyx.SupportSQLiteDatabase; -import net.sqlcipher.harmonyx.SupportSQLiteOpenHelper; - - public class SupportHelper implements SupportSQLiteOpenHelper { - private SQLiteOpenHelper standardHelper; - private byte[] passphrase; - private final boolean clearPassphrase; - - SupportHelper(final SupportSQLiteOpenHelper.Configuration configuration, - byte[] passphrase, final SQLiteDatabaseHook hook, - boolean clearPassphrase) { - SQLiteDatabase.loadLibs(configuration.context); - this.passphrase = passphrase; - this.clearPassphrase = clearPassphrase; - - standardHelper = - new SQLiteOpenHelper(configuration.context, configuration.name, - null, configuration.callback.version, hook) { - @Override - public void onCreate(SQLiteDatabase db) { - configuration.callback.onCreate(db); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, - int newVersion) { - configuration.callback.onUpgrade(db, oldVersion, - newVersion); - } - - @Override - public void onDowngrade(SQLiteDatabase db, int oldVersion, - int newVersion) { - configuration.callback.onDowngrade(db, oldVersion, - newVersion); - } - - @Override - public void onOpen(SQLiteDatabase db) { - configuration.callback.onOpen(db); - } - - @Override - public void onConfigure(SQLiteDatabase db) { - configuration.callback.onConfigure(db); - } - }; - } - - @Override - public String getDatabaseName() { - return standardHelper.getDatabaseName(); - } - - @Override - public void setWriteAheadLoggingEnabled(boolean enabled) { - standardHelper.setWriteAheadLoggingEnabled(enabled); - } - - @Override - public SupportSQLiteDatabase getWritableDatabase() { - SQLiteDatabase result; - try { - result = standardHelper.getWritableDatabase(passphrase); - } catch (SQLiteException ex){ - if(passphrase != null){ - boolean isCleared = true; - for(byte b : passphrase){ - isCleared = isCleared && (b == (byte)0); - } - if (isCleared) { - throw new IllegalStateException("The passphrase appears to be cleared. This happens by " + - "default the first time you use the factory to open a database, so we can remove the " + - "cleartext passphrase from memory. If you close the database yourself, please use a " + - "fresh SupportFactory to reopen it. If something else (e.g., Room) closed the " + - "database, and you cannot control that, use SupportFactory boolean constructor option " + - "to opt out of the automatic password clearing step. See the project README for more information.", ex); - } - } - throw ex; - } - if(clearPassphrase && passphrase != null) { - for (int i = 0; i < passphrase.length; i++) { - passphrase[i] = (byte)0; - } - } - return result; - } - - @Override - public SupportSQLiteDatabase getReadableDatabase() { - return getWritableDatabase(); - } - - @Override - public void close() { - standardHelper.close(); - } - } diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SimpleSQLiteQuery.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SimpleSQLiteQuery.java deleted file mode 100644 index ad7ae83b01255a495b55095ee4f2bae4c4088e54..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SimpleSQLiteQuery.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -/** - * A basic implementation of {@link SupportSQLiteQuery} which receives a query and its args and - * binds args based on the passed in Object type. - */ -public final class SimpleSQLiteQuery implements SupportSQLiteQuery { - private final String mQuery; - private final Object[] mBindArgs; - - /** - * Creates an SQL query with the sql string and the bind arguments. - * - * @param query The query string, can include bind arguments (.e.g ?). - * @param bindArgs The bind argument value that will replace the placeholders in the query. - */ - public SimpleSQLiteQuery(String query, Object[] bindArgs) { - mQuery = query; - mBindArgs = bindArgs; - } - - /** - * Creates an SQL query without any bind arguments. - * - * @param query The SQL query to execute. Cannot include bind parameters. - */ - public SimpleSQLiteQuery(String query) { - this(query, null); - } - - @Override - public String getSql() { - return mQuery; - } - - @Override - public void bindTo(SupportSQLiteProgram statement) { - bind(statement, mBindArgs); - } - - @Override - public int getArgCount() { - return mBindArgs == null ? 0 : mBindArgs.length; - } - - /** - * Binds the given arguments into the given sqlite statement. - * - * @param statement The sqlite statement - * @param bindArgs The list of bind arguments - */ - public static void bind(SupportSQLiteProgram statement, Object[] bindArgs) { - if (bindArgs == null) { - return; - } - final int limit = bindArgs.length; - for (int i = 0; i < limit; i++) { - final Object arg = bindArgs[i]; - bind(statement, i + 1, arg); - } - } - - private static void bind(SupportSQLiteProgram statement, int index, Object arg) { - if (arg == null) { - statement.bindNull(index); - } else if (arg instanceof byte[]) { - statement.bindBlob(index, (byte[]) arg); - } else if (arg instanceof Float) { - statement.bindDouble(index, (Float) arg); - } else if (arg instanceof Double) { - statement.bindDouble(index, (Double) arg); - } else if (arg instanceof Long) { - statement.bindLong(index, (Long) arg); - } else if (arg instanceof Integer) { - statement.bindLong(index, (Integer) arg); - } else if (arg instanceof Short) { - statement.bindLong(index, (Short) arg); - } else if (arg instanceof Byte) { - statement.bindLong(index, (Byte) arg); - } else if (arg instanceof String) { - statement.bindString(index, (String) arg); - } else if (arg instanceof Boolean) { - statement.bindLong(index, ((Boolean) arg) ? 1 : 0); - } else { - throw new IllegalArgumentException("Cannot bind " + arg + " at index " + index - + " Supported types: null, byte[], float, double, long, int, short, byte," - + " string"); - } - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteDatabase.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteDatabase.java deleted file mode 100644 index 54b4abda75702e05f11ef4e68f48215bef585693..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteDatabase.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -import net.sqlcipher.SQLException; -import ohos.data.rdb.RdbStore; -import ohos.data.rdb.TransactionObserver; - -import ohos.data.rdb.ValuesBucket; -import ohos.data.resultset.ResultSet; -import ohos.utils.Pair; - -import java.io.Closeable; -import java.util.List; -import java.util.Locale; - - -@SuppressWarnings("unused") -public interface SupportSQLiteDatabase extends Closeable { - /** - * Compiles the given SQL statement. - * - * @param sql The sql query. - * @return Compiled statement. - */ - SupportSQLiteStatement compileStatement(String sql); - - /** - * Begins a transaction in EXCLUSIVE mode. - *

- * Transactions can be nested. - * When the outer transaction is ended all of - * the work done in that transaction and all of the nested transactions will be committed or - * rolled back. The changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. - *

- *

Here is the standard idiom for transactions: - * - *

-     *   db.beginTransaction();
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- */ - void beginTransaction(); - - /** - * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When - * the outer transaction is ended all of the work done in that transaction - * and all of the nested transactions will be committed or rolled back. The - * changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they - * will be committed. - *

- * Here is the standard idiom for transactions: - * - *

-     *   db.beginTransactionNonExclusive();
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- */ - void beginTransactionNonExclusive(); - - /** - * Begins a transaction in EXCLUSIVE mode. - *

- * Transactions can be nested. - * When the outer transaction is ended all of - * the work done in that transaction and all of the nested transactions will be committed or - * rolled back. The changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. - *

- *

Here is the standard idiom for transactions: - * - *

-     *   db.beginTransactionWithListener(listener);
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- * - * @param transactionListener listener that should be notified when the transaction begins, - * commits, or is rolled back, either explicitly or by a call to - * {@link #yieldIfContendedSafely}. - */ - void beginTransactionWithListener(TransactionObserver transactionListener); - - /** - * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When - * the outer transaction is ended all of the work done in that transaction - * and all of the nested transactions will be committed or rolled back. The - * changes will be rolled back if any transaction is ended without being - * marked as clean (by calling setTransactionSuccessful). Otherwise they - * will be committed. - *

- * Here is the standard idiom for transactions: - * - *

-     *   db.beginTransactionWithListenerNonExclusive(listener);
-     *   try {
-     *     ...
-     *     db.setTransactionSuccessful();
-     *   } finally {
-     *     db.endTransaction();
-     *   }
-     * 
- * - * @param transactionListener listener that should be notified when the - * transaction begins, commits, or is rolled back, either - * explicitly or by a call to {@link #yieldIfContendedSafely}. - */ - void beginTransactionWithListenerNonExclusive(TransactionObserver transactionListener); - - /** - * End a transaction. See beginTransaction for notes about how to use this and when transactions - * are committed and rolled back. - */ - void endTransaction(); - - /** - * Marks the current transaction as successful. Do not do any more database work between - * calling this and calling endTransaction. Do as little non-database work as possible in that - * situation too. If any errors are encountered between this and endTransaction the transaction - * will still be committed. - * - * @throws IllegalStateException if the current thread is not in a transaction or the - * transaction is already marked as successful. - */ - void setTransactionSuccessful(); - - /** - * Returns true if the current thread has a transaction pending. - * - * @return True if the current thread is in a transaction. - */ - boolean inTransaction(); - - /** - * Returns true if the current thread is holding an active connection to the database. - *

- * The name of this method comes from a time when having an active connection - * to the database meant that the thread was holding an actual lock on the - * database. Nowadays, there is no longer a true "database lock" although threads - * may block if they cannot acquire a database connection to perform a - * particular operation. - *

- * - * @return True if the current thread is holding an active connection to the database. - */ - boolean isDbLockedByCurrentThread(); - - /** - * Temporarily end the transaction to let other threads run. The transaction is assumed to be - * successful so far. Do not call setTransactionSuccessful before calling this. When this - * returns a new transaction will have been created but not marked as successful. This assumes - * that there are no nested transactions (beginTransaction has only been called once) and will - * throw an exception if that is not the case. - * - * @return true if the transaction was yielded - */ - boolean yieldIfContendedSafely(); - - /** - * Temporarily end the transaction to let other threads run. The transaction is assumed to be - * successful so far. Do not call setTransactionSuccessful before calling this. When this - * returns a new transaction will have been created but not marked as successful. This assumes - * that there are no nested transactions (beginTransaction has only been called once) and will - * throw an exception if that is not the case. - * - * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if - * the lock was actually yielded. This will allow other background - * threads to make some - * more progress than they would if we started the transaction - * immediately. - * @return true if the transaction was yielded - */ - boolean yieldIfContendedSafely(long sleepAfterYieldDelay); - - /** - * Gets the database version. - * - * @return the database version - */ - int getVersion(); - - /** - * Sets the database version. - * - * @param version the new database version - */ - void setVersion(int version); - - /** - * Returns the maximum size the database may grow to. - * - * @return the new maximum database size - */ - long getMaximumSize(); - - /** - * Sets the maximum size the database will grow to. The maximum size cannot - * be set below the current size. - * - * @param numBytes the maximum database size, in bytes - * @return the new maximum database size - */ - long setMaximumSize(long numBytes); - - /** - * Returns the current database page size, in bytes. - * - * @return the database page size, in bytes - */ - long getPageSize(); - - /** - * Sets the database page size. The page size must be a power of two. This - * method does not work if any data has been written to the database file, - * and must be called right after the database has been created. - * - * @param numBytes the database page size, in bytes - */ - void setPageSize(long numBytes); - - /** - * Runs the given query on the database. If you would like to have typed bind arguments, - * use {@link #query(SupportSQLiteQuery)}. - * - * @param query The SQL query that includes the query and can bind into a given compiled - * program. - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * @see #query(SupportSQLiteQuery) - */ - ResultSet query(String query); - - /** - * Runs the given query on the database. If you would like to have bind arguments, - * use {@link #query(SupportSQLiteQuery)}. - * - * @param query The SQL query that includes the query and can bind into a given compiled - * program. - * @param bindArgs The query arguments to bind. - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * @see #query(SupportSQLiteQuery) - */ - ResultSet query(String query, Object[] bindArgs); - - /** - * Runs the given query on the database. - *

- * This class allows using type safe sql program bindings while running queries. - * - * @param query The SQL query that includes the query and can bind into a given compiled - * program. - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - * @see SimpleSQLiteQuery - */ - ResultSet query(SupportSQLiteQuery query); - - /** - * Runs the given query on the database. - *

- * This class allows using type safe sql program bindings while running queries. - * - * @param query The SQL query that includes the query and can bind into a given compiled - * program. - * @param cancellationSignal A signal to cancel the operation in progress, or null if none. - * If the operation is canceled, then {@link OperationCanceledException} will be thrown - * when the query is executed. - * @return A {@link ResultSet} object, which is positioned before the first entry. Note that - * {@link ResultSet}s are not synchronized, see the documentation for more details. - */ - /* @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) - ResultSet query(SupportSQLiteQuery query*//*, CancellationSignal cancellationSignal*//*);*/ - - /** - * Convenience method for inserting a row into the database. - * - * @param table the table to insert the row into - * @param values this map contains the initial column values for the - * row. The keys should be the column names and the values the - * column values - * @param conflictAlgorithm for insert conflict resolver. One of - * {@link RdbStore.ConflictResolution#ON_CONFLICT_NONE}, {@link RdbStore.ConflictResolution#ON_CONFLICT_ROLLBACK}, - * {@link RdbStore.ConflictResolution#ON_CONFLICT_ABORT}, {@link RdbStore.ConflictResolution#ON_CONFLICT_FAIL}, - * {@link RdbStore.ConflictResolution#ON_CONFLICT_IGNORE}, {@link RdbStore.ConflictResolution#ON_CONFLICT_REPLACE}. - * @return the row ID of the newly inserted row, or -1 if an error occurred - * @throws SQLException If the insert fails - */ - long insert(String table, int conflictAlgorithm, ValuesBucket values) throws SQLException; - - /** - * Convenience method for deleting rows in the database. - * - * @param table the table to delete from - * @param whereClause the optional WHERE clause to apply when deleting. - * Passing null will delete all rows. - * @param whereArgs You may include ?s in the where clause, which - * will be replaced by the values from whereArgs. The values - * will be bound as Strings. - * @return the number of rows affected if a whereClause is passed in, 0 - * otherwise. To remove all rows and get a count pass "1" as the - * whereClause. - */ - int delete(String table, String whereClause, Object[] whereArgs); - - /** - * Convenience method for updating rows in the database. - * - * @param table the table to update in - * @param conflictAlgorithm for update conflict resolver. One of - * {@link RdbStore.ConflictResolution#ON_CONFLICT_NONE}, {@link RdbStore.ConflictResolution#ON_CONFLICT_ROLLBACK}, - * {@link RdbStore.ConflictResolution#ON_CONFLICT_ABORT}, {@link RdbStore.ConflictResolution#ON_CONFLICT_FAIL}, - * {@link RdbStore.ConflictResolution#ON_CONFLICT_IGNORE}, {@link RdbStore.ConflictResolution#ON_CONFLICT_REPLACE}. - * @param values a map from column names to new column values. null is a - * valid value that will be translated to NULL. - * @param whereClause the optional WHERE clause to apply when updating. - * Passing null will update all rows. - * @param whereArgs You may include ?s in the where clause, which - * will be replaced by the values from whereArgs. The values - * will be bound as Strings. - * @return the number of rows affected - */ - int update(String table, int conflictAlgorithm, - ValuesBucket values, String whereClause, Object[] whereArgs); - - /** - * Execute a single SQL statement that does not return any data. - *

- * When using {@link #enableWriteAheadLogging()}, journal_mode is - * automatically managed by this class. So, do not set journal_mode - * using "PRAGMA journal_mode'" statement if your app is using - * {@link #enableWriteAheadLogging()} - *

- * - * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are - * not supported. - * @throws SQLException if the SQL string is invalid - * @see #query(SupportSQLiteQuery) - */ - void execSQL(String sql) throws SQLException; - - /** - * Execute a single SQL statement that does not return any data. - *

- * When using {@link #enableWriteAheadLogging()}, journal_mode is - * automatically managed by this class. So, do not set journal_mode - * using "PRAGMA journal_mode'" statement if your app is using - * {@link #enableWriteAheadLogging()} - *

- * - * @param sql the SQL statement to be executed. Multiple statements separated by semicolons - * are - * not supported. - * @param bindArgs only byte[], String, Long and Double are supported in selectionArgs. - * @throws SQLException if the SQL string is invalid - * @see #query(SupportSQLiteQuery) - */ - void execSQL(String sql, Object[] bindArgs) throws SQLException; - - /** - * Returns true if the database is opened as read only. - * - * @return True if database is opened as read only. - */ - boolean isReadOnly(); - - /** - * Returns true if the database is currently open. - * - * @return True if the database is currently open (has not been closed). - */ - boolean isOpen(); - - /** - * Returns true if the new version code is greater than the current database version. - * - * @param newVersion The new version code. - * @return True if the new version code is greater than the current database version. - */ - boolean needUpgrade(int newVersion); - - /** - * Gets the path to the database file. - * - * @return The path to the database file. - */ - String getPath(); - - /** - * Sets the locale for this database. Does nothing if this database has - * the {@link SQLiteDatabase#NO_LOCALIZED_COLLATORS} flag set or was opened read only. - * - * @param locale The new locale. - * @throws SQLException if the locale could not be set. The most common reason - * for this is that there is no collator available for the locale you - * requested. - * In this case the database remains unchanged. - */ - void setLocale(Locale locale); - - /** - * Sets the maximum size of the prepared-statement cache for this database. - * (size of the cache = number of compiled-sql-statements stored in the cache). - *

- * Maximum cache size can ONLY be increased from its current size (default = 10). - * If this method is called with smaller size than the current maximum value, - * then IllegalStateException is thrown. - *

- * This method is thread-safe. - * - * @param cacheSize the size of the cache. can be (0 to - * {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}) - * @throws IllegalStateException if input cacheSize gt; - * {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}. - */ - void setMaxSqlCacheSize(int cacheSize); - - /** - * Sets whether foreign key constraints are enabled for the database. - *

- * By default, foreign key constraints are not enforced by the database. - * This method allows an application to enable foreign key constraints. - * It must be called each time the database is opened to ensure that foreign - * key constraints are enabled for the session. - *

- * A good time to call this method is right after calling {@code #openOrCreateDatabase} - * or in the {@link SupportSQLiteOpenHelper.Callback#onConfigure} callback. - *

- * When foreign key constraints are disabled, the database does not check whether - * changes to the database will violate foreign key constraints. Likewise, when - * foreign key constraints are disabled, the database will not execute cascade - * delete or update triggers. As a result, it is possible for the database - * state to become inconsistent. To perform a database integrity check, - * call {@link #isDatabaseIntegrityOk}. - *

- * This method must not be called while a transaction is in progress. - *

- * See also SQLite Foreign Key Constraints - * for more details about foreign key constraint support. - *

- * - * @param enable True to enable foreign key constraints, false to disable them. - * @throws IllegalStateException if the are transactions is in progress - * when this method is called. - */ - // @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) - void setForeignKeyConstraintsEnabled(boolean enable); - - /** - * This method enables parallel execution of queries from multiple threads on the - * same database. It does this by opening multiple connections to the database - * and using a different database connection for each query. The database - * journal mode is also changed to enable writes to proceed concurrently with reads. - *

- * When write-ahead logging is not enabled (the default), it is not possible for - * reads and writes to occur on the database at the same time. Before modifying the - * database, the writer implicitly acquires an exclusive lock on the database which - * prevents readers from accessing the database until the write is completed. - *

- * In contrast, when write-ahead logging is enabled (by calling this method), write - * operations occur in a separate log file which allows reads to proceed concurrently. - * While a write is in progress, readers on other threads will perceive the state - * of the database as it was before the write began. When the write completes, readers - * on other threads will then perceive the new state of the database. - *

- * It is a good idea to enable write-ahead logging whenever a database will be - * concurrently accessed and modified by multiple threads at the same time. - * However, write-ahead logging uses significantly more memory than ordinary - * journaling because there are multiple connections to the same database. - * So if a database will only be used by a single thread, or if optimizing - * concurrency is not very important, then write-ahead logging should be disabled. - *

- * After calling this method, execution of queries in parallel is enabled as long as - * the database remains open. To disable execution of queries in parallel, either - * call {@link #disableWriteAheadLogging} or close the database and reopen it. - *

- * The maximum number of connections used to execute queries in parallel is - * dependent upon the device memory and possibly other properties. - *

- * If a query is part of a transaction, then it is executed on the same database handle the - * transaction was begun. - *

- * Writers should use {@link #beginTransactionNonExclusive()} or - * {@link #beginTransactionWithListenerNonExclusive(TransactionObserver)} - * to start a transaction. Non-exclusive mode allows database file to be in readable - * by other threads executing queries. - *

- * If the database has any attached databases, then execution of queries in parallel is NOT - * possible. Likewise, write-ahead logging is not supported for read-only databases - * or memory databases. In such cases, {@code enableWriteAheadLogging} returns false. - *

- * The best way to enable write-ahead logging is to pass the - * {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag to - * {@link SQLiteDatabase#openDatabase}. This is more efficient than calling - *

-     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
-     *             SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
-     *             myDatabaseErrorHandler);
-     *     db.enableWriteAheadLogging();
-     * 
- *

- * Another way to enable write-ahead logging is to call {@code enableWriteAheadLogging} - * after opening the database. - *

-     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
-     *             SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
-     *     db.enableWriteAheadLogging();
-     * 
- *

- * See also SQLite Write-Ahead Logging for - * more details about how write-ahead logging works. - *

- * - * @return True if write-ahead logging is enabled. - * @throws IllegalStateException if there are transactions in progress at the - * time this method is called. WAL mode can only be changed when - * there are no - * transactions in progress. - * @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING - * @see #disableWriteAheadLogging - */ - boolean enableWriteAheadLogging(); - - /** - * This method disables the features enabled by {@link #enableWriteAheadLogging()}. - * - * @throws IllegalStateException if there are transactions in progress at the - * time this method is called. WAL mode can only be changed when - * there are no - * transactions in progress. - * @see #enableWriteAheadLogging - */ - //@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) - void disableWriteAheadLogging(); - - /** - * Returns true if write-ahead logging has been enabled for this database. - * - * @return True if write-ahead logging has been enabled for this database. - * @see #enableWriteAheadLogging - * @see RdbStore.ConflictResolution#ENABLE_WRITE_AHEAD_LOGGING - */ - //@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) - boolean isWriteAheadLoggingEnabled(); - - /** - * Returns list of full path names of all attached databases including the main database - * by executing 'pragma database_list' on the database. - * - * @return ArrayList of pairs of (database name, database file path) or null if the database - * is not open. - */ - List> getAttachedDbs(); - - /** - * Runs 'pragma integrity_check' on the given database (and all the attached databases) - * and returns true if the given database (and all its attached databases) pass integrity_check, - * false otherwise. - *

- * If the result is false, then this method logs the errors reported by the integrity_check - * command execution. - *

- * Note that 'pragma integrity_check' on a database can take a long time. - * - * @return true if the given database (and all its attached databases) pass integrity_check, - * false otherwise. - */ - boolean isDatabaseIntegrityOk(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteOpenHelper.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteOpenHelper.java deleted file mode 100644 index ab949db9b6beaecb18966bbadeeed4967bd53359..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteOpenHelper.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -import ohos.data.DatabaseHelper; -import net.sqlcipher.database.SQLiteException; -import ohos.hiviewdfx.HiLog; -import ohos.hiviewdfx.HiLogLabel; -import ohos.utils.Pair; -import ohos.app.Context; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -/** - * An interface to map the behavior of {@link net.sqlcipher.sqlite.SQLiteOpenHelper}. - * Note that since that class requires overriding certain methods, support implementation - * uses {@link Factory#create(Configuration)} to create this and {@link Callback} to implement - * the methods that should be overridden. - */ -@SuppressWarnings("unused") -public interface SupportSQLiteOpenHelper { - /** - * Return the name of the SQLite database being opened, as given to - * the constructor. - * @return string - */ - String getDatabaseName(); - static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00202, "SupportSQLiteOpenHelper"); - - /** - * Enables or disables the use of write-ahead logging for the database. - * - * Write-ahead logging cannot be used with read-only databases so the value of - * this flag is ignored if the database is opened read-only. - * - * @param enabled True if write-ahead logging should be enabled, false if it - * should be disabled. - * @see SupportSQLiteDatabase#enableWriteAheadLogging() - */ - /* @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)*/ - void setWriteAheadLoggingEnabled(boolean enabled); - - /** - * Create and/or open a database that will be used for reading and writing. - * The first time this is called, the database will be opened and - * {@link Callback#onCreate}, {@link Callback#onUpgrade} and/or {@link Callback#onOpen} will be - * called. - * - *

Once opened successfully, the database is cached, so you can - * call this method every time you need to write to the database. - * (Make sure to call {@link #close} when you no longer need the database.) - * Errors such as bad permissions or a full disk may cause this method - * to fail, but future attempts may succeed if the problem is fixed.

- * - *

Database upgrade may take a long time, you - * should not call this method from the application main thread, including - * from {@link ContentProvider#onCreate ContentProvider.onCreate()}. - * - * @return a read/write database object valid until {@link #close} is called - * @throws SQLiteException if the database cannot be opened for writing - */ - SupportSQLiteDatabase getWritableDatabase(); - - /** - * Create and/or open a database. This will be the same object returned by - * {@link #getWritableDatabase} unless some problem, such as a full disk, - * requires the database to be opened read-only. In that case, a read-only - * database object will be returned. If the problem is fixed, a future call - * to {@link #getWritableDatabase} may succeed, in which case the read-only - * database object will be closed and the read/write object will be returned - * in the future. - * - *

Like {@link #getWritableDatabase}, this method may - * take a long time to return, so you should not call it from the - * application main thread, including from - * {@link ContentProvider#onCreate ContentProvider.onCreate()}. - * - * @return a database object valid until {@link #getWritableDatabase} - * or {@link #close} is called. - * @throws SQLiteException if the database cannot be opened - */ - SupportSQLiteDatabase getReadableDatabase(); - - /** - * Close any open database object. - */ - void close(); - - /** - * Handles various lifecycle events for the SQLite connection, similar to - * {@link net.sqlcipher.sqlite.SQLiteOpenHelper}. - */ - @SuppressWarnings({"unused", "WeakerAccess"}) - abstract class Callback { - private static final String TAG = "SupportSQLite"; - /** - * Version number of the database (starting at 1); if the database is older, - * {@link Callback#onUpgrade(SupportSQLiteDatabase, int, int)} - * will be used to upgrade the database; if the database is newer, - * {@link Callback#onDowngrade(SupportSQLiteDatabase, int, int)} - * will be used to downgrade the database. - */ - public final int version; - - /** - * Creates a new Callback to get database lifecycle events. - * @param version The version for the database instance. See {@link #version}. - */ - public Callback(int version) { - this.version = version; - } - - /** - * Called when the database connection is being configured, to enable features such as - * write-ahead logging or foreign key support. - *

- * This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade}, - * or {@link #onOpen} are called. It should not modify the database except to configure the - * database connection as required. - *

- *

- * This method should only call methods that configure the parameters of the database - * connection, such as {@link SupportSQLiteDatabase#enableWriteAheadLogging} - * {@link SupportSQLiteDatabase#setForeignKeyConstraintsEnabled}, - * {@link SupportSQLiteDatabase#setLocale}, - * {@link SupportSQLiteDatabase#setMaximumSize}, or executing PRAGMA statements. - *

- * - * @param db The database. - */ - public void onConfigure(SupportSQLiteDatabase db) { - - } - - /** - * Called when the database is created for the first time. This is where the - * creation of tables and the initial population of the tables should happen. - * - * @param db The database. - */ - public abstract void onCreate(SupportSQLiteDatabase db); - - /** - * Called when the database needs to be upgraded. The implementation - * should use this method to drop tables, add tables, or do anything else it - * needs to upgrade to the new schema version. - * - *

- * The SQLite ALTER TABLE documentation can be found - * here. If you add new columns - * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns - * you can use ALTER TABLE to rename the old table, then create the new table and then - * populate the new table with the contents of the old table. - *

- * This method executes within a transaction. If an exception is thrown, all changes - * will automatically be rolled back. - *

- * - * @param db The database. - * @param oldVersion The old database version. - * @param newVersion The new database version. - */ - public abstract void onUpgrade(SupportSQLiteDatabase db, int oldVersion, int newVersion); - - /** - * Called when the database needs to be downgraded. This is strictly similar to - * {@link #onUpgrade} method, but is called whenever current version is newer than requested - * one. - * However, this method is not abstract, so it is not mandatory for a customer to - * implement it. If not overridden, default implementation will reject downgrade and - * throws SQLiteException - * - *

- * This method executes within a transaction. If an exception is thrown, all changes - * will automatically be rolled back. - *

- * - * @param db The database. - * @param oldVersion The old database version. - * @param newVersion The new database version. - */ - public void onDowngrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) { - throw new SQLiteException("Can't downgrade database from version " - + oldVersion + " to " + newVersion); - } - - /** - * Called when the database has been opened. The implementation - * should check {@link SupportSQLiteDatabase#isReadOnly} before updating the - * database. - *

- * This method is called after the database connection has been configured - * and after the database schema has been created, upgraded or downgraded as necessary. - * If the database connection must be configured in some way before the schema - * is created, upgraded, or downgraded, do it in {@link #onConfigure} instead. - *

- * - * @param db The database. - */ - public void onOpen(SupportSQLiteDatabase db) { - - } - - /** - * The method invoked when database corruption is detected. Default implementation will - * delete the database file. - * - * @param db the {@link SupportSQLiteDatabase} object representing the database on which - * corruption is detected. - */ - public void onCorruption(SupportSQLiteDatabase db) { - // the following implementation is taken from {@link DefaultDatabaseErrorHandler}. - - HiLog.error(label, "Corruption reported by sqlite on database: %{default}s", db.getPath()); - // is the corruption detected even before database could be 'opened'? - if (!db.isOpen()) { - // database files are not even openable. delete this database file. - // NOTE if the database has attached databases, then any of them could be corrupt. - // and not deleting all of them could cause corrupted database file to remain and - // make the application crash on database open operation. To avoid this problem, - // the application should provide its own {@link DatabaseErrorHandler} impl class - // to delete ALL files of the database (including the attached databases). - deleteDatabaseFile(db.getPath()); - return; - } - - List> attachedDbs = null; - try { - // Close the database, which will cause subsequent operations to fail. - // before that, get the attached database list first. - try { - attachedDbs = db.getAttachedDbs(); - } catch (SQLiteException e) { - /* ignore */ - } - try { - db.close(); - } catch (IOException e) { - /* ignore */ - } - } finally { - // Delete all files of this corrupt database and/or attached databases - if (attachedDbs != null) { - for (Pair p : attachedDbs) { - deleteDatabaseFile(p.s); - } - } else { - // attachedDbs = null is possible when the database is so corrupt that even - // "PRAGMA database_list;" also fails. delete the main database file - deleteDatabaseFile(db.getPath()); - } - } - } - - private void deleteDatabaseFile(String fileName) { - if (fileName.equalsIgnoreCase(":memory:") || fileName.trim().length() == 0) { - return; - } - HiLog.warn(label, "deleting the database file: %{private}s",fileName); - try { - /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - DatabaseHelper databaseHelper = new DatabaseHelper(); - databaseHelper.deleteRdbStore(fileName); //TODO build - } else {*/ - try { - final boolean deleted = new File(fileName).delete(); - if (!deleted) { - HiLog.error(label, "Could not delete the database file %{private}s",fileName); - } - } catch (Exception error) { - HiLog.error(label, "error while deleting corrupted database file %{private}s", error); - } - // } - } catch (Exception e) { - /* print warning and ignore exception */ - HiLog.warn(label, "delete failed: ", e); - } - } - } - - /** - * The configuration to create an SQLite open helper object using {@link Factory}. - */ - @SuppressWarnings("WeakerAccess") - class Configuration { - /** - * Context to use to open or create the database. - */ - public final Context context; - /** - * Name of the database file, or null for an in-memory database. - */ - public final String name; - /** - * The callback class to handle creation, upgrade and downgrade. - */ - public final Callback callback; - - Configuration(Context context, String name, Callback callback) { - this.context = context; - this.name = name; - this.callback = callback; - } - - /** - * Creates a new Configuration.Builder to create an instance of Configuration. - * - * @param context to use to open or create the database. - * @return builder - */ - public static Builder builder(Context context) { - return new Builder(context); - } - - /** - * Builder class for {@link Configuration}. - */ - public static class Builder { - Context mContext; - String mName; - Callback mCallback; - - public Configuration build() { - if (mCallback == null) { - throw new IllegalArgumentException("Must set a callback to create the" - + " configuration."); - } - if (mContext == null) { - throw new IllegalArgumentException("Must set a non-null context to create" - + " the configuration."); - } - return new Configuration(mContext, mName, mCallback); - } - - Builder(Context context) { - mContext = context; - } - - /** - * Returns the builder for given name - * @param name Name of the database file, or null for an in-memory database. - * @return This - */ - public Builder name(String name) { - mName = name; - return this; - } - - /** - * Returns the builder for given callback - * @param callback The callback class to handle creation, upgrade and downgrade. - * @return this - */ - public Builder callback(Callback callback) { - mCallback = callback; - return this; - } - } - } - - /** - * Factory class to create instances of {@link SupportSQLiteOpenHelper} using - * {@link Configuration}. - */ - interface Factory { - /** - * Creates an instance of {@link SupportSQLiteOpenHelper} using the given configuration. - * - * @param configuration The configuration to use while creating the open helper. - * - * @return A SupportSQLiteOpenHelper which can be used to open a database. - */ - SupportSQLiteOpenHelper create(Configuration configuration); - } -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteProgram.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteProgram.java deleted file mode 100644 index 24fb6161577cade8ce71a116d005a577f4b5fd1e..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteProgram.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -import java.io.Closeable; - -@SuppressWarnings("unused") -public interface SupportSQLiteProgram extends Closeable { - /** - * Bind a NULL value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind null to - */ - void bindNull(int index); - - /** - * Bind a long value to this statement. The value remains bound until - * {@link #clearBindings} is called. - *addToBindArgs - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - void bindLong(int index, long value); - - /** - * Bind a double value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind - */ - void bindDouble(int index, double value); - - /** - * Bind a String value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind, must not be null - */ - void bindString(int index, String value); - - /** - * Bind a byte array value to this statement. The value remains bound until - * {@link #clearBindings} is called. - * - * @param index The 1-based index to the parameter to bind - * @param value The value to bind, must not be null - */ - void bindBlob(int index, byte[] value); - - /** - * Clears all existing bindings. Unset bindings are treated as NULL. - */ - void clearBindings(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQuery.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQuery.java deleted file mode 100644 index 0d7ab0ac81f590f5b8e7b62a9bd1009eed7f2445..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQuery.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -public interface SupportSQLiteQuery { - /** - * The SQL query. This query can have placeholders(?) for bind arguments. - * - * @return The SQL query to compile - */ - String getSql(); - - /** - * Callback to bind the query parameters to the compiled statement. - * - * @param statement The compiled statement - */ - void bindTo(SupportSQLiteProgram statement); - - /** - * Returns the number of arguments in this query. This is equal to the number of placeholders - * in the query string. See: https://www.sqlite.org/c3ref/bind_blob.html for details. - * - * @return The number of arguments in the query. - */ - int getArgCount(); -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQueryBuilder.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQueryBuilder.java deleted file mode 100644 index 0ff03b36e1b87ea56f5526127e75fac89506b1d6..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteQueryBuilder.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -import java.util.regex.Pattern; - -/** - * A simple query builder to create SQL SELECT queries. - */ -@SuppressWarnings("unused") -public final class SupportSQLiteQueryBuilder { - private static final Pattern sLimitPattern = - Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?"); - - private boolean mDistinct = false; - private final String mTable; - private String[] mColumns = null; - private String mSelection; - private Object[] mBindArgs; - private String mGroupBy = null; - private String mHaving = null; - private String mOrderBy = null; - private String mLimit = null; - - /** - * Creates a query for the given table name. - * - * @param tableName The table name(s) to query. - * - * @return A builder to create a query. - */ - public static SupportSQLiteQueryBuilder builder(String tableName) { - return new SupportSQLiteQueryBuilder(tableName); - } - - private SupportSQLiteQueryBuilder(String table) { - mTable = table; - } - - /** - * Adds DISTINCT keyword to the query. - * - * @return this - */ - public SupportSQLiteQueryBuilder distinct() { - mDistinct = true; - return this; - } - - /** - * Sets the given list of columns as the columns that will be returned. - * - * @param columns The list of column names that should be returned. - * - * @return this - */ - public SupportSQLiteQueryBuilder columns(String[] columns) { - mColumns = columns; - return this; - } - - /** - * Sets the arguments for the WHERE clause. - * - * @param selection The list of selection columns - * @param bindArgs The list of bind arguments to match against these columns - * - * @return this - */ - public SupportSQLiteQueryBuilder selection(String selection, Object[] bindArgs) { - mSelection = selection; - mBindArgs = bindArgs; - return this; - } - - /** - * Adds a GROUP BY statement. - * - * @param groupBy The value of the GROUP BY statement. - * - * @return this - */ - @SuppressWarnings("WeakerAccess") - public SupportSQLiteQueryBuilder groupBy(String groupBy) { - mGroupBy = groupBy; - return this; - } - - /** - * Adds a HAVING statement. You must also provide {@link #groupBy(String)} for this to work. - * - * @param having The having clause. - * - * @return this - */ - public SupportSQLiteQueryBuilder having(String having) { - mHaving = having; - return this; - } - - /** - * Adds an ORDER BY statement. - * - * @param orderBy The order clause. - * - * @return this - */ - public SupportSQLiteQueryBuilder orderBy(String orderBy) { - mOrderBy = orderBy; - return this; - } - - /** - * Adds a LIMIT statement. - * - * @param limit The limit value. - * - * @return this - */ - public SupportSQLiteQueryBuilder limit(String limit) { - if (!isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) { - throw new IllegalArgumentException("invalid LIMIT clauses:" + limit); - } - mLimit = limit; - return this; - } - - /** - * Creates the {@link SupportSQLiteQuery} that can be passed into - * {@link SupportSQLiteDatabase#query(SupportSQLiteQuery)}. - * - * @return a new query - */ - public SupportSQLiteQuery create() { - if (isEmpty(mGroupBy) && !isEmpty(mHaving)) { - throw new IllegalArgumentException( - "HAVING clauses are only permitted when using a groupBy clause"); - } - StringBuilder query = new StringBuilder(120); - - query.append("SELECT "); - if (mDistinct) { - query.append("DISTINCT "); - } - if (mColumns != null && mColumns.length != 0) { - appendColumns(query, mColumns); - } else { - query.append(" * "); - } - query.append(" FROM "); - query.append(mTable); - appendClause(query, " WHERE ", mSelection); - appendClause(query, " GROUP BY ", mGroupBy); - appendClause(query, " HAVING ", mHaving); - appendClause(query, " ORDER BY ", mOrderBy); - appendClause(query, " LIMIT ", mLimit); - - return new SimpleSQLiteQuery(query.toString(), mBindArgs); - } - - private static void appendClause(StringBuilder s, String name, String clause) { - if (!isEmpty(clause)) { - s.append(name); - s.append(clause); - } - } - - /** - * Add the names that are non-null in columns to s, separating - * them with commas. - * @param s sting builder - * @param columns columns - */ - private static void appendColumns(StringBuilder s, String[] columns) { - int n = columns.length; - - for (int i = 0; i < n; i++) { - String column = columns[i]; - if (i > 0) { - s.append(", "); - } - s.append(column); - } - s.append(' '); - } - - private static boolean isEmpty(String input) { - return input == null || input.length() == 0; - } -} - diff --git a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteStatement.java b/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteStatement.java deleted file mode 100644 index 4c1b543e03fe34e4ef7ea7ec50b53e893479d57e..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/harmonyx/SupportSQLiteStatement.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.harmonyx; - -@SuppressWarnings("unused") -public interface SupportSQLiteStatement extends SupportSQLiteProgram { - /** - * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example - * CREATE / DROP table, view, trigger, index etc. - * - * @throws net.sqlcipher.SQLException If the SQL string is invalid for - * some reason - */ - void execute(); - - /** - * Execute this SQL statement, if the the number of rows affected by execution of this SQL - * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements. - * - * @return the number of rows affected by this SQL statement execution. - * @throws net.sqlcipher.SQLException If the SQL string is invalid for - * some reason - */ - int executeUpdateDelete(); - - /** - * Execute this SQL statement and return the ID of the row inserted due to this call. - * The SQL statement should be an INSERT for this to be a useful call. - * - * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. - * - * @throws net.sqlcipher.SQLException If the SQL string is invalid for - * some reason - */ - long executeInsert(); - - /** - * Execute a statement that returns a 1 by 1 table with a numeric value. - * For example, SELECT COUNT(*) FROM table; - * - * @return The result of the query. - * - * @throws net.sqlcipher.sqlite.SQLiteDoneException if the query returns zero rows - */ - long simpleQueryForLong(); - /** - * Execute a statement that returns a 1 by 1 table with a text value. - * For example, SELECT COUNT(*) FROM table; - * - * @return The result of the query. - * - * @throws net.sqlcipher.sqlite.SQLiteDoneException if the query returns zero rows - */ - String simpleQueryForString(); -} diff --git a/sqlcipher/src/main/java/net/sqlcipher/utils/TextUtils.java b/sqlcipher/src/main/java/net/sqlcipher/utils/TextUtils.java deleted file mode 100644 index a3d39152d9166239bcd18da9824d32e5626446ba..0000000000000000000000000000000000000000 --- a/sqlcipher/src/main/java/net/sqlcipher/utils/TextUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.sqlcipher.utils; - -public class TextUtils { - public static boolean isEmpty(CharSequence str) { - return str == null || str.length() == 0; - } -}