伯克利数据库不能使用不同的 Dbt 初始化来设置值

Berkeley DB cannot set value with different Dbt initialization

本文关键字:初始化 Dbt 设置 不能 数据库 伯克利      更新时间:2023-10-16

代码的唯一区别是数据的初始化。这有效:

        Dbt key, data(&b, sizeof(int));
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);

但这不会:

        Dbt key, data;
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_data(&b);
        data.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);

我用 https://docs.oracle.com/cd/E17076_04/html/api_reference/CXX/dbt.html 阅读文档,我没有看到这两种方式的区别。这令人困惑。

完整的代码和结果如下所示:

$ cat db.cpp
#include <db.h>
#include <db_cxx.h>
#include <exception>
#include <iostream>
using namespace std;
int main() {
        Db db(NULL, 0);
        u_int32_t oFlags = DB_CREATE | DB_TRUNCATE;
        try {
            db.open(NULL, "test.db", NULL, DB_HASH, oFlags, 0);
        } catch (DbException &e) {
            cout << "DbException" << endl;
        } catch (std::exception &e) {
        }
        int a = 5, b = 6, c = 0, result[1]= {-1};
        Dbt key, data(&b, sizeof(int));
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);
        cout << (db.get(NULL, &key, &data, 0) == DB_NOTFOUND) << endl;
        cout << c << endl;
        db.put(NULL, &key, &data, 0);
        key.set_data(&a);
        data.set_data(result);
        data.set_ulen(sizeof(int));
        cout << (db.get(NULL, &key, &data, 0) )<< endl;
        cout << *((int *) data.get_data()) << endl;
        cout << result[0] << endl;
        return 0;
}
$ rm test.db ; g++ db.cpp -ldb_cxx-5.1; ./a.out
1
0
0
6
6
$ cat db.cpp
#include <db.h>
#include <db_cxx.h>
#include <exception>
#include <iostream>
using namespace std;
int main() {
        Db db(NULL, 0);
        u_int32_t oFlags = DB_CREATE | DB_TRUNCATE;
        try {
            db.open(NULL, "test.db", NULL, DB_HASH, oFlags, 0);
        } catch (DbException &e) {
            cout << "DbException" << endl;
        } catch (std::exception &e) {
        }
        int a = 5, b = 6, c = 0, result[1]= {-1};
        Dbt key, data;
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_data(&b);
        data.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);
        cout << (db.get(NULL, &key, &data, 0) == DB_NOTFOUND) << endl;
        cout << c << endl;
        db.put(NULL, &key, &data, 0);
        key.set_data(&a);
        data.set_data(result);
        data.set_ulen(sizeof(int));
        cout << (db.get(NULL, &key, &data, 0) )<< endl;
        cout << *((int *) data.get_data()) << endl;
        cout << result[0] << endl;
        return 0;
}
$ rm test.db ; g++ db.cpp -ldb_cxx-5.1; ./a.out
1
0
0
-1
-1

你需要调用Dbt.set_size()Dbt.set_ulen()仅设置 Dbt.data 指向的内存的分配大小。 Dbt.size具有密钥或数据的实际使用长度。 将这些调用添加到第二个示例中应该可以使其正常工作:

    Dbt key, data;
    key.set_data(&a);
    key.set_ulen(sizeof(int));
    key.set_size(sizeof(int));
    data.set_data(&b);
    data.set_ulen(sizeof(int));
    data.set_size(sizeof(int));
    data.set_flags(DB_DBT_USERMEM);

至于为什么Dbt key在没有set_size的情况下为你工作,我完全不确定。 也许您对堆栈上的未初始化数据很幸运? 如果你想知道,你可以打印出key.size的值。

需要

明确的是,您无需在put()之前设置ulen。 它只需要在你做一个get()之前设置,让BDB知道它必须读入多少内存。