public void onOpen(ISQLiteDatabase db) { setDatabase(db); SquidDatabase.this.onOpen(db); } }
Table[] tables = getTables(); if (tables != null) { for (Table table : tables) { table.appendCreateTableSql(getCompileContext(), sql, sqlVisitor); db.execSQL(sql.toString()); sql.setLength(0); View[] views = getViews(); if (views != null) { for (View view : views) { view.createViewSql(getCompileContext(), sql); db.execSQL(sql.toString()); sql.setLength(0); Index[] indexes = getIndexes(); if (indexes != null) { for (Index idx : indexes) { tryCreateIndex(idx); SquidDatabase.this.onTablesCreated(db);
private String attachTo(SquidDatabase attachTo) { if (attachedTo != null) { throw new IllegalArgumentException( "Database " + getName() + " is already attached to " + attachedTo.getName()); } if (inTransaction()) { throw new IllegalStateException( "Cannot attach database " + getName() + " to " + attachTo.getName() + " -- " + getName() + " is in a transaction on the calling thread"); } acquireExclusiveLock(); String attachedAs = getAttachedName(); if (!attachTo.tryExecSql("ATTACH '" + getDatabasePath() + "' AS '" + attachedAs + "'")) { releaseExclusiveLock(); // Failed return null; } else { attachedTo = attachTo; return attachedAs; } }
/** * Copies the database file and any supporting journal or WAL files needed to open the DB to the given directory. * This method acquires the exclusive lock on the database before copying, which will prevent any other threads * from reading or writing to the database while the copying is in progress. If this method is called from within * a transaction, an exception will be thrown. This method is intended for debugging purposes only. * * @param toDir the directory to copy the database files to * @return true if copying the database files succeeded, false otherwise */ public boolean copyDatabase(File toDir) { acquireExclusiveLock(); try { return copyDatabaseLocked(toDir); } finally { releaseExclusiveLock(); } }
/** * Clear all data in the database. This method acquires the exclusive lock before closing the db -- it will block * if other threads are in transactions. This method will throw an exception if called from within a transaction. * <p> * It is not safe to call this method from within any of the database open or migration hooks (e.g. * {@link #onUpgrade(ISQLiteDatabase, int, int)}, {@link #onOpen(ISQLiteDatabase)}, * {@link #onMigrationFailed(MigrationFailedException)}), etc. * <p> * WARNING: Any open database resources (e.g. cursors) will be invalid after calling this method. Do not call this * method if any open cursors may be in use. The existing database file will be deleted and all data will be lost. */ public final void clear() { acquireExclusiveLock(); try { closeAndDeleteLocked(); } finally { releaseExclusiveLock(); } }
/** * @return the current SQLite version as a {@link VersionCode} * @throws RuntimeException if the version could not be read */ public VersionCode getSqliteVersion() { VersionCode toReturn = sqliteVersion; if (toReturn == null) { acquireNonExclusiveLock(); try { synchronized (databaseInstanceLock) { getDatabase(); // Opening the database will populate the sqliteVersion field return sqliteVersion; } } finally { releaseNonExclusiveLock(); } } return toReturn; }
private void openForWritingLocked() { boolean areDataChangedNotificationsEnabled = areDataChangedNotificationsEnabled(); setDataChangedNotificationsEnabled(false); try { try { ISQLiteDatabase db = getOpenHelper().openForWriting(); setDatabase(db); } catch (RecreateDuringMigrationException recreate) { recreateLocked(); } catch (MigrationFailedException fail) { onError(fail.getMessage(), fail); isInMigrationFailedHook = true; try { if (!isOpen()) { closeLocked(); onMigrationFailed(fail); } finally { isInMigrationFailedHook = false; if (!isOpen()) { closeLocked(); throw new RuntimeException("Failed to open database"); onError("Failed to open database: " + getName(), e); closeLocked(); onDatabaseOpenFailed(e, retryCount);
/** * Execute a SQL {@link com.yahoo.squidb.sql.Insert} statement * * @return the row id of the last row inserted on success, -1 on failure */ private long insertInternal(Insert insert) { CompiledStatement compiled = insert.compile(getCompileContext()); acquireNonExclusiveLock(); try { return getDatabase().executeInsert(compiled.sql, compiled.sqlArgs); } finally { releaseNonExclusiveLock(); } }
/** * Execute a raw SQL statement * * @param sql the statement to execute * @return true if the statement executed without an error * @see ISQLiteDatabase#execSQL(String) */ public boolean tryExecSql(String sql) { acquireNonExclusiveLock(); try { getDatabase().execSQL(sql); return true; } catch (RuntimeException e) { onError("Failed to execute statement: " + sql, e); return false; } finally { releaseNonExclusiveLock(); } }
private void closeAndDeleteInternal(boolean deleteAfterClose) { clearPreparedStatementCache(); if (isOpen()) { onClose(database); database.close(); } setDatabase(null); if (deleteAfterClose) { getOpenHelper().deleteDatabase(); } helper = null; }
Table table = getTable(modelClass); acquireNonExclusiveLock(); try { PreparedInsertCache insertCache = preparedInsertCache.get(); newRow = preparedStatement.executeInsert(); } finally { releaseNonExclusiveLock(); newRow = insertRowLegacy(item, table, conflictAlgorithm); notifyForTable(DataChangedNotifier.DBOperation.INSERT, item, table, newRow); item.setRowId(newRow); item.markSaved();
throw new IllegalStateException("Can't attach a database to a database that is itself attached"); if (inTransaction()) { throw new IllegalStateException("Can't attach a database while in a transaction on the current thread"); acquireExclusiveLock(); try { return other.attachTo(this); } finally { releaseExclusiveLock();
/** * Close the database if it has been opened previously. This method acquires the exclusive lock before closing the * db -- it will block if other threads are in transactions. This method will throw an exception if called from * within a transaction. * <p> * It is not safe to call this method from within any of the database open or migration hooks (e.g. * {@link #onUpgrade(ISQLiteDatabase, int, int)}, {@link #onOpen(ISQLiteDatabase)}, * {@link #onMigrationFailed(MigrationFailedException)}), etc. * <p> * WARNING: Any open database resources (e.g. cursors) will be invalid after calling this method. Do not call this * method if any open cursors may be in use. */ public final void close() { acquireExclusiveLock(); try { closeLocked(); } finally { releaseExclusiveLock(); } }
/** * Clears the database and recreates an empty version of it. This method acquires the exclusive lock before closing * the db -- it will block if other threads are in transactions. This method will throw an exception if called from * within a transaction. * <p> * If called from within the {@link #onUpgrade(ISQLiteDatabase, int, int)} or * {@link #onDowngrade(ISQLiteDatabase, int, int)} hooks, this method will abort the remainder of the * migration and simply clear the database. This method is also safe to call from within * {@link #onMigrationFailed(MigrationFailedException)} * <p> * WARNING: Any open database resources (e.g. cursors) will be invalid after calling this method. Do not call this * method if any open cursors may be in use. The existing database file will be deleted and all data will be lost, * with a new empty database taking its place. * * @see #clear() */ public final void recreate() { if (isInMigration) { throw new RecreateDuringMigrationException(); } else if (isInMigrationFailedHook || databaseOpenFailedRetryCount > 0) { recreateLocked(); // Safe to call here, necessary locks are already held in this case } else { acquireExclusiveLock(); try { recreateLocked(); } finally { releaseExclusiveLock(); } } }
protected <TYPE extends AbstractModel> SquidCursor<TYPE> fetchFirstItem(Class<TYPE> modelClass, Query query) { boolean immutableQuery = query.isImmutable(); Field<Integer> beforeLimit = query.getLimit(); SqlTable<?> beforeTable = query.getTable(); query = query.limit(1); // If argument was frozen, we may get a new object SquidCursor<TYPE> cursor = query(modelClass, query); if (!immutableQuery) { query.from(beforeTable).limit(beforeLimit); // Reset for user } cursor.moveToFirst(); return cursor; }
/** * @return a CompileContext that this SquidDatabase should use when compiling SQL statements like {@link Query}, * {@link Insert}, {@link Update}, and {@link Delete}. If necessary, users can customize the returned * CompileContext object by overriding {@link #buildCompileContext(CompileContext.Builder)} to e.g. specify a * different implementation of {@link com.yahoo.squidb.sql.ArgumentResolver} to use. */ public final CompileContext getCompileContext() { CompileContext.Builder builder = new CompileContext.Builder(getSqliteVersion()); buildCompileContext(builder); return builder.build(); }
@Override protected void onTablesCreated(ISQLiteDatabase db) { super.onTablesCreated(db); }
private void closeAndDeleteLocked() { synchronized (databaseInstanceLock) { closeAndDeleteInternal(true); } }
private void openForWritingLocked() { boolean areDataChangedNotificationsEnabled = areDataChangedNotificationsEnabled(); setDataChangedNotificationsEnabled(false); try { try { ISQLiteDatabase db = getOpenHelper().openForWriting(); setDatabase(db); } catch (RecreateDuringMigrationException recreate) { recreateLocked(); } catch (MigrationFailedException fail) { onError(fail.getMessage(), fail); isInMigrationFailedHook = true; try { if (!isOpen()) { closeLocked(); onMigrationFailed(fail); } finally { isInMigrationFailedHook = false; if (!isOpen()) { closeLocked(); throw new RuntimeException("Failed to open database"); onError("Failed to open database: " + getName(), e); closeLocked(); onDatabaseOpenFailed(e, retryCount);
private void ensureSqlCompiles(String sql) { acquireNonExclusiveLock(); try { getDatabase().ensureSqlCompiles(sql); } finally { releaseNonExclusiveLock(); } }