Skip to content

Commit 639e362

Browse files
authored
feat: do not create temporary file before opening connection
prior behaviour was to temporarily create a non-existing db-file to test for write-permission removed such test, and rely on the native code to throw an error if permissions are insufficient Closes: xerial#1260
1 parent f3dff86 commit 639e362

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed

src/main/java/org/sqlite/SQLiteConnection.java

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -251,26 +251,7 @@ private static DB open(String url, String origFileName, Properties props) throws
251251
throw new SQLException(String.format("failed to load %s: %s", resourceName, e));
252252
}
253253
} else {
254-
File file = new File(fileName).getAbsoluteFile();
255-
File parent = file.getParentFile();
256-
if (parent != null && !parent.exists()) {
257-
for (File up = parent; up != null && !up.exists(); ) {
258-
parent = up;
259-
up = up.getParentFile();
260-
}
261-
throw new SQLException(
262-
"path to '" + fileName + "': '" + parent + "' does not exist");
263-
}
264-
265-
// check write access if file does not exist
266-
try {
267-
// The extra check to exists() is necessary as createNewFile()
268-
// does not follow the JavaDoc when used on read-only shares.
269-
if (!file.exists() && file.createNewFile()) file.delete();
270-
} catch (Exception e) {
271-
throw new SQLException("opening db: '" + fileName + "': " + e.getMessage());
272-
}
273-
fileName = file.getAbsolutePath();
254+
fileName = new File(fileName).getAbsolutePath();
274255
}
275256
}
276257

src/test/java/org/sqlite/ConnectionTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import java.io.FileOutputStream;
77
import java.io.IOException;
88
import java.io.InputStream;
9+
import java.nio.file.AccessDeniedException;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.nio.file.Paths;
913
import java.sql.*;
1014
import java.util.ArrayList;
1115
import java.util.Properties;
@@ -14,6 +18,8 @@
1418
import java.util.concurrent.Executors;
1519
import java.util.concurrent.Future;
1620
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.api.condition.DisabledOnOs;
22+
import org.junit.jupiter.api.condition.OS;
1723
import org.junit.jupiter.api.io.TempDir;
1824
import org.sqlite.SQLiteConfig.JournalMode;
1925
import org.sqlite.SQLiteConfig.Pragma;
@@ -409,4 +415,49 @@ public void overrideURIPragmaValuesWithProperties() throws Exception {
409415
stat.close();
410416
conn.close();
411417
}
418+
419+
@Test
420+
public void openNonExistingFileNoCreate() {
421+
Path nonExisting = Paths.get("non_existing.db").toAbsolutePath();
422+
assertThat(Files.exists(nonExisting)).isFalse();
423+
SQLiteConfig cfg = new SQLiteConfig();
424+
cfg.resetOpenMode(SQLiteOpenMode.CREATE);
425+
assertThatExceptionOfType(SQLiteException.class)
426+
.isThrownBy(
427+
() -> {
428+
@SuppressWarnings({"resource", "unused"})
429+
Connection _c = cfg.createConnection("jdbc:sqlite:" + nonExisting);
430+
})
431+
.satisfies(
432+
e ->
433+
assertThat(e.getResultCode())
434+
.isEqualTo(SQLiteErrorCode.SQLITE_CANTOPEN));
435+
assertThat(Files.exists(nonExisting)).isFalse();
436+
}
437+
438+
@DisabledOnOs(OS.WINDOWS) // File.setReadOnly doesn't seem to work here
439+
@Test
440+
public void openNonExistingFileInReadOnlyDirectory(@TempDir Path tmpDir) {
441+
assertThat(tmpDir.toFile().setReadOnly()).isTrue();
442+
assertThat(Files.exists(tmpDir)).isTrue();
443+
Path nonExisting = tmpDir.resolve("non_existing.db").toAbsolutePath();
444+
assertThatThrownBy(() -> Files.createFile(nonExisting))
445+
.isInstanceOf(AccessDeniedException.class);
446+
assertThat(Files.exists(nonExisting)).isFalse();
447+
SQLiteConfig cfg = new SQLiteConfig();
448+
assertThatExceptionOfType(SQLiteException.class)
449+
.isThrownBy(
450+
() -> {
451+
@SuppressWarnings({"resource", "unused"})
452+
Connection _c = cfg.createConnection("jdbc:sqlite:" + nonExisting);
453+
})
454+
.satisfies(
455+
e ->
456+
// It would be nice, if the native error code were more specific on
457+
// why the file can't be
458+
// opened, but this is what we get:
459+
assertThat(e.getResultCode())
460+
.isEqualTo(SQLiteErrorCode.SQLITE_CANTOPEN));
461+
assertThat(Files.exists(nonExisting)).isFalse();
462+
}
412463
}

0 commit comments

Comments
 (0)