Reputation: 451
I think my question is related to this one, but that one is talking about a png and I'm not sure how to translate that to my case.
I have a database created with sqlite in a file ending with .db. Now I have a program that only reads from this database. Is there a way to include the databse file into the executable?
Now if I compile I have to keep the executable and file together. This dependency could be removed by having the database file at an absolute path, but I'm also working on hpc clusters so that doesn't work. I need a relative path such that the db file is at the same hierarchy as my main.cpp but I want to be able to copy the execuatably without coping the db file, so in some way the db file is already part of the executable.
Upvotes: 1
Views: 1351
Reputation: 14603
There exists an age-old trick to append something (such as a virus, but in this case a database) to the end of the executable. The executable will usually work just fine, but you can read (and perhaps even write) to the database as well. The already-mentioned custom VFS can help you accomplish this task.
The other solution might be to consider the database as a kind of resource, such as a Windows resource or a Qt resource. You can then compress/compile your database into your executable. Accessing the resource (database) would then depend on what framework you use.
Upvotes: 1
Reputation: 96
There is sqlite3_deserialize routine, that takes database dump from array and "loads" it into suplied database connection. Combined with in-memory db, it can be used to accomplish what you want.
// Plain dump of file. Made with xxd -i
unisgned char db_dump[] = {0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20 ....etc
// Create empty, readonly in-memory db
sqlite3* db = NULL;
sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READONLY, NULL);
// Reopen db with dump of other one
rc = sqlite3_deserialize(db, "main", db_dump, sizeof(db_dump), sizeof(db_dump),
SQLITE_DESERIALIZE_READONLY);
Full, runnable example (too long to post here)
Upvotes: 2
Reputation: 30830
Asssuming you embedded the SQLite database in your binary, you have an const char *embedded_start
and size_t embedded_length
that denote the start and length of the database.
The answer depends on how much work you're willing to put in it:
FILE *db = tmpfile();
fwrite(embedded_start, embedded_length, 1, db);
fflush(db);
std::string path = std::string{"/proc/self/fd/"} + std::to_string(fileno(db));
sqlite3_open_v2(path.c_str(), &dbconn, SQLITE_OPEN_READONLY, nullptr);
/proc/self/fd/X
.Upvotes: 1