Skip to content

Commit 5334c97

Browse files
committed
Support mkdir -p behavior when DB file does not exist
Currently, if you supply a DB path that includes directories which do not exist, sqlite3 will not attempt to create them and the open will crash. This adds a quick attempt to `mkdir` on the db path to ensure all intermediary directories exist before attempting to create the DB file for cases that `SQLITE_OPEN_CREATE` flag is enabled and would expect the file to be created when non-existant
1 parent c163e92 commit 5334c97

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

c_src/sqlite3.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
*/
20+
#include <libgen.h> /* Needed for dirname() */
2021
#define SQLITE_CORE 1
2122
#define SQLITE_AMALGAMATION 1
2223
#ifndef SQLITE_PRIVATE
@@ -34781,6 +34782,9 @@ static struct unix_syscall {
3478134782
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
3478234783
#endif
3478334784

34785+
{ "dirname", (sqlite3_syscall_ptr)dirname, 0 },
34786+
#define osDirname ((char*(*)(const char*))aSyscall[29].pCurrent)
34787+
3478434788
}; /* End of the overrideable system calls */
3478534789

3478634790

@@ -67971,6 +67975,14 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
6797167975
if( isMemdb ){
6797267976
flags |= BTREE_MEMORY;
6797367977
}
67978+
if( !isMemdb ){
67979+
/* SQLITE_OPEN_CREATE will create the DB file if not existing, but
67980+
** will not create intermediary directories if they are missing.
67981+
** So let's preemptively create the intermediate directories here
67982+
** before trying to open the DB file.
67983+
*/
67984+
osMkdir(osDirname(zFilename), 0777);
67985+
}
6797467986
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
6797567987
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
6797667988
}

test/exqlite/sqlite3_test.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ defmodule Exqlite.Sqlite3Test do
1818

1919
File.rm(path)
2020
end
21+
22+
test "creates database path on disk when non-existant" do
23+
{:ok, path} = Temp.path()
24+
{:ok, conn} = Sqlite3.open(path <> "/non_exist")
25+
26+
assert conn
27+
28+
File.rm(path)
29+
end
2130
end
2231

2332
describe ".close/2" do

0 commit comments

Comments
 (0)