gpt4 book ai didi

c - 如何检测 sqlite3 是否创建了数据库文件?

转载 作者:行者123 更新时间:2023-12-03 17:07:30 26 4
gpt4 key购买 nike

我正在编写一个使用 sqlite3 数据库文件来存储其数据的程序。如果我打开一个数据库文件

sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)

如果数据库文件不存在,则创建该文件。如何在打开数据库文件之前确定它是否存在? sqlite3 shell 使用如下代码:
  /* Go ahead and open the database file if it already exists.  If the
** file does not exist, delay opening it. This prevents empty database
** files from being created if a user mistypes the database name argument
** to the sqlite command-line tool.
*/
if( access(data.zDbFilename, 0)==0 ){
open_db(&data, 0);
}

但是,当数据库文件由 access 之后的另一个进程创建时,此代码具有竞争条件。打电话和之前 open_db调用(检查时间与使用时间)。

另一个答案(我现在找不到)建议检查 application_iduser_version领域。如果它们为零,则刚刚创建了一个数据库。我研究了这种方法,发现许多应用程序实际上并不费心在新创建的数据库中设置这些字段,因此这种方法充其量是模糊的,我认为它不能解决我的问题。

有没有一种方法可以在不涉及这样的竞争条件的情况下在打开数据库之前确定数据库是否存在?如果我只能找出数据库文件是否已被 sqlite3 初始化(例如,截断的文件填充了 sqlite3 header ),这也是可以接受的。

拥有这样一个例程的目的是能够找出我是否需要在数据库中创建我需要的所有表。我不想意外覆盖由不同应用程序放置在那里的另一个文件。

示例代码

可以在以下 bash 脚本中找到问题的简化说明。它模拟两个应用程序。它们都以类似的方式工作:
  • 创建或打开数据库 test.db
  • 如果数据库之前不存在,则创建一个表test并在其中写入一行。第一个应用程序的值为 1,第二个应用程序的值为 2。
  • 打印数据库的内容。

  • 这是代码:
    #!/bin/sh

    # sleeps are inserted to make the race conditions easier to trigger

    application() {
    echo Checking if database exists...
    [ ! -f test.db ]
    status=$?
    sleep 2

    if (exit $status)
    then
    echo Database not found, making tables
    sqlite3 test.db "CREATE TABLE IF NOT EXISTS test (a);"
    sleep 2
    echo Writing initial record into database
    sqlite3 test.db "INSERT INTO test VALUES ($1);"
    sleep 2
    else
    echo Database found, checking if it belongs to me
    fi

    echo Printing content of database
    sqlite3 test.db "SELECT * FROM test;"
    }

    rm -f test.db
    echo First test: app1 and app1 race
    application 1 & (sleep 1 ; application 1)

    rm -f test.db
    echo Second test: app2 and app1 race
    application 2 & (sleep 1 ; application 1)

    我的目标是确保以下情况永远不会发生:
  • 应用程序的一个实例打开数据库文件,断定它没有初始化并初始化它(通过创建表并写入初始记录),即使它已经包含来自同一应用程序的不同实例或来自不同应用程序的数据.
  • 属于不同应用程序的数据库文件被写入。

  • application如果编程正确,每次运行只会初始化数据库,如果它之前没有初始化。因此,您将看到的唯一输出是仅包含行 1 的数据库。或仅包含行 2 的数据库.

    最佳答案

    无法将新创建的数据库与之前创建的空数据库区分开来。

    但是,空数据库是唯一存在此问题的数据库。
    通过检查 sqlite_master 是否可以检测到任何其他数据库表不是空的。在事务中执行此操作和您的表创建,并且没有竞争条件。

    如果您第一次写入数据库(即实际创建文件的时间)正在设置 application_id ,那么您就知 Prop 有其他 ID 的任何文件都不是您的。 (注册的应用程序 ID 是唯一的。)

    关于c - 如何检测 sqlite3 是否创建了数据库文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35554607/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com