diff --git a/packages/myddas/Makefile.in b/packages/myddas/Makefile.in index 1eaca7f5d..84a708df3 100644 --- a/packages/myddas/Makefile.in +++ b/packages/myddas/Makefile.in @@ -21,7 +21,7 @@ YAPLIBDIR=@libdir@/Yap # CC=@CC@ YAP_EXTRAS=@YAP_EXTRAS@ -CFLAGS= $(YAP_EXTRAS) @SHLIB_CFLAGS@ $(YAP_EXTRAS) $(DEFS) -I$(srcdir) -I../.. -I$(srcdir)/../../include -I$(srcdir)/../../H -I$(srcdir)/../../OPTYap -I$(srcdir)/../../os +CFLAGS= $(YAP_EXTRAS) @SHLIB_CFLAGS@ $(YAP_EXTRAS) $(DEFS) -I$(srcdir) -I../.. -I$(srcdir)/../../include -I$(srcdir)/../../H -I$(srcdir)/../../OPTYap -I$(srcdir)/../../os @MYDDAS_CPPFLAGS@ LDFLAGS=@LDFLAGS@ # # @@ -47,7 +47,8 @@ MYDDAS_HEADERS= \ MYDDAS_SOURCES= \ myddas_mysql.c \ myddas_odbc.c \ - myddas_util.c \ + myddas_sqlite3.c \ + myddas_util.c \ myddas_initialization.c \ myddas_shared.c \ myddas_statistics.c \ @@ -79,7 +80,7 @@ all: $(SOBJS) $(CC) -c $(CFLAGS) $< -o $@ @DO_SECOND_LD@%.@SO@: $(OBJS) -@DO_SECOND_LD@ @SHLIB_LD@ $(LDFLAGS) -o $@ $(OBJS) @EXTRA_LIBS_FOR_DLLS@ @MYDDAS_LIBS@ +@DO_SECOND_LD@ @SHLIB_LD@ $(LDFLAGS) -o $@ $(OBJS) @EXTRA_LIBS_FOR_DLLS@ @MYDDAS_LIBS@ install: all install_myddas install-examples mkdir -p $(DESTDIR)$(SHAREDIR) diff --git a/packages/myddas/configure.in b/packages/myddas/configure.in index c49a17c60..f98b5205b 100644 --- a/packages/myddas/configure.in +++ b/packages/myddas/configure.in @@ -1,23 +1,66 @@ -MYDDAS_VERSION=0.9.1 +MYDDAS_VERSION=0.9.2 AC_DEFINE_UNQUOTED(MYDDAS_VERSION, $MYDDAS_VERSION, [myddas release]) -AC_ARG_WITH(myddas, - [ --with-myddas[[=DIR]] with the MYDDAS library], +OLD_LIBS="$LIBS" +OLD_CPPFLAGS="$CPPFLAGS" +MYDDAS_CPPFLAGS="" + +AC_ARG_ENABLE(myddas, + [ --enable-myddas[[=DIR]] with the MYDDAS library], if test "$withval" = yes; then yap_cv_myddas=/usr elif test "$withval" = no; then yap_cv_myddas=no else - yap_cv_myddas=$with_myddas + yap_cv_myddas=$withval LDFLAGS="$LDFLAGS -L${yap_cv_myddas}/lib " - CPPFLAGS="$CPPFLAGS -I${yap_cv_myddas}/include " - ODBC_LDFLAGS="-L${yap_cv_myddas}/lib " - ODBC_CFLAGS="-I${yap_cv_myddas}/include " - SQLITE3_LDFLAGS="-L${yap_cv_myddas}/lib " - SQLITE3_CFLAGS="-I${yap_cv_myddas}/include " - fi, + CPPFLAGS="$CPPFLAGS -I${yap_cv_myddas}/include " + MYDDAS_CPPFLAGS="$MYDDAS_CPPFLAGS -I${yap_cv_myddas}/include " +fi, [yap_cv_myddas=/usr]) +AC_ARG_WITH(mysql, + [ --with-mysql[[=DIR]] with the MYSQL library], + if test "$withval" = yes; then + yap_cv_mysql=/usr + elif test "$withval" = no; then + yap_cv_mysql=no + else + yap_cv_mysql=$withval + LDFLAGS="$LDFLAGS -L${yap_cv_mysql}/lib " + CPPFLAGS="$CPPFLAGS -I${yap_cv_mysql}/include " + MYDDAS_CPPFLAGS="$MYDDAS_CPPFLAGS -I${yap_cv_mysql}/include " + fi, + [yap_cv_mysql=/usr]) + +AC_ARG_WITH(odbc, + [ --with-odbc[[=DIR]] with an ODBC library], + if test "$withval" = yes; then + yap_cv_odbc=/usr + elif test "$withval" = no; then + yap_cv_odbc=no + else + yap_cv_odbc=$withval + LDFLAGS="$LDFLAGS -L${yap_cv_odbc}/lib " + CPPFLAGS="$CPPFLAGS -I${yap_cv_odbc}/include " + MYDDAS_CPPFLAGS="$MYDDAS_CPPFLAGS -I${yap_cv_odbc}/include " + fi, + [yap_cv_odbc=/usr]) + +AC_ARG_WITH(sqlite3, + [ --with-sqlite3[[=DIR]] with an SQLITE3 library], + if test "$withval" = yes; then + yap_cv_sqlite3=/usr + elif test "$withval" = no; then + yap_cv_sqlite3=no + else + yap_cv_sqlite3=$withval + LDFLAGS="$LDFLAGS -L${yap_cv_sqlite3}/lib " + CPPFLAGS="$CPPFLAGS -I${yap_cv_sqlite3}/include " + MYDDAS_CPPFLAGS="$MYDDAS_CPPFLAGS -I${yap_cv_sqlite3}/include " + fi, + [yap_cv_sqlite3=/usr]) + AC_ARG_ENABLE(myddas-stats, [ --enable-myddas-stats enable the MYDDAS library statistics support], if test "$yap_cv_myddas" = no; then @@ -38,7 +81,6 @@ if test "$yap_cv_myddas" != "no" then PKG_MYDDAS="packages/myddas" dnl check for mysql - OLD_LIBS="$LIBS" AC_SEARCH_LIBS(mysql_init, [mysqlclient], [yap_cv_mysql="yes" MYDDAS_LIBS="-lmysqlclient $MYDDAS_LIBS"], [yap_cv_mysql="no"]) AC_CHECK_HEADERS(mysql/mysql.h, [], [yap_cv_mysql="no"]) if test "$yap_cv_mysql" = yes @@ -50,36 +92,47 @@ then case "$target_os" in *darwin*) LIBS="$LIBS -framework CoreFoundation" - MYDDAS_LIBS="$MYDDAS_LIBS -framework CoreFoundation" ;; **) ;; esac AC_SEARCH_LIBS(SQLAllocHandle, [odbc], [yap_cv_odbc="yes"], [yap_cv_odbc="no"]) - if test "$yap_cv_odbc" = yes + if test "$yap_cv_odbc" != no then - MYDDAS_LIBS="$MYDDAS_LIBS -lodbc" + LIBS="$LIBS -lodbc" else AC_SEARCH_LIBS(SQLAllocHandle, [iodbc], [yap_cv_odbc="yes"], [yap_cv_odbc="no"]) - if test "$yap_cv_odbc" = yes + if test "$yap_cv_odbc" != no then - MYDDAS_LIBS="$MYDDAS_LIBS -liodbc" + LIBS="$LIBS -liodbc" else AC_SEARCH_LIBS(SQLAllocHandle, [odbc32], [yap_cv_odbc="yes" ], [yap_cv_odbc="no"]) - if test "$yap_cv_odbc" = yes + if test "$yap_cv_odbc" != no then - MYDDAS_LIBS="$MYDDAS_LIBS -lodbc32" + LIBS="$LIBS -lodbc32" fi fi fi #from SWI ODBC library. AC_CHECK_HEADERS(windef.h) - AC_CHECK_HEADERS(sql.h, [ ], [yap_cv_odbc="no"]) - if test "$yap_cv_odbc" = yes + AC_CHECK_HEADERS(sql.h, [yap_cv_odbc="yes" ], [yap_cv_odbc="no"]) + if test "$yap_cv_odbc" != no then YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_ODBC" fi + #from SWI PROSQLITE library. + AC_CHECK_LIB(sqlite3, sqlite3_open, + LIBS="-lsqlite3 $LIBS" + havelib=yes) + + + AC_CHECK_HEADERS(sqlite3.h, [], [yap_cv_sqlite3="no"]) + if test "$yap_cv_sqlite3" != no + then + YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_SQLITE3" + fi + if test "$myddasstats" = "yes" then YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_STATS" @@ -89,24 +142,16 @@ then then YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_TOP_LEVEL" fi - #from SWI PROSQLITE library. - AC_CHECK_LIB(sqlite3, sqlite3_open, - MYDDAS_LIBS="-lsqlite3 $MYDDAS_LIBS" - havelib=yes) - - AC_CHECK_HEADERS(sqlite3.h, [], [yap_cv_sqlite3="no"]) - if test "$yap_cv_odbc" = yes - then - YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_SQLITE3" - fi - - LIBS="$OLD_LIBS" + MYDDAS_LIBS="$LIBS" + LIBS="$OLD_LIBS" + CPPFLAGS="$OLD_CPPFLAGS" else ENABLE_MYDDAS="" fi AC_SUBST(PKG_MYDDAS) +AC_SUBST(MYDDAS_CPPFLAGS) AC_SUBST(MYDDAS_LIBS) diff --git a/packages/myddas/myddas.h b/packages/myddas/myddas.h index a2f29b79d..619626df9 100644 --- a/packages/myddas/myddas.h +++ b/packages/myddas/myddas.h @@ -112,6 +112,8 @@ typedef struct myddas_list_preds *MYDDAS_UTIL_PREDICATE; typedef struct myddas_stats_time_struct *MYDDAS_STATS_TIME; typedef struct myddas_global_stats *MYDDAS_GLOBAL_STATS; typedef struct myddas_stats_struct *MYDDAS_STATS_STRUCT; +#else +typedef void *MYDDAS_STATS_TIME; #endif #ifdef DEBUG diff --git a/packages/myddas/myddas_sqlite3.c b/packages/myddas/myddas_sqlite3.c new file mode 100644 index 000000000..7b216d5af --- /dev/null +++ b/packages/myddas/myddas_sqlite3.c @@ -0,0 +1,746 @@ +/************************************************************************* +* * +* YAP Prolog * +* * +* Yap Prolog was developed at NCCUP - Universidade do Porto * +* * +* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * +* * +************************************************************************** +* * +* File: myddas_sqlite3.c * +* Last rev: 22/03/05 * +* mods: * +* comments: Predicates for comunicating with a sqlite3 database system * +* * +*************************************************************************/ + +#ifdef MYDDAS_SQLITE3 + +#include +#include +#include +#include +#include "Yap.h" +#include "Yatom.h" +#include "YapText.h" +#include "cut_c.h" +#include "eval.h" +#include "myddas.h" +#ifdef MYDDAS_STATS +#include "myddas_structs.h" +#include "myddas_statistics.h" +#endif +#include "myddas_wkb2prolog.h" + +#define CALL_SQLITE(f) \ +{ \ + int i; \ + i = sqlite3_ ## f; \ + if (i != SQLITE_OK) { \ + fprintf (stderr, "%s failed with status %d: %s\n", \ + #f, i, sqlite3_errmsg (db)); \ + exit (1); \ + } \ +} \ + +#define CALL_SQLITE_EXPECT(f,x) \ +{ \ + int i; \ + i = sqlite3_ ## f; \ + if (i != SQLITE_ ## x) { \ + fprintf (stderr, "%s failed with status %d: %s\n", \ + #f, i, sqlite3_errmsg (db)); \ + exit (1); \ + } \ +} \ + +static Int null_id = 0; + +typedef struct result_set { + sqlite3_stmt *stmt; + sqlite3 *db; + char **res_set; + int nrows; + int length; +} resultSet; + +void Yap_InitMYDDAS_SQLitePreds(void); +void Yap_InitBackMYDDAS_sqlite3Preds(void); + + +static Int c_sqlite3_connect( USES_REGS1 ); +static Int c_sqlite3_disconnect( USES_REGS1 ); +static Int c_sqlite3_number_of_fields( USES_REGS1 ); +static Int c_sqlite3_get_attributes_types( USES_REGS1 ); +static Int c_sqlite3_query( USES_REGS1 ); +static Int c_sqlite3_table_write( USES_REGS1 ); +static Int c_sqlite3_row( USES_REGS1 ); +static Int c_sqlite3_row_cut( USES_REGS1 ); +static Int c_sqlite3_get_fields_properties( USES_REGS1 ); +static Int c_sqlite3_get_next_result_set( USES_REGS1 ); +static Int c_sqlite3_get_database( USES_REGS1 ); +static Int c_sqlite3_change_database( USES_REGS1 ); + +void Yap_InitMYDDAS_SQLitePreds(void) +{ + /* db_dbect: Host x User x Passwd x Database x dbection x ERROR_CODE */ + Yap_InitCPred("c_sqlite3_connect", 7, c_sqlite3_connect, 0); + + /* db_number_of_fields: Relation x connection x NumberOfFields */ + Yap_InitCPred("c_sqlite3_number_of_fields",3, c_sqlite3_number_of_fields, 0); + + /* db_get_attributes_types: Relation x TypesList */ + Yap_InitCPred("c_sqlite3_get_attributes_types", 3, c_sqlite3_get_attributes_types, 0); + + /* db_query: SQLQuery x ResultSet x conection */ + Yap_InitCPred("c_sqlite3_query", 5, c_sqlite3_query, 0); + + /* db_disconnect: connection */ + Yap_InitCPred("c_sqlite3_disconnect", 1,c_sqlite3_disconnect, 0); + + /* db_table_write: Result Set */ + Yap_InitCPred("c_sqlite3_table_write", 1, c_sqlite3_table_write, 0); + + /* db_get_fields_properties: PredName x connection x PropertiesList*/ + Yap_InitCPred("c_sqlite3_get_fields_properties",3,c_sqlite3_get_fields_properties,0); + + Yap_InitCPred("c_sqlite3_get_next_result_set",2,c_sqlite3_get_next_result_set,0); + + /* c_sqlite3_get_database: connection x DataBaseName */ + Yap_InitCPred("c_sqlite3_get_database",2,c_sqlite3_get_database,0); + + /* c_sqlite3_change_database: connection x DataBaseName */ + Yap_InitCPred("c_sqlite3_change_database",2,c_sqlite3_change_database,0); + + +} + +void Yap_InitBackMYDDAS_sqlite3Preds(void) +{ + /* db_row: ResultSet x Arity x ListOfArgs */ + Yap_InitCPredBackCut("c_sqlite3_row", 3, sizeof(Int), + c_sqlite3_row, + c_sqlite3_row, + c_sqlite3_row_cut, 0); + +} + +static Int +c_sqlite3_connect( USES_REGS1 ) { + + Term arg_file = Deref(ARG1); + Term arg_db = ARG2; + + MYDDAS_UTIL_CONNECTION new = NULL; + sqlite3 *db; + + char *file = AtomName(AtomOfTerm(arg_file)); + + CALL_SQLITE( open(file, &db) ); + + if (!Yap_unify(arg_db, MkAddressTerm(db))) + return FALSE; + else + { + /* Criar um novo no na lista de ligacoes*/ + new = myddas_util_add_connection(db,NULL); + + if (new == NULL){ +#ifdef DEBUG + fprintf(stderr, "ERROR: ** c_db_my_connect ** Error allocating memory\n"); +#endif + return FALSE; + } + return TRUE; + } + +} + +static MYDDAS_STATS_TIME +myddas_stat_init_query( sqlite3 *db ) +{ +#ifdef MYDDAS_STATS + MYDDAS_UTIL_connecTION node = myddas_util_search_connection(db); + MyddasULInt count = 0; + + /* Count the number of querys made to the server */ + MyddasULInt number_querys; + MYDDAS_STATS_CON_GET_NUMBER_QUERIES_MADE(node,number_querys); + MYDDAS_STATS_CON_SET_NUMBER_QUERIES_MADE(node,++number_querys); + MYDDAS_STATS_CON_GET_NUMBER_QUERIES_MADE_COUNT(node,count); + MYDDAS_STATS_CON_SET_NUMBER_QUERIES_MADE_COUNT(node,++count); + /* Measure time spent by the sqlite3 Server + processing the SQL Query */ + return myddas_stats_walltime(); +#else + return NULL; +#endif +} + + +static MYDDAS_STATS_TIME +myddas_stat_end_query( MYDDAS_STATS_TIME start ) +{ + MYDDAS_STATS_TIME diff = NULL; +#ifdef MYDDAS_STATS + /* Measure time spent by the sqlite3 Server + processing the SQL Query */ + end = myddas_stats_walltime(); + + MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy); + myddas_stats_subtract_time(diff,end,start); + diff = myddas_stats_time_copy_to_final(diff); + + MYDDAS_FREE(end,struct myddas_stats_time_struct); + MYDDAS_FREE(start,struct myddas_stats_time_struct); + + MYDDAS_STATS_CON_GET_TOTAL_TIME_DBSERVER(node,total_time); + /* Automacally updates the MYDDAS_STRUCTURE */ + myddas_stats_add_time(total_time,diff,total_time); + MYDDAS_STATS_CON_GET_TOTAL_TIME_DBSERVER_COUNT(node,count); + MYDDAS_STATS_CON_SET_TOTAL_TIME_DBSERVER_COUNT(node,++count); + + MYDDAS_STATS_TIME time = NULL; + MYDDAS_STATS_CON_GET_LAST_TIME_DBSERVER(node,time); + myddas_stats_move_time(diff,time); + MYDDAS_STATS_CON_GET_LAST_TIME_DBSERVER_COUNT(node,count); + MYDDAS_STATS_CON_SET_LAST_TIME_DBSERVER_COUNT(node,++count); +#endif + return diff; +} + +/* +static void +myddas_stat_transfer_query( MYDDAS_STATS_TIME diff ) +{ +#ifdef MYDDAS_STATS_DISABLED + /* Measure time spent by the sqlite3 Server + transferring the result of the last query + back to the client */ + start = myddas_stats_walltime(); + /* Measure time spent by the sqlite3 Server + transferring the result of the last query + back to the client */ + end = myddas_stats_walltime(); + + MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy); + myddas_stats_subtract_time(diff,end,start); + diff = myddas_stats_time_copy_to_final(diff); + + MYDDAS_FREE(end,struct myddas_stats_time_struct); + MYDDAS_FREE(start,struct myddas_stats_time_struct); + + MYDDAS_STATS_CON_GET_TOTAL_TIME_TRANSFERING(node,total_time); + /* Automacally updates the MYDDAS_STRUCTURE */ + myddas_stats_add_time(total_time,diff,total_time); + MYDDAS_STATS_CON_GET_TOTAL_TIME_TRANSFERING_COUNT(node,count); + MYDDAS_STATS_CON_SET_TOTAL_TIME_TRANSFERING_COUNT(node,++count); + + time = NULL; + MYDDAS_STATS_CON_GET_LAST_TIME_TRANSFERING(node,time); + MYDDAS_STATS_CON_GET_LAST_TIME_TRANSFERING_COUNT(node,count); + MYDDAS_STATS_CON_SET_LAST_TIME_TRANSFERING_COUNT(node,++count); + myddas_stats_move_time(diff,time); + + /* Measure the number of Rows returned from the server */ + if (res_set != NULL) + { + /* With an INSERT statement, sqlite3_(use or store)_result() + returns a NULL pointer*/ + + /* This is only works if we use sqlite3_store_result */ + MyddasUInt numberRows = sqlite3_num_rows(res_set); + MyddasUInt rows; + + MYDDAS_STATS_CON_GET_TOTAL_ROWS(node,rows); + numberRows = numberRows + rows; + MYDDAS_STATS_CON_SET_TOTAL_ROWS(node,numberRows); + MYDDAS_STATS_CON_GET_TOTAL_ROWS_COUNT(node,count); + MYDDAS_STATS_CON_SET_TOTAL_ROWS_COUNT(node,++count); + + /* Calculate the ammount of data sent by the server */ + MyddasUInt total,number_fields = sqlite3_num_fields(res_set); + sqlite3_ROW row; + MyddasULInt i; + total=0; + while ((row = sqlite3_fetch_row(res_set)) != NULL){ + sqlite3_field_seek(res_set,0); + + for(i=0;idb = db; + + start = myddas_stat_init_query( db ); + + /* Send query to server and process it */ + if (strcmp(mode,"store_result")!=0) { + // Leave data for extraction + CALL_SQLITE (prepare_v2(db, sql, -1, &stmt, NULL) ); + rs->stmt = stmt; + rs->res_set = NULL; + rs->nrows = -1; + rs->length = sqlite3_column_count( stmt ); + if (!Yap_unify(arg_arity, MkIntegerTerm(rs->length))) + { + free(rs); + return FALSE; + } + if (!Yap_unify(arg_result_set, MkAddressTerm( rs))) + { + free(rs); + return FALSE; + } + return TRUE; + } else{ + // construct an intermediate table, res_set + char **res_set; + char *msg; + int nrows; + + CALL_SQLITE (get_table(db, sql, &res_set, &nrows, &length, &msg) ); + + end = myddas_stat_end_query( start ); + if (res_set == NULL) + { +#ifdef DEBUG + printf("Empty Query!\n"); +#endif + return TRUE; + } + //INSERT statements don't return any res_set + if (nrows == 0) { + return TRUE; + } + if (!Yap_unify(arg_arity, MkIntegerTerm(nrows))){ + free(rs); + sqlite3_free_table(res_set); + return FALSE; + } + rs->stmt = NULL; + rs->res_set = res_set; + rs->nrows = nrows; + rs->length = length; + if (!Yap_unify(arg_result_set, MkAddressTerm( rs))) + { + free(rs); + sqlite3_free_table(res_set); + return FALSE; + } + } + return TRUE; +} + + +static Int +c_sqlite3_number_of_fields( USES_REGS1 ) { + Term arg_relation = Deref(ARG1); + Term arg_db = Deref(ARG2); + Term arg_fields = ARG3; + + char *relation = AtomName(AtomOfTerm(arg_relation)); + sqlite3 *db = AddressOfTerm(arg_db); + sqlite3_stmt *stmt; + + char sql[256]; + + sprintf(sql,"SELECT * FROM TABLE `%s`",relation); + + /* executar a query SQL */ + CALL_SQLITE (prepare_v2(db, sql, -1, &stmt, NULL) ); + + int fields = sqlite3_column_count( stmt ); + + CALL_SQLITE (finalize( stmt ) ); + + return Yap_unify(arg_fields, MkIntegerTerm( fields )); +} + + +/* db_get_attributes_types: RelName x connection -> TypesList */ +static Int +c_sqlite3_get_attributes_types( USES_REGS1 ) { + Term arg_relation = Deref(ARG1); + Term arg_db = Deref(ARG2); + Term arg_types_list = Deref(ARG3); + Term list, head; + + char *relation = AtomName(AtomOfTerm(arg_relation)); + sqlite3 *db = (sqlite3 *) IntegerOfTerm(arg_db); + char sql[256]; + int row; + + sqlite3_stmt *stmt; + Int rc = TRUE; + + sprintf(sql,"SELECT * FROM TABLE `%s`",relation); + + /* executar a query SQL */ + CALL_SQLITE (prepare_v2(db, sql, -1, &stmt, NULL) ); + + int fields = sqlite3_column_count( stmt ); + + list = arg_types_list; + + for (row = 0; row < fields; row++) + { + const char *tm; + + + head = HeadOfTerm(list); + rc = ( + rc && Yap_unify(head, MkAtomTerm(Yap_LookupAtom(sqlite3_column_name(stmt, row))) ) ); + list = TailOfTerm(list); + head = HeadOfTerm(list); + list = TailOfTerm(list); + + int type = sqlite3_column_type(stmt,row ); + switch(type) { + case SQLITE_INTEGER: + tm = "integer"; + break; + case SQLITE_FLOAT: + tm = "real"; + break; + case SQLITE_TEXT: + tm = "string"; + break; + case SQLITE_BLOB: + tm = "blob"; + break; + case SQLITE_NULL: + tm = "null"; + break; + } + if (!Yap_unify(head, MkAtomTerm(Yap_LookupAtom(tm))) ) + rc = FALSE; + } + + CALL_SQLITE (finalize( stmt ) ); + + return rc; + +} + +/* db_disconnect */ +static Int +c_sqlite3_disconnect( USES_REGS1 ) { + Term arg_db = Deref(ARG1); + + sqlite3 *db = (sqlite3 *) IntegerOfTerm(arg_db); + + if ((myddas_util_search_connection(db)) != NULL) + { + myddas_util_delete_connection(db); + sqlite3_close(db); + return TRUE; + } + else + { + return FALSE; + } +} + +/* db_table_write: Result Set */ +static Int +c_sqlite3_table_write( USES_REGS1 ) { + /* + Term arg_res_set = Deref(ARG1); + sqlite3_RES *res_set = (sqlite3_RES *) IntegerOfTerm(arg_res_set); + + mydas_util_table_write(res_set); + sqlite3_free_result(res_set); + */ + return TRUE; +} + +static Int +c_sqlite3_get_fields_properties( USES_REGS1 ) { + Term nome_relacao = Deref(ARG1); + Term arg_db = Deref(ARG2); + Term fields_properties_list = Deref(ARG3); + Term head, list; + + char *relation = AtomName(AtomOfTerm(nome_relacao)); + char sql[256]; + Int num_fields,i; + sqlite3 *db = (sqlite3 *) (IntegerOfTerm(arg_db)); + + sqlite3_stmt *stmt; + + sprintf(sql,"SELECT * FROM TABLE `%s`",relation); + + /* executar a query SQL */ + CALL_SQLITE (prepare_v2(db, sql, -1, &stmt, NULL) ); + + Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"),4); + + Term properties[4]; + + list = fields_properties_list; + + num_fields = sqlite3_column_count( stmt ); + + for (i=0;istmt = stmt; + rs->res_set = NULL; + rs->nrows = -1; + rs->length = sqlite3_column_count( stmt ); + rs->db = db; + Yap_unify(arg_next_res_set, MkAddressTerm(rs)); + } + return TRUE; +} + +static Int +c_sqlite3_get_database( USES_REGS1 ) { + Term arg_con = Deref(ARG1); + Term arg_database = Deref(ARG2); + + if (!Yap_unify(arg_database,arg_con)) + return FALSE; + + return TRUE; + +} + +static Int +c_sqlite3_change_database( USES_REGS1 ) { + /* no-op for now */ + return TRUE; +} + +static Int +c_sqlite3_row_cut( USES_REGS1 ) { + struct result_set *res_set=NULL; + sqlite3 *db = res_set->db; + + res_set = AddressOfTerm(EXTRA_CBACK_CUT_ARG(Term,1)); + CALL_SQLITE( finalize( res_set->stmt ) ); + free(res_set); + return TRUE; +} + +#define cvt( s ) cvt__( s PASS_REGS ) + +static Term +cvt__(const char *s USES_REGS) { + return Yap_CharsToTDQ( s, CurrentModule PASS_REGS); +} + +/* db_row: ResultSet x Arity_ListOfArgs x ListOfArgs -> */ +static Int +c_sqlite3_row( USES_REGS1 ) { +#ifdef MYDDAS_STATS + /* Measure time used by the */ + /* c_sqlite3_row function */ + //MYDDAS_STATS_TIME start,end,total_time,diff; + MyddasULInt count = 0; + start = myddas_stats_walltime(); +#endif + Term arg_result_set = Deref(ARG1); + Term arg_arity = Deref(ARG2); + Term arg_list_args = Deref(ARG3); + Int rc = TRUE; + + if (IsVarTerm( arg_result_set ) ) { + if (!c_sqlite3_query( PASS_REGS1 ) ) { + cut_fail(); + } + arg_result_set = Deref(ARG1); + EXTRA_CBACK_ARG(3,1)= arg_result_set ; + EXTRA_CBACK_ARG(3,2)= MkIntegerTerm(0) ; + } + struct result_set *res_set = (struct result_set *) IntegerOfTerm(arg_result_set); + + Term head, list, null_atom[1]; + Int i, arity; + list = arg_list_args; + arity = IntegerOfTerm(arg_arity); + sqlite3 *db = res_set->db; + + if (res_set->stmt == NULL ) { + CACHE_REGS + Int indx = IntegerOfTerm(EXTRA_CBACK_CUT_ARG(Term,2)); + Int rc = true; + // data needs to be copied to Prolog + // row by row + while (indx/arity < res_set->nrows) + { + for (i = 0; i < arity; i++) + { + /* Ts -> List */ + const char *field = res_set->res_set[indx++]; + head = HeadOfTerm(list); + list = TailOfTerm(list); + rc = (rc && Yap_unify(head, cvt( field )) ); + } + if (rc) + return rc; + } + cut_fail(); + } + // busy-waiting + int res; + while((res = sqlite3_step(res_set->stmt)) == SQLITE_BUSY); + if (res == SQLITE_DONE) { + // no more data + CALL_SQLITE (finalize( res_set->stmt ) ); + free(res_set); +#ifdef MYDDAS_STATS + end = myddas_stats_walltime(); + + MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy); + myddas_stats_subtract_time(diff,end,start); + diff = myddas_stats_time_copy_to_final(diff); + + MYDDAS_FREE(end,struct myddas_stats_time_struct); + MYDDAS_FREE(start,struct myddas_stats_time_struct); + + MYDDAS_STATS_GET_DB_ROW_FUNCTION(total_time); + myddas_stats_add_time(total_time,diff,total_time); + MYDDAS_STATS_GET_DB_ROW_FUNCTION_COUNT(count); + MYDDAS_STATS_SET_DB_ROW_FUNCTION_COUNT(++count); + + MYDDAS_FREE(diff,struct myddas_stats_time_struct); +#endif /* MYDDAS_STATS */ + cut_fail(); /* This macro already does a return FALSE */ + + } else if (res == SQLITE_ROW) { + list = arg_list_args; + Term tf; + + for (i = 0; i < arity; i++) + { + /* convert data types here */ + head = HeadOfTerm(list); + list = TailOfTerm(list); + + int type = sqlite3_column_type(res_set->stmt, i); + switch(type) { + case SQLITE_INTEGER: + tf = Yap_Mk64IntegerTerm( sqlite3_column_int64(res_set->stmt, i)); + break; + case SQLITE_FLOAT: + tf = MkFloatTerm( sqlite3_column_double(res_set->stmt, i)); + break; + case SQLITE_TEXT: + tf = MkAtomTerm( Yap_LookupAtom((const char *)sqlite3_column_text(res_set->stmt, i) )); + break; + case SQLITE_BLOB: + { + size_t bytes = sqlite3_column_bytes(res_set->stmt, i); + tf = Yap_AllocExternalDataInStack(EXTERNAL_BLOB, bytes); + memcpy( ExternalBlobFromTerm( tf ), sqlite3_column_blob(res_set->stmt, i), bytes ); + } + break; + case SQLITE_NULL: + null_atom[0] = MkIntegerTerm(null_id++); + tf = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("null"),1),1,null_atom); + break; + } + } + if (!Yap_unify(head, tf)) + rc = FALSE; +#ifdef MYDDAS_STATS + end = myddas_stats_walltime(); + + MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy); + myddas_stats_subtract_time(diff,end,start); + diff = myddas_stats_time_copy_to_final(diff); + + MYDDAS_FREE(end,struct myddas_stats_time_struct); + MYDDAS_FREE(start,struct myddas_stats_time_struct); + + MYDDAS_STATS_GET_DB_ROW_FUNCTION(total_time); + myddas_stats_add_time(total_time,diff,total_time); + MYDDAS_STATS_GET_DB_ROW_FUNCTION_COUNT(count); + MYDDAS_STATS_SET_DB_ROW_FUNCTION_COUNT(++count); + + MYDDAS_FREE(diff,struct myddas_stats_time_struct); +#endif /* MYDDAS_STATS */ + } else + { + Yap_Error(SYSTEM_ERROR, TermNil, "sqlite3: %s", sqlite3_errmsg( db ) ); + } + return rc; +} + + +#endif /* MYDDAS_sqlite3 */ diff --git a/packages/myddas/pl/myddas_assert_predicates.ypp b/packages/myddas/pl/myddas_assert_predicates.ypp index b03179dc0..617bef5eb 100644 --- a/packages/myddas/pl/myddas_assert_predicates.ypp +++ b/packages/myddas/pl/myddas_assert_predicates.ypp @@ -71,7 +71,10 @@ db_import(Connection,RelationName,PredName) :- ( ConType == mysql -> c_db_my_number_of_fields(RelationName,Con,Arity) ; + ConType == odbc -> c_db_odbc_number_of_fields(RelationName,Con,Arity) + ; + c_sqllite3_number_of_fields(RelationName,Con,Arity) ), db_module(Module), not c_db_check_if_exists_pred(PredName,Arity,Module), @@ -86,7 +89,10 @@ db_import(Connection,RelationName,PredName) :- ( ConType == mysql -> c_db_my_get_attributes_types(RelationName,Con,TypesList) ; - c_db_odbc_get_attributes_types(RelationName,Con,TypesList) + ConType == odbc -> + c_db_odbc_get_attributes_types(RelationName,Con,TypesList) + ; + c_sqlite3_get_attributes_types(RelationName,Con,TypesList) ), % assert attributes facts @@ -108,6 +114,17 @@ db_import(Connection,RelationName,PredName) :- ','(M:c_db_my_query(FinalSQL,ResultSet,Con,Mode,_), ','(!,M:c_db_my_row(ResultSet,Arity,LA))))))))] + ; + ConType == sqlit3 -> + + Assert =..[':-',P,','(M:'$copy_term_nv'(P,[],G,_), + ','(M:translate(G,G,Code), + ','(M:queries_atom(Code,FinalSQL), + ','(M:db_my_result_set(Mode), + ','(M:'$write_or_not'(FinalSQL), + ','(M:c_sqlit3_query(FinalSQL,ResultSet,Con,Mode,_), + ','(!,M:c_sqlit3_row(ResultSet,Arity,LA))))))))] + ; '$make_a_list'(Arity,BindList), Assert =..[':-',P,','(M:'$copy_term_nv'(P,[],G,_), diff --git a/packages/myddas/pl/myddas_errors.ypp b/packages/myddas/pl/myddas_errors.ypp index ca1514fd8..e31c37e1f 100644 --- a/packages/myddas/pl/myddas_errors.ypp +++ b/packages/myddas/pl/myddas_errors.ypp @@ -84,6 +84,8 @@ c_db_connection_type(Con,ConType), ( ConType == mysql -> c_db_my_number_of_fields(Relation,Con,Arity) + ; ConType == sqlit3 -> + c_sqlit3_number_of_fields(Relation,Con,Arity) ; c_db_odbc_number_of_fields(Relation,Con,Arity) ), @@ -92,6 +94,8 @@ '$make_a_list'(Arity,FieldsProperties), ( ConType == mysql -> c_db_my_get_fields_properties(Relation,Con,FieldsProperties) + ;ConType == sqlit3 -> + c_sqlit3_get_fields_properties(Relation,Con,FieldsProperties) ; c_db_odbc_get_fields_properties(Relation,Con,FieldsProperties) ), @@ -110,6 +114,10 @@ nonvar(Password), atom(Connection), get_value(Connection,[]). % Nao pode ter nenhum valor atribuido +'$error_checks'(db_open(sqlit3,Connection,File,_User,_Password)) :- !, + nonvar(File), % == \+var(ODBCEntry) + atom(Connection), + get_value(Connection,[]). % Nao pode ter nenhum valor atribuido '$error_checks'(db_view(Connection,Pred,DbGoal)) :- !, atom(Connection), nonvar(DbGoal), diff --git a/packages/myddas/pl/myddas_util_predicates.ypp b/packages/myddas/pl/myddas_util_predicates.ypp index e481a5deb..03836c73c 100644 --- a/packages/myddas/pl/myddas_util_predicates.ypp +++ b/packages/myddas/pl/myddas_util_predicates.ypp @@ -411,7 +411,7 @@ % % This predicate asserts facts in a Module, but if that -% fact already exists, it dosen't assert it +% fact already exists, it doesn't assert it % '$assert_facts'(Module,Fact):- Module:Fact,!.