Yet another SQLite binding for SWI-Prolog

With great trepidation I announce the 0.1 version of the swiplite pack (add-on). It is not ready but it can already be used; or at least looked at.

The code is available at GitHub - borisvassilev/swiplite: SQLite for SWI-Prolog.

You should be able to clone it and see what is in there. I have tried to document it. There is a README; there is also a DEVELOPMENT readme. If you manage to follow the instructions there you’d be able to access the predicate documentation by starting a local PlDoc server.

If you are brave you can install the pack using the two releases. “Latest” is currently 0.1. You can use for example:

?- pack_install(swiplite,
   [url('https://github.com/borisvassilev/swiplite/archive/0.1.zip')]).

I have doubts about everything:

  • was such a binding really necessary?
  • the license
  • names: the pack, the library, the predicates…
  • error handling
  • documentation style

and so on. Any feedback is greatly appreciated.

One additional note: you might remember this post. There I asked if it is a good idea to embed the full SQLite source code in the source distribution of this pack. In order to avoid this question, I now have, in addition to the main branch, a branch called sqlite3-amalgamation which includes the latest SQLite source, instead of using the SQLite installation that CMake finds on your system. This is available as release 0.1.1, so:

?- pack_install(swiplite,
   [url('https://github.com/borisvassilev/swiplite/archive/0.1.1.zip')]).

Either way, you should be able to see something along these lines:

?- use_module(library(sqlite)).
true.

?- sqlite_open(foo, DB, [memory(true)]),
   sqlite_prepare(DB, "select sqlite_version()", S),
   sqlite_eval(S, row(V)),
   sqlite_finalize(S),
   sqlite_close(DB).
DB = <sqlite_connection>(closed),
S = <sqlite_statement>(finalized),
V = "3.47.1".

As you see, this is very low-level. You should be using setup_call_cleanup/3 anyway. You can look at the tests to get an idea how to use it. I will share any useful higher-level library once I have one.

One final note: This is a hobby project. I don’t believe that this competes, in terms of features, with any of the currently available methods to use SQLite from SWI-Prolog. It is written by me from scratch; but I did read quite a bit of the code I found in SWI-Prolog · GitHub.

You make that hard to judge as you do not say what motivated you to create it :slight_smile: Just bundling sqlite should not be enough. You could simply have created a package derived from https://www.swi-prolog.org/pack/list?p=prosqlite.

You can also use the quite rich ODBC interface. But yes, setting up ODBC can be cumbersome (depending on your environment). I’d suspect a native binding to be easier to manage and faster.

As for the license, I’d go for something more permissive. Both SWI-Prolog and SQlite have permissive licenses. Using the GPL effectively turns everything into GPL at the moment someone adds your pack to his/her project.

1 Like

My meta-comment is: why did you decide to use C instead of C++? The latter should be both easier to use and less error-prone (e.g., handling errors and cleanup) than the C interface; there is a small performance hit but I think it’s unlikely to cause problems. (If you do use C++, be sure to use the new version: SWI-cpp2.h.)

I didn’t want to influence anyone’s judgement by selling it too hard. :slight_smile: I was not able to figure out how to use SQL parameters and bind values to them with prosqlite. The garbage collection through the blob interface was also a bit unclear so I did it quite differently.

I will change the license maybe.

Because I don’t know how to program, esp in C++. Learning C++ might be my next hobby project.

You can mostly use C++ as a “better C than C”. And I’ve tried to document the trickier uses of “smart pointers” and RAII – if the documentation isn’t good enough, please send me feedback!

BTW, as you’re “learning” … what development environment and platform are you using?

I use a text editor? I have a Linux and a Mac OS and have tried to test both with this particular pack.

If you mean this “amalgamation” thing, I guess I just like the sound of it. There is no reason to use it on any Linux or Mac OS, since both have SQLite installed, and if not, it can be obtained from a package manager. I added the option to use it because it was easy. I wanted to learn how to distribute a pack.

I am not even sure if it is a good idea to offer two different versions, nor if using the 0.1 and the 0.1.1 to distinguish them.

By what magic did this pack end up here: "swiplite" pack for SWI-Prolog ??

I don’t think it was ready for that kind of publishing. Also, somehow the 0.1.1 ended up there and this shouldn’t have happened, either. I have marked the 0.1 release as “Latest” in GitHub. I guess I need to read more :smiley:

Should I have used:

?- pack_install(swiplite,
   [ url('https://github.com/borisvassilev/swiplite/archive/0.1.zip'),
     register(false)
   ]).

??

4 posts were split to a new topic: Pack publish policies

I now added proper installation instructions and some background on why this work was necessary in the README.

1 Like

This interface makes sense to me. I do miss an sqlite_eval(++Statement, -Row) as nondet predicate. That allows for a comfortable definition of a normal Prolog predicate based on an SQL query, as well as providing comfortable access to too many rows to fit in memory. You can build that on top of sqlite_eval/4 with some work, but that looks clumsy (and probably slower than it needs to be). You could also define an API that is compatible to lazy_list/2, such that you can provide a list view on an arbitrary large set of rows.

I haven’t looked at it. but it would be nice if the data representation is compatible with the ODBC and ProSQlite packs as far as possible, such that you can easily switch between these.

1 Like

Thank you for the feedback. I specifically defined sqlite_eval/4 as it is now because I thought this can be used with lazy_list/2, in order to be able to then use member/2 on that list to get the backtracking semidet predicate you descibe. I will revisit this for certain since this was the intent anyway.

As speed seems to be one of the intends of the low-level statement oriented approach, adding a foreign nondet predicate will quite likely outperform the lazy list approach, in particular if there are only a few results. That may be different if you cannot cheaply use the same statement in multiple backtracking queries.

1 Like

There is now a V0.3 release available for installation. The full code is as before at GitHub - borisvassilev/swiplite: SQLite for SWI-Prolog. I changed the license to MIT and added a predicate that fetches result rows on backtracking.

Now I really should use this for a while to get rid of all the design errors and bugs.

1 Like