sql >> Databáze >  >> RDS >> SQLite

Jak číst číslo verze z databázového souboru v Androidu, který je umístěn ve složce aktiv

Neexistuje jediné číslo verze, místo toho může být číslo verze více hodnot.

Předpokládám, že mluvíte o user_version kterou používá Android SDK SQLiteOpenHelper.

Je zde také id_aplikace , kterou lze stejně jako user_version použít jako uživatelskou proměnnou.

S SQLite_Version jste se již setkali, takže to lze zlevnit.

Je zde také data_version, je nepravděpodobné, že to bude číslo verze, protože je zamýšleno k použití jako indikace, zda byl databázový soubor změněn v reálném čase.

Existuje také schema_version, pravděpodobně to NECHCETE používat jako Upozornění:Zneužití tohoto pragmatu může vést k poškození databáze.

uživatelská_verze

Jak již bylo řečeno, pravděpodobně mluvíte o user_version . První věc, kterou je třeba poznamenat, je, že se jedná o uživatelem ovládanou proměnnou/pole zpřístupněnou pro vlastní použití. SQlite nepoužívá ani nemění user_version ale umožňuje jeho změnu a použití.

Navíc správci SQLite (jako je DB Browser, Navicat atd.) by automaticky nezměnili číslo verze. Jako takový byste museli záměrně změnit user_version, aby byl dostupný před zkopírováním databázového souboru do složky aktiv (všimněte si, že pokud tak učiníte a používáte podtřídu SQLiteOpenHelper že onUpgrade a onDowngrade mohou být volány metody).

Pokud se uživatelská_verze konkrétně nezměnila a k databázi přistupoval pouze nástroj SQLite Manager, pak její uživatelská verze bude 0. Pokud byl databázový soubor otevřen zkopírováním databázového souboru z aplikace pro Android, která využívá podtřídu SQLiteOpenHelper, bude mít user_version 1 nebo více (v závislosti na poslední hodnotě použité jako 4. parametr konstruktoru SQLiteOpenHelper). Samozřejmě pokud se user_version změní programově, pak by se taková změna projevila i v případě, že by byl soubor zkopírován do nástroje SQlite Manager.

Před zkopírováním souboru by se user_version obvykle změnil v nástroji SQlite Manager na vhodnou hodnotu.

Můžete změnit user_version pomocí SQL PRAGMA user_version = 5; Můžete načíst user_version pomocí buď PRAGMA user_version nebo SELECT * FROM pragma_user_version;

Pokud potřebujete zkontrolovat verzi před otevřením databáze, můžete přečíst 4 bajty s offsetem 60 a převést 4 bajty na celé číslo, abyste porovnali user_version s jinou hodnotou. V opačném případě byste pravděpodobně museli zkopírovat soubor, pravděpodobně s jiným názvem, ze složky aktiv, otevřít jej jako SQLiteDatabase a načíst user_version pomocí výše uvedeného SQL a poté jej porovnat s jinou hodnotou, čímž se soubor databáze zavře. Smazání souboru, pokud to není potřeba, jinak smazání předchozího databázového souboru a následné přejmenování zkopírovaného souboru.

Příklad

Následuje pracovní příklad (upozorňuji, že Kotlin používám jen zřídka a toto bylo převedeno pomocí AS studio z javy).

To používá třídu, konkrétně SQLAssetVersionCheck který ze souboru extrahuje číslo verze místo otevření souboru jako 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
    }
}

A zde je aktivita, která používá výše uvedenou třídu dvakrát, aby se pokusila zkontrolovat verzi v testdb soubor.

  • Při prvním použití nebyl nalezen databázový soubor testdb jak to vypadá v aktivech složku (nikoli podadresář databází).

  • Druhé použití najde testdb soubor jako podadresář databáze je zadán (3. parametr úplného konstruktoru), který najdete v assets/databases/ složka, tj. 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")
    }
}

Výsledek (protokol) :-

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
  • První pokus nenajde soubor (zobrazí se výjimka, která byla zachycena) a zobrazí řádek Výsledek kontroly verze byl - The Asset, for Database testdb was not found at testdb k zobrazení.

  • Druhý pokus funguje a má za následek Výsledek kontroly verze byl - Majetek byl nalezen a číslo verze 5 bylo nižší než verze ke kontrole, která byla 100

  • Mezera prázdných řádků byla přidána, aby se oddělil druhý pokus od prvního.

Další

Po použití nástroje SQLite Manager (Navicat) a pomocí :-

PRAGMA user_version = 101;

Poté zkopírujte soubor (po uzavření připojení v Navicat) do složky aktiv (takže mám dva soubory testdb), výsledek je :-

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
  • tj. nový soubor má user_version jako 101, takže první najde soubor, druhý najde soubor (user_version 5) jako předtím.



  1. převod datového typu varchar na datový typ datetime vedl k hodnotě mimo rozsah

  2. uložené procedury s sqlAlchemy

  3. sql server 2008 management studio nekontroluje syntaxi mého dotazu

  4. Databázový model pro online průzkum. Část 3