Nicos sqlite interface
This commit is contained in:
parent
4d7b270ce4
commit
3268920dc8
16
packages/prosqlite/Makefile
Normal file
16
packages/prosqlite/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
SOBJ= $(PACKSODIR)/prosqlite.$(SOEXT)
|
||||
CFLAGS+=-std=c99
|
||||
LIBS= -lsqlite3
|
||||
|
||||
all: $(SOBJ)
|
||||
|
||||
$(SOBJ): c/prosqlite.o
|
||||
mkdir -p $(PACKSODIR)
|
||||
$(LD) $(LDSOFLAGS) -o $@ $(SWISOLIB) $< $(LIBS)
|
||||
|
||||
check::
|
||||
install::
|
||||
clean:
|
||||
rm -f c/prosqlite.o
|
||||
distclean: clean
|
||||
rm -f $(SOBJ)
|
85
packages/prosqlite/Makefile.in
Normal file
85
packages/prosqlite/Makefile.in
Normal file
@ -0,0 +1,85 @@
|
||||
################################################################
|
||||
# Makefile template for SWI-Prolog PROSQLITE interface
|
||||
#
|
||||
# This template is used by configure to create Makefile. See
|
||||
# the file INSTALL for further installation instructions.
|
||||
#
|
||||
# License: LGPL
|
||||
#
|
||||
# Author: Nicos Angelopoulos & Jan Wielemaker (jan@swi.psy.uva.nl)
|
||||
################################################################
|
||||
|
||||
PACKAGE=prosqlite
|
||||
DOC=prosqlite
|
||||
include ../Makefile.defs
|
||||
|
||||
CFLAGS+= @PROSQLITE_CFLAGS@ -I.
|
||||
LDSOFLAGS+= @PROSQLITE_LDFLAGS@
|
||||
|
||||
LIBS=@LIBS@
|
||||
NETLIBS=@NETLIBS@
|
||||
|
||||
LIBPL= @PROSQLITE_PLTARGETS@
|
||||
TARGETS= @PROSQLITE_TARGETS@
|
||||
|
||||
PROSQLITEOBJ= prosqlite.o
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
nolib::
|
||||
@echo "WARNING: Could not find sqlite library; skipped"
|
||||
|
||||
|
||||
prosqlite.o: $(srcdir)/c/prosqlite.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
prosqlite.@SO@: $(PROSQLITEOBJ)
|
||||
$(LD) $(LDSOFLAGS) -o $@ $(AROBJ) @PROSQLITE_LIBS@ $(LIBPLSO)
|
||||
|
||||
install: $(TARGETS) $(addprefix $(srcdir)/, $(LIBPL)) install-examples
|
||||
mkdir -p $(DESTDIR)$(SOLIBDIR)
|
||||
for f in $(TARGETS); do \
|
||||
[ "$$f" = nolib ] || $(INSTALL_PROGRAM) $$f $(DESTDIR)$(SOLIBDIR); \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(PLLIBDIR)
|
||||
for f in $(LIBPL); do \
|
||||
$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(PLLIBDIR); \
|
||||
done
|
||||
$(MKINDEX)
|
||||
|
||||
ln-install::
|
||||
@$(MAKE) INSTALL_DATA='../ln-install' INSTALL_PROGRAM='../ln-install' install
|
||||
|
||||
rpm-install: install
|
||||
|
||||
html-install::
|
||||
mkdir -p $(DESTDIR)$(PKGDOCDIR)
|
||||
$(INSTALL) -m 644 $(DOC).html $(DESTDIR)$(PKGDOCDIR)
|
||||
|
||||
pdf-install::
|
||||
mkdir -p $(DESTDIR)$(PKGDOCDIR)
|
||||
$(INSTALL) -m 644 $(DOC).pdf $(DESTDIR)$(PKGDOCDIR)
|
||||
|
||||
nnuninstall::
|
||||
(cd $(SOLIBDIR) && rm -f $(TARGETS))
|
||||
(cd $(PLLIBDIR) && rm -f $(LIBPL))
|
||||
$(PL) -f none -g make -t halt
|
||||
|
||||
################################################################
|
||||
# Check
|
||||
################################################################
|
||||
|
||||
check::
|
||||
|
||||
|
||||
################################################################
|
||||
# Clean
|
||||
################################################################
|
||||
|
||||
clean:
|
||||
rm -f $(AROBJ) *~ *.o *% a.out core config.log
|
||||
|
||||
distclean: clean
|
||||
rm -f $(TARGETS) config.cache config.h config.status Makefile
|
||||
rm -f $(DOC).aux $(DOC).log $(DOC).out $(DOC).toc
|
||||
rm -rf autom4te.cache
|
39
packages/prosqlite/Readme.txt
Normal file
39
packages/prosqlite/Readme.txt
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
proSQLite: a Prolog interface to the SQLite database system.
|
||||
--------------------
|
||||
|
||||
|
||||
This Prolog library was developed on SWI-Prolog 6.1.12 under linux.
|
||||
It should compile easily on linux or MACs. It is also likely
|
||||
that it compiles easily for YAP Prolog.
|
||||
|
||||
On SWI-Prolog is higly recommended that you install from with the engine
|
||||
via
|
||||
|
||||
?- pack_install( prosqlite ).
|
||||
|
||||
This takes care of everything and you can then load the library via
|
||||
|
||||
?- [library(prosqlite)].
|
||||
|
||||
If you need to compile from sources, edit buildenv.sh to fit your system
|
||||
and in a bourne-compatible shell do :
|
||||
|
||||
$ source env/buildenv.sh
|
||||
$ make
|
||||
|
||||
The publication corresponding to this library is :
|
||||
|
||||
Exploring file based databases via an Sqlite interface
|
||||
Canisius Sander, Nicos Angelopoulos and Lodewyk Wessels
|
||||
ICLP Workshop on Logic-based methods in Programming Environments (September, 2012. Budapest, Hungary).
|
||||
|
||||
|
||||
---------
|
||||
|
||||
|
||||
|
||||
Nicos Angelopoulos, November 2013. (0.1.0 @ August 2012)
|
||||
---
|
||||
http://stoics.org.uk/~nicos/
|
||||
nicos_mlists_06@yahoo.co.uk
|
345
packages/prosqlite/c/prosqlite.c
Normal file
345
packages/prosqlite/c/prosqlite.c
Normal file
@ -0,0 +1,345 @@
|
||||
#include <sqlite3.h>
|
||||
#include <SWI-Stream.h>
|
||||
#include <SWI-Prolog.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
atom_t row_atom;
|
||||
functor_t minus2_functor;
|
||||
|
||||
static atom_t ATOM_true;
|
||||
static atom_t ATOM_false;
|
||||
|
||||
|
||||
int PL_SQLite_Connection_release(atom_t connection)
|
||||
{
|
||||
printf("release\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PL_blob_t PL_SQLite_Connection = {
|
||||
PL_BLOB_MAGIC,
|
||||
PL_BLOB_UNIQUE | PL_BLOB_NOCOPY,
|
||||
"SQLiteConnection",
|
||||
PL_SQLite_Connection_release, // release
|
||||
0, // compare
|
||||
0, // write
|
||||
0 // acquire
|
||||
};
|
||||
|
||||
|
||||
static foreign_t c_sqlite_connect(term_t filename, term_t connection)
|
||||
{
|
||||
char *filename_c;
|
||||
|
||||
if (PL_get_atom_chars(filename, &filename_c))
|
||||
{
|
||||
sqlite3* handle;
|
||||
if (sqlite3_open(filename_c, &handle) == SQLITE_OK)
|
||||
{
|
||||
return PL_unify_blob(connection, handle, sizeof(sqlite3*),
|
||||
&PL_SQLite_Connection);
|
||||
}
|
||||
}
|
||||
|
||||
PL_free(filename_c);
|
||||
PL_fail;
|
||||
}
|
||||
|
||||
|
||||
static foreign_t c_sqlite_disconnect(term_t connection)
|
||||
{
|
||||
sqlite3* db;
|
||||
if (PL_get_blob(connection, (void**)&db, 0, 0))
|
||||
{
|
||||
if (sqlite3_close(db) == SQLITE_OK)
|
||||
{
|
||||
PL_succeed;
|
||||
} else {
|
||||
printf("SQLite returned error at closing database \n");
|
||||
PL_fail;
|
||||
};
|
||||
}
|
||||
|
||||
printf("could not get connection to close \n");
|
||||
PL_fail;
|
||||
}
|
||||
|
||||
|
||||
typedef struct query_context
|
||||
{
|
||||
sqlite3_stmt* statement;
|
||||
functor_t row_functor;
|
||||
int num_columns;
|
||||
int* column_types;
|
||||
} query_context;
|
||||
|
||||
|
||||
query_context* new_query_context(sqlite3_stmt* statement)
|
||||
{
|
||||
int i;
|
||||
|
||||
query_context* context = (query_context*)malloc(sizeof(query_context));
|
||||
context->num_columns = sqlite3_column_count(statement);
|
||||
context->row_functor = PL_new_functor(row_atom, context->num_columns);
|
||||
context->statement = statement;
|
||||
|
||||
context->column_types = (int*)malloc(sizeof(int) * context->num_columns);
|
||||
for (i = 0; i < context-> num_columns; i++)
|
||||
context->column_types[i] = sqlite3_column_type(statement, i);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
void free_query_context(query_context* context)
|
||||
{
|
||||
sqlite3_finalize(context->statement);
|
||||
free(context->column_types);
|
||||
free(context);
|
||||
}
|
||||
|
||||
|
||||
int unify_row_term(term_t row, query_context* context)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!PL_unify_functor(row, context->row_functor))
|
||||
PL_fail;
|
||||
|
||||
for (i = 0; i < context->num_columns; i++)
|
||||
{
|
||||
term_t col_term = PL_new_term_ref();
|
||||
|
||||
switch (context->column_types[i])
|
||||
{
|
||||
case SQLITE_INTEGER:
|
||||
if ( !PL_put_integer(col_term, sqlite3_column_int(context->statement, i)) )
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case SQLITE_FLOAT:
|
||||
if ( !PL_put_float(col_term, sqlite3_column_double(context->statement, i)) )
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case SQLITE_TEXT:
|
||||
if (sqlite3_column_bytes(context->statement,i))
|
||||
PL_put_atom_chars(col_term, sqlite3_column_text(context->statement, i));
|
||||
else
|
||||
// this should probably never be the case (should be SQLITE_NULL) but firefox's places.sqlite
|
||||
// has 0 length texts
|
||||
PL_put_atom_chars(col_term, "" );
|
||||
|
||||
break;
|
||||
|
||||
case SQLITE_BLOB:
|
||||
// TODO: what prolog type should BLOBs be mapped to?
|
||||
// PL_put_blob?
|
||||
break;
|
||||
|
||||
case SQLITE_NULL:
|
||||
// TODO: what about this?
|
||||
// PL_put_nil?
|
||||
if (sqlite3_column_bytes(context->statement,i))
|
||||
// this should probably never be the case (should be SQLITE_TEXT?) but firefox's places.sqlite
|
||||
// has non 0 length nulls
|
||||
PL_put_atom_chars(col_term, sqlite3_column_text(context->statement, i));
|
||||
else
|
||||
// PL_put_nil(col_term) // would be more correct probably
|
||||
PL_put_atom_chars(col_term, "" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PL_unify_arg(i + 1, row, col_term))
|
||||
PL_fail;
|
||||
}
|
||||
|
||||
PL_succeed;
|
||||
}
|
||||
|
||||
static foreign_t c_sqlite_version(term_t ver, term_t datem)
|
||||
{
|
||||
term_t tmp = PL_new_term_ref();
|
||||
|
||||
if ( PL_unify_term(tmp,PL_FUNCTOR_CHARS,":",2,PL_INT, 1, PL_INT, 2) && // Minor + Fix
|
||||
PL_unify_term(ver,PL_FUNCTOR_CHARS,":",2,PL_INT, 0, PL_TERM, tmp ) && // Major
|
||||
PL_unify_term(datem,PL_FUNCTOR_CHARS,"date",3,PL_INT, 2013, PL_INT, 11, PL_INT, 1) )
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
// PL_unify_term(ver,PL_FUNCTOR_CHARS,":",1,PL_CHARS,
|
||||
}
|
||||
|
||||
int raise_sqlite_exception(sqlite3* db)
|
||||
{
|
||||
term_t except = PL_new_term_ref();
|
||||
if ( PL_unify_term(except,
|
||||
PL_FUNCTOR_CHARS, "sqlite_error", 2,
|
||||
PL_INT, sqlite3_errcode(db),
|
||||
PL_CHARS, sqlite3_errmsg(db)) )
|
||||
return PL_raise_exception(except);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Copied and adapted from the odbc package
|
||||
int formatted_string(term_t in, char** out)
|
||||
{
|
||||
term_t av = PL_new_term_refs(3);
|
||||
static predicate_t format;
|
||||
//char *out = NULL;
|
||||
size_t len = 0;
|
||||
*out = NULL;
|
||||
IOSTREAM *fd = Sopenmem(out, &len, "w");
|
||||
|
||||
if (!fd)
|
||||
return FALSE; /* resource error */
|
||||
if (!format)
|
||||
format = PL_predicate("format", 3, "user");
|
||||
|
||||
if (!PL_unify_stream(av+0, fd) ||
|
||||
!PL_get_arg(1, in, av+1) ||
|
||||
!PL_get_arg(2, in, av+2) ||
|
||||
!PL_call_predicate(NULL, PL_Q_PASS_EXCEPTION, format, av))
|
||||
{
|
||||
Sclose(fd);
|
||||
if (*out)
|
||||
PL_free(*out);
|
||||
return FALSE;
|
||||
}
|
||||
Sclose(fd);
|
||||
|
||||
if (*out)
|
||||
PL_free(*out);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int get_query_string(term_t tquery, char** query)
|
||||
{
|
||||
if (PL_is_functor(tquery, minus2_functor))
|
||||
return formatted_string(tquery, query);
|
||||
else
|
||||
return PL_get_chars(tquery, query, CVT_ATOM|CVT_STRING|BUF_MALLOC|REP_UTF8);
|
||||
}
|
||||
|
||||
|
||||
// Jan says "You must call PL_free() on the query strings after you are done with them!"
|
||||
// fixme: check here or at Prolog that Connection/Alias IS open: otherwise
|
||||
// we get sqlite_error(21,library routine called out of sequence)
|
||||
static foreign_t c_sqlite_query(term_t connection, term_t query, term_t row,
|
||||
control_t handle)
|
||||
{
|
||||
sqlite3* db;
|
||||
query_context* context;
|
||||
term_t tmp = PL_new_term_ref();
|
||||
int changes = 0;
|
||||
|
||||
switch (PL_foreign_control(handle))
|
||||
{
|
||||
case PL_FIRST_CALL:
|
||||
PL_get_blob(connection, (void**)&db, 0, 0);
|
||||
|
||||
char* query_c;
|
||||
sqlite3_stmt* statement;
|
||||
if (!get_query_string(query, &query_c))
|
||||
{
|
||||
PL_free(query_c);
|
||||
PL_fail;
|
||||
};
|
||||
|
||||
if (sqlite3_prepare(db, query_c, -1, &statement, 0) != SQLITE_OK)
|
||||
{ PL_free(query_c);
|
||||
return raise_sqlite_exception(db);
|
||||
}
|
||||
|
||||
PL_free(query_c);
|
||||
|
||||
bool recurrent = false;
|
||||
switch (sqlite3_step(statement))
|
||||
{
|
||||
case SQLITE_ROW:
|
||||
context = new_query_context(statement);
|
||||
recurrent = true;
|
||||
if ( unify_row_term(row, context) )
|
||||
PL_retry_address(context);
|
||||
/*FALLTHROUGH*/
|
||||
case SQLITE_DONE:
|
||||
if (recurrent)
|
||||
{
|
||||
free_query_context(context);
|
||||
PL_fail;
|
||||
} else
|
||||
{
|
||||
|
||||
int what = sqlite3_column_count(statement);
|
||||
if (what) { /* >0 means statement is supposed to return results */
|
||||
sqlite3_finalize(statement);
|
||||
PL_fail;
|
||||
}
|
||||
else { /* statement is a INSERT/DELETE/UPDATE which do not return anything */
|
||||
context = new_query_context(statement);
|
||||
changes = sqlite3_changes(db);
|
||||
if (PL_unify_term(tmp,PL_FUNCTOR_CHARS,"row",1,PL_INT64, (int)changes))
|
||||
if( !PL_unify(row,tmp) )
|
||||
{ free_query_context(context);
|
||||
PL_fail;}
|
||||
free_query_context(context);
|
||||
PL_succeed;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
case PL_REDO:
|
||||
|
||||
context = PL_foreign_context_address(handle);
|
||||
switch (sqlite3_step(context->statement))
|
||||
{
|
||||
case SQLITE_ROW:
|
||||
if ( unify_row_term(row, context) )
|
||||
PL_retry_address(context);
|
||||
/*FALLTHROUGH*/
|
||||
case SQLITE_DONE:
|
||||
free_query_context(context);
|
||||
PL_fail;
|
||||
}
|
||||
|
||||
case PL_PRUNED:
|
||||
context = PL_foreign_context_address(handle);
|
||||
free_query_context(context);
|
||||
PL_succeed;
|
||||
}
|
||||
|
||||
PL_fail;
|
||||
}
|
||||
|
||||
|
||||
install_t install_prosqlite()
|
||||
{
|
||||
|
||||
ATOM_true = PL_new_atom("true");
|
||||
ATOM_false = PL_new_atom("false");
|
||||
|
||||
row_atom = PL_new_atom("row");
|
||||
minus2_functor = PL_new_functor(PL_new_atom("-"), 2);
|
||||
PL_register_foreign("c_sqlite_version", 2, c_sqlite_version, 0);
|
||||
PL_register_foreign("c_sqlite_connect", 2, c_sqlite_connect, 0);
|
||||
PL_register_foreign("c_sqlite_disconnect", 1, c_sqlite_disconnect, 0);
|
||||
PL_register_foreign("c_sqlite_query", 3, c_sqlite_query,
|
||||
PL_FA_NONDETERMINISTIC);
|
||||
}
|
||||
|
||||
|
||||
install_t uninstall_prosqlite()
|
||||
{
|
||||
PL_unregister_atom(row_atom);
|
||||
PL_unregister_blob_type(&PL_SQLite_Connection);
|
||||
}
|
81
packages/prosqlite/configure.in
Normal file
81
packages/prosqlite/configure.in
Normal file
@ -0,0 +1,81 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
m4_ifdef([HAS_TOP],[m4_ignore],[
|
||||
AC_INIT(install-sh)
|
||||
AC_PREREQ([2.50])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
])
|
||||
|
||||
PKG_PROSQLITE="packages/prosqlite"
|
||||
AC_SUBST(PKG_PROSQLITE)
|
||||
|
||||
AC_SUBST(PROSQLITE_TARGETS)
|
||||
AC_SUBST(PROSQLITE_PLTARGETS)
|
||||
AC_SUBST(PROSQLITE_CFLAGS)
|
||||
AC_SUBST(PROSQLITE_LDFLAGS)
|
||||
AC_SUBST(PROSQLITE_LIBS)
|
||||
|
||||
m4_ifdef([HAS_TOP],[m4_ignore],[
|
||||
m4_include([../ac_swi_c.m4])
|
||||
])
|
||||
|
||||
yap_cv_prosqlite=yes
|
||||
|
||||
yap_cv_prosqlite=yes
|
||||
AC_ARG_WITH(sqlite,
|
||||
[ --with-prosqlite(=location) interface to sqlite],
|
||||
if test "$withval" = yes; then
|
||||
PROSQLITE_DIR=/usr
|
||||
elif test "$withval" = no; then
|
||||
yap_cv_prosqlite=no
|
||||
else
|
||||
PROSQLITE_DIR=$withval
|
||||
fi,
|
||||
[PROSQLITE_DIR=/usr ])
|
||||
|
||||
havelib=no
|
||||
|
||||
if test $yap_cv_prosqlite = yes; then
|
||||
OCFLAGS="${CFLAGS}"
|
||||
OCPPFLAGS="${CPPFLAGS}"
|
||||
OCIFLAGS="${CIFLAGS}"
|
||||
OLDFLAGS="${LDFLAGS}"
|
||||
|
||||
if test ! -z "$PROSQLITE_DIR"; then
|
||||
PROSQLITE_CFLAGS="-I${PROSQLITE_DIR}/include"
|
||||
PROSQLITE_LDFLAGS="-L${PROSQLITE_DIR}/lib"
|
||||
CFLAGS="-I${PROSQLITE_DIR}/include ${CFLAGS}"
|
||||
CPPFLAGS="-I${PROSQLITE_DIR}/include ${CPPFLAGS}"
|
||||
CIFLAGS="-I${PROSQLITE_DIR}/include ${CIFLAGS}"
|
||||
LDFLAGS="-L${PROSQLITE_DIR}/lib ${LDFLAGS}"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(sqlite3, sqlite3_open,
|
||||
PROSQLITE_LIBS="-lsqlite3 $LIBS"
|
||||
havelib=yes)
|
||||
|
||||
AC_CHECK_HEADERS(sqlite3.h, [], [])
|
||||
|
||||
CFLAGS="${OCFLAGS}"
|
||||
CPPFLAGS="${OCPPFLAGS}"
|
||||
CIFLAGS="${OCIFLAGS}"
|
||||
LDFLAGS="${OLDFLAGS}"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test "$havelib" = yes &&
|
||||
test "$ac_cv_header_sqlite3_h" = yes; then
|
||||
PROSQLITE_TARGETS="prosqlite.$SO"
|
||||
PROSQLITE_PLTARGETS="prolog/prosqlite.pl"
|
||||
else
|
||||
echo "ERROR: Cannot find odbc library or the header sql.h"
|
||||
echo "WARNING: PROSQLITE interface will not be built"
|
||||
PROSQLITE_TARGETS=""
|
||||
fi
|
||||
|
||||
m4_ifdef([HAS_TOP],[m4_ignore],[
|
||||
AC_OUTPUT(Makefile)
|
||||
])
|
||||
|
||||
|
343
packages/prosqlite/doc/pldoc.css
Normal file
343
packages/prosqlite/doc/pldoc.css
Normal file
@ -0,0 +1,343 @@
|
||||
/* $Id$
|
||||
|
||||
CSS for PlDoc, the SWI-Prolog source documentation system
|
||||
Author: Jan Wielemaker
|
||||
Copying: Public domain
|
||||
|
||||
For a tutorial on CSS, see
|
||||
<http://www.htmldog.com/guides/cssbeginner/selectors/>
|
||||
*/
|
||||
|
||||
h1.file, h1.module, h1.dir, h1.wiki
|
||||
{ background: url("h1-bg.png") top left;
|
||||
}
|
||||
|
||||
h2.wiki
|
||||
{ background: url("h2-bg.png") top left;
|
||||
}
|
||||
|
||||
.undef
|
||||
{ color: red;
|
||||
}
|
||||
|
||||
a.builtin
|
||||
{ color: navy;
|
||||
}
|
||||
|
||||
.defbody
|
||||
{ margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.arglist
|
||||
{ font-style: italic;
|
||||
}
|
||||
|
||||
table.paramlist td
|
||||
{ vertical-align: top;
|
||||
}
|
||||
|
||||
.pred, .det, .functor
|
||||
{ font-weight: bold;
|
||||
}
|
||||
|
||||
span.pred-tag
|
||||
{ float: right;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
color: #202020;
|
||||
}
|
||||
|
||||
dl.tags dt
|
||||
{ font-weight: bold;
|
||||
}
|
||||
|
||||
dt.keyword-bug, dt.keyword-deprecated, dt.keyword-tbd
|
||||
{ font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
dt.pubdef
|
||||
{ background: url("pub-bg.png") top left;
|
||||
}
|
||||
|
||||
dt.multidef
|
||||
{ background: url("multi-bg.png") top left;
|
||||
}
|
||||
|
||||
dt.privdef
|
||||
{ background: url("priv-bg.png") top left;
|
||||
}
|
||||
|
||||
dt.undoc, h2.undoc
|
||||
{ background-color: #ffbc87;
|
||||
}
|
||||
|
||||
img.action
|
||||
{ border: 0;
|
||||
padding-top: 0.2em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
dl.tags
|
||||
{ font-size: 80%;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
dl.latex, ul.latex, ol.latex
|
||||
{ margin-top: 0.7em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
dl.termlist
|
||||
{ margin-top: 0.7em;
|
||||
margin-bottom: 1em;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
dl.undoc
|
||||
{ margin-top: 0.7em;
|
||||
}
|
||||
|
||||
dl.wiki
|
||||
{ margin-top: 0.7em;
|
||||
margin-bottom: 1em;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
dl.wiki dt
|
||||
{ font-weight: bold;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.argdescr
|
||||
{ padding-left: 1em;
|
||||
}
|
||||
|
||||
table.wiki
|
||||
{ margin-top: 0.7em;
|
||||
margin-left: 1.5em;
|
||||
border: 1px outset blue;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
table.wiki td
|
||||
{ border: 1px inset gray;
|
||||
padding: 3px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
img.icon
|
||||
{ border: 0;
|
||||
height: 32px;
|
||||
float: right;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
pre.code
|
||||
{ margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
border: 1px dotted;
|
||||
padding-top: 5px;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 5px;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* Navigation bar */
|
||||
|
||||
div.navhdr
|
||||
{ border: 1px dotted;
|
||||
padding: 5px 5px 3px 5px; /* top,right,bottom,left */
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
div.navhdr div.jump
|
||||
{ float: left;
|
||||
}
|
||||
|
||||
div.navhdr div.search
|
||||
{ float: right;
|
||||
}
|
||||
|
||||
div.src_formats
|
||||
{ text-align: right;
|
||||
color: #444;
|
||||
font: smaller;
|
||||
border: 1px #ccc solid;
|
||||
padding-right: 5px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Summary index */
|
||||
|
||||
table.summary
|
||||
{ width: 100%;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
table.summary th.category
|
||||
{ text-align: center;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
border: 1px dotted;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.4em;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
table.summary th.section
|
||||
{ text-align: left;
|
||||
background-color: #bbffba;
|
||||
}
|
||||
|
||||
table.summary th
|
||||
{ text-align: left;
|
||||
background-color: #b9daff;
|
||||
}
|
||||
|
||||
table.summary td
|
||||
{ /*overflow:hidden; white-space:nowrap; text-overflow:ellipsis;*/
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
tr.private
|
||||
{ color: #707070;
|
||||
background-color: #fbffa6;
|
||||
}
|
||||
|
||||
/* Search */
|
||||
|
||||
span.for
|
||||
{ font-style: italic;
|
||||
}
|
||||
|
||||
div.search-results
|
||||
{ font-size: larger;
|
||||
font-weight: bold;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div.search-counts
|
||||
{ font-style: italic;
|
||||
font-size: smaller;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.search-options
|
||||
{ font-size: 70%;
|
||||
}
|
||||
|
||||
span.search-in, span.search-match
|
||||
{ border: 1px inset;
|
||||
padding: 3px 5px 1px 1px;
|
||||
}
|
||||
|
||||
span.search-help
|
||||
{ padding-left: 1em;
|
||||
}
|
||||
|
||||
div.synopsis
|
||||
{ text-align: right;
|
||||
margin-top: 15pt;
|
||||
}
|
||||
|
||||
span.synopsis-hdr
|
||||
{ font-weight: bold;
|
||||
padding-right: 1ex;
|
||||
}
|
||||
|
||||
div.synopsis code
|
||||
{ background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
span.autoload, span.builtin, span.cfunc
|
||||
{ margin-left: 5pt;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
span.anot
|
||||
{ float: right;
|
||||
margin-right: 5pt;
|
||||
font-style: italic;
|
||||
font-size: smaller;
|
||||
padding-top: 0.2em;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
span.file_anot
|
||||
{ vertical-align: text-top;
|
||||
margin-right: 5pt;
|
||||
font-style: italic;
|
||||
font-size: 60%;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
/* Footnotes from latex2html */
|
||||
sup.fn { color: blue; text-decoration: underline; }
|
||||
span.fn-text { display: none; }
|
||||
sup.fn span {display: none;}
|
||||
sup:hover span
|
||||
{ display: block !important;
|
||||
position: absolute; top: auto; left: auto; width: 80%;
|
||||
color: #000; background: white;
|
||||
border: 2px solid;
|
||||
padding: 5px; margin: 10px; z-index: 100;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
span.sec-nr
|
||||
{
|
||||
}
|
||||
|
||||
span.sec-title
|
||||
{ margin-left: 0.5em;
|
||||
}
|
||||
|
||||
/* Listing support */
|
||||
|
||||
dl.comment, div.comment
|
||||
{ color: #006400;
|
||||
border: 2px inset;
|
||||
padding: 5px 5px 0px 5px;
|
||||
|
||||
background-color: #e5e5e5;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
pre.listing
|
||||
{ margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
span.line-no
|
||||
{ font-weight: normal;
|
||||
font-size: 0.8em;
|
||||
color: #505050;
|
||||
background-color: white;
|
||||
border: 1px inset;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
div.comment h1.module
|
||||
{ margin-top: 0;
|
||||
}
|
||||
|
||||
a.prolog_version
|
||||
{ font-style: italic;
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
a.nofile /* non-existing file-link */
|
||||
{ color: black;
|
||||
font-family: monospace;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.nofile:hover /* non-existing file-link */
|
||||
{ color: red;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
311
packages/prosqlite/doc/prosqlite.html
Normal file
311
packages/prosqlite/doc/prosqlite.html
Normal file
@ -0,0 +1,311 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>prosqlite.pl</title>
|
||||
<link href="pldoc.css" rel="stylesheet" type="text/css">
|
||||
<meta
|
||||
http-equiv="content-type"
|
||||
content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navhdr">
|
||||
<div class="jump">
|
||||
<div>
|
||||
<a class="prolog_version" href="http://www.swi-prolog.org"> SWI-Prolog 6.3.19</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search">
|
||||
</div>
|
||||
<br clear="right">
|
||||
</div>
|
||||
<h1 class="file">prosqlite.pl -- proSQLite: a Prolog interface to the SQLite database system.</h1>
|
||||
<p>This library follows the design and borrows code from the ODBC library of SWI-Prolog
|
||||
<a
|
||||
href="http://www.swi-prolog.org/pldoc/packasqlite_connectge/odbc.html">http://www.swi-prolog.org/pldoc/packasqlite_connectge/odbc.html</a> .</p>
|
||||
<p>The SQLite system is a powerful zero-configuration management systme that interacts
|
||||
with single-file databases that are cross-platform compatible binaries.</p>
|
||||
<p>ProSQLite provides three layers of interaction with SQLite databases.
|
||||
At the lower level is the querying via SQL statements. A second layer
|
||||
allows the interogation of the database dictionary, and the final level
|
||||
facilitates the viewing of database tables as predicates.
|
||||
See the publication pointed to by <a href="#sqlite_citation/2">sqlite_citation/2</a>, for further details.
|
||||
If you use prosqlite in your research, please consider citing this publication.</p>
|
||||
<p>The library has been developed and tested on SWI 6.3.2 but it should
|
||||
also work on YAP Prolog.</p>
|
||||
<p>The easiest way to install on SWI is via the package manager.
|
||||
Simply do:</p>
|
||||
<pre class="code" ext=""> ?- pack_install( prosqlite ).</pre>
|
||||
<p>And you are good to go.</p>
|
||||
<p>There are good/full examples in the sources, directory examples/.
|
||||
For instance test by :</p>
|
||||
<pre class="code" ext=""> ?- [predicated].
|
||||
?- predicated.</pre>
|
||||
<p>There is a sister package, db_facts (also installable via the manager).
|
||||
Db_facts, allow interaction with the underlying database via Prolog terms,
|
||||
That library can also be used as a common compatibility layer for the ODBC
|
||||
and proSQLite libraries of SWI-Prolog, as it works on both type of connections.</p>
|
||||
<p>ProSQLite is <a href="/doc_for?object=prolog_debug:debug/1">debug/1</a> aware: call <code>debug(sqlite)</code> to see what is sent to
|
||||
the sqlite engine.</p>
|
||||
<p>There are MS wins DLLs included in the sources and recent version of the SWI package
|
||||
manager will install these properly.</p>
|
||||
<dl class="tags">
|
||||
<dt class="keyword-author">author</dt>
|
||||
<dd class="keyword-author">- Nicos Angelopoulos</dd>
|
||||
<dd class="keyword-author">- Sander Canisius</dd>
|
||||
<dt class="keyword-version">version</dt>
|
||||
<dd class="keyword-version">- 0.1.2, 2013/11/1</dd>
|
||||
<dt class="keyword-see">See also</dt>
|
||||
<dd class="keyword-see">- Sander Canisius, Nicos Angelopoulos and Lodewyk Wessels. proSQLite: Prolog file based databases via an SQLite interface. In the proceedings of Practical Aspects of Declarative languages (PADL 2013), (2013, Rome, Italy).</dd>
|
||||
<dd class="keyword-see">- Sander Canisius, Nicos Angelopoulos and Lodewyk Wessels. Exploring file based databases via an Sqlite interface. In the ICLP Workshop on Logic-based methods in Programming Environments, p. 2-9, (2012, Budapest, Hungary).</dd>
|
||||
<dd class="keyword-see">- <a href="http://stoics.org.uk/~nicos/pbs/wlpe2012_sqlite.pdf">http://stoics.org.uk/~nicos/pbs/wlpe2012_sqlite.pdf</a></dd>
|
||||
<dd class="keyword-see">- <a href="http://stoics.org.uk/~nicos/sware/prosqlite">http://stoics.org.uk/~nicos/sware/prosqlite</a></dd>
|
||||
<dd class="keyword-see">- <a href="http://stoics.org.uk/~nicos/sware/db_facts">http://stoics.org.uk/~nicos/sware/db_facts</a></dd>
|
||||
<dd class="keyword-see">- <a href="http://www.sqlite.org/">http://www.sqlite.org/</a></dd>
|
||||
<dd class="keyword-see">- files in examples/ directory</dd>
|
||||
<dd class="keyword-see">- also available as a SWI pack <a href="http://www.swi-prolog.org/pack/list">http://www.swi-prolog.org/pack/list</a></dd>
|
||||
<dt class="keyword-license">license</dt>
|
||||
<dd class="keyword-license">- Perl Artistic License</dd>
|
||||
<dt class="keyword-tbd">To be done</dt>
|
||||
<dd class="keyword-tbd">- set pragmas</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_version/2">
|
||||
<b class="pred">sqlite_version</b>
|
||||
<var class="arglist">(-Version, -Date)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">The current version. <var>Version</var> is a Mj:Mn:Fx term, and date is a <code>date(Y,M,D)</code> term.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_binary_version/2">
|
||||
<b class="pred">sqlite_binary_version</b>
|
||||
<var class="arglist">(-Version, -Date)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">The current version of the binaries. If the installed binaries are not compiled from
|
||||
the sources, then this might be different (=older) that the sqlite Porlog source version
|
||||
returned by <a href="#sqlite_version/2">sqlite_version/2</a>. <var>Version</var> is a Mj:Mn:Fx term, and date is a <code>date(Y,M,D)</code> term.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_citation/2">
|
||||
<b class="pred">sqlite_citation</b>
|
||||
<var class="arglist">(-Atom, -Bibterm)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Succeeds once for each publication related to this library. <var>Atom</var> is the atom representation
|
||||
suitable for printing while <var>Bibterm</var> is a <code>bibtex(Type,Key,Pairs)</code> term of the same publication.
|
||||
Produces all related publications on backtracking.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_connect/2">
|
||||
<b class="pred">sqlite_connect</b>
|
||||
<var class="arglist">(+File, ?Alias)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Open a connection to an sqlite <var>File</var>. If <var>Alias</var> is a variable, an opaque atom
|
||||
is generated and unified to it. The opened db connection to file can be accessed via <var>Alias</var>.
|
||||
|
||||
<pre class="code" ext=""> sqlite_connect('uniprot.sqlite', uniprot).</pre>
|
||||
</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_connect/3">
|
||||
<b class="pred">sqlite_connect</b>
|
||||
<var class="arglist">(+File, ?Connection, +Options)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Open a connection to an sqlite <var>File</var>. If <var>Connection</var> is a variable, an opaque atom
|
||||
is generated, otherwise the opened file is connected to handle Connecction.
|
||||
<var>Options</var> is a sinlge term or a list of terms from the following:
|
||||
<ul>
|
||||
<li><code>alias(Atom)</code> identify the connection as Alias in all transactions</li>
|
||||
<li><code>as_predicates(AsPred)</code> if true, create hook predicates that map
|
||||
|
||||
<center>each sqlite table to a prolog predicate.
|
||||
These are created in module user, and it is
|
||||
the user's responsibility to be unique in this module.</center>
|
||||
</li>
|
||||
<li><code>at_module(AtMod)</code> the module at which the predicates will be asserted at
|
||||
(if <code>as_predicates(true)</code>) is also given). Default is <code>user</code>.</li>
|
||||
<li><code>table_as(Table,Pname,Arity)</code> map the table to predicate with name Pname. Arity should be
|
||||
defined for this representaition as per with_arity() option.</li>
|
||||
<li><code>arity(arity)</code> Arity denotes the arity of access clauses to be added in the prolog database that
|
||||
|
||||
<center>correspond to SQLite tables. The default is <code>arity</code>, which asserts a
|
||||
predicate matching the arity of the table.
|
||||
<code>both</code> adds two predicates, one matching the arity and a single argument one.
|
||||
The later can be interrogated with something like</center>
|
||||
|
||||
<pre class="code" ext=""> ?- phones( [name=naku, telephone=T] ).</pre>
|
||||
|
||||
<center><code>unary</code> only adds the unary version, and <code>palette</code> adds a suite of predicates
|
||||
with arities from 1 to N, where N is the number of columns.
|
||||
These can be interrogated by :</center>
|
||||
|
||||
<pre class="code" ext=""> ?- phones( name=Name ).
|
||||
?- phones( name=naku, telephone=T ).
|
||||
?- phones( [name=naku, telephone=T] ).</pre>
|
||||
|
||||
<center>Predicated tables can be used to insert values to the database by virtue of all
|
||||
their columns are give ground values.</center>
|
||||
</li>
|
||||
<li><code>exists(Boolean)</code> do not throw an error if file does not exist and
|
||||
|
||||
<center>Boolean is false. Default is true and an error is
|
||||
thrown if the Sqlite file does not exist.</center>
|
||||
</li>
|
||||
<li><code>ext(Ext)</code> database files are assumed to have an sqlite extension at their end.
|
||||
To ovewrite this give Ext ('' for no extension).</li>
|
||||
<li><code>verbose(Verb)</code> Iff Verb==true printa message about which file is used- from within C (false).</li>
|
||||
</ul>
|
||||
|
||||
<p>When unary predicates are defined the columns can be interrogated/accessed by list pairs of the form Column=Value.
|
||||
Column-Value and Column:Value are also recognised.</p>
|
||||
|
||||
<p>So for example, for table <code>phones</code> with columns Name, Address and Phone, prosqlite will add</p>
|
||||
|
||||
<pre class="code" ext=""> phones(_,_,_)</pre>
|
||||
|
||||
<pre class="code">as a response to as_predicates, and</pre>
|
||||
|
||||
<pre class="code" ext=""> phones(_)</pre>
|
||||
|
||||
<p>if Arity is <code>unary</code></p>
|
||||
|
||||
<p>The latter can be interrogated by</p>
|
||||
|
||||
<pre class="code" ext=""> phones( ['Name'=naku','Phone'=Phone] ).</pre>
|
||||
|
||||
<p>which will return the phone <code>number(s)</code> associated with individual named by <code>naku</code>.</p>
|
||||
|
||||
<p>See source file <a class="file" href="../examples/predicated.pl">examples/predicated.pl</a> .</p></dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_disconnect/1">
|
||||
<b class="pred">sqlite_disconnect</b>
|
||||
<var class="arglist">(+Alias)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Terminate the connection to a SQLite database file.
|
||||
|
||||
<pre class="code" ext=""> sqlite_disconnect(uniprot).</pre>
|
||||
</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_current_connection/1">
|
||||
<b class="pred">sqlite_current_connection</b>
|
||||
<var class="arglist">(-Connection)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Return or interrogate the name of open connection handles.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_default_connection/1">
|
||||
<b class="pred">sqlite_default_connection</b>
|
||||
<var class="arglist">(-Connection)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Return or interrogate the name of the default connection. This is the
|
||||
last connection opened.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_query/2">
|
||||
<b class="pred">sqlite_query</b>
|
||||
<var class="arglist">(+Sql, -Row)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Post an <var>Sql</var> query to default connection and get row result in <var>Row</var>.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_query/3">
|
||||
<b class="pred">sqlite_query</b>
|
||||
<var class="arglist">(+Connection, +Sql, -Row)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Post an <var>Sql</var> query to Sqlite <var>Connection</var> and get row result in <var>Row</var>.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_format_query/3">
|
||||
<b class="pred">sqlite_format_query</b>
|
||||
<var class="arglist">(+Connection, +FAs, -Row)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Post a format style Sql query to Sqlite <var>Connection</var> and get row result in <var>Row</var>.
|
||||
<var>FAs</var> is a - pair structure : Format-Arguments.
|
||||
|
||||
<pre class="code" ext=""> sqlite_format_query(uniprot, 'PRAGMA table_info(~w)'-Table, row(_, Column, _, _, _, _))</pre>
|
||||
</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_current_table/2">
|
||||
<b class="pred">sqlite_current_table</b>
|
||||
<var class="arglist">(+Connection, -Table)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Return or interrogate tables in the Sqlite database associated with <var>Connection</var>.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_current_table/3">
|
||||
<b class="pred">sqlite_current_table</b>
|
||||
<var class="arglist">(+Connection, ?Table, -Facet)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody"><var>Facet</var> is a property of <var>Table</var> found at <var>Connection</var>. Currently only <code>arity(Arity)</code> is
|
||||
delivered.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_table_column/3">
|
||||
<b class="pred">sqlite_table_column</b>
|
||||
<var class="arglist">(+Connection, ?Table, -Column)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Return or interrogate tables and columns in the Sqlite database associated with <var>Connection</var>.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_table_column/4">
|
||||
<b class="pred">sqlite_table_column</b>
|
||||
<var class="arglist">(+Connection, ?Table, ?Column, -Facet)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody"><var>Facet</var> is one of:
|
||||
<ul>
|
||||
<li><code>position(Nth0)</code> position of the <var>Column</var> in the table, first being 0.</li>
|
||||
<li><code>data_type(Dtype)</code> the data type for the column</li>
|
||||
<li><code>nullable(Null)</code> can this column be set to the null value</li>
|
||||
<li><code>defautl(Default)</code> the default value for the</li>
|
||||
<li><code>primary_key(Key)</code> is this column part of the primary key ?</li>
|
||||
</ul></dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_pragma/3">
|
||||
<b class="pred">sqlite_pragma</b>
|
||||
<var class="arglist">(+Alias, +Pragma, -Row)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Interrogate SQLite Pragmas. Currently only reading is supported.
|
||||
<var>Pragma</var> can be an atom or a - separated pair, as in <code>table_info-TableName</code>.
|
||||
|
||||
<pre class="code" ext=""> sqlite_pragma( phone_db, encoding, Row).</pre>
|
||||
</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_table_count/3">
|
||||
<b class="pred">sqlite_table_count</b>
|
||||
<var class="arglist">(+Connection, +Table, -Count)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">True if <var>Count</var> is the number of rows in Sqlite <var>Connection</var> associated <var>Table</var>.</dd>
|
||||
<dt class="pubdef">
|
||||
<span style="float:right"></span>
|
||||
<a name="sqlite_date_sql_atom/2">
|
||||
<b class="pred">sqlite_date_sql_atom</b>
|
||||
<var class="arglist">(Date, Sql)</var>
|
||||
</a>
|
||||
</dt>
|
||||
<dd class="defbody">Convert between a Prolog <a
|
||||
href="../../../../../local/git/lib/swipl-6.3.19/library/http/http_header.pl#date/3">date/3</a> term and an <var>Sql</var> atom.
|
||||
The conversion is bidirectional.</dd>
|
||||
</dl>
|
||||
</body>
|
||||
</html>
|
10
packages/prosqlite/pack.pl
Normal file
10
packages/prosqlite/pack.pl
Normal file
@ -0,0 +1,10 @@
|
||||
name(prosqlite).
|
||||
version('0.1.2').
|
||||
title('An SWI-Prolog interface to SQLite').
|
||||
keywords([sqlite,database,sql]).
|
||||
author( 'Sander Canisius', 'http://bioinformatics.nki.nl/~canisius' ).
|
||||
author( 'Nicos Angelopoulos', 'http://stoics.org.uk/~nicos' ).
|
||||
packager( 'Nicos Angelopoulos', 'http://stoics.org.uk/~nicos' ).
|
||||
maintainer( 'Nicos Angelopoulos', 'http://stoics.org.uk/~nicos' ).
|
||||
home( 'http://stoics.org.uk/~nicos/sware/prosqlite' ).
|
||||
download( 'http://stoics.org.uk/~nicos/sware/packs/prosqlite/prosqlite-*.tgz' ).
|
764
packages/prosqlite/prolog/prosqlite.pl
Normal file
764
packages/prosqlite/prolog/prosqlite.pl
Normal file
@ -0,0 +1,764 @@
|
||||
:- module( prosqlite,
|
||||
[ sqlite_connect/2, % +FileName, -Conn
|
||||
sqlite_connect/3, % +FileName, -Conn, +Opts
|
||||
sqlite_disconnect/1, % +Conn
|
||||
sqlite_current_connection/1,% -Conn
|
||||
sqlite_query/2, % +SQL, -Row
|
||||
sqlite_query/3, % +Conn, +SQL, -Row
|
||||
sqlite_format_query/3, % +Conn, +SQL, -Row
|
||||
sqlite_current_table/2, % +Conn, -Table
|
||||
sqlite_current_table/3, % +Conn, ?Table, -Facet
|
||||
sqlite_table_column/3, % +Conn, ?Table, ?Column
|
||||
sqlite_table_column/4, % +Conn, ?Table, ?Column, -Facet
|
||||
sqlite_table_count/3, % +Conn, +Table, -Count
|
||||
sqlite_default_connection/1,% -Conn
|
||||
sqlite_date_sql_atom/2, % ?Date, ?SqlAtom
|
||||
sqlite_pragma/3, % ?Date, ?SqlAtom
|
||||
sqlite_version/2, % -Version, -Date
|
||||
sqlite_binary_version/2, % -Version, -Date
|
||||
sqlite_citation/2 % -Atom, Bibterm
|
||||
] ).
|
||||
|
||||
:- use_module(library(lists)).
|
||||
|
||||
% android does it by loading the code at startup.
|
||||
:- if prolog_flag( host_type , Host), \+ sub_atom(Host, _, _, 0, androideabi).
|
||||
:- use_module(library(shlib)).
|
||||
:- load_foreign_library(foreign(prosqlite)).
|
||||
:- endif.
|
||||
|
||||
:- dynamic( sqlite_connection/3 ).
|
||||
:- dynamic( sqlite_db:sqlite_asserted/4 ).
|
||||
|
||||
/** <module> proSQLite: a Prolog interface to the SQLite database system.
|
||||
|
||||
This library follows the design and borrows code from the ODBC library of SWI-Prolog
|
||||
http://www.swi-prolog.org/pldoc/packasqlite_connectge/odbc.html .
|
||||
|
||||
The SQLite system is a powerful zero-configuration management systme that interacts
|
||||
with single-file databases that are cross-platform compatible binaries.
|
||||
|
||||
ProSQLite provides three layers of interaction with SQLite databases.
|
||||
At the lower level is the querying via SQL statements. A second layer
|
||||
allows the interogation of the database dictionary, and the final level
|
||||
facilitates the viewing of database tables as predicates.
|
||||
See the publication pointed to by sqlite_citation/2, for further details.
|
||||
If you use prosqlite in your research, please consider citing this publication.
|
||||
|
||||
The library has been developed and tested on SWI 6.3.2 but it should
|
||||
also work on YAP Prolog.
|
||||
|
||||
|
||||
The easiest way to install on SWI is via the package manager.
|
||||
Simply do:
|
||||
==
|
||||
?- pack_install( prosqlite ).
|
||||
==
|
||||
And you are good to go.
|
||||
|
||||
There are good/full examples in the sources, directory examples/.
|
||||
For instance test by :
|
||||
==
|
||||
?- [predicated].
|
||||
?- predicated.
|
||||
==
|
||||
|
||||
There is a sister package, db_facts (also installable via the manager).
|
||||
Db_facts, allow interaction with the underlying database via Prolog terms,
|
||||
That library can also be used as a common compatibility layer for the ODBC
|
||||
and proSQLite libraries of SWI-Prolog, as it works on both type of connections.
|
||||
|
||||
|
||||
ProSQLite is debug/1 aware: call =|debug(sqlite)|= to see what is sent to
|
||||
the sqlite engine.
|
||||
|
||||
There are MS wins DLLs included in the sources and recent version of the SWI package
|
||||
manager will install these properly.
|
||||
|
||||
@version 0.1.2, 2013/11/1
|
||||
@license Perl Artistic License
|
||||
@author Nicos Angelopoulos
|
||||
@author Sander Canisius
|
||||
@see Sander Canisius, Nicos Angelopoulos and Lodewyk Wessels. proSQLite: Prolog file based databases via an SQLite interface. In the proceedings of Practical Aspects of Declarative languages (PADL 2013), (2013, Rome, Italy).
|
||||
@see Sander Canisius, Nicos Angelopoulos and Lodewyk Wessels. Exploring file based databases via an Sqlite interface. In the ICLP Workshop on Logic-based methods in Programming Environments, p. 2-9, (2012, Budapest, Hungary).
|
||||
@see http://stoics.org.uk/~nicos/pbs/wlpe2012_sqlite.pdf
|
||||
@see http://stoics.org.uk/~nicos/sware/prosqlite
|
||||
@see http://stoics.org.uk/~nicos/sware/db_facts
|
||||
@see http://www.sqlite.org/
|
||||
@see files in examples/ directory
|
||||
@see also available as a SWI pack http://www.swi-prolog.org/pack/list
|
||||
|
||||
@tbd set pragmas
|
||||
|
||||
*/
|
||||
|
||||
:- use_module( library(debug) ).
|
||||
:- at_halt( sqlite_disconnect ).
|
||||
|
||||
/* defaults and start ups */
|
||||
arity_flag_values( [arity,unary,both,palette] ).
|
||||
|
||||
%-Section interface predicates
|
||||
%
|
||||
|
||||
%% sqlite_version( -Version, -Date ).
|
||||
% The current version. Version is a Mj:Mn:Fx term, and date is a date(Y,M,D) term.
|
||||
%
|
||||
sqlite_version( 0:1:2, date(2013,11,1) ).
|
||||
|
||||
%% sqlite_binary_version( -Version, -Date ).
|
||||
% The current version of the binaries. If the installed binaries are not compiled from
|
||||
% the sources, then this might be different (=older) that the sqlite Porlog source version
|
||||
% returned by sqlite_version/2. Version is a Mj:Mn:Fx term, and date is a date(Y,M,D) term.
|
||||
%
|
||||
sqlite_binary_version( Ver, Date ) :-
|
||||
c_sqlite_version( Ver, Date ).
|
||||
|
||||
%% sqlite_citation( -Atom, -Bibterm ).
|
||||
% Succeeds once for each publication related to this library. Atom is the atom representation
|
||||
% suitable for printing while Bibterm is a bibtex(Type,Key,Pairs) term of the same publication.
|
||||
% Produces all related publications on backtracking.
|
||||
sqlite_citation( Atom, bibtex(Type,Key,Pairs) ) :-
|
||||
Atom = 'Sander Canisius, Nicos Angelopoulos and Lodewyk Wessels. proSQLite: Prolog file based databases via an SQLite interface. In the proceedings of Practical Aspects of Declarative languages (PADL 2013), (2013, Rome, Italy).',
|
||||
Type = inproceedings,
|
||||
Key = 'CanisiusS+2013',
|
||||
Pairs = [
|
||||
author = 'Sander Canisius and Nicos Angelopoulos and Lodewyk Wessels',
|
||||
title = 'Exploring file based databases via an Sqlite interface',
|
||||
booktitle = 'In ICLP Workshop on Logic-based methods in Programming Environments (WLPE\'12)',
|
||||
year = 2012,
|
||||
pages= '2-9',
|
||||
month = 'September',
|
||||
address = 'Budapest, Hungary',
|
||||
url = 'http://stoics.org.uk/~nicos/pbs/padl2013-prosqlite.pdf'
|
||||
].
|
||||
|
||||
sqlite_citation( Atom, bibtex(Type,Key,Pairs) ) :-
|
||||
Atom = 'Exploring file based databases via an Sqlite interface. \n Canisius Sander, Nicos Angelopoulos and Lodewyk Wessels \n In the ICLP Workshop on Logic-based methods in Programming Environments (WLPE\'12),\n p.2-9, 2012. Budapest, Hungary.',
|
||||
Type = inproceedings,
|
||||
Key = 'CanisiusS+2012',
|
||||
Pairs = [
|
||||
author = 'Sander Canisius and Nicos Angelopoulos and Lodewyk Wessels',
|
||||
title = 'Exploring file based databases via an Sqlite interface',
|
||||
booktitle = 'In ICLP Workshop on Logic-based methods in Programming Environments (WLPE\'12)',
|
||||
year = 2012,
|
||||
pages= '2-9',
|
||||
month = 'September',
|
||||
address = 'Budapest, Hungary',
|
||||
url = 'http://stoics.org.uk/~nicos/pbs/wlpe2012_sqlite.pdf'
|
||||
].
|
||||
|
||||
|
||||
%% sqlite_connect(+File, ?Alias).
|
||||
%
|
||||
% Open a connection to an sqlite File. If Alias is a variable, an opaque atom
|
||||
% is generated and unified to it. The opened db connection to file can be accessed via Alias.
|
||||
%
|
||||
% ==
|
||||
% sqlite_connect('uniprot.sqlite', uniprot).
|
||||
% ==
|
||||
%
|
||||
sqlite_connect(File, Conn) :-
|
||||
sqlite_connect(File, Conn, []).
|
||||
|
||||
/** sqlite_connect(+File, ?Connection, +Options).
|
||||
|
||||
Open a connection to an sqlite File. If Connection is a variable, an opaque atom
|
||||
is generated, otherwise the opened file is connected to handle Connecction.
|
||||
Options is a sinlge term or a list of terms from the following:
|
||||
|
||||
* alias(Atom) identify the connection as Alias in all transactions
|
||||
|
||||
* as_predicates(AsPred) if true, create hook predicates that map
|
||||
each sqlite table to a prolog predicate.
|
||||
These are created in module user, and it is
|
||||
the user's responsibility to be unique in this module.
|
||||
|
||||
* at_module(AtMod) the module at which the predicates will be asserted at
|
||||
(if as_predicates(true)) is also given). Default is =|user|=.
|
||||
|
||||
* table_as(Table,Pname,Arity) map the table to predicate with name Pname. Arity should be
|
||||
defined for this representaition as per with_arity() option.
|
||||
|
||||
* arity(arity) Arity denotes the arity of access clauses to be added in the prolog database that
|
||||
correspond to SQLite tables. The default is =|arity|=, which asserts a
|
||||
predicate matching the arity of the table.
|
||||
=|both|= adds two predicates, one matching the arity and a single argument one.
|
||||
The later can be interrogated with something like
|
||||
==
|
||||
?- phones( [name=naku, telephone=T] ).
|
||||
==
|
||||
=|unary|= only adds the unary version, and =|palette|= adds a suite of predicates
|
||||
with arities from 1 to N, where N is the number of columns.
|
||||
These can be interrogated by :
|
||||
==
|
||||
?- phones( name=Name ).
|
||||
?- phones( name=naku, telephone=T ).
|
||||
?- phones( [name=naku, telephone=T] ).
|
||||
==
|
||||
|
||||
Predicated tables can be used to insert values to the database by virtue of all
|
||||
their columns are give ground values.
|
||||
|
||||
* exists(Boolean) do not throw an error if file does not exist and
|
||||
Boolean is false. Default is true and an error is
|
||||
thrown if the Sqlite file does not exist.
|
||||
|
||||
* ext(Ext) database files are assumed to have an sqlite extension at their end.
|
||||
To ovewrite this give Ext ('' for no extension).
|
||||
|
||||
* verbose(Verb) Iff Verb==true printa message about which file is used- from within C (false).
|
||||
|
||||
|
||||
When unary predicates are defined the columns can be interrogated/accessed by list pairs of the form Column=Value.
|
||||
Column-Value and Column:Value are also recognised.
|
||||
|
||||
So for example, for table =|phones|= with columns Name, Address and Phone, prosqlite will add
|
||||
|
||||
==
|
||||
phones(_,_,_)
|
||||
==
|
||||
|
||||
as a response to as_predicates, and
|
||||
|
||||
==
|
||||
phones(_)
|
||||
==
|
||||
if Arity is =|unary|=
|
||||
|
||||
The latter can be interrogated by
|
||||
|
||||
==
|
||||
phones( ['Name'=naku','Phone'=Phone] ).
|
||||
==
|
||||
which will return the phone number(s) associated with individual named by =|naku|=.
|
||||
|
||||
|
||||
See source file examples/predicated.pl .
|
||||
|
||||
*/
|
||||
|
||||
sqlite_connect(FileIn, Conn, OptIn) :-
|
||||
to_list( OptIn, Opts ),
|
||||
( memberchk(ext(Ext),Opts) -> true; Ext=sqlite ),
|
||||
( file_name_extension(_,Ext,FileIn) -> File=FileIn; file_name_extension(FileIn,Ext,File) ),
|
||||
sqlite_connect_1(File, Conn, Opts).
|
||||
|
||||
sqlite_connect_1(File, _Conn, Opts) :-
|
||||
\+ exists_file(File),
|
||||
\+ memberchk(exists(false), Opts),
|
||||
!,
|
||||
open(File, read, _). % just so it throws a nice error
|
||||
sqlite_connect_1(File1, Conn, Opts) :-
|
||||
sqlite_alias(Opts, Conn, Alias),
|
||||
\+ var(Alias),
|
||||
sqlite_connection(Conn,File2,_),
|
||||
!,
|
||||
( File1==File2 ->
|
||||
print_message( informational, sqlite(connection_already_open(Conn)) )
|
||||
;
|
||||
sqlite_error( alias_in_use(Conn,File2) )
|
||||
).
|
||||
sqlite_connect_1(File, Alias, Opts) :-
|
||||
sqlite_alias(Opts, Conn, Alias),
|
||||
( sqlite_connection(_Conn1,File,Alias1) ->
|
||||
portray_message( informational, file_already_open(File,Alias1) )
|
||||
;
|
||||
true
|
||||
),
|
||||
( (memberchk(verbose(Verb),Opts),Verb==true) ->
|
||||
print_message( informational, sqlite(db_at(File)) )
|
||||
;
|
||||
true
|
||||
),
|
||||
c_sqlite_connect(File, Conn),
|
||||
asserta( sqlite_connection(Alias,File,Conn) ),
|
||||
( sqlite_establish_predicates(Opts, Conn) ->
|
||||
true
|
||||
;
|
||||
retractall( sqlite_connection(Alias,File,Conn) ),
|
||||
c_sqlite_disconnect(Conn),
|
||||
sqlite_error( predicated_creation_error(File,Alias) )
|
||||
).
|
||||
|
||||
/*
|
||||
sqlite_connect(File, Conn, Opts) :-
|
||||
c_sqlite_connect(File, Internal),
|
||||
!,
|
||||
assert( sqlite_connection(Conn,File,Internal) ).
|
||||
*/
|
||||
|
||||
% this is currently private only for use with at_halt.
|
||||
%
|
||||
sqlite_disconnect :-
|
||||
sqlite_connection(Alias,_,_),
|
||||
sqlite_disconnect( Alias ),
|
||||
fail.
|
||||
sqlite_disconnect.
|
||||
|
||||
%% sqlite_disconnect( +Alias ).
|
||||
%
|
||||
% Terminate the connection to a SQLite database file.
|
||||
%
|
||||
% ==
|
||||
% sqlite_disconnect(uniprot).
|
||||
% ==
|
||||
%
|
||||
sqlite_disconnect( Alias ) :-
|
||||
once( sqlite_connection(Alias,_,Conn) ),
|
||||
!,
|
||||
debug( sqlite, 'Disconnecting from db with alias: ~w.', [Alias] ),
|
||||
c_sqlite_disconnect( Conn ),
|
||||
retractall( sqlite_connection(Alias,_,Conn) ),
|
||||
findall( pam(Pname,Arity,Mod), sqlite_db:sqlite_asserted(Conn,Pname,Arity,Mod), PAs ),
|
||||
maplist( sqlite_clean_up_predicated_for(Conn), PAs ).
|
||||
|
||||
sqlite_disconnect( Alias ) :-
|
||||
sqlite_fail( not_a_connection(Alias) ).
|
||||
|
||||
sqlite_clean_up_predicated_for( Conn, pam(Pname,Arity,Mod) ) :-
|
||||
% functor( Head, Pname, Arity ),
|
||||
% retractall( Mod:Head ),
|
||||
abolish( Mod:Pname, Arity ),
|
||||
retractall( sqlite_db:sqlite_asserted(Conn,Pname,Arity,Mod) ).
|
||||
|
||||
%% sqlite_current_connection(-Connection).
|
||||
%
|
||||
% Return or interrogate the name of open connection handles.
|
||||
%
|
||||
sqlite_current_connection(Conn) :-
|
||||
sqlite_connection(Conn,_,_).
|
||||
|
||||
%% sqlite_default_connection(-Connection).
|
||||
%
|
||||
% Return or interrogate the name of the default connection. This is the
|
||||
% last connection opened.
|
||||
%
|
||||
sqlite_default_connection(Alias) :-
|
||||
sqlite_connection(Alias,_,_),
|
||||
!.
|
||||
|
||||
%% sqlite_query(+Sql, -Row).
|
||||
%
|
||||
% Post an Sql query to default connection and get row result in Row.
|
||||
%
|
||||
sqlite_query(Sql, Row) :-
|
||||
sqlite_default_connection(Alias),
|
||||
sqlite_query(Alias, Sql, Row).
|
||||
|
||||
%% sqlite_query(+Connection, +Sql, -Row).
|
||||
%
|
||||
% Post an Sql query to Sqlite Connection and get row result in Row.
|
||||
%
|
||||
sqlite_query(Alias, Query, Row) :-
|
||||
sqlite_alias_connection(Alias, Connection),
|
||||
debug( sqlite, 'Alias: ~w, sending: ~a', [Alias,Query] ),
|
||||
c_sqlite_query(Connection, Query, Row).
|
||||
|
||||
%% sqlite_format_query(+Connection, +FAs, -Row).
|
||||
%
|
||||
% Post a format style Sql query to Sqlite Connection and get row result in Row.
|
||||
% FAs is a - pair structure : Format-Arguments.
|
||||
%
|
||||
% ==
|
||||
% sqlite_format_query(uniprot, 'PRAGMA table_info(~w)'-Table, row(_, Column, _, _, _, _))
|
||||
% ==
|
||||
%
|
||||
%
|
||||
sqlite_format_query(Alias, Format-Arguments, Row) :-
|
||||
format(atom(Query), Format, Arguments),
|
||||
sqlite_query(Alias, Query, Row).
|
||||
|
||||
%% sqlite_current_table(+Connection, -Table).
|
||||
%
|
||||
% Return or interrogate tables in the Sqlite database associated with Connection.
|
||||
%
|
||||
sqlite_current_table(Alias, Table) :-
|
||||
var( Table ),
|
||||
!,
|
||||
sqlite_query(Alias, 'SELECT name FROM sqlite_master WHERE type = "table"', row(Table)).
|
||||
sqlite_current_table(Alias, Table) :-
|
||||
ground( Table ),
|
||||
sqlite_query(Alias, 'SELECT name FROM sqlite_master WHERE type = "table"', row(TableIn)),
|
||||
%13.10.26: have a look at the C code above to see if 'row(Table)' can work on the above line.
|
||||
Table = TableIn,
|
||||
!.
|
||||
|
||||
%% sqlite_current_table(+Connection, ?Table, -Facet ).
|
||||
%
|
||||
% Facet is a property of Table found at Connection. Currently only arity(Arity) is
|
||||
% delivered.
|
||||
sqlite_current_table(Connection, Table, Facet ) :-
|
||||
sqlite_current_table(Connection, Table),
|
||||
sqlite_facet_table( Facet, Connection, Table ).
|
||||
|
||||
%% sqlite_table_column(+Connection, ?Table, -Column).
|
||||
%
|
||||
% Return or interrogate tables and columns in the Sqlite database associated with Connection.
|
||||
%
|
||||
sqlite_table_column( Alias, Table, Column ) :-
|
||||
set_table( Alias, Table ),
|
||||
sqlite_format_query(Alias, 'PRAGMA table_info(~w)'-Table, row(_, Column, _, _, _, _)).
|
||||
|
||||
%% sqlite_table_column(+Connection, ?Table, ?Column, -Facet).
|
||||
%
|
||||
% Facet is one of:
|
||||
% * position(Nth0) position of the Column in the table, first being 0.
|
||||
% * data_type(Dtype) the data type for the column
|
||||
% * nullable(Null) can this column be set to the null value
|
||||
% * defautl(Default) the default value for the
|
||||
% * primary_key(Key) is this column part of the primary key ?
|
||||
%
|
||||
sqlite_table_column(Alias, Table, Column, Facet) :-
|
||||
set_table( Alias, Table ),
|
||||
sqlite_format_query(Alias, 'PRAGMA table_info(~w)'-Table, Row ),
|
||||
Row = row(_, Column, _, _, _, _),
|
||||
sqlite_pragma_info_facet( Row, Facet ).
|
||||
|
||||
sqlite_pragma_info_facet( row(Nth0,_,_,_,_,_), position(Nth0) ).
|
||||
sqlite_pragma_info_facet( row(_,_,Dtype,_,_,_), data_type(Dtype) ).
|
||||
sqlite_pragma_info_facet( row(_,_,_,Null,_,_), nullable(Null) ). % fixme, ensure same semantics as ODBC
|
||||
sqlite_pragma_info_facet( row(_,_,_,_,Default,_), default(Default) ).
|
||||
sqlite_pragma_info_facet( row(_,_,_,_,_,Key), primary_key(Key) ).
|
||||
|
||||
%% sqlite_pragma( +Alias, +Pragma, -Row ).
|
||||
%
|
||||
% Interrogate SQLite Pragmas. Currently only reading is supported.
|
||||
% Pragma can be an atom or a - separated pair, as in =|table_info-TableName|=.
|
||||
%
|
||||
%==
|
||||
% sqlite_pragma( phone_db, encoding, Row).
|
||||
%==
|
||||
sqlite_pragma( Alias, Pragma-Par, Row ) :-
|
||||
!,
|
||||
atomic_list_concat( ['PRAGMA',Pragma,'(~w)'],' ', Query ),
|
||||
sqlite_format_query( Alias, Query-Par, Row ).
|
||||
sqlite_pragma( Alias, Pragma, Row ) :-
|
||||
atomic_list_concat( ['PRAGMA',Pragma],' ', Query ),
|
||||
sqlite_query( Alias, Query, Row ).
|
||||
|
||||
% pragmas_info( [...,encoding,...,secure_delete,synchronous,temp_store,writable_schema] ).
|
||||
pragmas_comm( [shrink_memory] ).
|
||||
|
||||
|
||||
set_table( Alias, Table ) :-
|
||||
( var(Table) ->
|
||||
sqlite_current_table(Alias, Table)
|
||||
;
|
||||
true
|
||||
).
|
||||
|
||||
%% sqlite_table_count(+Connection, +Table, -Count).
|
||||
%
|
||||
% True if Count is the number of rows in Sqlite Connection associated Table.
|
||||
%
|
||||
sqlite_table_count(Alias, Table, Count) :-
|
||||
Sel = 'Select count (*) from ~w',
|
||||
sqlite_format_query(Alias, Sel-Table, row(Count)),
|
||||
!.
|
||||
|
||||
/** sqlite_date_sql_atom( Date, Sql ).
|
||||
|
||||
Convert between a Prolog date/3 term and an Sql atom.
|
||||
The conversion is bidirectional.
|
||||
*/
|
||||
sqlite_date_sql_atom( date(Y,M,D), Sql ) :-
|
||||
ground( Sql ),
|
||||
!,
|
||||
atomic_list_concat( Consts, '/', Sql ),
|
||||
maplist( atom_number, Consts, [Y,M,D] ).
|
||||
sqlite_date_sql_atom( date(Y,M,D), Sql ) :-
|
||||
atomic_list_concat( ['"',Y], Ya ),
|
||||
atomic_list_concat( [D,'"'], Da ),
|
||||
atomic_list_concat( [Ya,M,Da], '/', Sql ).
|
||||
|
||||
|
||||
%-Section non-interface sqlite specific predicates
|
||||
%
|
||||
|
||||
sqlite_alias(Opts, _Conn, Alias) :-
|
||||
memberchk(alias(Alias), Opts),
|
||||
!.
|
||||
sqlite_alias(_Opts, _Conn, Alias ) :-
|
||||
atomic( Alias ),
|
||||
!.
|
||||
sqlite_alias(_Opts, Conn, Conn).
|
||||
|
||||
sqlite_establish_predicates( Opts, Conn ) :-
|
||||
memberchk(as_predicates(true), Opts),
|
||||
!,
|
||||
findall(T-C, sqlite_table_column(Conn,T,C), TCs ),
|
||||
findall( T, member(T-_,TCs), RepTs ),
|
||||
sort( RepTs, Ts ),
|
||||
findall( T-Cs, (member(T,Ts),findall(C,member(T-C,TCs),Cs)), TdCs ),
|
||||
( memberchk(at_module(Mod), Opts) -> true; Mod = user ),
|
||||
arity_option( Opts, ArityF ),
|
||||
sqlite_establish_tables(TdCs, Conn, Mod, ArityF, Opts ).
|
||||
sqlite_establish_predicates(_Opts, _Conn ).
|
||||
|
||||
sqlite_establish_tables( [], _Conn, _Mod, _ArityF, _Opts ).
|
||||
sqlite_establish_tables( [Table-Columns|T], Conn, Mod, ArityF, Opts ) :-
|
||||
( memberchk(table_as(Table,Pname,TArityF), Opts) ->
|
||||
true
|
||||
;
|
||||
Pname = Table, TArityF = ArityF
|
||||
),
|
||||
sqlite_establish_table(TArityF,Table,Pname,Columns,Conn,Mod),
|
||||
% Internal = 'Internal prosqlite error. Unable to establish table',
|
||||
% throw( Internal:TArityF/Table ) % handled furter up now
|
||||
sqlite_establish_tables( T, Conn, Mod, ArityF, Opts ).
|
||||
|
||||
sqlite_establish_table( arity, Table, Pname, Columns, Conn, Mod ) :-
|
||||
length( Columns, Arity ),
|
||||
sqlite_establish_table_typed( Table, Pname, Columns, Conn, Mod, predicate, Arity ).
|
||||
sqlite_establish_table( both, Table, Pname, Columns, Conn, Mod ) :-
|
||||
sqlite_establish_table_typed( Table, Pname, Columns, Conn, Mod, unary, 1 ),
|
||||
length( Columns, Arity ),
|
||||
sqlite_establish_table_typed( Table, Pname, Columns, Conn, Mod, predicate, Arity ).
|
||||
sqlite_establish_table( unary, Table, Pname, Columns, Conn, Mod ) :-
|
||||
sqlite_establish_table_typed( Table, Pname, Columns, Conn, Mod, unary, 1 ).
|
||||
sqlite_establish_table( palette, Table, Pname, Columns, Conn, Mod ) :-
|
||||
length( Columns, Arity ),
|
||||
% Shorter is Arity - 1,
|
||||
findall( _, ( between(1,Arity,I),
|
||||
sqlite_establish_table_typed(Table, Pname, Columns, Conn, Mod, palette, I)
|
||||
), _ ).
|
||||
|
||||
sqlite_establish_table_typed( Table, Pname, Columns, Conn, Mod, ArityF, Arity ) :-
|
||||
functor( Head, Pname, Arity ),
|
||||
Head =..[Pname|Args],
|
||||
Body = prosqlite:sqlite_holds(Conn,Table,Arity,ArityF,Columns,Args),
|
||||
( clause(Mod:Head,_Body) ->
|
||||
sqlite_fail( maps_to_existing_predicate(Pname,Arity) )
|
||||
;
|
||||
true
|
||||
),
|
||||
% retractall( Mod:Head ), % fixme: double check this and test it works
|
||||
( sqlite_db:sqlite_asserted(Conn1,Pname,Args,_Mod1) ->
|
||||
sqlite_fail( predicate_already_registered(Conn1,Pname,Arity) )
|
||||
;
|
||||
Mod:assert((Head :- Body))
|
||||
),
|
||||
assert( sqlite_db:sqlite_asserted(Conn,Pname,Arity,Mod) ).
|
||||
% assert((Head :- Body)),
|
||||
|
||||
sqlite_holds( AliasOr, Name, _Arity, Type, Columns, Args ) :-
|
||||
sqlite_alias_connection( AliasOr, Conn ),
|
||||
pl_as_predicate_to_sql_ready_data( Type, Columns, Args, KnwnClmPrs, UnKnwnCs, UnKnwnAs ),
|
||||
sqlite_holds_unknown( UnKnwnCs, UnKnwnAs, KnwnClmPrs, Name, Columns, Conn ).
|
||||
|
||||
/* fixme:
|
||||
sqlite_holds_unknown( [], _UnKnwnAs, KnwnClmPrs, Name, Columns, Conn ) :-
|
||||
shall we throw an error if there is nothing to report and nothing to assert ?
|
||||
*/
|
||||
|
||||
sqlite_holds_unknown( UnKnwnCs, UnKnwnAs, KnwnClmPrs, Name, _Columns, Conn ) :-
|
||||
sql_clm_value_pairs_to_where(KnwnClmPrs, Where),
|
||||
atomic_list_concat( UnKnwnCs, ',', UnC ),
|
||||
atomic_list_concat( ['Select ',UnC,'From',Name,Where,';'], ' ', Sql ),
|
||||
Row =.. [row|UnKnwnAs],
|
||||
debug( sqlite, 'Conn: ~w, sending: ~a', [Conn,Sql] ),
|
||||
c_sqlite_query(Conn, Sql, Row).
|
||||
|
||||
sqlite_alias_connection( Alias, Connection ) :-
|
||||
sqlite_connection( Alias,_,Connection ),
|
||||
!.
|
||||
% allows access with either alias or connection :
|
||||
sqlite_alias_connection( Connection, Connection ) :-
|
||||
sqlite_connection(_,_,Connection),
|
||||
!.
|
||||
sqlite_alias_connection( Alias, _Connection ) :-
|
||||
sqlite_error( unknown_alias(Alias) ).
|
||||
|
||||
% fixme: we should really use the db_facts code here.
|
||||
pl_as_predicate_to_sql_ready_data( unary, Columns, [Args], KnwnClmPrs, UnKnwnCs, UnKnwnAs ) :-
|
||||
pl_look_for_args_to_un_known( Args, Columns, KnwnClmPrs, UnKnwnCs, UnKnwnAs ).
|
||||
pl_as_predicate_to_sql_ready_data( palette, Columns, ArgsIn, KnwnClmPrs, UnKnwnCs, UnKnwnAs ) :-
|
||||
( (ArgsIn=[Args],is_list(Args)) -> true; Args = ArgsIn ),
|
||||
pl_args_column_arg_ground_or_not_pairs(Args,Columns,KnwnClmPrs,UnKnwnCs,UnKnwnAs),
|
||||
( maplist(var,Args) ->
|
||||
true % then a palette predicate has been called with full arity and all variables
|
||||
;
|
||||
% maplist( look_for_pair,Args,_,_),
|
||||
findall( LFA, (member(LFA,Args),look_for_pair_silent(LFA,_,_)), [] )
|
||||
% then a palette predicate has been called with full arity and look_for_pair
|
||||
),
|
||||
!.
|
||||
pl_as_predicate_to_sql_ready_data( palette, Columns, ArgsIn, KnwnClmPrs, UnKnwnCs, UnKnwnAs ) :-
|
||||
( (ArgsIn=[Args],is_list(Args)) -> true; Args = ArgsIn ),
|
||||
pl_look_for_args_to_un_known( Args, Columns, KnwnClmPrs, UnKnwnCs, UnKnwnAs ).
|
||||
pl_as_predicate_to_sql_ready_data( predicate, Columns, Args, KnwnClmPrs, UnKnwnCs, UnKnwnAs ) :-
|
||||
pl_args_column_arg_ground_or_not_pairs( Args, Columns, KnwnClmPrs, UnKnwnCs, UnKnwnAs ).
|
||||
|
||||
pl_args_column_arg_ground_or_not_pairs( [], [], [], [], [] ).
|
||||
pl_args_column_arg_ground_or_not_pairs( [A|As], [C|Cs], Knwn, UnCs, UnAs ) :-
|
||||
( ground(A) ->
|
||||
Knwn = [C-A|TKnwn],
|
||||
TUnCs = UnCs,
|
||||
TUnAs = UnAs
|
||||
;
|
||||
TKnwn = Knwn,
|
||||
UnCs = [C|TUnCs],
|
||||
UnAs = [A|TUnAs]
|
||||
),
|
||||
pl_args_column_arg_ground_or_not_pairs( As, Cs, TKnwn, TUnCs, TUnAs ).
|
||||
|
||||
pl_look_for_args_to_un_known( [], _Columns, [], [], [] ).
|
||||
pl_look_for_args_to_un_known( [A|As], Columns, Knwn, UnKnwnCs, UnKnownAs ) :-
|
||||
look_for_pair( A, Clm, Val ),
|
||||
is_one_of_columns( Clm, Columns ),
|
||||
( ground(Val) ->
|
||||
Knwn = [Clm-Val|TKnwn],
|
||||
TUnKnwnCs = UnKnwnCs,
|
||||
TUnKnownAs = UnKnownAs
|
||||
;
|
||||
TKnwn = Knwn,
|
||||
UnKnwnCs = [Clm|TUnKnwnCs],
|
||||
UnKnownAs = [Val|TUnKnownAs]
|
||||
),
|
||||
pl_look_for_args_to_un_known( As, Columns, TKnwn, TUnKnwnCs, TUnKnownAs ).
|
||||
|
||||
is_one_of_columns( Clm, Columns ) :-
|
||||
memberchk( Clm, Columns ),
|
||||
!.
|
||||
is_one_of_columns( Clm, Columns ) :-
|
||||
sqlite_error( unknown_column(Clm,Columns) ).
|
||||
|
||||
look_for_pair( Pair, K, V ) :-
|
||||
look_for_pair_silent( Pair, K, V ),
|
||||
!.
|
||||
look_for_pair( Term, _A, _B ) :-
|
||||
% print_message(informational, pack(git_fetch(Dir))).
|
||||
sqlite_error( pair_representation(Term) ).
|
||||
% type_error( 'Binary compound with functor {=,-,:}', Term ).
|
||||
% Type = 'Binary compound with functor {=,-,:}',
|
||||
% print_message( error, error(type_error(Type,Term)) ),
|
||||
% abort.
|
||||
|
||||
look_for_pair_silent( A=B, A, B ).
|
||||
look_for_pair_silent( A-B, A, B ).
|
||||
look_for_pair_silent( A:B, A, B ).
|
||||
|
||||
/* error messages */
|
||||
|
||||
sqlite_error( Term ) :-
|
||||
Type = error,
|
||||
print_message( Type, sqlite(Term) ),
|
||||
abort.
|
||||
|
||||
sqlite_fail( Term ) :-
|
||||
Type = informational,
|
||||
sqlite_fail( Type, Term ).
|
||||
|
||||
sqlite_fail( Type, Term ) :-
|
||||
print_message( Type, sqlite(Term) ),
|
||||
fail.
|
||||
|
||||
%-Section error handling.
|
||||
|
||||
:- multifile prolog:message//1.
|
||||
|
||||
prolog:message(sqlite(Message)) -->
|
||||
message(Message).
|
||||
|
||||
|
||||
message( pair_representation(Term) ) -->
|
||||
['Wrong term type ~q in predicated table arguments. Expected binary with functor, {=,:,-}.' - [Term] ].
|
||||
message( unknown_column(Clm,Columns) ) -->
|
||||
[ 'Unkown column, ~q expected one in ~q.' - [Clm,Columns] ].
|
||||
message( unknown_alias(Alias) ) -->
|
||||
['Not a known alias or connection:~q.' - Alias ].
|
||||
message( wrong_arity_value(ArityF) ) -->
|
||||
{ arity_flag_values( Arities ) },
|
||||
[ 'Unrecognised arity option value ~q, expected ~q.' - [ArityF,Arities] ].
|
||||
message( predicated_creation_error(File,Alias) ) -->
|
||||
[ 'Closed connection ~q to file ~q due to failure in predicated table creation.' - [Alias,File] ].
|
||||
message( connection_already_open(Conn) ) -->
|
||||
[ 'Connection already open ~q.'- [Conn] ].
|
||||
message( alias_in_use(Conn,File) ) -->
|
||||
[ 'Alias/connection ~q already in use for file ~q.'- [Conn,File] ].
|
||||
message( not_a_connection(Alias) ) -->
|
||||
[ 'Not an open connection or known alias to a connection: ~q' - [Alias] ].
|
||||
message( insufficient_columns(Goal,Op) ) -->
|
||||
[ 'Insufficient number of known column values in ~q for operation ~q.' - [Goal,Op] ].
|
||||
message( predicate_already_registered(Conn,Pname,Arity) ) -->
|
||||
[ 'Predicate ~q already registered by connection ~q' - [Pname/Arity,Conn] ].
|
||||
message( maps_to_existing_predicate(Pname,Arity) ) -->
|
||||
['Predicated table maps to existing predicate ~q.' - [Pname/Arity] ].
|
||||
message( file_already_open(File,Alias) ) -->
|
||||
['File, ~q already open with alias ~q.' - [File,Alias] ].
|
||||
message( db_at(File) ) -->
|
||||
['Using database from file: ~q.' - [File] ].
|
||||
message( asserting_non_ground(Goal) ) -->
|
||||
[ 'Asserting non ground term ~q.' - [Goal] ].
|
||||
message( debug(Format,Args) ) -->
|
||||
[ 'Found Format (1st arg) ~q and Args (2nd arg) ~q.' - [Format,Args] ].
|
||||
|
||||
%-Section sqlite non-specific auxiliary predicates
|
||||
%
|
||||
to_list(OptIn, Opts) :-
|
||||
is_list(OptIn),
|
||||
!,
|
||||
Opts = OptIn.
|
||||
to_list(Opt, [Opt] ).
|
||||
|
||||
dquote( Val, Quoted ) :-
|
||||
number( Val ),
|
||||
!,
|
||||
Quoted = Val.
|
||||
dquote( Val, Quoted ) :-
|
||||
atom( Val ),
|
||||
!,
|
||||
atomic_list_concat( ['"',Val,'"'], Quoted ).
|
||||
dquote( Val, Quoted ) :-
|
||||
is_list( Val ),
|
||||
append( [0'"|Val], [0'"], QuotedCs ),
|
||||
atom_codes( Quoted, QuotedCs ).
|
||||
|
||||
sql_clm_value_pairs_to_where(Known, Where) :-
|
||||
sql_clm_value_pairs_to_where_conjunction(Known, Conjunction),
|
||||
sql_where_conjunction_to_where(Conjunction, Where).
|
||||
|
||||
sql_where_conjunction_to_where('', '' ) :- !.
|
||||
sql_where_conjunction_to_where(Conjunction, Where ) :-
|
||||
atom_concat( 'Where ', Conjunction, Where ).
|
||||
|
||||
sql_clm_value_pairs_to_where_conjunction([], '').
|
||||
sql_clm_value_pairs_to_where_conjunction([K-V|T], Where) :-
|
||||
sql_clm_value_pairs_to_where_conjunction(T, InWhere),
|
||||
sql_clm_and_val_to_sql_equals_atom(K, V, KVAtm),
|
||||
( InWhere == '' ->
|
||||
Where = KVAtm
|
||||
;
|
||||
atomic_list_concat([KVAtm, ' AND ', InWhere], Where)
|
||||
).
|
||||
|
||||
sql_clm_and_val_to_sql_equals_atom(K, V, KVAtm) :-
|
||||
( number(V) ->
|
||||
atom_number(Vatm, V),
|
||||
atom_concat('=',Vatm,EqV)
|
||||
;
|
||||
atom_concat(V, '\'', VDsh),
|
||||
atom_concat('=\'',VDsh,EqV)
|
||||
),
|
||||
atom_concat(K, EqV, KVAtm).
|
||||
|
||||
sqlite_facet_table( arity(Arity), Connection, Table ) :-
|
||||
findall( Column, sqlite_table_column(Connection, Table, Column), Columns ),
|
||||
length( Columns, Arity ).
|
||||
|
||||
arity_option( Opts, ArityF ) :-
|
||||
memberchk( arity(ArityF), Opts ),
|
||||
arity_flag_values( Arities ),
|
||||
memberchk( ArityF, Arities ),
|
||||
!.
|
||||
arity_option( Opts, ArityF ) :-
|
||||
memberchk( arity(ArityF), Opts ),
|
||||
!,
|
||||
sqlite_fail( wrong_arity_value(ArityF) ).
|
||||
arity_option( _Opts, arity ). % default for this flag, although we should
|
||||
% move all defaults to one location/list (fixme)
|
||||
|
||||
kv_decompose( [], [], [] ).
|
||||
kv_decompose( [K-V|T], [K|Ks], [V|Vs] ) :-
|
||||
kv_decompose( T, Ks, Vs ).
|
Reference in New Issue
Block a user