This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/myddas/sqlite3/myddas_sqlite3.c

708 lines
22 KiB
C
Raw Normal View History

2015-11-05 17:06:15 +00:00
/*************************************************************************
2017-11-18 00:04:42 +00:00
* *
* 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 *
* *
*************************************************************************/
2015-11-05 17:06:15 +00:00
#include <sqlite3.h>
2017-11-18 00:04:42 +00:00
2015-11-05 17:06:15 +00:00
#include "Yap.h"
2017-11-18 00:04:42 +00:00
#include "YapEval.h"
2015-11-05 17:06:15 +00:00
#include "YapText.h"
2017-11-18 00:04:42 +00:00
#include "Yatom.h"
2015-11-05 17:06:15 +00:00
#include "cut_c.h"
#include "myddas.h"
2017-11-18 00:04:42 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2015-11-05 17:06:15 +00:00
#ifdef MYDDAS_STATS
#include "myddas_statistics.h"
2017-11-18 00:04:42 +00:00
#include "myddas_structs.h"
2015-11-05 17:06:15 +00:00
#endif
2016-01-03 02:06:09 +00:00
//#include "myddas_wkb2prolog.h"
2017-11-18 00:04:42 +00:00
#define CALL_SQLITE(t, f) \
2016-01-03 02:06:09 +00:00
{ \
int i; \
i = sqlite3_##f; \
if (i != SQLITE_OK) { \
2018-06-28 12:48:29 +01:00
Yap_ThrowError(EVALUATION_ERROR_DBMS, MkStringTerm(#f), "%s failed with status %d: %s\n", \
2017-11-18 00:04:42 +00:00
#f, i, sqlite3_errmsg(db)); \
2016-01-03 02:06:09 +00:00
} \
}
#define CALL_SQLITE_EXPECT(f, x) \
{ \
int i; \
i = sqlite3_##f; \
if (i != SQLITE_##x) { \
2018-06-28 12:48:29 +01:00
Yap_ThrowError(EVALUATION_ERROR_DBMS, MkStringTerm(#f), "%s failed with status %d: %s\n", #f, i, \
2016-01-03 02:06:09 +00:00
sqlite3_errmsg(db)); \
exit(1); \
} \
}
2015-11-05 17:06:15 +00:00
static Int null_id = 0;
typedef struct result_set {
sqlite3_stmt *stmt;
sqlite3 *db;
int nrows;
int length;
} resultSet;
2017-11-18 00:04:42 +00:00
static void Yap_InitMYDDAS_SQLITE3Preds(void);
static void Yap_InitBackMYDDAS_SQLITE3Preds(void);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
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_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);
static Int c_sqlite3_connect(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_file = Deref(ARG1);
Term arg_db = ARG4;
MYDDAS_UTIL_CONNECTION new = NULL;
sqlite3 *db;
2016-01-03 02:06:09 +00:00
const char *file = AtomName(AtomOfTerm(arg_file));
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "connect sqlite3 %s",file);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
CALL_SQLITE(ARG1, open(file, &db));
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "connect sqlite3 %p",db);
2015-11-05 17:06:15 +00:00
if (!Yap_unify(arg_db, MkAddressTerm(db))) {
2018-03-26 23:12:48 +01:00
return false;
} else {
2016-01-03 02:06:09 +00:00
/* Criar um novo no na lista de ligacoes*/
new = myddas_util_add_connection(db, NULL, API_SQLITE3);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
if (new == NULL) {
2015-11-05 17:06:15 +00:00
#ifdef DEBUG
fprintf(stderr, "ERROR: ** c_db_my_connect ** Error allocating memory\n");
2015-11-05 17:06:15 +00:00
#endif
2018-03-26 23:12:48 +01:00
return false;
2015-11-05 17:06:15 +00:00
}
2018-03-26 23:12:48 +01:00
return true;
2016-01-03 02:06:09 +00:00
}
2015-11-05 17:06:15 +00:00
}
#ifdef MYDDAS_STATS
2016-01-03 02:06:09 +00:00
static MYDDAS_STATS_TIME myddas_stat_init_query(sqlite3 *db) {
2015-11-05 17:06:15 +00:00
MYDDAS_UTIL_connecTION node = myddas_util_search_connection(db);
MyddasULInt count = 0;
/* Count the number of querys made to the server */
MyddasULInt number_querys;
2016-01-03 02:06:09 +00:00
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);
2015-11-05 17:06:15 +00:00
/* Measure time spent by the sqlite3 Server
processing the SQL Query */
return myddas_stats_walltime();
return NULL;
}
2017-11-18 00:04:42 +00:00
static MYDDAS_STATS_TIME myddas_stat_end_query(MYDDAS_STATS_TIME start) {
2015-11-05 17:06:15 +00:00
MYDDAS_STATS_TIME diff = NULL;
/* Measure time spent by the sqlite3 Server
processing the SQL Query */
end = myddas_stats_walltime();
2016-01-03 02:06:09 +00:00
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff, time_copy);
myddas_stats_subtract_time(diff, end, start);
2015-11-05 17:06:15 +00:00
diff = myddas_stats_time_copy_to_final(diff);
2016-01-03 02:06:09 +00:00
MYDDAS_FREE(end, struct myddas_stats_time_struct);
MYDDAS_FREE(start, struct myddas_stats_time_struct);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
MYDDAS_STATS_CON_GET_TOTAL_TIME_DBSERVER(node, total_time);
2015-11-05 17:06:15 +00:00
/* Automacally updates the MYDDAS_STRUCTURE */
2016-01-03 02:06:09 +00:00
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);
2015-11-05 17:06:15 +00:00
MYDDAS_STATS_TIME time = NULL;
2016-01-03 02:06:09 +00:00
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);
2015-11-05 17:06:15 +00:00
return diff;
}
/* measure transfer time */
2016-01-03 02:06:09 +00:00
static void myddas_stat_transfer_query(MYDDAS_STATS_TIME diff) {
2015-11-05 17:06:15 +00:00
/* 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();
2016-01-03 02:06:09 +00:00
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff, time_copy);
myddas_stats_subtract_time(diff, end, start);
2015-11-05 17:06:15 +00:00
diff = MYDDAS_STATS_TIME_copy_to_final(diff);
2016-01-03 02:06:09 +00:00
MYDDAS_FREE(end, struct myddas_stats_time_struct);
MYDDAS_FREE(start, struct myddas_stats_time_struct);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
MYDDAS_STATS_CON_GET_TOTAL_TIME_TRANSFERING(node, total_time);
2015-11-05 17:06:15 +00:00
/* Automacally updates the MYDDAS_STRUCTURE */
2016-01-03 02:06:09 +00:00
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);
2015-11-05 17:06:15 +00:00
time = NULL;
2016-01-03 02:06:09 +00:00
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);
2015-11-05 17:06:15 +00:00
/* Measure the number of Rows returned from the server */
2016-01-03 02:06:09 +00:00
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_stat_transfer_query(diff);
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; i < number_fields; i++) {
if (row[i] != NULL)
total = total + strlen(row[i]);
2015-11-05 17:06:15 +00:00
}
}
2016-01-03 02:06:09 +00:00
MYDDAS_STATS_CON_SET_LAST_BYTES_TRANSFERING_FROM_DBSERVER(node, total);
MYDDAS_STATS_CON_GET_LAST_BYTES_TRANSFERING_FROM_DBSERVER_COUNT(node,
count);
MYDDAS_STATS_CON_SET_LAST_BYTES_TRANSFERING_FROM_DBSERVER_COUNT(node,
++count);
MyddasUInt bytes = 0;
MYDDAS_STATS_CON_GET_TOTAL_BYTES_TRANSFERING_FROM_DBSERVER(node, bytes);
total = total + bytes;
MYDDAS_STATS_CON_SET_TOTAL_BYTES_TRANSFERING_FROM_DBSERVER(node, total);
MYDDAS_STATS_CON_GET_TOTAL_BYTES_TRANSFERING_FROM_DBSERVER_COUNT(node,
count);
MYDDAS_STATS_CON_SET_TOTAL_BYTES_TRANSFERING_FROM_DBSERVER_COUNT(node,
++count);
}
2015-11-05 17:06:15 +00:00
}
#endif
/* db_query: SQLQuery x ResultSet x connection */
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_query(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_sql_query = Deref(ARG1);
Term arg_result_set = Deref(ARG2);
Term arg_db = Deref(ARG3);
2016-08-02 01:16:39 +01:00
// Term arg_mode = Deref(ARG4); // ignored by SQLite3
2015-11-05 17:06:15 +00:00
Term arg_arity = Deref(ARG5);
2016-01-03 02:06:09 +00:00
const char *sql = AtomName(AtomOfTerm(arg_sql_query));
2015-11-05 17:06:15 +00:00
sqlite3 *db = AddressOfTerm(arg_db);
sqlite3_stmt *stmt;
2017-11-18 00:04:42 +00:00
#if MYDDAS_STATS
2015-11-05 17:06:15 +00:00
MYDDAS_STATS_TIME start, end;
2017-11-18 00:04:42 +00:00
#endif
2016-01-03 02:06:09 +00:00
struct result_set *rs = malloc(sizeof(struct result_set));
2015-11-05 17:06:15 +00:00
if (!rs)
return FALSE;
rs->db = db;
2017-11-18 00:04:42 +00:00
#if MYDDAS_STATS
2016-01-03 02:06:09 +00:00
start = myddas_stat_init_query(db);
2017-11-18 00:04:42 +00:00
#endif
// printf("Query %s\n", sql);
2016-01-03 02:06:09 +00:00
/* Send query to server and process it */
2017-11-18 00:04:42 +00:00
// Leave data for extraction
CALL_SQLITE(ARG1, prepare_v2(db, sql, -1, &stmt, NULL));
rs->stmt = stmt;
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;
2015-11-05 17:06:15 +00:00
}
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_number_of_fields(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_relation = Deref(ARG1);
Term arg_db = Deref(ARG2);
Term arg_fields = ARG3;
2016-01-03 02:06:09 +00:00
const char *relation = AtomName(AtomOfTerm(arg_relation));
2015-11-05 17:06:15 +00:00
sqlite3 *db = AddressOfTerm(arg_db);
sqlite3_stmt *stmt;
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", " sqlite3 relation %s",relation);
2015-11-05 17:06:15 +00:00
char sql[256];
2016-01-03 02:06:09 +00:00
sprintf(sql, "SELECT * FROM `%s`", relation);
2015-11-05 17:06:15 +00:00
/* executar a query SQL */
2017-11-18 00:04:42 +00:00
CALL_SQLITE(ARG1, prepare_v2(db, sql, -1, &stmt, NULL));
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
int fields = sqlite3_column_count(stmt);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
CALL_SQLITE(ARG1, finalize(stmt));
2015-11-05 17:06:15 +00:00
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", " sqlite3 fields %d",fields);
return Yap_unify(arg_fields, MkIntegerTerm(fields));
2015-11-05 17:06:15 +00:00
}
/* db_get_attributes_types: RelName x connection -> TypesList */
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_get_attributes_types(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_relation = Deref(ARG1);
Term arg_db = Deref(ARG2);
2017-11-18 00:04:42 +00:00
Term list, tf, *tfp = &tf;
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
const char *relation = AtomName(AtomOfTerm(arg_relation));
sqlite3 *db = (sqlite3 *)IntegerOfTerm(arg_db);
2015-11-05 17:06:15 +00:00
char sql[256];
int row;
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", " sqlite3 reelation %s get_attributes",relation);
2015-11-05 17:06:15 +00:00
sqlite3_stmt *stmt;
2016-01-03 02:06:09 +00:00
sprintf(sql, "SELECT * FROM `%s`", relation);
2015-11-05 17:06:15 +00:00
/* executar a query SQL */
2017-11-18 00:04:42 +00:00
CALL_SQLITE(MkStringTerm(sql), prepare_v2(db, sql, -1, &stmt, NULL));
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
int fields = sqlite3_column_count(stmt);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
for (row = 0; row < fields; row++) {
2015-11-05 17:06:15 +00:00
const char *tm;
2017-11-18 00:04:42 +00:00
list = Yap_MkNewPairTerm();
*tfp = list;
RepPair(list)[0] =
MkAtomTerm(Yap_LookupAtom(sqlite3_column_name(stmt, row)));
tfp = RepPair(list) + 1;
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
int type = sqlite3_column_type(stmt, row);
switch (type) {
case SQLITE_INTEGER:
tm = "integer";
2015-11-05 17:06:15 +00:00
break;
case SQLITE_FLOAT:
tm = "real";
break;
case SQLITE_TEXT:
tm = "string";
break;
case SQLITE_BLOB:
tm = "blob";
break;
case SQLITE_NULL:
tm = "";
break;
2017-11-18 00:04:42 +00:00
default:
tm = "?";
break;
2015-11-05 17:06:15 +00:00
}
2018-03-26 23:12:48 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", " sqlite3 attributes %s:%s ",sqlite3_column_name(stmt, row),tm);
list = Yap_MkNewPairTerm();
2017-11-18 00:04:42 +00:00
*tfp = list;
RepPair(list)[0] = MkAtomTerm(Yap_LookupAtom(tm));
tfp = RepPair(list) + 1;
tfp = RepPair(list) + 1;
2015-11-05 17:06:15 +00:00
}
2017-11-18 00:04:42 +00:00
*tfp = TermNil;
CALL_SQLITE(ARG1, finalize(stmt));
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
return Yap_unify(tf, ARG3);
2015-11-05 17:06:15 +00:00
}
/* db_disconnect */
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_disconnect(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_db = Deref(ARG1);
2016-01-03 02:06:09 +00:00
sqlite3 *db = (sqlite3 *)IntegerOfTerm(arg_db);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
if ((myddas_util_search_connection(db)) != NULL) {
myddas_util_delete_connection(db);
sqlite3_close(db);
return TRUE;
} else {
return FALSE;
}
2015-11-05 17:06:15 +00:00
}
/* db_table_write: Result Set */
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_table_write(USES_REGS1) {
2015-11-05 17:06:15 +00:00
/*
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;
}
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_get_fields_properties(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term nome_relacao = Deref(ARG1);
Term arg_db = Deref(ARG2);
Term fields_properties_list = Deref(ARG3);
Term head, list;
2016-01-03 02:06:09 +00:00
const char *relation = AtomName(AtomOfTerm(nome_relacao));
2015-11-05 17:06:15 +00:00
char sql[256];
2016-01-03 02:06:09 +00:00
Int num_fields, i;
sqlite3 *db = (sqlite3 *)(IntegerOfTerm(arg_db));
2015-11-05 17:06:15 +00:00
sqlite3_stmt *stmt;
2016-01-03 02:06:09 +00:00
sprintf(sql, "SELECT * FROM `%s`", relation);
2015-11-05 17:06:15 +00:00
/* executar a query SQL */
2016-01-03 02:06:09 +00:00
// printf(" SQL 4: %s\n", sql);
2017-11-18 00:04:42 +00:00
CALL_SQLITE(ARG1, prepare_v2(db, sql, -1, &stmt, NULL));
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"), 4);
2015-11-05 17:06:15 +00:00
Term properties[4];
list = fields_properties_list;
2016-01-03 02:06:09 +00:00
num_fields = sqlite3_column_count(stmt);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
for (i = 0; i < num_fields; i++) {
int not_null, prim, auto_inc;
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
head = HeadOfTerm(list);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
const char *col = sqlite3_column_name(stmt, i);
properties[0] = MkAtomTerm(Yap_LookupAtom(col));
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
CALL_SQLITE(properties[0],
table_column_metadata(db, NULL, relation, col, NULL, NULL,
2016-01-03 02:06:09 +00:00
&not_null, &prim, &auto_inc));
properties[1] = MkIntegerTerm(not_null); // Can't be NULL
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
properties[2] = MkIntegerTerm(prim); // It''s a primary key
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
properties[3] = MkIntegerTerm(auto_inc);
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
list = TailOfTerm(list);
if (!Yap_unify(head, Yap_MkApplTerm(functor, 4, properties))) {
return FALSE;
2015-11-05 17:06:15 +00:00
}
2016-01-03 02:06:09 +00:00
}
2015-11-05 17:06:15 +00:00
sqlite3_finalize(stmt);
return TRUE;
}
/* c_sqlite3_get_next_result_set: connection * NextResSet */
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_get_next_result_set(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_db = Deref(ARG1);
Term arg_next_res_set = Deref(ARG2);
2016-01-03 02:06:09 +00:00
sqlite3 *db = (sqlite3 *)(IntegerOfTerm(arg_db));
2015-11-05 17:06:15 +00:00
sqlite3_stmt *stmt;
2016-01-03 02:06:09 +00:00
if ((stmt = sqlite3_next_stmt(db, NULL)) != NULL) {
struct result_set *rs = malloc(sizeof(struct result_set));
2015-11-05 17:06:15 +00:00
if (!rs)
return FALSE;
rs->stmt = stmt;
rs->nrows = -1;
2016-01-03 02:06:09 +00:00
rs->length = sqlite3_column_count(stmt);
2015-11-05 17:06:15 +00:00
rs->db = db;
Yap_unify(arg_next_res_set, MkAddressTerm(rs));
}
return TRUE;
}
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_get_database(USES_REGS1) {
2015-11-05 17:06:15 +00:00
Term arg_con = Deref(ARG1);
Term arg_database = Deref(ARG2);
2016-01-03 02:06:09 +00:00
if (!Yap_unify(arg_database, arg_con))
2015-11-05 17:06:15 +00:00
return FALSE;
return TRUE;
}
2016-01-03 02:06:09 +00:00
static Int c_sqlite3_change_database(USES_REGS1) {
2015-11-05 17:06:15 +00:00
/* no-op for now */
return TRUE;
}
2017-08-21 12:41:15 +01:00
typedef struct row_state {
2017-11-18 00:04:42 +00:00
struct result_set *res_set;
int count;
2017-08-21 12:41:15 +01:00
} ROW_STATE;
2015-11-05 17:06:15 +00:00
2017-08-21 12:41:15 +01:00
static Int c_sqlite3_row_terminate(USES_REGS1) {
struct row_state *rs = AddressOfTerm(Deref(ARG1));
struct result_set *res_set = rs->res_set;
2015-11-05 17:06:15 +00:00
sqlite3 *db = res_set->db;
2017-11-18 00:04:42 +00:00
// no more data
2018-06-28 12:48:29 +01:00
CALL_SQLITE(Deref(ARG1), finalize(res_set->stmt));
2017-11-18 00:04:42 +00:00
free(res_set);
free(rs);
2017-08-21 12:41:15 +01:00
return true;
2015-11-05 17:06:15 +00:00
}
/* db_row: ResultSet x Arity_ListOfArgs x ListOfArgs -> */
2017-08-21 12:41:15 +01:00
static Int c_sqlite3_row_initialise(USES_REGS1) {
2015-11-05 17:06:15 +00:00
#ifdef MYDDAS_STATS
/* Measure time used by the */
/* c_sqlite3_row function */
2016-01-03 02:06:09 +00:00
// MYDDAS_STATS_TIME start,end,total_time,diff;
2015-11-05 17:06:15 +00:00
MyddasULInt count = 0;
start = myddas_stats_walltime();
#endif
Term arg_result_set = Deref(ARG1);
2017-08-21 12:41:15 +01:00
struct result_set *res_set;
2017-11-18 00:04:42 +00:00
struct row_state *rs = malloc(sizeof(struct row_state));
2017-08-21 12:41:15 +01:00
if (rs == NULL) {
2017-11-18 00:04:42 +00:00
Yap_Error(RESOURCE_ERROR_HEAP, ARG1, "sqlite3_row");
2017-08-21 12:41:15 +01:00
} else {
2017-11-18 00:04:42 +00:00
if (!Yap_unify(ARG2, MkAddressTerm(rs)))
return false;
2017-08-21 12:41:15 +01:00
}
2015-11-05 17:06:15 +00:00
2016-01-03 02:06:09 +00:00
if (IsVarTerm(arg_result_set)) {
if (!c_sqlite3_query(PASS_REGS1)) {
2017-08-21 12:41:15 +01:00
return false;
2015-11-05 17:06:15 +00:00
}
arg_result_set = Deref(ARG1);
}
2017-08-21 12:41:15 +01:00
res_set = AddressOfTerm(arg_result_set);
2017-11-18 00:04:42 +00:00
rs->res_set = res_set;
rs->count = 0;
return true;
2017-08-21 12:41:15 +01:00
}
2015-11-05 17:06:15 +00:00
2017-08-21 12:41:15 +01:00
/* db_row: ResultSet x Arity_ListOfArgs x ListOfArgs -> */
static Int c_sqlite3_row(USES_REGS1) {
#ifdef MYDDAS_STATS
2017-11-18 00:04:42 +00:00
/* Measure time used by the */
/* c_sqlite3_row function */
// MYDDAS_STATS_TIME start,end,total_time,diff;
MyddasULInt count = 0;
start = myddas_stats_walltime();
2017-08-21 12:41:15 +01:00
#endif
2017-11-18 00:04:42 +00:00
Term arg_arity = Deref(ARG2);
Term arg_list_args = Deref(ARG3);
Int rc = TRUE;
struct row_state *rs = AddressOfTerm(Deref(ARG4));
struct result_set *res_set = rs->res_set;
Term head, list, null_atom[1];
Int i, arity;
list = arg_list_args;
arity = IntegerOfTerm(arg_arity);
sqlite3 *db = res_set->db;
// busy-waiting
int res;
if ((res = sqlite3_step(res_set->stmt)) == SQLITE_BUSY)
Yap_Error(SYSTEM_ERROR_INTERNAL, ARG1,
"sqlite3_row deadlocked (SQLITE_BUSY)");
;
if (res == SQLITE_DONE) {
2015-11-05 17:06:15 +00:00
#ifdef MYDDAS_STATS
2017-11-18 00:04:42 +00:00
end = myddas_stats_walltime();
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff, time_copy);
myddas_stats_subtract_time(diff, end, start);
diff = myddas_stats_time_copy_to_final(diff);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_FREE(end, struct myddas_stats_time_struct);
MYDDAS_FREE(start, struct myddas_stats_time_struct);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_STATS_GET_DB_ROW_FUNCTION(total_time);
myddas_stats_add_time(total_time, diff, total_time);
MYDDAS_STATS_SET_DB_ROW_FUNCTION_COUNT(++rs->count);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_FREE(diff, struct myddas_stats_time_struct);
2016-01-03 02:06:09 +00:00
#endif /* MYDDAS_STATS */
2017-11-18 00:04:42 +00:00
cut_fail(); /* This macro already does a return FALSE */
} else if (res == SQLITE_ROW) {
list = arg_list_args;
Term tf = 0;
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);
void *pt;
tf = Yap_AllocExternalDataInStack(EXTERNAL_BLOB, bytes, &pt);
2018-06-30 14:33:32 +01:00
memmove(pt, sqlite3_column_blob(res_set->stmt, i), bytes);
2017-11-18 00:04:42 +00:00
} 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;
}
2015-11-05 17:06:15 +00:00
#ifdef MYDDAS_STATS
2017-11-18 00:04:42 +00:00
end = myddas_stats_walltime();
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
myddas_stats_subtract_time(diff, end, start);
diff = myddas_stats_time_copy_to_final(diff);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_FREE(end, struct myddas_stats_time_struct);
MYDDAS_FREE(start, struct myddas_stats_time_struct);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
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);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
MYDDAS_FREE(diff, struct myddas_stats_time_struct);
2015-11-05 17:06:15 +00:00
#endif /* MYDDAS_STATS */
2017-11-18 00:04:42 +00:00
} else {
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "sqlite3: %s",
sqlite3_errmsg(db));
}
return rc;
2015-11-05 17:06:15 +00:00
}
2017-11-18 00:04:42 +00:00
static void Yap_InitMYDDAS_SQLITE3Preds(void) {
Term cm = CurrentModule;
CurrentModule = MkAtomTerm(Yap_LookupAtom("myddas_sqlite3"));
2017-11-18 00:04:42 +00:00
/* db_dbect: Host x User x Passwd x Database x dbection x ERROR_CODE */
Yap_InitCPred("c_sqlite3_connect", 4, c_sqlite3_connect, 0);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
/* db_number_of_fields: Relation x connection x NumberOfFields */
Yap_InitCPred("c_sqlite3_number_of_fields", 3, c_sqlite3_number_of_fields, 0);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
/* db_get_attributes_types: Relation x TypesList */
Yap_InitCPred("c_sqlite3_get_attributes_types", 3,
c_sqlite3_get_attributes_types, 0);
2015-11-05 17:06:15 +00:00
2017-11-18 00:04:42 +00:00
/* db_query: SQLQuery x ResultSet x conection */
Yap_InitCPred("c_sqlite3_query", 5, c_sqlite3_query, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
/* db_disconnect: connection */
Yap_InitCPred("c_sqlite3_disconnect", 1, c_sqlite3_disconnect, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
/* db_table_write: Result Set */
Yap_InitCPred("c_sqlite3_table_write", 1, c_sqlite3_table_write, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
/* db_get_fields_properties: PredName x connection x PropertiesList*/
Yap_InitCPred("c_sqlite3_get_fields_properties", 3,
c_sqlite3_get_fields_properties, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
Yap_InitCPred("c_sqlite3_get_next_result_set", 2,
c_sqlite3_get_next_result_set, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
/* c_sqlite3_get_database: connection x DataBaseName */
Yap_InitCPred("c_sqlite3_get_database", 2, c_sqlite3_get_database, 0);
2017-08-21 12:41:15 +01:00
2017-11-18 00:04:42 +00:00
/* c_sqlite3_change_database: connection x DataBaseName */
Yap_InitCPred("c_sqlite3_change_database", 2, c_sqlite3_change_database, 0);
CurrentModule = cm;
2017-08-21 12:41:15 +01:00
}
2017-11-18 00:04:42 +00:00
static void Yap_InitBackMYDDAS_SQLITE3Preds(void) {
Term cm = CurrentModule;
CurrentModule = MkAtomTerm(Yap_LookupAtom("myddas_sqlite3"));
2017-11-18 00:04:42 +00:00
/* db_row: ResultSet x Arity x ListOfArgs */
// Yap_InitCPredBack("c_sqlite3_row", 3, 0, c_sqlite3_row_initialise,
// c_sqlite3_row, c_sqlite3_row_terminate);
Yap_InitCPred("c_sqlite3_row_initialise", 2, c_sqlite3_row_initialise, 0);
2018-06-28 12:48:29 +01:00
Yap_InitCPred("c_sqlite3_row_terminate", 2, c_sqlite3_row_terminate, 0);
2017-11-18 00:04:42 +00:00
Yap_InitCPredBack("c_sqlite3_row_get", 4, 0, c_sqlite3_row, c_sqlite3_row, 0);
CurrentModule = cm;
2017-08-21 12:41:15 +01:00
}
2017-11-18 00:04:42 +00:00
X_API void init_sqlite3(void) {
2018-03-19 15:41:06 +00:00
Yap_InitMYDDAS_SQLITE3Preds();
2017-07-25 01:10:44 +01:00
Yap_InitBackMYDDAS_SQLITE3Preds();
2017-07-25 01:10:44 +01:00
}
#ifdef _WIN32
#include <windows.h>
int WINAPI win_sqlite3(HANDLE hinst, DWORD reason, LPVOID reserved);
int WINAPI win_sqlite3(HANDLE hinst, DWORD reason, LPVOID reserved) {
switch (reason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return 1;
}
2017-08-21 12:41:15 +01:00
#endif