SQLite:如何将 memvfs 扩展嵌入到 Amalgamation 中?
SQLite: How embed the memvfs extension to Amalgamation?
我需要load/save内存缓冲区中的 SQLite 数据库。为此,我想将 memvfs 扩展嵌入到 sqlite3 代码中并将其完全编译为 sqlite3.dll.
怎么做到的?
更新1:
我想使用 memvfs 作为临时内存缓冲区。我的程序将数据从网络加载到缓冲区,连接到该内存缓冲区并将数据恢复到空的内存数据库中。我认为将 memvfs 包含到 sqlite 合并中会提高性能。
更新2:
如果你想使用 memvfs 扩展,请注意源代码中自述文件注释中的错误。使用 "PRAGMA journal_mode=OFF" 代替 "journal_mode=NONE"
更新3:
memvfs.c 中的另一个错误 - 使用 'max' 而不是 'maxsz' 作为 URI 中的 maxsz 参数。
sqlite 开发人员精心设置了一个耙子:(
演示使用 memvfs 的测试程序:
#include <fcntl.h>
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
sqlite3 *db;
char *err;
// Open an in-memory database to use as a handle for loading the memvfs extension
if (sqlite3_open(":memory:", &db) != SQLITE_OK) {
fprintf(stderr, "open :memory: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_enable_load_extension(db, 1);
if (sqlite3_load_extension(db, "./memvfs", NULL, &err) != SQLITE_OK) {
fprintf(stderr, "load extension: %s\n", err);
return EXIT_FAILURE;
}
// Done with this database
sqlite3_close(db);
// Read the real database into memory
int fd = open("foo.db", O_RDONLY);
if (fd < 0) {
perror("open");
return EXIT_FAILURE;
}
struct stat s;
if (fstat(fd, &s) < 0) {
perror("fstat");
return EXIT_FAILURE;
}
void *memdb = sqlite3_malloc64(s.st_size);
if (read(fd, memdb, s.st_size) != s.st_size) {
perror("read");
return EXIT_FAILURE;
}
close(fd);
// And open that memory with memvfs now that it holds a valid database
char *memuri = sqlite3_mprintf("file:whatever?ptr=0x%p&sz=%lld&freeonclose=1",
memdb, (long long)s.st_size);
printf("Trying to open '%s'\n", memuri);
if (sqlite3_open_v2(memuri, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
"memvfs") != SQLITE_OK) {
fprintf(stderr, "open memvfs: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_free(memuri);
// Try querying the database to show it works.
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, "SELECT b FROM test", -1, &stmt, NULL) !=
SQLITE_OK) {
fprintf(stderr, "prepare: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return EXIT_FAILURE;
}
for (int rc = sqlite3_step(stmt); rc == SQLITE_ROW; rc = sqlite3_step(stmt)) {
printf("%d\n", sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
用法:
# Create a test database to use with memvfs
$ sqlite3 foo.db
sqlite> CREATE TABLE test(b INTEGER);
sqlite> INSERT INTO test VALUES (1), (2);
sqlite> .quit
# Compile the memvfs module and test program
$ gcc -O -fPIC -shared -o memvfs.so memvfs.c
$ gcc -O -Wall -Wextra testmem.c -lsqlite3
# And run it.
$ ./a.out
Trying to open 'file:whatever?ptr=0x56653FE2B940&sz=8192&freeonclose=1'
1
2
如果您将其直接编译到您的程序中而不是使用可加载模块,则工作流程相同;您只需使用正确的参数调用 sqlite3_memvfs_init()
而不是使用 sqlite3_load_extension()
.
我需要load/save内存缓冲区中的 SQLite 数据库。为此,我想将 memvfs 扩展嵌入到 sqlite3 代码中并将其完全编译为 sqlite3.dll.
怎么做到的?
更新1:
我想使用 memvfs 作为临时内存缓冲区。我的程序将数据从网络加载到缓冲区,连接到该内存缓冲区并将数据恢复到空的内存数据库中。我认为将 memvfs 包含到 sqlite 合并中会提高性能。
更新2:
如果你想使用 memvfs 扩展,请注意源代码中自述文件注释中的错误。使用 "PRAGMA journal_mode=OFF" 代替 "journal_mode=NONE"
更新3:
memvfs.c 中的另一个错误 - 使用 'max' 而不是 'maxsz' 作为 URI 中的 maxsz 参数。 sqlite 开发人员精心设置了一个耙子:(
演示使用 memvfs 的测试程序:
#include <fcntl.h>
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
sqlite3 *db;
char *err;
// Open an in-memory database to use as a handle for loading the memvfs extension
if (sqlite3_open(":memory:", &db) != SQLITE_OK) {
fprintf(stderr, "open :memory: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_enable_load_extension(db, 1);
if (sqlite3_load_extension(db, "./memvfs", NULL, &err) != SQLITE_OK) {
fprintf(stderr, "load extension: %s\n", err);
return EXIT_FAILURE;
}
// Done with this database
sqlite3_close(db);
// Read the real database into memory
int fd = open("foo.db", O_RDONLY);
if (fd < 0) {
perror("open");
return EXIT_FAILURE;
}
struct stat s;
if (fstat(fd, &s) < 0) {
perror("fstat");
return EXIT_FAILURE;
}
void *memdb = sqlite3_malloc64(s.st_size);
if (read(fd, memdb, s.st_size) != s.st_size) {
perror("read");
return EXIT_FAILURE;
}
close(fd);
// And open that memory with memvfs now that it holds a valid database
char *memuri = sqlite3_mprintf("file:whatever?ptr=0x%p&sz=%lld&freeonclose=1",
memdb, (long long)s.st_size);
printf("Trying to open '%s'\n", memuri);
if (sqlite3_open_v2(memuri, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
"memvfs") != SQLITE_OK) {
fprintf(stderr, "open memvfs: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_free(memuri);
// Try querying the database to show it works.
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, "SELECT b FROM test", -1, &stmt, NULL) !=
SQLITE_OK) {
fprintf(stderr, "prepare: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return EXIT_FAILURE;
}
for (int rc = sqlite3_step(stmt); rc == SQLITE_ROW; rc = sqlite3_step(stmt)) {
printf("%d\n", sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
用法:
# Create a test database to use with memvfs
$ sqlite3 foo.db
sqlite> CREATE TABLE test(b INTEGER);
sqlite> INSERT INTO test VALUES (1), (2);
sqlite> .quit
# Compile the memvfs module and test program
$ gcc -O -fPIC -shared -o memvfs.so memvfs.c
$ gcc -O -Wall -Wextra testmem.c -lsqlite3
# And run it.
$ ./a.out
Trying to open 'file:whatever?ptr=0x56653FE2B940&sz=8192&freeonclose=1'
1
2
如果您将其直接编译到您的程序中而不是使用可加载模块,则工作流程相同;您只需使用正确的参数调用 sqlite3_memvfs_init()
而不是使用 sqlite3_load_extension()
.