SQLite: Как встроить расширение memvfs в Amalgamation? - PullRequest
0 голосов
/ 23 ноября 2018

Мне нужно загрузить / сохранить базу данных SQLite в буфере памяти.Для этого я хочу встроить расширение memvfs в код sqlite3 и скомпилировать его полностью как sqlite3.dll.

Как это сделать?

Update1:

Я хочу использовать memvfs в качестве буфера временной памяти.Моя программа загружает данные из сети в буфер, подключается к этому буферу памяти и восстанавливает данные в пустую базу данных в памяти.Я полагаю, что включение memvfs в объединение sqlite улучшит производительность.

Update2:

Если вы хотите использовать расширение memvfs, обратите внимание на ошибку в комментарии readme в источнике.Вместо этого используйте «PRAGMA journal_mode = OFF » «journal_mode = NONE»

Update3:

Еще одна ошибка в memvfs.c - используйте 'max'вместо 'maxsz' для параметра maxsz в URI.Разработчики sqlite тщательно установили грабли: (

1 Ответ

0 голосов
/ 24 ноября 2018

Тестовая программа для демонстрации с использованием 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().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...