vrischmann / zig-sqlite

zig-sqlite is a small wrapper around sqlite's C API, making it easier to use with Zig.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't create a new database

greenfork opened this issue · comments

I have followed the instructions on the readme page to install the package. It works when the database file already exists but fails when there's no file. Here I have come up with a minimal example, copy these to files in a directory:

// build.zig
const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    var target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();
    const sqlite = b.addStaticLibrary("sqlite", null);
    sqlite.addCSourceFile("zig-sqlite/c/sqlite3.c", &[_][]const u8{"-std=c99"});
    sqlite.linkLibC();
    target.setGnuLibCVersion(2, 28, 0);

    const test_all = b.step("test", "Run tests");
    {
        const test_cases = b.addTest("test.zig");
        test_cases.use_stage1 = true;
        test_cases.linkLibC();
        test_cases.linkLibrary(sqlite);
        test_cases.addPackagePath("sqlite", "zig-sqlite/sqlite.zig");
        test_cases.addIncludeDir("zig-sqlite/c");
        test_cases.setTarget(target);
        test_cases.setBuildMode(mode);
        test_all.dependOn(&test_cases.step);
    }
}
// test.zig
const std = @import("std");
const testing = std.testing;
const sqlite = @import("sqlite");

test {
    var sqlite_diags = sqlite.Diagnostics{};
    var db = sqlite.Db.init(.{
        .mode = .{ .File = "/tmp/my1.db" },
        .open_flags = .{
            .write = true,
            .create = true,
        },
        .diags = &sqlite_diags,
    }) catch |err| {
        std.log.err("Unable to open a database, got error {}. Diagnostics: {s}", .{ err, sqlite_diags });
        return err;
    };
    _ = db;
}

Then in this directory do:

git clone https://github.com/vrischmann/zig-sqlite.git
zig build test

produces errors:

Test [1/1] test ""... [default] (err): Unable to open a database, got error error.SQLiteCantOpen. Diagnostics: {code: 14, near: -1, message: unable to open database file}
Test [1/1] test ""... FAIL (SQLiteCantOpen)
???:?:?: 0x23a9df in ??? (???)
???:?:?: 0x2371fa in ??? (???)
???:?:?: 0x234cc5 in ??? (???)
0 passed; 0 skipped; 1 failed.
1 errors were logged.
error: the following test command failed with exit code 1:
/home/grfork/playground/zig/sqlite-create/zig-cache/o/44494cb3e2811184d2e00efd590e9a75/test /home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/zig
error: test...
error: The following command exited with error code 1:
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/zig test -fstage1 /home/grfork/playground/zig/sqlite-create/test.zig -lc /home/grfork/playground/zig/sqlite-create/zig-cache/o/3949b424e2d7bce08f1f932ad6d308e5/libsqlite.a -lc --cache-dir /home/grfork/playground/zig/sqlite-create/zig-cache --global-cache-dir /home/grfork/.cache/zig --name test -target native-native-gnu.2.28 -mcpu=znver1+clwb+rdpid+wbnoinvd --pkg-begin sqlite /home/grfork/playground/zig/sqlite-create/zig-sqlite/sqlite.zig --pkg-end -I /home/grfork/playground/zig/sqlite-create/zig-sqlite/c --enable-cache
error: the following build command failed with exit code 1:
/home/grfork/playground/zig/sqlite-create/zig-cache/o/ac78f7eee61de2d365856bb219b09142/build /home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/zig /home/grfork/playground/zig/sqlite-create /home/grfork/playground/zig/sqlite-create/zig-cache /home/grfork/.cache/zig test

You need to set the target and mode on the sqlite library too:

    sqlite.setTarget(target);
    sqlite.setBuildMode(mode);

I'm not sure why it fails when not adding this.

And yeah it looks like the readme instructions are incomplete.

Added:

const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    var target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();
    const sqlite = b.addStaticLibrary("sqlite", null);
    sqlite.addCSourceFile("zig-sqlite/c/sqlite3.c", &[_][]const u8{"-std=c99"});
    sqlite.linkLibC();
    target.setGnuLibCVersion(2, 28, 0);
    sqlite.setTarget(target);
    sqlite.setBuildMode(mode);

    const test_all = b.step("test", "Run tests");
    {
        const test_cases = b.addTest("test.zig");
        test_cases.use_stage1 = true;
        test_cases.linkLibrary(sqlite);
        test_cases.addPackagePath("sqlite", "zig-sqlite/sqlite.zig");
        test_cases.addIncludeDir("zig-sqlite/c");
        test_cases.setTarget(target);
        test_cases.setBuildMode(mode);
        test_all.dependOn(&test_cases.step);
    }
}

same error.

Right, I accidentally executed the test with the file already existing so it passed.
I already saw this error some time ago but found no way to resolve it.

Building with musl instead works fine (zig build -Dtarget=native-linux-musl).

I did a little digging, the error SQLITE_CANTOPEN is ultimately due to a lstat call here.

For /tmp/my1.db there's two calls to this function and the last to osLstat returns -1 indicating an error but somehow errno is 0.
According to the manpage of lstat:

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set to indicate the error.

so I'm not sure what exactly is wrong here, especially since building with musl works fine.

Pretty sure it's this issue actually.

Wow, that is really great digging! Although compiling with musl doesn't work likely because of this bug, stacktrace below. I guess we will have to wait.

LLD Link... ld.lld: error: undefined symbol: fcntl64
>>> referenced by sqlite3.c
>>>               /home/grfork/reps/kisa/zig-cache/o/c2a889cf3c0c39e873430b7b2a06c1ae/sqlite3.o:(aSyscall) in archive /home/grfork/reps/kisa/zig-cache/o/fd2cb9b8210617d6e8799fc92a43893c/libsqlite.a
error: FileNotFound
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/io/reader.zig:141:39: 0x2b727e in readUntilDelimiter (build)
        /// large enough to hold the entire contents, `error.StreamTooLong` is returned.
                                      ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/os.zig:3072:19: 0x2b6a4f in readlinkZ (build)
        .INVAL => return error.NotLink,
                  ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/os.zig:3049:9: 0x2cdbd3 in readlink (build)
        return readlinkZ(&file_path_c, out_buffer);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/os.zig:2753:19: 0x29dc3c in mkdiratZ (build)
        .EXIST => return error.PathAlreadyExists,
                  ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/os.zig:2713:9: 0x28ba4d in mkdirat (build)
        return mkdiratZ(dir_fd, &sub_dir_path_c, mode);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/fs.zig:1361:9: 0x28b94b in makeDir (build)
        try os.mkdirat(self.fd, sub_path, default_new_dir_mode);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/os.zig:1683:23: 0x2d7060 in openatZ (build)
            .NOENT => return error.FileNotFound,
                      ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/fs.zig:1110:13: 0x2c212c in openFileZ (build)
            try os.openatZ(self.fd, sub_path, os_flags, 0);
            ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/fs.zig:1037:9: 0x2a8c5e in openFile (build)
        return self.openFileZ(&path_c, flags);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/fs.zig:2250:24: 0x31af00 in updateFile (build)
        var src_file = try source_dir.openFile(source_path, .{});
                       ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:1088:29: 0x32e6e7 in updateFile (build)
        const prev_status = try fs.Dir.updateFile(cwd, source_path, cwd, dest_path, .{});
                            ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:3420:9: 0x312e27 in make (build)
        try builder.updateFile(self.artifact.getOutputSource().getPath(builder), full_dest_path);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:3655:9: 0x29e037 in make (build)
        try self.makeFn(self);
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:508:9: 0x28c65a in makeOneStep (build)
        try s.make();
        ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:502:17: 0x28c5d2 in makeOneStep (build)
                return err;
                ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:502:17: 0x28c5d2 in makeOneStep (build)
                return err;
                ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:502:17: 0x28c5d2 in makeOneStep (build)
                return err;
                ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/std/build.zig:463:13: 0x28c338 in make (build)
            try self.makeOneStep(s);
            ^
/home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/lib/build_runner.zig:213:21: 0x28f17b in main (build)
            else => return err,
                    ^
error: the following build command failed with exit code 1:
/home/grfork/reps/kisa/zig-cache/o/23e6fb3e45833344747486887817bc72/build /home/grfork/zig-linux-x86_64-0.10.0-dev.3685+dae7aeb33/zig /home/grfork/reps/kisa /home/grfork/reps/kisa/zig-cache /home/grfork/.cache/zig -Dtarget=native-linux-musl run

This is weird, this linking error happens when building with glibc and not specifying the glibc version with

target.setGnuLibCVersion(2, 28, 0);

In your reproducer code you have to remove this line, then building with zig build test -Dtarget=native-linux-musl works for me.