Няма един номер на версията, вместо това номерът на версията може да бъде няколко стойности.
Предполагам, че говорите за user_version който използва SQLiteOpenHelper SDK за Android.
Има и application_id , който подобно на user_version може да се използва като потребителска променлива.
Вече сте се сблъсквали с SQLite_Version, така че това може да бъде намалено.
Има и data_version, малко вероятно това е номерът на версията, тъй като е предназначен да се използва като индикация дали файлът на базата данни е променен в реално време.
Има и schema_version, вероятно НЕ искате да го използвате като Предупреждение:Злоупотребата с тази прагма може да доведе до повреда на базата данни.
потребителска_версия
Както вече казахме, вероятно говорите за user_version . Първото нещо, което трябва да се отбележи, е, че това е променлива/поле, контролирана от потребителя, достъпно за потребителска употреба. SQlite не използва и не променя user_version но позволява да се променя и използва.
Освен това SQLite мениджърите (като DB Browser, Navicat и т.н.) няма да променят автоматично номера на версията. По този начин ще трябва умишлено да промените user_version, за да бъде наличен, преди да копирате файла на базата данни в папката с активи (отбелязвайки, че ако го направите и използвате подклас на SQLiteOpenHelper
че onUpgrade
и onDowngrade
методи могат да бъдат извикани).
Ако user_version не е специално променена и базата данни е била достъпна само от инструмента SQLite Manager, тогава нейната user_version ще бъде 0. Ако файлът на базата данни е отворен чрез копиране на файла на базата данни от приложение за Android, което използва подклас на SQLiteOpenHelper, той ще има user_version от 1 или повече (в зависимост от последната стойност, използвана като 4-ти параметър към конструктора на SQLiteOpenHelper). Разбира се, ако user_version се промени програмно, тогава такава промяна също ще бъде отразена, ако файлът бъде копиран в инструмент SQlite Manager.
Преди да копирате файла, user_version обикновено се променя в инструмента SQlite Manager на подходяща стойност.
Можете да промените user_version използвайки SQL PRAGMA user_version = 5;
Можете да извлечете user_version използвайки или PRAGMA user_version
или SELECT * FROM pragma_user_version;
Ако трябва да проверите версията, преди да отворите базата данни, тогава можете да прочетете 4-те байта при отместване 60 и да конвертирате 4-те байта в цяло число, за да проверите user_version спрямо друга стойност. В противен случай вероятно ще трябва да копирате файла, вероятно използвайки различно име, от папката с активи, да го отворите като SQLiteDatabase и да извлечете user_version с помощта на SQL по-горе и след това да го проверите спрямо другата стойност, затваряйки файла на базата данни. Изтриването на файла, ако не е необходимо, в противен случай изтриване на предишния файл на базата данни и след това преименуване на копирания файл.
Пример
Следва работещ пример (отбелязвайки, че рядко използвам Kotlin и това е преобразувано с помощта на AS studio от java).
Това използва клас, а именно SQLAssetVersionCheck който извлича номера на версията от файла, вместо да отваря файла като SQLiteDatabase.
SQLAssetVersionCheck.kt :-
class SQLAssetVersionCheck
/**
* Full SQLAssetVersionCheck Constructor - sub directories can be specified
* @param context Assets are part of package so use the context to get the asset file
* @param dbName The database name (i.e. the file name)
* @param subDirectories The sub-directories as per the heirarchial order
* @param dbVersion The database version to check against
*/
(context: Context, val databaseName: String, subDirectories: Array<String>?, dbVersion: Int) {
val assetPath: String
var databaseVersion: Int = 0
private set
var result: Int = 0
private set
init {
assetPath = applySubDirectories(databaseName, subDirectories)
Log.d("SQLAVC", "Looking for Asset $assetPath")
var stage = 0
try {
val `is` = context.assets.open(assetPath)
stage++
// Get the first 64 bytes of the header
val v = ByteArray(64)
`is`.read(v, 0, 64)
// only interested in the 4 bytes from offset 60 so get them
val v2 = ByteArray(4)
for (i in 60..63) {
v2[i - 60] = v[i]
}
stage++
// Done with the InputStream so close it
`is`.close()
// Extarct the stored DBVersion
databaseVersion = ByteBuffer.wrap(v2).int
if (databaseVersion < dbVersion) {
result = ASSETVERSIONLOW
}
if (databaseVersion > dbVersion) {
result = ASSETVERSIONHIGH
}
if (databaseVersion == dbVersion) {
result = ASSETVERSIONMATCH
}
} catch (e: IOException) {
e.printStackTrace()
when (stage) {
0 -> result = ASSETNOTFOUND
1 -> result = ASSETIOERROR
}
}
}
constructor(context: Context, dbName: String, dbVersion: Int) : this(context, dbName, null, dbVersion) {}
private fun applySubDirectories(dbname: String, subDirectories: Array<String>?): String {
val base = StringBuffer("")
var firstdirectory = true
if (subDirectories != null) {
for (d in subDirectories) {
if (!firstdirectory) {
base.append(File.separatorChar)
}
firstdirectory = false
base.append(d)
}
}
if (base.length > 0) {
base.append(File.separatorChar)
}
base.append(dbname)
return base.toString()
}
companion object {
val ASSETNOTFOUND = -2
val ASSETIOERROR = -3
val ASSETVERSIONMATCH = 0
val ASSETVERSIONHIGH = 1
val ASSETVERSIONLOW = -1
}
}
И ето дейност, която използва горния клас два пъти, за да се опита да провери версията в testdb файл.
-
Първото използване не намира файла на базата данни testdb както се търси вактиви папка (не поддиректорията на базата данни).
-
Второто използване намира testdb файл като поддиректория бази данни е посочен (3-ти параметър на пълния конструктор), намиращ се в активи/бази от данни/ папка, т.е. assets/databases/testdb :-
MainActivity.kt :-
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val db_version_to_check_against = 100
var mAVC1 = SQLAssetVersionCheck(this, "testdb", 100)
var result = ""
when (mAVC1.result) {
SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC1.databaseName + " was not located at " + mAVC1.assetPath
SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
mAVC1.databaseVersion.toString() +
" was higher than the version to be checked which was " +
db_version_to_check_against.toString()
SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
mAVC1.databaseVersion.toString() +
" was lower than the version to be checked which was " +
db_version_to_check_against.toString()
SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
}
Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")
var mAVC2 = SQLAssetVersionCheck(this, "testdb", arrayOf("databases"), db_version_to_check_against)
result = ""
when (mAVC2.result) {
SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC2.databaseName + " was not located at " + mAVC2.assetPath
SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
mAVC2.databaseVersion.toString() +
" was higher than the version to be checked which was " +
db_version_to_check_against.toString()
SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
mAVC2.databaseVersion.toString() +
" was lower than the version to be checked which was " +
db_version_to_check_against.toString()
SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
}
Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")
}
}
Резултат (регистрационен файл) :-
2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning W/System.err: java.io.FileNotFoundException: testdb
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.content.res.AssetManager.nativeOpenAsset(Native Method)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.content.res.AssetManager.open(AssetManager.java:744)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.content.res.AssetManager.open(AssetManager.java:721)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:31)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:67)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at com.example.so54741423assetdbversioning.MainActivity.onCreate(MainActivity.kt:17)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.Activity.performCreate(Activity.java:7136)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.Activity.performCreate(Activity.java:7127)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.os.Looper.loop(Looper.java:193)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6669)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset, for Database testdb was not located at testdb
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:11:34.477 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
-
Първият опит не намира файла (показва се изключението, което е уловено) и показва реда Резултатът от проверката на версията беше - Активът, за база данни testdb не беше разположен в testdb да се покаже.
-
Вторият опит работи и води до Резултатът от проверката на версията беше - Активът беше открит и номерът на версията, който беше 5, беше по-нисък от версията за проверка, която беше 100
-
Празнината на празните редове беше добавена, за да се раздели втория опит от първия.
Допълнително
След като използвате инструмента SQLite Manager (Navicat) и използвате :-
PRAGMA user_version = 101;
След това копирате файла (след затваряне на връзката в Navicat) в папката с активи (така че имам два файла testdb), резултатът е:-
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 101 was higher than the version to be checked which was 100
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
- т.е. новият файл има user_version като 101 и така първият намира файла, вторият намира файла (user_version 5) както преди.