android - tiene - otorgar privilegios a un usuario oracle
Intento escribir una base de datos de solo lectura... pero no estoy (1)
Resuelto al cambiarlo a una conexión de base de datos grabable. La clave estaba en la documentación del código de error 776 :
(776) SQLITE_READONLY_ROLLBACK
El código de error SQLITE_READONLY_ROLLBACK es un código de error extendido para SQLITE_READONLY. El código de error SQLITE_READONLY_ROLLBACK indica que no se puede abrir una base de datos porque tiene un diario activo que debe retrotraerse pero no puede porque la base de datos es de solo lectura.
Durante el desarrollo, con frecuencia estoy interrumpiendo la aplicación que se está ejecutando actualmente para instalar y ejecutar una nueva versión. Esto ocasiona que el sistema detenga la aplicación actualmente en ejecución. Si el código de Javascript en WebView se encuentra en el medio de escribir en la base de datos a través de su conexión de escritura por separado cuando la aplicación se numera, entonces un diario caliente se quedará atrás.
Cuando se inicia la nueva versión de la aplicación, se abre la conexión de base de datos de solo lectura en el código nativo de Java. Cuando esta conexión detecta el diario, intenta deshacer el diario. Y debido a que es una conexión de solo lectura, falla.
(Esto encaja con el bloqueo que se observa de inmediato en el arranque después de haber hecho un cambio).
La solución correcta es, por lo tanto, hacer que la conexión Java sea una conexión grabable. Esta conexión nunca intenta escribir durante el funcionamiento normal, pero debe escribir cuando se recupera de una escritura interrumpida previa a través de la conexión grabable de WebView.
Tengo una conexión de base de datos de solo lectura. A veces, al leer datos de la base de datos con una consulta SELECT
, arroja una SQLiteReadOnlyDatabaseException
.
Abro la conexión de esta manera:
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
La consulta es:
Select * FROM BudgetVersions WHERE entityId = ?
Leo datos de la base de datos usando db.rawQuery()
, así:
String query = ...;
Cursor c = db.rawQuery(query, new String[]{ activeBudgetId });
try {
if (c.moveToFirst()) {
bv.versionName = c.getString(c.getColumnIndexOrThrow("versionName"));
return bv;
} else {
return null;
}
} finally {
c.close();
}
Muy raramente, recibo un bloqueo como este, dentro de la llamada a c.moveToFirst()
:
Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 776)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:845)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
Como solución alternativa, podría intentar usar una conexión de base de datos grabable, pero me gustaría saber por qué está ocurriendo el bloqueo.
La tabla de la que estoy leyendo es una tabla SQLite estándar:
CREATE TABLE BudgetVersions (
entityId VARCHAR PRIMARY KEY NOT NULL UNIQUE,
budgetId VARCHAR NOT NULL,
versionName VARCHAR NOT NULL,
dateFormat VARCHAR,
currencyFormat VARCHAR,
lastAccessedOn DATETIME,
isTombstone BOOL NOT NULL,
deviceKnowledge NUMERIC NOT NULL
);
He visto cómo se produce el bloqueo tanto en un emulador KitKat como en un dispositivo que ejecuta Lollipop.
Existe una conexión grabable separada abierta a la misma base de datos al mismo tiempo , propiedad de un WebView. La base de datos se está actualizando por código JavaScript en WebView, y se puede leer en la capa nativa de Android / Java con esta conexión de solo lectura.
Espero que esto pueda ser la causa principal del problema, pero me gustaría entender en detalle por qué una conexión de solo lectura interferiría con una conexión grabable por separado.
Soy muy consciente de que el consejo general es usar una única conexión a la base de datos, pero dado que la conexión que se puede escribir es propiedad de WebView
, no tengo acceso fácil desde el código de Java.