У нас возникла странная ошибка с Android SQLite: когда мы создаем базу данных, закрываем ее, снова открываем, добавляем столбцы и выполняем запрос, например. снова количество столбцов, мы получаем старое значение.
Мы используем новейшие встроенные инструменты и целевую версию SDK (33). Вот короткий тест, демонстрирующий проблему:
Код: Выделить всё
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase.*
import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.SupportSQLiteOpenHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SmallBugTest {
private val TEST_DB = "small-bug-test"
private val context = InstrumentationRegistry.getInstrumentation().context
private lateinit var db: SupportSQLiteDatabase
@Before
fun setup() {
//The bug doesn't seem to appear if everything is done is one session (at least with this suite), so let's simulate two sessions
/* Database is created */
SupportSQLiteOpenHelper.Configuration(context, TEST_DB,
object : SupportSQLiteOpenHelper.Callback(1) {
override fun onCreate(db: SupportSQLiteDatabase) = createDb(db)
override fun onUpgrade(
db: SupportSQLiteDatabase,
oldVersion: Int,
newVersion: Int
) = throw AssertionError()
}).let { FrameworkSQLiteOpenHelperFactory().create(it).writableDatabase }.close()
/* Database is closed, e.g. приложение закрыто */
/////////////////////////////////// ////////
/* База данных открыта, но не создана */
db = SupportSQLiteOpenHelper.Configuration(context, TEST_DB,
object : SupportSQLiteOpenHelper.Callback(1) {
переопределить fun onCreate(db: SupportSQLiteDatabase) = throw AssertionError()
переопределить fun onUpgrade(
db: SupportSQLiteDatabase,
oldVersion: Int,< br /> newVersion: Int
) = throw AssertionError()
}).let { FrameworkSQLiteOpenHelperFactory().create(it).writableDatabase
Private fun createDb(db: SupportSQLiteDatabase) {
db.execSQL(
"CREATE TABLE `TEST_TABLE` (" + //
"`column0` TEXT NOT NULL," +
" `column1` TEXT NOT NULL" +
")"
)
db.execSQL("INSERT INTO `TEST_TABLE` (`column0`, `column1`) VALUES ('content0', ' content1')")
db.version = 1
}
@Test
fun CauseBug() { //Если этот тест пройден успешно, произошла ошибка
db.query("SELECT * FROM TEST_TABLE").close()
modifySchema(db)
db.query("SELECT * FROM TEST_TABLE").use {
it.moveToFirst()
AssertArrayEquals(
arrayOf("column0", "column1"),
it.columnNames
) // Должно быть ["column0", "column1", "column2"]
Private fun ModifySchema(db: SupportSQLiteDatabase) {
db.execSQL( "ALTER TABLE `TEST_TABLE` RENAME TO `TEST_TABLE_OLD`")
db.execSQL(
"CREATE TABLE `TEST_TABLE` (" + //
"`column0` TEXT NOT NULL," +
"`column1` TEXT NOT NULL", +
"`column2` TEXT" +
")"
)
db.execSQL("INSERT INTO `TEST_TABLE ` (`column0`, `column1`) SELECT `column0`, `column1` FROM `TEST_TABLE_OLD`")
db.execSQL("DROP TABLE `TEST_TABLE_OLD`")
db.update(
"TEST_TABLE",
CONFLICT_NONE,
ContentValues().also { it.put("column2", "content2"); },
null,
null
)
}
}
Код: Выделить всё
(Support)SQLiteDatabaseКод: Выделить всё
PreparedStatementКод: Выделить всё
acquirePreparedStatementКод: Выделить всё
acquirePreparedStatementКод: Выделить всё
PreparedStatementCache mPreparedStatementCacheSome operations on the cursor for a query (e.g.
Код: Выделить всё
Cursor#getXКод: Выделить всё
queryКод: Выделить всё
getColumnCountКод: Выделить всё
getColumnNamesAccordingly if a query is dispatched and cached and then the table is changed to have more columns and then a query with the same sql text is dispatched, the resulting cursor from the second query will use the same PS internally and return correct content values for the new columns, but will still report the same (now outdated!)
Код: Выделить всё
columnCountsКод: Выделить всё
columnNamesThere's also an issue in the Google bug tracker where we've noted our findings but haven't found a workaround yet: https://issuetracker.google.com/issues/ ... #comment18
Have you encountered this problem and found a workaround?
We created this sample project if you want to see it in action: https://github.com/SailReal/Android-Issue-153521693
Источник: https://stackoverflow.com/questions/780 ... ring-table
Мобильная версия