first step on separating drivers from library
This commit is contained in:
parent
48f5a824e0
commit
036876299f
@ -7,7 +7,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "Yap.h"
|
#include "Yap.h"
|
||||||
#include "myddas.h"
|
#include "myddas.h"
|
||||||
#include "myddas_structs.h"
|
|
||||||
#ifdef MYDDAS_STATS
|
#ifdef MYDDAS_STATS
|
||||||
#include "myddas_statistics.h"
|
#include "myddas_statistics.h"
|
||||||
#endif
|
#endif
|
||||||
@ -19,7 +18,7 @@ myddas_init_initialize_myddas(void){
|
|||||||
/* We cannot call MYDDAS_MALLOC were because the global
|
/* We cannot call MYDDAS_MALLOC were because the global
|
||||||
register isn't yet initialized */
|
register isn't yet initialized */
|
||||||
global = (MYDDAS_GLOBAL) malloc (sizeof(struct myddas_global));
|
global = (MYDDAS_GLOBAL) malloc (sizeof(struct myddas_global));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUGX
|
||||||
printf ("MALLOC %p %s %d\n",global,__FILE__,__LINE__);
|
printf ("MALLOC %p %s %d\n",global,__FILE__,__LINE__);
|
||||||
#endif
|
#endif
|
||||||
global->myddas_top_connections = NULL;
|
global->myddas_top_connections = NULL;
|
||||||
@ -63,9 +62,9 @@ myddas_init_initialize_connection(void *conn,void *enviromment,
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
new->api = api;
|
||||||
new->predicates=NULL;
|
new->predicates=NULL;
|
||||||
new->connection=conn;
|
new->connection=conn;
|
||||||
new->api = api;
|
|
||||||
new->odbc_enviromment=enviromment;
|
new->odbc_enviromment=enviromment;
|
||||||
|
|
||||||
/* It saves n queries, doing at once n+1 queries */
|
/* It saves n queries, doing at once n+1 queries */
|
||||||
@ -88,30 +87,5 @@ myddas_init_initialize_connection(void *conn,void *enviromment,
|
|||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
MYDDAS_UTIL_PREDICATE
|
|
||||||
myddas_init_initialize_predicate(char *pred_name, int pred_arity,
|
|
||||||
char *pred_module, MYDDAS_UTIL_PREDICATE next){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_PREDICATE new = NULL;
|
|
||||||
MYDDAS_MALLOC(new,struct myddas_list_preds);
|
|
||||||
|
|
||||||
if (new == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
new->pred_name=pred_name;
|
|
||||||
new->pred_arity=pred_arity;
|
|
||||||
new->pred_module=pred_module;
|
|
||||||
|
|
||||||
/* List integrity */
|
|
||||||
new->next=next;
|
|
||||||
new->previous=NULL;
|
|
||||||
/* If there's already at least one node
|
|
||||||
on the list */
|
|
||||||
if (next != NULL)
|
|
||||||
next->previous=new;
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,405 +0,0 @@
|
|||||||
#if defined MYDDAS_ODBC || defined MYDDAS_MYSQL || defined MYDDAS_SQLITE3
|
|
||||||
|
|
||||||
#include "Yap.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "cut_c.h"
|
|
||||||
#include "myddas.h"
|
|
||||||
#include "myddas_structs.h"
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
#include "myddas_statistics.h"
|
|
||||||
#endif
|
|
||||||
#ifdef MYDDAS_ODBC
|
|
||||||
#include <sql.h>
|
|
||||||
#endif /*MYDDAS_ODBC*/
|
|
||||||
#ifdef MYDDAS_MYSQL
|
|
||||||
#include <mysql/mysql.h>
|
|
||||||
#endif /*MYDDAS_MYSQL*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Search for the predicate in the given predicate list*/
|
|
||||||
static MYDDAS_UTIL_PREDICATE
|
|
||||||
myddas_util_find_predicate(char *, Int , char *, MYDDAS_UTIL_PREDICATE);
|
|
||||||
/* Deletes a predicate list */
|
|
||||||
static void
|
|
||||||
myddas_util_delete_predicate_list(MYDDAS_UTIL_PREDICATE);
|
|
||||||
|
|
||||||
/* Prints a error message */
|
|
||||||
static void
|
|
||||||
myddas_util_error_message(char *,Int,char *);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MYDDAS_MYSQL
|
|
||||||
/* Auxilary function to table_write*/
|
|
||||||
static void
|
|
||||||
n_print(Int , char );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Type: MYSQL->1 ODBC->2*/
|
|
||||||
Short
|
|
||||||
myddas_util_connection_type(void *con){
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION con_node =
|
|
||||||
myddas_util_search_connection(con);
|
|
||||||
|
|
||||||
if (con_node == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (con_node->odbc_enviromment != NULL) /* ODBC */
|
|
||||||
return 2;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MYDDAS_UTIL_PREDICATE
|
|
||||||
myddas_util_search_predicate(char *pred_name, Int pred_arity,
|
|
||||||
char *pred_module){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_PREDICATE pred=NULL;
|
|
||||||
MYDDAS_UTIL_CONNECTION top = Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
|
|
||||||
for (;top!=NULL;top=top->next)
|
|
||||||
{
|
|
||||||
if ((pred=myddas_util_find_predicate(pred_name,pred_arity,pred_module,top->predicates)))
|
|
||||||
return pred;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When using this function, we must guarante that this predicate
|
|
||||||
it's unique */
|
|
||||||
MYDDAS_UTIL_CONNECTION
|
|
||||||
myddas_util_add_predicate(char *pred_name, Int pred_arity,
|
|
||||||
char *pred_module, void *con){
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION node_con =
|
|
||||||
myddas_util_search_connection(con);
|
|
||||||
|
|
||||||
MYDDAS_UTIL_PREDICATE new =
|
|
||||||
myddas_init_initialize_predicate(pred_name,pred_arity,pred_module,node_con->predicates);
|
|
||||||
|
|
||||||
if (new == NULL)
|
|
||||||
{
|
|
||||||
myddas_util_error_message("Could not initialize predicate node",__LINE__,__FILE__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_con->predicates=new;
|
|
||||||
return node_con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
myddas_util_delete_predicate(MYDDAS_UTIL_PREDICATE to_delete){
|
|
||||||
CACHE_REGS
|
|
||||||
if (to_delete->next != NULL)
|
|
||||||
to_delete->next->previous = to_delete->previous;
|
|
||||||
if (to_delete->previous != NULL)
|
|
||||||
to_delete->previous->next = to_delete->next;
|
|
||||||
else //First predicate of the predicate list
|
|
||||||
{
|
|
||||||
MYDDAS_UTIL_CONNECTION con_node = Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
for(;con_node != NULL; con_node = con_node->next)
|
|
||||||
if (con_node->predicates == to_delete)
|
|
||||||
break;
|
|
||||||
con_node->predicates = to_delete->next;
|
|
||||||
}
|
|
||||||
MYDDAS_FREE(to_delete,struct myddas_list_preds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
myddas_util_delete_connection(void *conn){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_CONNECTION to_delete = myddas_util_search_connection(conn);
|
|
||||||
|
|
||||||
if (to_delete == NULL)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Removes the predicates list */
|
|
||||||
myddas_util_delete_predicate_list(to_delete->predicates);
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Removes the stats list */
|
|
||||||
myddas_stats_delete_stats_list(to_delete->stats);
|
|
||||||
#endif
|
|
||||||
/* List Integrety */
|
|
||||||
/* Is the last element of the list */
|
|
||||||
if ((to_delete->next) != NULL)
|
|
||||||
to_delete->next->previous = to_delete->previous;
|
|
||||||
|
|
||||||
/* Is the first element of the list */
|
|
||||||
if (to_delete == (Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections))
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections = to_delete->next;
|
|
||||||
else
|
|
||||||
to_delete->previous->next=to_delete->next;
|
|
||||||
|
|
||||||
MYDDAS_FREE(to_delete,struct myddas_list_connection);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION
|
|
||||||
myddas_util_search_connection(void *conn){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_CONNECTION list = Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
if (conn == 0) { /* We want all the statistics */
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (;list!=NULL;list=list->next)
|
|
||||||
if (list->connection == conn)
|
|
||||||
return list;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION
|
|
||||||
myddas_util_add_connection(void *conn, void *enviromment){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_CONNECTION node=NULL;
|
|
||||||
MYDDAS_UTIL_CONNECTION temp=NULL;
|
|
||||||
|
|
||||||
if ((node = myddas_util_search_connection(conn)) != NULL)
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
//put the new connection node on the top of the list
|
|
||||||
temp = myddas_init_initialize_connection(conn,enviromment,Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections);
|
|
||||||
if (temp == NULL)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
myddas_util_error_message("Could not initialize connection node",__LINE__,__FILE__);
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections = temp;
|
|
||||||
return Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_ODBC
|
|
||||||
/* This function searches the MYDDAS list for odbc connections
|
|
||||||
If there isn't any, it returns NULL. This is a nice way to know
|
|
||||||
if there is any odbc connections left on the list*/
|
|
||||||
SQLHENV
|
|
||||||
myddas_util_get_odbc_enviromment(SQLHDBC connection){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_CONNECTION top = Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
|
|
||||||
for (;top != NULL;top=top->next)
|
|
||||||
if (top->connection == ((void *)connection))
|
|
||||||
return top->odbc_enviromment;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
UInt
|
|
||||||
myddas_util_get_total_multi_queries_number(MYDDAS_UTIL_CONNECTION con){
|
|
||||||
return con->total_number_queries;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
myddas_util_set_total_multi_queries_number(MYDDAS_UTIL_CONNECTION con,
|
|
||||||
UInt number){
|
|
||||||
con->total_number_queries = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_MYSQL
|
|
||||||
/* Auxilary function to table_write*/
|
|
||||||
static void
|
|
||||||
n_print(Int n, char c)
|
|
||||||
{
|
|
||||||
for(;n>0;n--) printf("%c",c);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static
|
|
||||||
void myddas_util_error_message(char *message ,Int line,char *file){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf ("ERROR: %s at line %d in file %s\n",message,(int)line,file);
|
|
||||||
#else
|
|
||||||
printf ("ERROR: %s\n",message);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static MYDDAS_UTIL_PREDICATE
|
|
||||||
myddas_util_find_predicate(char *pred_name, Int pred_arity,
|
|
||||||
char *pred_module, MYDDAS_UTIL_PREDICATE list){
|
|
||||||
|
|
||||||
for(;list != NULL ; list = list->next)
|
|
||||||
if (pred_arity == list->pred_arity &&
|
|
||||||
!strcmp(pred_name,list->pred_name) &&
|
|
||||||
!strcmp(pred_module,list->pred_module))
|
|
||||||
return list;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
myddas_util_delete_predicate_list(MYDDAS_UTIL_PREDICATE preds_list){
|
|
||||||
CACHE_REGS
|
|
||||||
MYDDAS_UTIL_PREDICATE to_delete = NULL;
|
|
||||||
|
|
||||||
for (;preds_list != NULL;)
|
|
||||||
{
|
|
||||||
to_delete = preds_list;
|
|
||||||
preds_list = preds_list->next;
|
|
||||||
|
|
||||||
MYDDAS_FREE(to_delete,struct myddas_list_preds);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_MYSQL
|
|
||||||
void
|
|
||||||
myddas_util_table_write(MYSQL_RES *res_set){
|
|
||||||
|
|
||||||
MYSQL_ROW row;
|
|
||||||
MYSQL_FIELD *fields;
|
|
||||||
Int i,f;
|
|
||||||
|
|
||||||
if (mysql_num_rows(res_set) == 0)
|
|
||||||
{
|
|
||||||
printf ("Empty Set\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = mysql_num_fields(res_set);
|
|
||||||
|
|
||||||
fields = mysql_fetch_field(res_set);
|
|
||||||
for(i=0;i<f;i++)
|
|
||||||
{
|
|
||||||
printf("+");
|
|
||||||
if (strlen(fields[i].name)>fields[i].max_length) fields[i].max_length=strlen(fields[i].name);
|
|
||||||
n_print(fields[i].max_length+2,'-');
|
|
||||||
}
|
|
||||||
printf("+\n");
|
|
||||||
|
|
||||||
for(i=0;i<f;i++)
|
|
||||||
{
|
|
||||||
printf("|");
|
|
||||||
printf(" %s ",fields[i].name);
|
|
||||||
n_print(fields[i].max_length - strlen(fields[i].name),' ');
|
|
||||||
}
|
|
||||||
printf("|\n");
|
|
||||||
|
|
||||||
for(i=0;i<f;i++)
|
|
||||||
{
|
|
||||||
printf("+");
|
|
||||||
n_print(fields[i].max_length+2,'-');
|
|
||||||
}
|
|
||||||
printf("+\n");
|
|
||||||
|
|
||||||
while ((row = mysql_fetch_row(res_set)) != NULL)
|
|
||||||
{
|
|
||||||
for(i=0;i<f;i++)
|
|
||||||
{
|
|
||||||
printf("|");
|
|
||||||
if (row[i] != NULL)
|
|
||||||
{
|
|
||||||
printf(" %s ",row[i]);
|
|
||||||
n_print(fields[i].max_length - strlen(row[i]),' ');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(" NULL ");
|
|
||||||
n_print(fields[i].max_length - 4,' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("|\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<f;i++)
|
|
||||||
{
|
|
||||||
printf("+");
|
|
||||||
n_print(fields[i].max_length+2,'-');
|
|
||||||
}
|
|
||||||
printf("+\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//DELETE THIS WHEN DB_STATS IS COMPLETED
|
|
||||||
MyddasInt
|
|
||||||
get_myddas_top( void ){
|
|
||||||
CACHE_REGS
|
|
||||||
if (Yap_REGS.MYDDAS_GLOBAL_POINTER == NULL)
|
|
||||||
return 0;
|
|
||||||
return (Int)Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
myddas_util_get_pred_next(void *pointer){
|
|
||||||
MYDDAS_UTIL_PREDICATE temp = (MYDDAS_UTIL_PREDICATE) pointer;
|
|
||||||
return (void *) (temp->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
MyddasInt
|
|
||||||
myddas_util_get_pred_arity(void *pointer){
|
|
||||||
MYDDAS_UTIL_PREDICATE temp = (MYDDAS_UTIL_PREDICATE) pointer;
|
|
||||||
return temp->pred_arity;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
myddas_util_get_pred_name(void *pointer){
|
|
||||||
MYDDAS_UTIL_PREDICATE temp = (MYDDAS_UTIL_PREDICATE) pointer;
|
|
||||||
return temp->pred_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
myddas_util_get_pred_module(void *pointer){
|
|
||||||
MYDDAS_UTIL_PREDICATE temp = (MYDDAS_UTIL_PREDICATE) pointer;
|
|
||||||
return temp->pred_module;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
myddas_util_get_list_pred(MYDDAS_UTIL_CONNECTION node){
|
|
||||||
return (void *)(node->predicates);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void check_int( void ){
|
|
||||||
CACHE_REGS
|
|
||||||
|
|
||||||
MYDDAS_UTIL_PREDICATE pred = NULL;
|
|
||||||
MYDDAS_UTIL_CONNECTION top = Yap_REGS.MYDDAS_GLOBAL_POINTER->myddas_top_connections;
|
|
||||||
for ( ; top!=NULL ; top=top->next)
|
|
||||||
{
|
|
||||||
printf ("***************\n");
|
|
||||||
printf ("===== top =====\n");
|
|
||||||
printf ("======= %p =====\n",top);
|
|
||||||
printf ("CONN: = %p =====\n",top->connection);
|
|
||||||
printf ("ENV : = %p =====\n",top->odbc_enviromment);
|
|
||||||
printf ("PRED: = %p =====\n",top->predicates);
|
|
||||||
printf ("======= %p =====\n",top->previous);
|
|
||||||
printf ("======= %p =====\n",top->next);
|
|
||||||
if (top->predicates != NULL)
|
|
||||||
{
|
|
||||||
printf ("\t******\n");
|
|
||||||
printf ("\t===== PREDICADOS =====\n");
|
|
||||||
for (pred = top->predicates ; pred != NULL ; pred = pred->next)
|
|
||||||
{
|
|
||||||
printf ("\t--------------\n");
|
|
||||||
printf ("\t===== %p =====\n",pred);
|
|
||||||
printf ("\t===== %s =====\n",pred->pred_name);
|
|
||||||
printf ("\t===== %d =====\n",pred->pred_arity);
|
|
||||||
printf ("\t===== %s =====\n",pred->pred_module);
|
|
||||||
printf ("\t===== %p =====\n",pred->previous);
|
|
||||||
printf ("\t===== %p =====\n",pred->next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*defined MYDDAS_ODBC || defined MYDDAS_MYSQL*/
|
|
||||||
|
|
||||||
|
|
@ -1,30 +1,56 @@
|
|||||||
SET( CMAKE_FIND_FRAMEWORK LAST)
|
SET( CMAKE_FIND_FRAMEWORK LAST)
|
||||||
SET( CMAKE_FIND_APPBUNDLE LAST)
|
SET( CMAKE_FIND_APPBUNDLE LAST)
|
||||||
|
|
||||||
|
|
||||||
|
# Be sure to also update these in Makefile!
|
||||||
|
set(SO_MAJOR 1)
|
||||||
|
set(SO_MINOR 0)
|
||||||
|
set(SO_PATCH 0)
|
||||||
|
|
||||||
|
|
||||||
set( MYDDAS_SOURCES
|
set( MYDDAS_SOURCES
|
||||||
myddas_mysql.c
|
|
||||||
myddas_odbc.c
|
|
||||||
myddas_postgres.c
|
|
||||||
myddas_sqlite3.c
|
|
||||||
myddas_util.c
|
|
||||||
myddas_initialization.c
|
myddas_initialization.c
|
||||||
myddas_shared.c
|
myddas_shared.c
|
||||||
myddas_statistics.c
|
myddas_statistics.c
|
||||||
myddas_top_level.c
|
myddas_top_level.c
|
||||||
myddas_wkb2prolog.c )
|
myddas_wkb2prolog.c )
|
||||||
|
|
||||||
set( MYDDAS_PROLOG
|
set( MYDDAS_HEADERS
|
||||||
|
myddas.h
|
||||||
|
myddas_statistics.h
|
||||||
|
myddas_statistics_structs.h
|
||||||
|
myddas_structs.h
|
||||||
|
myddas_top_level.c
|
||||||
|
myddas_types.h
|
||||||
|
myddas_wkb2prolog.c )
|
||||||
|
|
||||||
|
set( MYDDAS_UTIL_SOURCES
|
||||||
|
myddas_util.c
|
||||||
|
myddas_initialization.c )
|
||||||
|
|
||||||
|
add_subdirectory (mysql)
|
||||||
|
add_subdirectory (odbc)
|
||||||
|
add_subdirectory (postgres)
|
||||||
|
add_subdirectory (sqlite3)
|
||||||
|
|
||||||
|
set( MYDDAS_YPP
|
||||||
pl/myddas.ypp
|
pl/myddas.ypp
|
||||||
pl/myddas_assert_predicates.ypp
|
pl/myddas_assert_predicates.ypp
|
||||||
pl/myddas_mysql.ypp
|
|
||||||
pl/myddas_sqlite3.ypp
|
|
||||||
pl/myddas_postgres.ypp
|
|
||||||
pl/myddas_top_level.ypp
|
pl/myddas_top_level.ypp
|
||||||
pl/myddas_errors.ypp
|
pl/myddas_errors.ypp
|
||||||
pl/myddas_prolog2sql.ypp
|
pl/myddas_prolog2sql.ypp
|
||||||
pl/myddas_util_predicates.ypp
|
pl/myddas_util_predicates.ypp
|
||||||
pl/myddas_prolog2sql_optimizer.ypp )
|
pl/myddas_prolog2sql_optimizer.ypp )
|
||||||
|
|
||||||
|
set( MYDDAS_PROLOG
|
||||||
|
myddas.yap
|
||||||
|
myddas_assert_predicates.yap
|
||||||
|
myddas_top_level.yap
|
||||||
|
myddas_errors.yap
|
||||||
|
myddas_prolog2sql.yap
|
||||||
|
myddas_util_predicates.yap
|
||||||
|
myddas_prolog2sql_optimizer.yap )
|
||||||
|
|
||||||
function(cpp_compile filename)
|
function(cpp_compile filename)
|
||||||
get_filename_component(base ${filename} NAME_WE)
|
get_filename_component(base ${filename} NAME_WE)
|
||||||
set(base_abs ${CMAKE_CURRENT_BINARY_DIR}/${base})
|
set(base_abs ${CMAKE_CURRENT_BINARY_DIR}/${base})
|
||||||
@ -35,87 +61,33 @@ function(cpp_compile filename)
|
|||||||
set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
|
set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
foreach(file ${MYDDAS_PROLOG})
|
foreach(file ${MYDDAS_YPP})
|
||||||
cpp_compile(GENERATED_SOURCES ${file})
|
cpp_compile(GENERATED_SOURCES ${file})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
source_group("" FILES ${MYDDAS_PROLOG})
|
source_group("" FILES ${MYDDAS_YPP})
|
||||||
source_group(generated FILES ${GENERATED_SOURCES})
|
source_group(generated FILES ${MYDDAS_YAP})
|
||||||
|
|
||||||
macro_optional_find_package(ODBC ON)
|
set_property( DIRECTORY ../..
|
||||||
macro_optional_find_package(MySQL ON)
|
APPEND PROPERTY COMPILE_DEFINITIONS USE_MYDDAS=1)
|
||||||
macro_optional_find_package(Sqlite3 ON)
|
|
||||||
macro_optional_find_package(PostgreSQL ON)
|
|
||||||
|
|
||||||
macro_log_feature (ODBC_FOUND "ODBC"
|
Add_custom_target (plmyddas ALL DEPENDS ${MYDDAS_YAP} ) # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} )
|
||||||
"Use ODBC Data-Base Interface "
|
|
||||||
"http://www.unixodbc.org" FALSE)
|
|
||||||
|
|
||||||
macro_log_feature (MYSQL_FOUND "MySQL"
|
|
||||||
"Use MYSQL Data-Base Interface "
|
|
||||||
"http://www.mysql.org" FALSE)
|
|
||||||
|
|
||||||
macro_log_feature (SQLITE3_FOUND "SQLite3"
|
add_library (myddas OBJECT
|
||||||
"SQL Light Data-Base "
|
${MYDDAS_SOURCES}
|
||||||
"http://www.sqlite3.org" FALSE)
|
${MYDDAS_UTIL_SOURCES}
|
||||||
|
${MYDDAS_HEADES}
|
||||||
|
)
|
||||||
|
|
||||||
macro_log_feature (PostgreSQL_FOUND "PostgreSQL"
|
set_target_properties (myddas PROPERTIES
|
||||||
"PostgreSQL Data-Base "
|
POSITION_INDEPENDENT_CODE ON
|
||||||
"http://www.postgresql.org" FALSE)
|
)
|
||||||
|
|
||||||
if (ODBC_FOUND OR MYSQL_FOUND OR SQLITE3_FOUND OR PostgreSQL_FOUND)
|
|
||||||
add_definitions (-DUSE_MYDDAS=1)
|
|
||||||
add_library (myddas SHARED ${MYDDAS_SOURCES})
|
|
||||||
target_link_libraries(myddas libYap)
|
|
||||||
if (ODBC_FOUND)
|
|
||||||
# ODBC_INCLUDE_DIRECTORIES, where to find sql.h
|
|
||||||
# ODBC_LIBRARIES, the libraries to link against to use ODBC
|
|
||||||
# ODBC_FOUND. If false, you cannot build anything that requires MySQL.
|
|
||||||
add_definitions (-DMYDDAS_ODBC=1)
|
|
||||||
target_link_libraries(myddas ${ODBC_LIBRARIES})
|
|
||||||
include_directories (${ODBC_INCLUDE_DIRECTORIES})
|
|
||||||
endif (ODBC_FOUND)
|
|
||||||
|
|
||||||
if (SQLITE3_FOUND)
|
|
||||||
# SQLITE3_FOUND - system has Sqlite3
|
|
||||||
# SQLITE3_INCLUDE_DIRS - the Sqlite3 include directory
|
|
||||||
# SQLITE3_LIBRARIES - Link these to use Sqlite3
|
|
||||||
# SQLITE3_DEFINITIONS - Compiler switches required for using Sqlite3
|
|
||||||
check_function_exists( sqlite3_table_column_metadata HAVE_SQLITE3_TABLE_COLUMN_METADATA )
|
|
||||||
if (HAVE_SQLITE3_TABLE_COLUMN_METADATA:INTERNAL=1)
|
|
||||||
add_definitions (-DMYDDAS_SQLITE3=1)
|
|
||||||
target_link_libraries(myddas ${SQLITE3_LIBRARIES})
|
|
||||||
include_directories (${SQLITE3_INCLUDE_DIRS})
|
|
||||||
endif()
|
|
||||||
endif (SQLITE3_FOUND)
|
|
||||||
|
|
||||||
if (MYSQL_FOUND)
|
cmake_dependent_option (USE_MYDDAS_Stats
|
||||||
# MYSQL_INCLUDE_DIR - where to find mysql.h, etc.
|
|
||||||
# MYSQL_LIBRARIES - List of libraries when using MySQL.
|
|
||||||
# MYSQL_FOUND - True if MySQL found.
|
|
||||||
add_definitions (-DMYDDAS_MYSQL=1)
|
|
||||||
target_link_libraries(myddas ${MYSQL_LIBRARIES})
|
|
||||||
include_directories (${MYSQL_INCLUDE_DIR})
|
|
||||||
endif (MYSQL_FOUND)
|
|
||||||
|
|
||||||
if (PostgreSQL_FOUND)
|
|
||||||
# PostgreSQL_INCLUDE_DIRS - Include directories for PostgreSQL
|
|
||||||
# PostgreSQL_LIBRARY_DIRS - Link directories for PostgreSQL libraries
|
|
||||||
# PostgreSQL_LIBRARIES - The PostgreSQL libraries.
|
|
||||||
add_definitions (-DMYDDAS_POSTGRES=1)
|
|
||||||
target_link_libraries(myddas ${PostgreSQL_LIBRARIES})
|
|
||||||
include_directories (${MYSQL_INCLUDE_DIRS})
|
|
||||||
endif (PostgreSQL_FOUND)
|
|
||||||
|
|
||||||
add_custom_target (plmyddas ALL DEPENDS ${GENERATED_SOURCES} ) # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} )
|
|
||||||
endif (ODBC_FOUND OR MYSQL_FOUND OR SQLITE3_FOUND OR PostgreSQL_FOUND)
|
|
||||||
|
|
||||||
cmake_dependent_option (WITH_MYDDAS_Stats
|
|
||||||
"enable the MYDDAS library statistics support" OFF
|
"enable the MYDDAS library statistics support" OFF
|
||||||
WITH_MYDDAS OFF)
|
USE_MYDDAS OFF)
|
||||||
#TODO:
|
#TODO:
|
||||||
|
|
||||||
cmake_dependent_option (WITH_MYDDAS_top_level
|
|
||||||
"enable the MYDDAS top-level support to MySQL" OFF
|
|
||||||
'WITH_MYDDAS AND MYSQL_FOUND' OFF)
|
|
||||||
#TODO:
|
|
||||||
|
@ -4,98 +4,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef MYDDAS_ODBC
|
#include "myddas_types.h"
|
||||||
#include <sql.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MYDDAS_MYSQL
|
|
||||||
#include <mysql/mysql.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* MYDDAS TYPES */
|
|
||||||
/* sizeof(MyddasPointer) Equal to the size of a integer on the given architecture */
|
|
||||||
/* sizeof(MyddasInt32) = 4 (Always) */
|
|
||||||
/* sizeof(MyddasUInt32) = 4 (Always) */
|
|
||||||
|
|
||||||
#if SIZEOF_INT_P==4
|
|
||||||
|
|
||||||
# if SIZEOF_INT==4
|
|
||||||
/* */ typedef int MyddasInt;
|
|
||||||
/* */ typedef unsigned int MyddasUInt;
|
|
||||||
/* */ typedef unsigned int MyddasPointer;
|
|
||||||
/* */ typedef int MyddasInt32;
|
|
||||||
/* */ typedef unsigned int MyddasUInt32;
|
|
||||||
# elif SIZEOF_LONG_INT==4
|
|
||||||
/* */ typedef long int MyddasInt;
|
|
||||||
/* */ typedef unsigned long int MyddasUInt;
|
|
||||||
/* */ typedef unsigned long int MyddasPointer;
|
|
||||||
/* */ typedef long int MyddasInt32;
|
|
||||||
/* */ typedef unsigned long int MyddasUInt32;
|
|
||||||
# else
|
|
||||||
# error MYDDAS require integer types of the same size as a pointer
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if SIZEOF_SHORT_INT==2
|
|
||||||
/* */ typedef short int MyddasSInt;
|
|
||||||
/* */ typedef unsigned short int MyddasUSInt;
|
|
||||||
# else
|
|
||||||
# error MYDDAS requires integer types half the size of a pointer
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if SIZEOF_LONG_INT==8
|
|
||||||
/* */ typedef long int MyddasLInt;
|
|
||||||
/* */ typedef unsigned long int MyddasULInt;
|
|
||||||
# elif SIZEOF_LONG_LONG_INT==8
|
|
||||||
/* */ typedef long long int MyddasLInt;
|
|
||||||
/* */ typedef unsigned long long int MyddasULInt;
|
|
||||||
# else
|
|
||||||
# error MYDDAS requires integer types double the size of a pointer
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#elif SIZEOF_INT_P==8
|
|
||||||
|
|
||||||
# if SIZEOF_INT==8
|
|
||||||
/* */ typedef int MyddasInt;
|
|
||||||
/* */ typedef unsigned int MyddasUInt;
|
|
||||||
/* */ typedef int MyddasLInt;
|
|
||||||
/* */ typedef unsigned int MyddasULInt;
|
|
||||||
/* */ typedef unsigned int MyddasPointer;
|
|
||||||
# elif SIZEOF_LONG_INT==8
|
|
||||||
/* */ typedef long int MyddasInt;
|
|
||||||
/* */ typedef unsigned long int MyddasUInt;
|
|
||||||
/* */ typedef int MyddasLInt;
|
|
||||||
/* */ typedef unsigned int MyddasULInt;
|
|
||||||
/* */ typedef unsigned long int MyddasPointer;
|
|
||||||
# elif SIZEOF_LONG_LONG_INT==8
|
|
||||||
/* */ typedef long long int MyddasInt;
|
|
||||||
/* */ typedef unsigned long long int MyddasUInt;
|
|
||||||
/* */ typedef int MyddasLInt;
|
|
||||||
/* */ typedef unsigned int MyddasULInt;
|
|
||||||
/* */ typedef unsigned long long int MyddasPointer;
|
|
||||||
# else
|
|
||||||
# error MYDDAS requires integer types of the same size as a pointer
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if SIZEOF_SHORT_INT==4
|
|
||||||
/* */ typedef short int MyddasSInt;
|
|
||||||
/* */ typedef unsigned short int MyddasUSInt;
|
|
||||||
/* */ typedef short int MyddasInt32;
|
|
||||||
/* */ typedef unsigned short int MyddasUInt32;
|
|
||||||
# elif SIZEOF_INT==4
|
|
||||||
/* */ typedef int MyddasSInt;
|
|
||||||
/* */ typedef unsigned int MyddasUSInt;
|
|
||||||
/* */ typedef int MyddasInt32;
|
|
||||||
/* */ typedef unsigned int MyddasUInt32;
|
|
||||||
# else
|
|
||||||
# error MYDDAS requires integer types half the size of a pointer
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
# error MYDDAS requires pointers of size 4 or 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Passar para o myddas_statictics.h ???????? */
|
/* Passar para o myddas_statictics.h ???????? */
|
||||||
#ifdef MYDDAS_STATS
|
#ifdef MYDDAS_STATS
|
||||||
@ -104,9 +13,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct myddas_global *MYDDAS_GLOBAL;
|
typedef struct myddas_global *MYDDAS_GLOBAL;
|
||||||
typedef struct myddas_util_query *MYDDAS_UTIL_QUERY;
|
#include "myddas_util.h"
|
||||||
typedef struct myddas_list_connection *MYDDAS_UTIL_CONNECTION;
|
|
||||||
typedef struct myddas_list_preds *MYDDAS_UTIL_PREDICATE;
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
#ifdef MYDDAS_STATS
|
||||||
typedef struct myddas_stats_time_struct *MYDDAS_STATS_TIME;
|
typedef struct myddas_stats_time_struct *MYDDAS_STATS_TIME;
|
||||||
@ -116,36 +23,6 @@ typedef struct myddas_stats_struct *MYDDAS_STATS_STRUCT;
|
|||||||
typedef void *MYDDAS_STATS_TIME;
|
typedef void *MYDDAS_STATS_TIME;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define MYDDAS_MALLOC(POINTER,TYPE) \
|
|
||||||
{ \
|
|
||||||
POINTER = (TYPE *) malloc(sizeof(TYPE)); \
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->memory_allocated+=sizeof(TYPE); \
|
|
||||||
/*printf ("MALLOC %p %s %d\n",POINTER,__FILE__,__LINE__);*/ \
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->malloc_called++; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define MYDDAS_MALLOC(POINTER,TYPE) \
|
|
||||||
{ \
|
|
||||||
POINTER = (TYPE *) malloc(sizeof(TYPE)); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define MYDDAS_FREE(POINTER,TYPE) \
|
|
||||||
{ \
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->memory_freed+=sizeof(TYPE); \
|
|
||||||
Yap_REGS.MYDDAS_GLOBAL_POINTER->free_called++; \
|
|
||||||
/*printf ("FREE %p %s %d\n",POINTER,__FILE__,__LINE__);*/ \
|
|
||||||
free(POINTER); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define MYDDAS_FREE(POINTER,TYPE) \
|
|
||||||
{ \
|
|
||||||
free(POINTER); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define MYDDAS_MEMORY_MALLOC_NR(NUMBER) \
|
#define MYDDAS_MEMORY_MALLOC_NR(NUMBER) \
|
||||||
NUMBER = Yap_REGS.MYDDAS_GLOBAL_POINTER->malloc_called;
|
NUMBER = Yap_REGS.MYDDAS_GLOBAL_POINTER->malloc_called;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#ifdef USE_MYDDAS
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -112,5 +111,3 @@ myddas_init_initialize_predicate(const char *pred_name, int pred_arity,
|
|||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -1,725 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* *
|
|
||||||
* 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_mysql.c *
|
|
||||||
* Last rev: 22/03/05 *
|
|
||||||
* mods: *
|
|
||||||
* comments: Predicates for comunicating with a mysql database system *
|
|
||||||
* *
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#if defined MYDDAS_MYSQL
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <mysql/mysql.h>
|
|
||||||
#include "Yap.h"
|
|
||||||
#include "Yatom.h"
|
|
||||||
#include "cut_c.h"
|
|
||||||
#include "myddas.h"
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
#include "myddas_structs.h"
|
|
||||||
#include "myddas_statistics.h"
|
|
||||||
#endif
|
|
||||||
#include "myddas_wkb2prolog.h"
|
|
||||||
|
|
||||||
#define IS_SQL_INT(FIELD) FIELD == FIELD_TYPE_INT24 || \
|
|
||||||
FIELD == FIELD_TYPE_LONG || \
|
|
||||||
FIELD == FIELD_TYPE_LONGLONG || \
|
|
||||||
FIELD == FIELD_TYPE_SHORT || \
|
|
||||||
FIELD == FIELD_TYPE_TINY
|
|
||||||
|
|
||||||
#define IS_SQL_FLOAT(FIELD) FIELD == FIELD_TYPE_DECIMAL || \
|
|
||||||
FIELD == FIELD_TYPE_DOUBLE || \
|
|
||||||
FIELD == FIELD_TYPE_FLOAT
|
|
||||||
|
|
||||||
#define IS_SQL_GEOMETRY(FIELD) FIELD == FIELD_TYPE_GEOMETRY
|
|
||||||
|
|
||||||
static Int null_id = 0;
|
|
||||||
|
|
||||||
static Int c_db_my_connect( USES_REGS1 );
|
|
||||||
static Int c_db_my_disconnect( USES_REGS1 );
|
|
||||||
static Int c_db_my_number_of_fields( USES_REGS1 );
|
|
||||||
static Int c_db_my_get_attributes_types( USES_REGS1 );
|
|
||||||
static Int c_db_my_query( USES_REGS1 );
|
|
||||||
static Int c_db_my_table_write( USES_REGS1 );
|
|
||||||
static Int c_db_my_row( USES_REGS1 );
|
|
||||||
static Int c_db_my_row_cut( USES_REGS1 );
|
|
||||||
static Int c_db_my_get_fields_properties( USES_REGS1 );
|
|
||||||
static Int c_db_my_get_next_result_set( USES_REGS1 );
|
|
||||||
static Int c_db_my_get_database( USES_REGS1 );
|
|
||||||
static Int c_db_my_change_database( USES_REGS1 );
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_MySQLPreds(void)
|
|
||||||
{
|
|
||||||
/* db_connect: Host x User x Passwd x Database x Connection x ERROR_CODE */
|
|
||||||
Yap_InitCPred("c_db_my_connect", 7, c_db_my_connect, 0);
|
|
||||||
|
|
||||||
/* db_number_of_fields: Relation x Connection x NumberOfFields */
|
|
||||||
Yap_InitCPred("c_db_my_number_of_fields",3, c_db_my_number_of_fields, 0);
|
|
||||||
|
|
||||||
/* db_get_attributes_types: Relation x TypesList */
|
|
||||||
Yap_InitCPred("c_db_my_get_attributes_types", 3, c_db_my_get_attributes_types, 0);
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x Connection */
|
|
||||||
Yap_InitCPred("c_db_my_query", 5, c_db_my_query, 0);
|
|
||||||
|
|
||||||
/* db_disconnect: Connection */
|
|
||||||
Yap_InitCPred("c_db_my_disconnect", 1,c_db_my_disconnect, 0);
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
Yap_InitCPred("c_db_my_table_write", 1, c_db_my_table_write, 0);
|
|
||||||
|
|
||||||
/* db_get_fields_properties: PredName x Connnection x PropertiesList*/
|
|
||||||
Yap_InitCPred("c_db_my_get_fields_properties",3,c_db_my_get_fields_properties,0);
|
|
||||||
|
|
||||||
|
|
||||||
Yap_InitCPred("c_db_my_get_next_result_set",2,c_db_my_get_next_result_set,0);
|
|
||||||
|
|
||||||
/* c_db_my_get_database: Connnection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_db_my_get_database",2,c_db_my_get_database,0);
|
|
||||||
|
|
||||||
/* c_db_my_change_database: Connnection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_db_my_change_database",2,c_db_my_change_database,0);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Yap_InitBackMYDDAS_MySQLPreds(void)
|
|
||||||
{
|
|
||||||
/* db_row: ResultSet x Arity x ListOfArgs */
|
|
||||||
Yap_InitCPredBackCut("c_db_my_row", 3, sizeof(Int),
|
|
||||||
c_db_my_row,
|
|
||||||
c_db_my_row,
|
|
||||||
c_db_my_row_cut, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_connect( USES_REGS1 ) {
|
|
||||||
Term arg_host = Deref(ARG1);
|
|
||||||
Term arg_user = Deref(ARG2);
|
|
||||||
Term arg_passwd = Deref(ARG3);
|
|
||||||
Term arg_database = Deref(ARG4);
|
|
||||||
Term arg_port = Deref(ARG5);
|
|
||||||
Term arg_socket = Deref(ARG6);
|
|
||||||
Term arg_conn = Deref(ARG7);
|
|
||||||
|
|
||||||
MYSQL *conn;
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION new = NULL;
|
|
||||||
|
|
||||||
char *host = AtomName(AtomOfTerm(arg_host));
|
|
||||||
char *user = AtomName(AtomOfTerm(arg_user));
|
|
||||||
char *passwd = AtomName(AtomOfTerm(arg_passwd));
|
|
||||||
char *database = AtomName(AtomOfTerm(arg_database));
|
|
||||||
Int port = IntegerOfTerm(arg_port);
|
|
||||||
|
|
||||||
char *socket;
|
|
||||||
if (IsNonVarTerm(arg_socket))
|
|
||||||
socket = AtomName(AtomOfTerm(arg_socket));
|
|
||||||
else
|
|
||||||
socket = NULL;
|
|
||||||
|
|
||||||
conn = mysql_init(NULL);
|
|
||||||
if (conn == NULL) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: ** c_db_my_connect ** error on init\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mysql_real_connect(conn, host, user, passwd, database, port, socket, CLIENT_MULTI_STATEMENTS) == NULL) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: ** c_db_my_connect ** error on connect\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_conn, MkIntegerTerm((Int)conn)))
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Criar um novo no na lista de ligacoes*/
|
|
||||||
new = myddas_util_add_connection(conn,NULL,MYDDAS_MYSQL);
|
|
||||||
|
|
||||||
if (new == NULL){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: ** c_db_my_connect ** Error allocating memory\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x Connection */
|
|
||||||
static Int
|
|
||||||
c_db_my_query( USES_REGS1 ) {
|
|
||||||
Term arg_sql_query = Deref(ARG1);
|
|
||||||
Term arg_result_set = Deref(ARG2);
|
|
||||||
Term arg_conn = Deref(ARG3);
|
|
||||||
Term arg_mode = Deref(ARG4);
|
|
||||||
Term arg_arity = Deref(ARG5);
|
|
||||||
|
|
||||||
char *sql = AtomName(AtomOfTerm(arg_sql_query));
|
|
||||||
char *mode = AtomName(AtomOfTerm(arg_mode));
|
|
||||||
MYSQL *conn = (MYSQL *) (IntegerOfTerm(arg_conn));
|
|
||||||
|
|
||||||
MYSQL_RES *res_set;
|
|
||||||
|
|
||||||
MyddasInt length=strlen(sql);
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
MYDDAS_UTIL_CONNECTION node = myddas_util_search_connection(conn);
|
|
||||||
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 MySQL Server
|
|
||||||
processing the SQL Query */
|
|
||||||
MYDDAS_STATS_TIME start,end,total_time,diff;
|
|
||||||
start = myddas_stats_walltime();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Send query to server and process it */
|
|
||||||
if (mysql_real_query(conn, sql, length) != 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: **c_db_my_query** Error on query! %s\n",sql);
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time spent by the MySQL 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
|
|
||||||
|
|
||||||
/* guardar os tuplos do lado do cliente */
|
|
||||||
if (strcmp(mode,"store_result")!=0) //True
|
|
||||||
res_set = mysql_use_result(conn);
|
|
||||||
else{
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time spent by the MySQL Server
|
|
||||||
transferring the result of the last query
|
|
||||||
back to the client */
|
|
||||||
start = myddas_stats_walltime();
|
|
||||||
#endif
|
|
||||||
res_set = mysql_store_result(conn);
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time spent by the MySQL 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, mysql_(use or store)_result()
|
|
||||||
returns a NULL pointer*/
|
|
||||||
|
|
||||||
/* This is only works if we use mysql_store_result */
|
|
||||||
MyddasUInt numberRows = mysql_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 = mysql_num_fields(res_set);
|
|
||||||
MYSQL_ROW row;
|
|
||||||
MyddasULInt i;
|
|
||||||
total=0;
|
|
||||||
while ((row = mysql_fetch_row(res_set)) != NULL){
|
|
||||||
mysql_field_seek(res_set,0);
|
|
||||||
|
|
||||||
for(i=0;i<number_fields;i++){
|
|
||||||
if (row[i] != NULL)
|
|
||||||
total = total + strlen(row[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
mysql_data_seek(res_set,0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
if (res_set == NULL)
|
|
||||||
{
|
|
||||||
//INSERT statements don't return any res_set
|
|
||||||
if (mysql_field_count(conn) == 0)
|
|
||||||
return TRUE;
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Empty Query!\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_arity, MkIntegerTerm(mysql_num_fields(res_set)))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_result_set, MkIntegerTerm((Int) res_set)))
|
|
||||||
{
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_number_of_fields( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term arg_fields = Deref(ARG3);
|
|
||||||
|
|
||||||
char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
MYSQL *conn = (MYSQL *) (IntegerOfTerm(arg_conn));
|
|
||||||
|
|
||||||
char sql[256];
|
|
||||||
|
|
||||||
MYSQL_RES *res_set;
|
|
||||||
|
|
||||||
sprintf(sql,"DESCRIBE `%s`",relation);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
if (mysql_query(conn, sql) != 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: **c_db_my_number_of_fields** Error on the query! %s\n",sql);
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* guardar os tuplos do lado do cliente */
|
|
||||||
if ((res_set = mysql_store_result(conn)) == NULL)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: **c_db_my_number_of_fields** Error storing the query! %s\n",sql);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_fields, MkIntegerTerm(mysql_num_rows(res_set)))){
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* db_get_attributes_types: RelName x Connection -> TypesList */
|
|
||||||
static Int
|
|
||||||
c_db_my_get_attributes_types( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term arg_types_list = Deref(ARG3);
|
|
||||||
|
|
||||||
char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
MYSQL *conn = (MYSQL *) IntegerOfTerm(arg_conn);
|
|
||||||
char sql[256];
|
|
||||||
|
|
||||||
MYSQL_RES *res_set;
|
|
||||||
MYSQL_ROW row;
|
|
||||||
Term head, list;
|
|
||||||
|
|
||||||
sprintf(sql,"DESCRIBE `%s`",relation);
|
|
||||||
|
|
||||||
Int length = strlen(sql);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
if (mysql_real_query(conn, sql, length) != 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Erro na query! %s\n",sql);
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
/* guardar os tuplos do lado do cliente */
|
|
||||||
if ((res_set = mysql_store_result(conn)) == NULL)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Query vazia!\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = arg_types_list;
|
|
||||||
|
|
||||||
while ((row = mysql_fetch_row(res_set)) != NULL)
|
|
||||||
{
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom(row[0])));
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
if (strncmp(row[1], "smallint",8) == 0 || strncmp(row[1],"int",3) == 0 ||
|
|
||||||
strncmp(row[1], "mediumint",9) == 0 || strncmp(row[1], "tinyint",7) == 0 ||
|
|
||||||
strncmp(row[1], "bigint",6) == 0 || strcmp(row[1], "year") == 0)
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom("integer")));
|
|
||||||
else if (strcmp(row[1], "float") == 0 || strncmp(row[1], "double",6) == 0
|
|
||||||
|| strcmp(row[1], "real") == 0)
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom("real")));
|
|
||||||
else Yap_unify(head, MkAtomTerm(Yap_LookupAtom("string")));
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_disconnect */
|
|
||||||
static Int
|
|
||||||
c_db_my_disconnect( USES_REGS1 ) {
|
|
||||||
Term arg_conn = Deref(ARG1);
|
|
||||||
|
|
||||||
MYSQL *conn = (MYSQL *) IntegerOfTerm(arg_conn);
|
|
||||||
|
|
||||||
if ((myddas_util_search_connection(conn)) != NULL)
|
|
||||||
{
|
|
||||||
myddas_util_delete_connection(conn);
|
|
||||||
mysql_close(conn);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
static Int
|
|
||||||
c_db_my_table_write( USES_REGS1 ) {
|
|
||||||
Term arg_res_set = Deref(ARG1);
|
|
||||||
|
|
||||||
MYSQL_RES *res_set = (MYSQL_RES *) IntegerOfTerm(arg_res_set);
|
|
||||||
|
|
||||||
myddas_util_table_write(res_set);
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_row_cut( USES_REGS1 ) {
|
|
||||||
MYSQL_RES *mysql_res=NULL;
|
|
||||||
|
|
||||||
mysql_res = (MYSQL_RES *) IntegerOfTerm(EXTRA_CBACK_CUT_ARG(Term,1));
|
|
||||||
mysql_free_result(mysql_res);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_row: ResultSet x Arity_ListOfArgs x ListOfArgs -> */
|
|
||||||
static Int
|
|
||||||
c_db_my_row( USES_REGS1 ) {
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time used by the */
|
|
||||||
/* c_db_my_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);
|
|
||||||
|
|
||||||
MYSQL_RES *res_set = (MYSQL_RES *) IntegerOfTerm(arg_result_set);
|
|
||||||
EXTRA_CBACK_ARG(3,1)=(CELL) MkIntegerTerm((Int)res_set);
|
|
||||||
MYSQL_ROW row;
|
|
||||||
MYSQL_FIELD *field;
|
|
||||||
|
|
||||||
|
|
||||||
Term head, list, null_atom[1];
|
|
||||||
Int i, arity;
|
|
||||||
|
|
||||||
arity = IntegerOfTerm(arg_arity);
|
|
||||||
|
|
||||||
while(TRUE)
|
|
||||||
{
|
|
||||||
if ((row = mysql_fetch_row(res_set)) != NULL)
|
|
||||||
{
|
|
||||||
mysql_field_seek(res_set,0);
|
|
||||||
list = arg_list_args;
|
|
||||||
|
|
||||||
for (i = 0; i < arity; i++)
|
|
||||||
{
|
|
||||||
/* Here we perform data type conversion. */
|
|
||||||
field = mysql_fetch_field(res_set);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
if (row[i] == NULL)
|
|
||||||
{
|
|
||||||
null_atom[0] = MkIntegerTerm(null_id++);
|
|
||||||
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("null"),1),1,null_atom)))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IS_SQL_INT(field->type))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkIntegerTerm(atoi(row[i]))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (IS_SQL_FLOAT(field->type))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkFloatTerm(atof(row[i]))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (IS_SQL_GEOMETRY(field->type))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, wkb2prolog(row[i])))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkAtomTerm(Yap_LookupAtom(row[i]))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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 */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mysql_free_result(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 */
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_get_fields_properties( USES_REGS1 ) {
|
|
||||||
Term nome_relacao = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term fields_properties_list = Deref(ARG3);
|
|
||||||
Term head, list;
|
|
||||||
|
|
||||||
char *relacao = AtomName(AtomOfTerm(nome_relacao));
|
|
||||||
char sql[256];
|
|
||||||
Int num_fields,i;
|
|
||||||
MYSQL_FIELD *fields;
|
|
||||||
MYSQL_RES *res_set;
|
|
||||||
MYSQL *conn = (MYSQL *) (IntegerOfTerm(arg_conn));
|
|
||||||
|
|
||||||
|
|
||||||
/* LIMIT 0 -> We only need the meta information about the fields
|
|
||||||
to know their properties, we don't need the results of the
|
|
||||||
query*/
|
|
||||||
sprintf (sql,"SELECT * FROM `%s` LIMIT 0",relacao);
|
|
||||||
|
|
||||||
Int length=strlen(sql);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
if (mysql_real_query(conn, sql, length) != 0)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("Erro na query! %s\n",sql);
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"),4);
|
|
||||||
|
|
||||||
Term properties[4];
|
|
||||||
|
|
||||||
|
|
||||||
/* guardar os tuplos do lado do cliente */
|
|
||||||
/* nao precisamos do resultado, mas apenas no res_set */
|
|
||||||
/* para obter a informa<6D><61>o atrav<61>s do mysql_fetch_fields*/
|
|
||||||
res_set = mysql_store_result(conn);
|
|
||||||
|
|
||||||
num_fields = mysql_num_fields(res_set);
|
|
||||||
fields = mysql_fetch_fields(res_set);
|
|
||||||
|
|
||||||
list = fields_properties_list;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (i=0;i<num_fields;i++)
|
|
||||||
{
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(fields[i].name));
|
|
||||||
|
|
||||||
if (fields[i].flags & NOT_NULL_FLAG)
|
|
||||||
properties[1] = MkIntegerTerm(1); //Can't be NULL
|
|
||||||
else
|
|
||||||
properties[1] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
if (fields[i].flags & PRI_KEY_FLAG)
|
|
||||||
properties[2] = MkIntegerTerm(1); //It''s a primary key
|
|
||||||
else
|
|
||||||
properties[2] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
if (fields[i].flags & AUTO_INCREMENT_FLAG)
|
|
||||||
properties[3] = MkIntegerTerm(1); //It's auto_incremented field
|
|
||||||
else
|
|
||||||
properties[3] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(functor,4,properties))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql_free_result(res_set);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c_db_my_get_next_result_set: Connection * NextResSet */
|
|
||||||
static Int
|
|
||||||
c_db_my_get_next_result_set( USES_REGS1 ) {
|
|
||||||
Term arg_conn = Deref(ARG1);
|
|
||||||
Term arg_next_res_set = Deref(ARG2);
|
|
||||||
|
|
||||||
MYSQL *conn = (MYSQL *) (IntegerOfTerm(arg_conn));
|
|
||||||
MYSQL_RES *res_set=NULL;
|
|
||||||
|
|
||||||
if (mysql_next_result(conn) == 0){
|
|
||||||
res_set = mysql_store_result(conn);
|
|
||||||
Yap_unify(arg_next_res_set, MkIntegerTerm((Int) res_set));
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_get_database( USES_REGS1 ) {
|
|
||||||
Term arg_con = Deref(ARG1);
|
|
||||||
Term arg_database = Deref(ARG2);
|
|
||||||
|
|
||||||
MYSQL *con = (MYSQL *) (IntegerOfTerm(arg_con));
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_database,MkAtomTerm(Yap_LookupAtom(con->db))))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_my_change_database( USES_REGS1 ) {
|
|
||||||
Term arg_con = Deref(ARG1);
|
|
||||||
Term arg_database = Deref(ARG2);
|
|
||||||
|
|
||||||
MYSQL *con = (MYSQL *) (IntegerOfTerm(arg_con));
|
|
||||||
char *database = AtomName(AtomOfTerm(arg_database));
|
|
||||||
|
|
||||||
if (mysql_select_db(con,database)!=0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MYDDAS_MYSQL */
|
|
@ -1,874 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* *
|
|
||||||
* 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_odbc.c *
|
|
||||||
* Last rev: 22/03/05 *
|
|
||||||
* mods: *
|
|
||||||
* comments: Predicates for comunicating with ODBC drivers *
|
|
||||||
* *
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#if defined MYDDAS_ODBC
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "Yap.h"
|
|
||||||
#include "Yatom.h"
|
|
||||||
#include "myddas.h"
|
|
||||||
#include "cut_c.h"
|
|
||||||
#include <sql.h>
|
|
||||||
#include <sqlucode.h>
|
|
||||||
|
|
||||||
static Int null_id = 0;
|
|
||||||
|
|
||||||
static Int c_db_odbc_connect( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_disconnect( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_number_of_fields( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_get_attributes_types( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_query( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_row( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_row_cut( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_get_fields_properties( USES_REGS1 );
|
|
||||||
static Int c_db_odbc_number_of_fields_in_query( USES_REGS1 );
|
|
||||||
|
|
||||||
static int
|
|
||||||
odbc_error(SQLSMALLINT type, SQLHANDLE hdbc, char *msg, char *print)
|
|
||||||
{
|
|
||||||
SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
|
|
||||||
SQLINTEGER NativeError;
|
|
||||||
SQLSMALLINT i=1, MsgLen;
|
|
||||||
|
|
||||||
SQLGetDiagRec(type, hdbc,i,SqlState,&NativeError,Msg, sizeof(Msg), &MsgLen);
|
|
||||||
fprintf(stderr,"%% error in SQLConnect: %s got error code %s\n%% SQL Message: %s\n", print, SqlState, Msg);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
SQLALLOCHANDLE(SQLSMALLINT HandleType, SQLHANDLE hdbc, SQLHANDLE *outHandle, char *print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
|
|
||||||
retcode = SQLAllocHandle(HandleType,hdbc,outHandle);
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
{
|
|
||||||
return odbc_error(HandleType, hdbc, "SQLAllocHandle(ENV)", print);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
SQLSETENVATTR(SQLHENV henv, SQLINTEGER att, SQLPOINTER p, SQLINTEGER len, char *print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
|
|
||||||
retcode = SQLSetEnvAttr(henv,att,p,len);
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
{
|
|
||||||
return odbc_error(SQL_HANDLE_ENV, henv, "SQLSetEnvAttr", print);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLCONNECT(SQLHDBC hdbc,
|
|
||||||
SQLCHAR *driver,
|
|
||||||
SQLCHAR *user,
|
|
||||||
SQLCHAR *password,
|
|
||||||
char *print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
|
|
||||||
retcode = SQLConnect(hdbc,driver,SQL_NTS,user,SQL_NTS,password,SQL_NTS);
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_DBC, hdbc, "SQLConnect", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLEXECDIRECT(SQLHSTMT StatementHandle,
|
|
||||||
SQLCHAR * StatementText,
|
|
||||||
char *print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLExecDirect(StatementHandle,StatementText,SQL_NTS);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, StatementHandle, "SQLExecDirect", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLDESCRIBECOL(SQLHSTMT sth,
|
|
||||||
SQLSMALLINT colno,
|
|
||||||
SQLCHAR * colname,
|
|
||||||
SQLSMALLINT bflength,
|
|
||||||
SQLSMALLINT * nmlengthp,
|
|
||||||
SQLSMALLINT * dtptr,
|
|
||||||
SQLULEN * colszptr,
|
|
||||||
SQLSMALLINT * ddptr,
|
|
||||||
SQLSMALLINT * nullableptr,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLDescribeCol(sth, colno, colname, bflength,
|
|
||||||
nmlengthp, dtptr, colszptr, ddptr,
|
|
||||||
nullableptr);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, sth, "SQLDescribeCol", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLSETCONNECTATTR(SQLHDBC hdbc,
|
|
||||||
SQLINTEGER attr,
|
|
||||||
SQLPOINTER vptr,
|
|
||||||
SQLINTEGER slen,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLSetConnectAttr(hdbc, attr, vptr, slen);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, hdbc, "SQLSetConnectAttr", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLBINDCOL(SQLHSTMT sthandle,
|
|
||||||
SQLUSMALLINT colno,
|
|
||||||
SQLSMALLINT tt,
|
|
||||||
SQLPOINTER tvptr,
|
|
||||||
SQLLEN blen,
|
|
||||||
SQLLEN * strl,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLBindCol(sthandle,colno,tt,tvptr,blen,strl);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, sthandle, "SQLBindCol", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLNUMRESULTCOLS(SQLHSTMT sthandle,
|
|
||||||
SQLSMALLINT * ncols,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLNumResultCols(sthandle,ncols);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, sthandle, "SQLNumResultCols", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLCLOSECURSOR(SQLHSTMT sthandle,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLCloseCursor(sthandle);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, sthandle, "SQLCloseCursor", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define SQLFETCH(A,print) \
|
|
||||||
{ \
|
|
||||||
SQLRETURN retcode; \
|
|
||||||
retcode = SQLFetch(A); \
|
|
||||||
if (retcode == SQL_NO_DATA) \
|
|
||||||
break; \
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) \
|
|
||||||
{ \
|
|
||||||
printf("Error in SQLFETCH: %s\n",print); \
|
|
||||||
return FALSE; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLGETDATA(SQLHSTMT sthandle,
|
|
||||||
SQLUSMALLINT Col_or_Param_Num,
|
|
||||||
SQLSMALLINT TargetType,
|
|
||||||
SQLPOINTER TargetValuePtr,
|
|
||||||
SQLLEN BufferLength,
|
|
||||||
SQLLEN * StrLen_or_IndPtr,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLGetData(sthandle, Col_or_Param_Num,
|
|
||||||
TargetType, TargetValuePtr,
|
|
||||||
BufferLength, StrLen_or_IndPtr);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, sthandle, "SQLGetData", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLDISCONNECT(SQLHSTMT sthandle,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLDisconnect(sthandle);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_DBC, sthandle, "SQLDisconnect", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLFREEHANDLE(SQLSMALLINT HandleType,
|
|
||||||
SQLHANDLE Handle,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLFreeHandle(HandleType, Handle);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(HandleType, Handle, "SQLDisconnect", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SQLPRIMARYKEYS(SQLHSTMT StatementHandle,
|
|
||||||
SQLCHAR * CatalogName,
|
|
||||||
SQLSMALLINT NameLength1,
|
|
||||||
SQLCHAR * SchemaName,
|
|
||||||
SQLSMALLINT NameLength2,
|
|
||||||
SQLCHAR * TableName,
|
|
||||||
SQLSMALLINT NameLength3,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLPrimaryKeys(StatementHandle,
|
|
||||||
CatalogName, NameLength1,
|
|
||||||
SchemaName, NameLength2,
|
|
||||||
TableName, NameLength3
|
|
||||||
);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, StatementHandle, "SQLPrimaryKeys", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************
|
|
||||||
NOT IN USE
|
|
||||||
static int SQLGETTYPEINFO(SQLHSTMT StatementHandle,
|
|
||||||
SQLSMALLINT DataType,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLGetTypeInfo(StatementHandle, DataType);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, StatementHandle, "SQLGetTypeInfo", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
********************************************/
|
|
||||||
|
|
||||||
static int SQLCOLATTRIBUTE( SQLHSTMT StatementHandle,
|
|
||||||
SQLUSMALLINT ColumnNumber,
|
|
||||||
SQLUSMALLINT FieldIdentifier,
|
|
||||||
SQLPOINTER CharacterAttributePtr,
|
|
||||||
SQLSMALLINT BufferLength,
|
|
||||||
SQLSMALLINT * StringLengthPtr,
|
|
||||||
SQLLEN * NumericAttributePtr,
|
|
||||||
char * print)
|
|
||||||
{
|
|
||||||
SQLRETURN retcode;
|
|
||||||
retcode = SQLColAttribute(StatementHandle,
|
|
||||||
ColumnNumber,
|
|
||||||
FieldIdentifier,
|
|
||||||
CharacterAttributePtr,
|
|
||||||
BufferLength,
|
|
||||||
StringLengthPtr,
|
|
||||||
NumericAttributePtr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
return odbc_error(SQL_HANDLE_STMT, StatementHandle, "SQLColAttribute", print);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Verificar tipo de dados*/
|
|
||||||
#define IS_SQL_INT(FIELD) FIELD == SQL_DECIMAL || \
|
|
||||||
FIELD == SQL_NUMERIC || \
|
|
||||||
FIELD == SQL_SMALLINT || \
|
|
||||||
FIELD == SQL_INTEGER || \
|
|
||||||
FIELD == SQL_TINYINT || \
|
|
||||||
FIELD == SQL_BIGINT
|
|
||||||
|
|
||||||
#define IS_SQL_FLOAT(FIELD) FIELD == SQL_FLOAT || \
|
|
||||||
FIELD == SQL_DOUBLE || \
|
|
||||||
FIELD == SQL_REAL
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_odbc_connect( USES_REGS1 ) {
|
|
||||||
Term arg_driver = Deref(ARG1);
|
|
||||||
Term arg_user = Deref(ARG2);
|
|
||||||
Term arg_passwd = Deref(ARG3);
|
|
||||||
Term arg_conn = Deref(ARG4);
|
|
||||||
|
|
||||||
MYDDAS_UTIL_CONNECTION new = NULL;
|
|
||||||
|
|
||||||
const char *driver = AtomName(AtomOfTerm(arg_driver));
|
|
||||||
const char *user = AtomName(AtomOfTerm(arg_user));
|
|
||||||
const char *passwd = AtomName(AtomOfTerm(arg_passwd));
|
|
||||||
|
|
||||||
SQLHENV henv;
|
|
||||||
SQLHDBC hdbc;
|
|
||||||
|
|
||||||
/*Allocate environment handle */
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv, "connect"))
|
|
||||||
return FALSE;
|
|
||||||
/* Set the ODBC version environment attribute */
|
|
||||||
if (!SQLSETENVATTR(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0, "connect"))
|
|
||||||
return FALSE;
|
|
||||||
/* Allocate connection handle */
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_DBC, henv, &hdbc, "connect"))
|
|
||||||
return FALSE;
|
|
||||||
/* Set login timeout to 6 seconds. */
|
|
||||||
if (!SQLSETCONNECTATTR(hdbc, SQL_LOGIN_TIMEOUT,(SQLPOINTER) 6, 0, "connect"))
|
|
||||||
return FALSE;
|
|
||||||
/* Connect to data source */
|
|
||||||
if (!SQLCONNECT(hdbc,
|
|
||||||
(SQLCHAR*) driver,
|
|
||||||
(SQLCHAR*) user,
|
|
||||||
(SQLCHAR*) passwd, "connect"))
|
|
||||||
return FALSE;
|
|
||||||
if (!Yap_unify(arg_conn, MkIntegerTerm((Int)(hdbc))))
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Criar um novo no na lista de ligacoes*/
|
|
||||||
//new = add_connection(&TOP,hdbc,henv);
|
|
||||||
new = myddas_util_add_connection(hdbc,henv,MYDDAS_ODBC);
|
|
||||||
if (new == NULL){
|
|
||||||
fprintf(stderr,"Error: could not allocate list memory\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x Arity x BindList x Connection */
|
|
||||||
static Int
|
|
||||||
c_db_odbc_query( USES_REGS1 ) {
|
|
||||||
Term arg_sql_query = Deref(ARG1);
|
|
||||||
Term arg_result_set = Deref(ARG2);
|
|
||||||
Term arg_arity = Deref(ARG3);
|
|
||||||
Term arg_bind_list = Deref(ARG4);
|
|
||||||
Term arg_conn = Deref(ARG5);
|
|
||||||
|
|
||||||
SQLCHAR *sql = (SQLCHAR *)AtomName(AtomOfTerm(arg_sql_query));
|
|
||||||
|
|
||||||
|
|
||||||
SQLHDBC hdbc =(SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
SQLHSTMT hstmt;
|
|
||||||
SQLSMALLINT type;
|
|
||||||
Int arity;
|
|
||||||
Int i;
|
|
||||||
|
|
||||||
/*Allocate an handle for the query*/
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt, "db_query"))
|
|
||||||
return FALSE;
|
|
||||||
/* Executes the query*/
|
|
||||||
if (!SQLEXECDIRECT(hstmt, sql, "db_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (IsNonVarTerm(arg_arity)){
|
|
||||||
arity = IntegerOfTerm(arg_arity);
|
|
||||||
|
|
||||||
|
|
||||||
char *bind_space=NULL;
|
|
||||||
|
|
||||||
//const Int functor_arity=3;
|
|
||||||
const Short functor_arity=3;
|
|
||||||
Functor functor = Yap_MkFunctor(Yap_LookupAtom("bind"),functor_arity);
|
|
||||||
Term properties[functor_arity];
|
|
||||||
|
|
||||||
Term head,list=arg_bind_list;
|
|
||||||
|
|
||||||
SQLULEN ColumnSizePtr;
|
|
||||||
SQLLEN *data_info=NULL;
|
|
||||||
|
|
||||||
for (i=1;i<=arity;i++)
|
|
||||||
{
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
if (!SQLDESCRIBECOL(hstmt,i,NULL,0,NULL,&type,&ColumnSizePtr,NULL,NULL,"db_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* +1 because of '\0' */
|
|
||||||
bind_space = malloc(sizeof(char)*(ColumnSizePtr+1));
|
|
||||||
data_info = malloc(sizeof(SQLINTEGER));
|
|
||||||
if (!SQLBINDCOL(hstmt,i,SQL_C_CHAR,bind_space,(ColumnSizePtr+1),data_info,"db_query")) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
properties[0] = MkIntegerTerm((Int)bind_space);
|
|
||||||
properties[2] = MkIntegerTerm((Int)data_info);
|
|
||||||
|
|
||||||
if (IS_SQL_INT(type))
|
|
||||||
properties[1]=MkAtomTerm(Yap_LookupAtom("integer"));
|
|
||||||
else if (IS_SQL_FLOAT(type))
|
|
||||||
properties[1]=MkAtomTerm(Yap_LookupAtom("real"));
|
|
||||||
else
|
|
||||||
properties[1]=MkAtomTerm(Yap_LookupAtom("string"));
|
|
||||||
|
|
||||||
Yap_unify(head,Yap_MkApplTerm(functor,functor_arity,properties));
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_result_set, MkIntegerTerm((Int) hstmt)))
|
|
||||||
{
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_query"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_query"))
|
|
||||||
return FALSE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_odbc_number_of_fields( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term arg_fields = Deref(ARG3);
|
|
||||||
|
|
||||||
|
|
||||||
const char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
|
|
||||||
SQLHDBC hdbc =(SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
SQLHSTMT hstmt;
|
|
||||||
|
|
||||||
char sql[256];
|
|
||||||
SQLSMALLINT number_fields;
|
|
||||||
|
|
||||||
sprintf(sql,"SELECT column_name from INFORMATION_SCHEMA.COLUMNS where table_name = \'%s\' GROUP BY column_name, dtd_identifier ORDER BY CAST(dtd_identifier AS INTEGER)",relation);
|
|
||||||
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt, "db_number_of_fields"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLEXECDIRECT(hstmt, (SQLCHAR *)sql, "db_number_of_fields"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Calcula o numero de campos*/
|
|
||||||
number_fields=0;
|
|
||||||
while(TRUE) {
|
|
||||||
SQLFETCH(hstmt,"db_number_of_fields");
|
|
||||||
number_fields++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_number_of_fields"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_number_of_fields"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_fields, MkIntegerTerm(number_fields)))
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* db_get_attributes_types: RelName x Connection -> TypesList */
|
|
||||||
static Int
|
|
||||||
c_db_odbc_get_attributes_types( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term arg_types_list = Deref(ARG3);
|
|
||||||
|
|
||||||
const char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
SQLHDBC hdbc =(SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
SQLHSTMT hstmt;
|
|
||||||
|
|
||||||
char sql[256];
|
|
||||||
Term head, list;
|
|
||||||
list = arg_types_list;
|
|
||||||
|
|
||||||
sprintf(sql,"SELECT column_name,data_type from INFORMATION_SCHEMA.COLUMNS WHERE table_name = \'%s\' GROUP BY column_name, dtd_identifier ORDER BY CAST(dtd_identifier AS INTEGER)",relation);
|
|
||||||
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt, "db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLEXECDIRECT(hstmt, (SQLCHAR *)sql, "db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
SQLFETCH(hstmt, "db_get_attributes_types");
|
|
||||||
|
|
||||||
/* Tentar fazer de uma maneira que a gente consiga calcular o tamanho que o
|
|
||||||
nome do campo vai ocupar, assim podemos alocar memoria dinamicamente*/
|
|
||||||
sql[0]='\0';
|
|
||||||
if (!SQLGETDATA(hstmt, 1, SQL_C_CHAR, sql, 256, NULL, "db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom(sql)));
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
sql[0]='\0';
|
|
||||||
if (!SQLGETDATA(hstmt, 2, SQL_C_CHAR, sql, 256, NULL, "db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (strncmp(sql, "smallint",8) == 0 || strncmp(sql,"int",3) == 0 ||
|
|
||||||
strncmp(sql, "mediumint",9) == 0 || strncmp(sql, "tinyint",7) == 0 ||
|
|
||||||
strncmp(sql, "bigint",6) == 0 || strcmp(sql, "year") == 0)
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom("integer")));
|
|
||||||
else
|
|
||||||
if (strcmp(sql, "float") == 0 || strncmp(sql, "double",6) == 0
|
|
||||||
|| strcmp(sql, "real") == 0)
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom("real")));
|
|
||||||
else
|
|
||||||
Yap_unify(head, MkAtomTerm(Yap_LookupAtom("string")));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_get_attributes_types"))
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_disconnect */
|
|
||||||
static Int
|
|
||||||
c_db_odbc_disconnect( USES_REGS1 ) {
|
|
||||||
Term arg_conn = Deref(ARG1);
|
|
||||||
|
|
||||||
SQLHDBC conn = (SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
SQLHENV henv = myddas_util_get_odbc_enviromment(conn);
|
|
||||||
|
|
||||||
if ((myddas_util_search_connection(conn)) != NULL)
|
|
||||||
{
|
|
||||||
myddas_util_delete_connection(conn);
|
|
||||||
/* More information about this process on
|
|
||||||
msdn.microsoft.com*/
|
|
||||||
if (!SQLDISCONNECT(conn,"db_disconnect"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_DBC,conn,"db_disconnect"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_ENV,henv,"db_disconnect"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_odbc_row_cut( USES_REGS1 ) {
|
|
||||||
|
|
||||||
SQLHSTMT hstmt = (SQLHSTMT) IntegerOfTerm(EXTRA_CBACK_CUT_ARG(Term,1));
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_row_cut"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_row_cut"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
release_list_args(Term arg_list_args, Term arg_bind_list, const char *error_msg)
|
|
||||||
{
|
|
||||||
Term list = arg_list_args;
|
|
||||||
Term list_bind = arg_bind_list;
|
|
||||||
|
|
||||||
while (IsPairTerm(list_bind))
|
|
||||||
{
|
|
||||||
Term head_bind = HeadOfTerm(list_bind);
|
|
||||||
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
list_bind = TailOfTerm(list_bind);
|
|
||||||
|
|
||||||
free((char *)IntegerOfTerm(ArgOfTerm(1,head_bind)));
|
|
||||||
free((SQLINTEGER *)IntegerOfTerm(ArgOfTerm(3,head_bind)));
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_row: ResultSet x BindList x ListOfArgs -> */
|
|
||||||
static Int
|
|
||||||
c_db_odbc_row( USES_REGS1 ) {
|
|
||||||
Term arg_result_set = Deref(ARG1);
|
|
||||||
Term arg_bind_list = Deref(ARG2);
|
|
||||||
Term arg_list_args = Deref(ARG3);
|
|
||||||
|
|
||||||
SQLHSTMT hstmt = (SQLHSTMT) IntegerOfTerm(arg_result_set);
|
|
||||||
|
|
||||||
/* EXTRA_CBACK_ARG(ARIDADE,LOCAL_ONDE_COLOCAR_VALOR)*/
|
|
||||||
EXTRA_CBACK_ARG(3,1)=(CELL) MkIntegerTerm((Int)hstmt);
|
|
||||||
|
|
||||||
Term head, list, null_atom[1];
|
|
||||||
Term head_bind, list_bind;
|
|
||||||
|
|
||||||
SQLRETURN retcode = SQLFetch(hstmt);
|
|
||||||
if (retcode == SQL_NO_DATA)
|
|
||||||
{
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_row"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_row"))
|
|
||||||
return FALSE;
|
|
||||||
if (!release_list_args(arg_list_args, arg_bind_list, "db_row")) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cut_fail();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
|
|
||||||
{
|
|
||||||
printf("erro no SQLFETCH number of fields\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *bind_value=NULL;
|
|
||||||
Term type;
|
|
||||||
|
|
||||||
list = arg_list_args;
|
|
||||||
list_bind = arg_bind_list;
|
|
||||||
SQLINTEGER *data_info=NULL;
|
|
||||||
|
|
||||||
while (IsPairTerm(list_bind))
|
|
||||||
{
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
head_bind = HeadOfTerm(list_bind);
|
|
||||||
list_bind = TailOfTerm(list_bind);
|
|
||||||
|
|
||||||
bind_value = (char *)IntegerOfTerm(ArgOfTerm(1,head_bind));
|
|
||||||
type = ArgOfTerm(2,head_bind);
|
|
||||||
data_info = (SQLINTEGER *)IntegerOfTerm(ArgOfTerm(3,head_bind));
|
|
||||||
|
|
||||||
if ((*data_info) == SQL_NULL_DATA){
|
|
||||||
null_atom[0] = MkIntegerTerm(null_id++);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("null"),1),1,null_atom)))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!strcmp(AtomName(AtomOfTerm(type)),"integer"))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkIntegerTerm(atol(bind_value))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (!strcmp(AtomName(AtomOfTerm(type)),"real"))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkFloatTerm(atof(bind_value))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (!strcmp(AtomName(AtomOfTerm(type)),"string"))
|
|
||||||
{
|
|
||||||
if (!Yap_unify(head, MkAtomTerm(Yap_LookupAtom(bind_value))))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Mudar esta funcao de forma a nao fazer a consulta, pois
|
|
||||||
no predicate db_sql_selet vai fazer duas vezes a mesma consutla*/
|
|
||||||
static Int
|
|
||||||
c_db_odbc_number_of_fields_in_query( USES_REGS1 ) {
|
|
||||||
Term arg_query = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term arg_fields = Deref(ARG3);
|
|
||||||
|
|
||||||
const char *sql = AtomName(AtomOfTerm(arg_query));
|
|
||||||
|
|
||||||
SQLHDBC hdbc =(SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
SQLHSTMT hstmt;
|
|
||||||
SQLSMALLINT number_cols=0;
|
|
||||||
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt,
|
|
||||||
"db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLEXECDIRECT(hstmt ,(SQLCHAR *)sql,
|
|
||||||
"db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!SQLNUMRESULTCOLS(hstmt,&number_cols,
|
|
||||||
"db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_fields, MkIntegerTerm(number_cols))){
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt, "db_number_of_fields_in_query"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_db_odbc_get_fields_properties( USES_REGS1 ) {
|
|
||||||
Term nome_relacao = Deref(ARG1);
|
|
||||||
Term arg_conn = Deref(ARG2);
|
|
||||||
Term fields_properties_list = Deref(ARG3);
|
|
||||||
Term head, list;
|
|
||||||
|
|
||||||
SQLCHAR *relacao = (SQLCHAR *)AtomName(AtomOfTerm(nome_relacao));
|
|
||||||
char sql[256];
|
|
||||||
char name[200];
|
|
||||||
Int i;
|
|
||||||
|
|
||||||
|
|
||||||
SQLSMALLINT num_fields=0;
|
|
||||||
SQLSMALLINT NullablePtr=0;
|
|
||||||
SQLLEN AutoIncrementPointer=0;
|
|
||||||
SQLHSTMT hstmt,hstmt2;
|
|
||||||
SQLHDBC hdbc =(SQLHDBC) (IntegerOfTerm(arg_conn));
|
|
||||||
|
|
||||||
|
|
||||||
/* LIMIT 0 -> We don't need the results of the query,
|
|
||||||
only the information about the fields of the relation*/
|
|
||||||
sprintf (sql,"SELECT * FROM `%s` LIMIT 0",relacao);
|
|
||||||
|
|
||||||
/*Allocate an handle for the query*/
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
/* Executes the query*/
|
|
||||||
if (!SQLEXECDIRECT(hstmt ,(SQLCHAR *)sql, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"),4);
|
|
||||||
Term properties[4];
|
|
||||||
|
|
||||||
if (!SQLNUMRESULTCOLS(hstmt,&num_fields,
|
|
||||||
"db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
list = fields_properties_list;
|
|
||||||
|
|
||||||
SQLSMALLINT bind_prim_key;
|
|
||||||
// rows in odbc start at 1 :)
|
|
||||||
Short *null=(Short *)malloc(sizeof(Short)*(1+num_fields));
|
|
||||||
|
|
||||||
if (!SQLALLOCHANDLE(SQL_HANDLE_STMT, hdbc, &hstmt2, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
/* Executes the query*/
|
|
||||||
if (!SQLPRIMARYKEYS(hstmt2,NULL,0,NULL,0,relacao,SQL_NTS, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
/* Associates bind value for the 5 column*/
|
|
||||||
if (!SQLBINDCOL(hstmt2,5,SQL_C_SSHORT,&bind_prim_key,sizeof(SQLSMALLINT),NULL,
|
|
||||||
"db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
SQLFETCH(hstmt2,"db_get_fields_properties");
|
|
||||||
null[bind_prim_key]=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt2,"db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt2, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (i=1;i<=num_fields;i++)
|
|
||||||
{
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
name[0]='\0';
|
|
||||||
SQLDESCRIBECOL(hstmt,i,(SQLCHAR *)name,200,NULL,NULL,NULL,NULL,&NullablePtr,
|
|
||||||
"db_get_fields_properties");
|
|
||||||
|
|
||||||
if (!SQLCOLATTRIBUTE(hstmt,i,SQL_DESC_AUTO_UNIQUE_VALUE,NULL,0,NULL,&AutoIncrementPointer,
|
|
||||||
"db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(name));
|
|
||||||
|
|
||||||
|
|
||||||
if (NullablePtr & SQL_NULLABLE)
|
|
||||||
properties[1] = MkIntegerTerm(1); //Can't be NULL
|
|
||||||
else
|
|
||||||
properties[1] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
if (null[i] == 1)
|
|
||||||
properties[2] = MkIntegerTerm(1); //It''s a primary key
|
|
||||||
else
|
|
||||||
properties[2] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
if (AutoIncrementPointer & SQL_TRUE)
|
|
||||||
properties[3] = MkIntegerTerm(1); //It's auto_incremented field
|
|
||||||
else
|
|
||||||
properties[3] = MkIntegerTerm(0);
|
|
||||||
|
|
||||||
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(functor,4,properties))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SQLCLOSECURSOR(hstmt,"db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
if (!SQLFREEHANDLE(SQL_HANDLE_STMT, hstmt2, "db_get_fields_properties"))
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_ODBCPreds(void)
|
|
||||||
{
|
|
||||||
/* db_connect: Host x User x Passwd x Database x Connection */
|
|
||||||
Yap_InitCPred("c_db_odbc_connect", 4, c_db_odbc_connect, 0);
|
|
||||||
|
|
||||||
/* db_number_of_fields: Relation x Connection x NumberOfFields */
|
|
||||||
Yap_InitCPred("c_db_odbc_number_of_fields",3, c_db_odbc_number_of_fields, 0);
|
|
||||||
|
|
||||||
/* db_number_of_fields_in_query: SQLQuery x Connection x NumberOfFields */
|
|
||||||
Yap_InitCPred("c_db_odbc_number_of_fields_in_query",3, c_db_odbc_number_of_fields_in_query, 0);
|
|
||||||
|
|
||||||
/* db_get_attributes_types: Relation x TypesList */
|
|
||||||
Yap_InitCPred("c_db_odbc_get_attributes_types", 3, c_db_odbc_get_attributes_types, 0);
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x Connection */
|
|
||||||
Yap_InitCPred("c_db_odbc_query", 5, c_db_odbc_query, 0);
|
|
||||||
|
|
||||||
/* db_disconnect: Connection */
|
|
||||||
Yap_InitCPred("c_db_odbc_disconnect", 1,c_db_odbc_disconnect, 0);
|
|
||||||
|
|
||||||
/* db_get_fields_properties: PredName x Connnection x PropertiesList */
|
|
||||||
Yap_InitCPred("c_db_odbc_get_fields_properties",3,c_db_odbc_get_fields_properties,0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Yap_InitBackMYDDAS_ODBCPreds(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* db_row: ResultSet x ListOfArgs */
|
|
||||||
Yap_InitCPredBackCut("c_db_odbc_row", 3, sizeof(Int),
|
|
||||||
c_db_odbc_row,
|
|
||||||
c_db_odbc_row,
|
|
||||||
c_db_odbc_row_cut, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*MYDDAS_ODBC*/
|
|
@ -1,890 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* *
|
|
||||||
* 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_postgres.c *
|
|
||||||
* Last rev: 22/03/05 *
|
|
||||||
* mods: *
|
|
||||||
* comments: Predicates for comunicating with a pq database system *
|
|
||||||
* *
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MYDDAS_POSTGRES
|
|
||||||
|
|
||||||
#include <libpq-fe.h>
|
|
||||||
|
|
||||||
#define BOOLOID 16
|
|
||||||
#define BYTEOID 17
|
|
||||||
#define CHAROID 18
|
|
||||||
#define NAMEOID 19
|
|
||||||
#define INT8OID 20
|
|
||||||
#define INT2OID 21
|
|
||||||
#define INT2VECTOROID 22
|
|
||||||
#define INT4OID 23
|
|
||||||
#define REGPROCOID 24
|
|
||||||
#define TEXTOID 25
|
|
||||||
#define OIDOID 26
|
|
||||||
#define TIDOID 27
|
|
||||||
#define XIDOID 28
|
|
||||||
#define CIDOID 29
|
|
||||||
#define OIDVECTOROID 30
|
|
||||||
#define JSONOID 114
|
|
||||||
#define XMLOID 142
|
|
||||||
#define PGNODETREEOID 194
|
|
||||||
#define POINTOID 600
|
|
||||||
#define LSEGOID 601
|
|
||||||
#define PATHOID 602
|
|
||||||
#define BOXOID 603
|
|
||||||
#define POLYGONOID 604
|
|
||||||
#define LINEOID 628
|
|
||||||
#define FLOAT4OID 700
|
|
||||||
#define FLOAT8OID 701
|
|
||||||
#define ABSTIMEOID 702
|
|
||||||
#define RELTIMEOID 703
|
|
||||||
#define TINTERVALOID 704
|
|
||||||
#define UNKNOWNOID 705
|
|
||||||
#define CIRCLEOID 718
|
|
||||||
#define CASHOID 790
|
|
||||||
#define MACADDROID 829
|
|
||||||
#define INETOID 869
|
|
||||||
#define CIDROID 650
|
|
||||||
#define INT2ARRAYOID 1005
|
|
||||||
#define INT4ARRAYOID 1007
|
|
||||||
#define TEXTARRAYOID 1009
|
|
||||||
#define OIDARRAYOID 1028
|
|
||||||
#define FLOAT4ARRAYOID 1021
|
|
||||||
#define ACLITEMOID 1033
|
|
||||||
#define CSTRINGARRAYOID 1263
|
|
||||||
#define BPCHAROID 1042
|
|
||||||
#define VARCHAROID 1043
|
|
||||||
#define DATEOID 1082
|
|
||||||
#define TIMEOID 1083
|
|
||||||
#define TIMESTAMPOID 1114
|
|
||||||
#define TIMESTAMPTZOID 1184
|
|
||||||
#define INTERVALOID 1186
|
|
||||||
#define TIMETZOID 1266
|
|
||||||
#define BITOID 1560
|
|
||||||
#define VARBITOID 1562
|
|
||||||
#define NUMERICOID 1700
|
|
||||||
#define REFCURSOROID 1790
|
|
||||||
#define REGPROCEDUREOID 2202
|
|
||||||
#define REGOPEROID 2203
|
|
||||||
#define REGOPERATOROID 2204
|
|
||||||
#define REGCLASSOID 2205
|
|
||||||
#define REGTYPEOID 2206
|
|
||||||
#define REGTYPEARRAYOID 2211
|
|
||||||
#define UUIDOID 2950
|
|
||||||
#define LSNOID 3220
|
|
||||||
#define TSVECTOROID 3614
|
|
||||||
#define GTSVECTOROID 3642
|
|
||||||
#define TSQUERYOID 3615
|
|
||||||
#define REGCONFIGOID 3734
|
|
||||||
#define REGDICTIONARYOID 3769
|
|
||||||
#define JSONBOID 3802
|
|
||||||
#define INT4RANGEOID 3904
|
|
||||||
#define RECORDOID 2249
|
|
||||||
#define RECORDARRAYOID 2287
|
|
||||||
#define CSTRINGOID 2275
|
|
||||||
#define ANYOID 2276
|
|
||||||
#define ANYARRAYOID 2277
|
|
||||||
#define VOIDOID 2278
|
|
||||||
#define TRIGGEROID 2279
|
|
||||||
#define EVTTRIGGEROID 3838
|
|
||||||
#define LANGUAGE_HANDLEROID 2280
|
|
||||||
#define INTERNALOID 2281
|
|
||||||
#define OPAQUEOID 2282
|
|
||||||
#define ANYELEMENTOID 2283
|
|
||||||
#define ANYNONARRAYOID 2776
|
|
||||||
#define ANYENUMOID 3500
|
|
||||||
#define FDW_HANDLEROID 3115
|
|
||||||
#define ANYRANGEOID 3831
|
|
||||||
|
|
||||||
#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_POSTGRES(f) \
|
|
||||||
{ \
|
|
||||||
res = PQ ## f; \
|
|
||||||
if (PQstatus(db) != CONNECTION_OK) { \
|
|
||||||
fprintf(stderr, "Error %s when calling %s, line %d\n", \
|
|
||||||
PQerrorMessage(db), #f,__LINE__); \
|
|
||||||
exit (1); \
|
|
||||||
} \
|
|
||||||
PQclear(res); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#define GET_POSTGRES(f, res) \
|
|
||||||
{ \
|
|
||||||
res = PQ ## f; \
|
|
||||||
if (PQstatus(db) != CONNECTION_OK) { \
|
|
||||||
fprintf (stderr, "%s failed with status %s, line %d\n", \
|
|
||||||
#f, PQerrorMessage (db), __LINE__); \
|
|
||||||
exit (1); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Int NULL_id = 0;
|
|
||||||
|
|
||||||
typedef struct result_set {
|
|
||||||
PGconn *db;
|
|
||||||
PGresult *res;
|
|
||||||
const char *stmt;
|
|
||||||
int i ;
|
|
||||||
int nrows;
|
|
||||||
int ncols;
|
|
||||||
} resultSet;
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_PGPreds(void);
|
|
||||||
void Yap_InitBackMYDDAS_PGPreds(void);
|
|
||||||
|
|
||||||
|
|
||||||
static Int c_postgres_connect( USES_REGS1 );
|
|
||||||
static Int c_postgres_disconnect( USES_REGS1 );
|
|
||||||
static Int c_postgres_number_of_fields( USES_REGS1 );
|
|
||||||
static Int c_postgres_get_attributes_types( USES_REGS1 );
|
|
||||||
static Int c_postgres_query( USES_REGS1 );
|
|
||||||
static Int c_postgres_table_write( USES_REGS1 );
|
|
||||||
static Int c_postgres_row( USES_REGS1 );
|
|
||||||
static Int c_postgres_row_cut( USES_REGS1 );
|
|
||||||
static Int c_postgres_get_fields_properties( USES_REGS1 );
|
|
||||||
static Int c_postgres_get_next_result_set( USES_REGS1 );
|
|
||||||
static Int c_postgres_get_database( USES_REGS1 );
|
|
||||||
static Int c_postgres_change_database( USES_REGS1 );
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_PGPreds(void)
|
|
||||||
{
|
|
||||||
/* db_dbect: Host x User x Passwd x Database x dbection x ERROR_CODE */
|
|
||||||
Yap_InitCPred("c_postgres_connect", 7, c_postgres_connect, 0);
|
|
||||||
|
|
||||||
/* db_number_of_fields: Relation x connection x NumberOfFields */
|
|
||||||
Yap_InitCPred("c_postgres_number_of_fields",3, c_postgres_number_of_fields, 0);
|
|
||||||
|
|
||||||
/* db_get_attributes_types: Relation x TypesList */
|
|
||||||
Yap_InitCPred("c_postgres_get_attributes_types", 3, c_postgres_get_attributes_types, 0);
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x conection */
|
|
||||||
Yap_InitCPred("c_postgres_query", 5, c_postgres_query, 0);
|
|
||||||
|
|
||||||
/* db_disconnect: connection */
|
|
||||||
Yap_InitCPred("c_postgres_disconnect", 1,c_postgres_disconnect, 0);
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
Yap_InitCPred("c_postgres_table_write", 1, c_postgres_table_write, 0);
|
|
||||||
|
|
||||||
/* db_get_fields_properties: PredName x connection x PropertiesList*/
|
|
||||||
Yap_InitCPred("c_postgres_get_fields_properties",3,c_postgres_get_fields_properties,0);
|
|
||||||
|
|
||||||
Yap_InitCPred("c_postgres_get_next_result_set",2,c_postgres_get_next_result_set,0);
|
|
||||||
|
|
||||||
/* c_postgres_get_database: connection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_postgres_get_database",2,c_postgres_get_database,0);
|
|
||||||
|
|
||||||
/* c_postgres_change_database: connection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_postgres_change_database",2,c_postgres_change_database,0);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Yap_InitBackMYDDAS_PGPreds(void)
|
|
||||||
{
|
|
||||||
/* db_row: ResultSet x Arity x ListOfArgs */
|
|
||||||
Yap_InitCPredBackCut("c_postgres_row", 3, sizeof(Int),
|
|
||||||
c_postgres_row,
|
|
||||||
c_postgres_row,
|
|
||||||
c_postgres_row_cut, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_postgres_connect( USES_REGS1 ) {
|
|
||||||
int i=0;
|
|
||||||
Term arg_host = Deref(ARG1);
|
|
||||||
Term arg_user = Deref(ARG2);
|
|
||||||
Term arg_passwd = Deref(ARG3);
|
|
||||||
Term arg_database = Deref(ARG4);
|
|
||||||
Term arg_port = Deref(ARG5);
|
|
||||||
Term arg_socket = Deref(ARG6);
|
|
||||||
Term arg_conn = ARG7;
|
|
||||||
Term tempty = MkAtomTerm(Yap_LookupAtom(""));
|
|
||||||
Term tzero = MkIntTerm(0);
|
|
||||||
|
|
||||||
const char *keywords[8], *values[8];
|
|
||||||
char ports[16];
|
|
||||||
|
|
||||||
if (IsApplTerm(arg_host)) {
|
|
||||||
keywords[i] = "hostaddr";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(ArgOfTerm(1, arg_host)))->StrOfAE;
|
|
||||||
} else {
|
|
||||||
keywords[i] = "host";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_host))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_user != tempty && IsAtomTerm(arg_user)) {
|
|
||||||
keywords[i] = "user";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_user))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_passwd != tempty && IsAtomTerm(arg_passwd)) {
|
|
||||||
keywords[i] = "password";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_passwd))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_database != tempty && IsAtomTerm(arg_database)) {
|
|
||||||
keywords[i] = "dbase";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_database))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_port != tzero && IsIntTerm(arg_port)) {
|
|
||||||
keywords[i] = "port";
|
|
||||||
snprintf(ports, sizeof(ports)-1, "%d", (int)IntOfTerm(arg_port));
|
|
||||||
values[i++] = ports;
|
|
||||||
} else if (IsNonVarTerm(arg_socket) && arg_socket != tempty && IsIntTerm(arg_socket)) {
|
|
||||||
keywords[i] = "port";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_database))->StrOfAE;
|
|
||||||
}
|
|
||||||
keywords[i] = NULL;
|
|
||||||
values[i++] = NULL;
|
|
||||||
|
|
||||||
/* Make a connection to the database */
|
|
||||||
PGconn *db = PQconnectdbParams(keywords, values, 0);
|
|
||||||
|
|
||||||
/* Check to see that the backend c onnection was successfully made */
|
|
||||||
if (PQstatus(db) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(db));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_conn, MkAddressTerm(db)))
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Criar um novo no na lista de ligacoes*/
|
|
||||||
MYDDAS_UTIL_CONNECTION cnew = myddas_util_add_connection(db,NULL,MYDDAS_POSTGRES);
|
|
||||||
|
|
||||||
if (cnew == NULL){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: ** c_db_my_connect ** Error allocating memory\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static MYDDAS_STATS_TIME
|
|
||||||
myddas_stat_init_query( PGconn *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 PG 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 PG Server
|
|
||||||
processing the SQL Query */
|
|
||||||
MYDDAS_STATS_TIME 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* measure transfer time */
|
|
||||||
static void
|
|
||||||
myddas_stat_transfer_query( MYDDAS_STATS_TIME diff )
|
|
||||||
{
|
|
||||||
/* Measure time spent by the PG Server
|
|
||||||
transferring the result of the last query
|
|
||||||
back to the client */
|
|
||||||
start = myddas_stats_walltime();
|
|
||||||
/* Measure time spent by the PG 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, PG_(use or store)_result()
|
|
||||||
returns a NULL pointer*/
|
|
||||||
|
|
||||||
/* This is only works if we use PG_store_result */
|
|
||||||
MyddasUInt numberRows = PG_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 = PG_num_fields(res_set);
|
|
||||||
PG_ROW row;
|
|
||||||
MyddasULInt i;
|
|
||||||
total=0;
|
|
||||||
while ((row = PG_fetch_row(res_set)) != NULL){
|
|
||||||
PG_field_seek(res_set,0);
|
|
||||||
|
|
||||||
for(i=0;i<number_fields;i++){
|
|
||||||
if (row[i] != NULL)
|
|
||||||
total = total + strlen(row[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x connection */
|
|
||||||
static Int
|
|
||||||
c_postgres_query( USES_REGS1 ) {
|
|
||||||
Term arg_sql_query = Deref(ARG1);
|
|
||||||
Term arg_result_set = Deref(ARG2);
|
|
||||||
Term arg_db = Deref(ARG3);
|
|
||||||
Term arg_mode = Deref(ARG4);
|
|
||||||
Term arg_arity = ARG5;
|
|
||||||
|
|
||||||
const char *sql = AtomName(AtomOfTerm(arg_sql_query));
|
|
||||||
const char *mode = AtomName(AtomOfTerm(arg_mode));
|
|
||||||
PGresult *res;
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
struct result_set *rs = malloc(sizeof( struct result_set));
|
|
||||||
if (!rs)
|
|
||||||
return FALSE;
|
|
||||||
rs->db = db;
|
|
||||||
rs->i = 0;
|
|
||||||
|
|
||||||
|
|
||||||
MYDDAS_STATS_TIME start, end;
|
|
||||||
start = myddas_stat_init_query( db );
|
|
||||||
|
|
||||||
const char *stmt = AtomName(Yap_LookupAtom(sql));
|
|
||||||
|
|
||||||
/* Send query to server and process it */
|
|
||||||
if (strcmp(mode,"store_result")!=0) {
|
|
||||||
// Leave data for extraction
|
|
||||||
CALL_POSTGRES (prepare(db, stmt, sql, 0, NULL) );
|
|
||||||
GET_POSTGRES (describePrepared(db, stmt) , res );
|
|
||||||
rs->stmt = stmt;
|
|
||||||
rs->res = NULL;
|
|
||||||
rs->nrows = -1;
|
|
||||||
rs->ncols = PQnfields(res);
|
|
||||||
if (!Yap_unify(arg_arity, MkIntegerTerm(rs->ncols)))
|
|
||||||
{
|
|
||||||
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
|
|
||||||
int nrows, ncols;
|
|
||||||
|
|
||||||
GET_POSTGRES (exec(db, sql), res );
|
|
||||||
end = myddas_stat_end_query( start );
|
|
||||||
ncols = PQnfields(res);
|
|
||||||
nrows = PQntuples(res);
|
|
||||||
//INSERT statements don't return any res_set
|
|
||||||
if (nrows == 0) {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (!Yap_unify(arg_arity, MkIntegerTerm(nrows))){
|
|
||||||
/*
|
|
||||||
* Should PGclear PGresult whenever it is no longer needed to avoid memory
|
|
||||||
* leaks
|
|
||||||
*/
|
|
||||||
free(rs);
|
|
||||||
PQclear(res);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
rs->stmt = NULL;
|
|
||||||
rs->res = res;
|
|
||||||
rs->nrows = nrows;
|
|
||||||
rs->ncols = ncols;
|
|
||||||
if (!Yap_unify(arg_result_set, MkAddressTerm( rs)))
|
|
||||||
{
|
|
||||||
free(rs);
|
|
||||||
PQclear(res);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_postgres_number_of_fields( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_db = Deref(ARG2);
|
|
||||||
Term arg_fields = ARG3;
|
|
||||||
|
|
||||||
const char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
const char *stmt;
|
|
||||||
PGresult *res;
|
|
||||||
|
|
||||||
char sql[256];
|
|
||||||
|
|
||||||
snprintf(sql, 255, "SELECT * FROM TABLE `%s`",relation);
|
|
||||||
// Leave data for extraction
|
|
||||||
stmt = AtomName(Yap_LookupAtom(sql));
|
|
||||||
CALL_POSTGRES (prepare(db, stmt, sql, 0, NULL) );
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
|
|
||||||
int nrows = PQntuples(res);
|
|
||||||
|
|
||||||
PQclear( res );
|
|
||||||
|
|
||||||
return Yap_unify(arg_fields, MkIntegerTerm( nrows ));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* db_get_attributes_types: RelName x connection -> TypesList */
|
|
||||||
static Int
|
|
||||||
c_postgres_get_attributes_types( USES_REGS1 ) {
|
|
||||||
Term arg_relation = Deref(ARG1);
|
|
||||||
Term arg_db = Deref(ARG2);
|
|
||||||
Term arg_types_list = Deref(ARG3);
|
|
||||||
Term list, head;
|
|
||||||
|
|
||||||
const char *relation = AtomName(AtomOfTerm(arg_relation));
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
char sql[256];
|
|
||||||
//int row;
|
|
||||||
PGresult *res;
|
|
||||||
|
|
||||||
const char *stmt;
|
|
||||||
Int rc = TRUE;
|
|
||||||
|
|
||||||
sprintf(sql,"SELECT * FROM TABLE `%s`",relation);
|
|
||||||
// Leave data for extraction
|
|
||||||
stmt = AtomName(Yap_LookupAtom(sql));
|
|
||||||
// Leave data for extraction
|
|
||||||
GET_POSTGRES (prepare(db, stmt, sql, 0, NULL), res );
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
|
|
||||||
|
|
||||||
int cols = PQnfields( res ), col;
|
|
||||||
|
|
||||||
list = arg_types_list;
|
|
||||||
|
|
||||||
for (col = 0; col < cols; col++)
|
|
||||||
{
|
|
||||||
const char *tm;
|
|
||||||
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
rc = (
|
|
||||||
rc && Yap_unify(head, MkAtomTerm(Yap_LookupAtom(PQfname(res, col))) ) );
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
Oid type = PQftype(res, col);
|
|
||||||
switch(type) {
|
|
||||||
case BYTEOID:
|
|
||||||
case CHAROID:
|
|
||||||
case INT2OID:
|
|
||||||
case INT4OID:
|
|
||||||
case INT8OID:
|
|
||||||
tm = "integer";
|
|
||||||
break;
|
|
||||||
case FLOAT4OID:
|
|
||||||
case FLOAT8OID:
|
|
||||||
tm = "real";
|
|
||||||
break;
|
|
||||||
case NAMEOID:
|
|
||||||
tm = "atom";
|
|
||||||
break;
|
|
||||||
case TEXTOID:
|
|
||||||
tm = "string";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tm = "unknown type";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!Yap_unify(head, MkAtomTerm(Yap_LookupAtom(tm))) )
|
|
||||||
rc = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear( res );
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_disconnect */
|
|
||||||
static Int
|
|
||||||
c_postgres_disconnect( USES_REGS1 ) {
|
|
||||||
Term arg_db = Deref(ARG1);
|
|
||||||
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
if ((myddas_util_search_connection(db)) != NULL)
|
|
||||||
{
|
|
||||||
myddas_util_delete_connection(db);
|
|
||||||
PQfinish(db);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
static Int
|
|
||||||
c_postgres_table_write( USES_REGS1 ) {
|
|
||||||
/*
|
|
||||||
Term arg_res_set = Deref(ARG1);
|
|
||||||
PG_RES *res_set = (PG_RES *) IntegerOfTerm(arg_res_set);
|
|
||||||
|
|
||||||
mydas_util_table_write(res_set);
|
|
||||||
PG_free_result(res_set);
|
|
||||||
*/
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_postgres_get_fields_properties( USES_REGS1 ) {
|
|
||||||
Term nome_relacao = Deref(ARG1);
|
|
||||||
Term arg_db = Deref(ARG2);
|
|
||||||
Term fields_properties_list = Deref(ARG3);
|
|
||||||
Term head, list;
|
|
||||||
PGresult *res;
|
|
||||||
|
|
||||||
const char *relation = AtomName(AtomOfTerm(nome_relacao));
|
|
||||||
char sql[256];
|
|
||||||
Int num_fields,i;
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
sprintf(sql,"\\d+ `%s`",relation);
|
|
||||||
|
|
||||||
GET_POSTGRES (exec(db, sql), res );
|
|
||||||
|
|
||||||
#if MYDDAS_STATS
|
|
||||||
end = myddas_stat_end_query( start );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"),4);
|
|
||||||
|
|
||||||
list = fields_properties_list;
|
|
||||||
|
|
||||||
num_fields = PQntuples(res);
|
|
||||||
|
|
||||||
int coln;
|
|
||||||
const char *propname;
|
|
||||||
|
|
||||||
if (( coln = PQfnumber(res,"Column")) < 0)
|
|
||||||
return FALSE;
|
|
||||||
if (( propname = PQfname(res,2)) == NULL)
|
|
||||||
return FALSE;
|
|
||||||
if (!strstr(propname, "Table") || !strstr(propname, "Modifiers") )
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (i=0;i<num_fields;i++)
|
|
||||||
{
|
|
||||||
Term properties[4];
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
|
|
||||||
if (!PQgetisnull(res, i, coln)) {
|
|
||||||
const char *col = PQgetvalue(res, i, coln);
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(col));
|
|
||||||
}
|
|
||||||
if (!PQgetisnull(res, i, 2)) {
|
|
||||||
const char *props = PQgetvalue(res, i, 2);
|
|
||||||
properties[1] = MkIntegerTerm(strstr(props, "not null") != NULL); //Can't be NULL
|
|
||||||
properties[2] = MkIntegerTerm(strstr(props, "prim") != NULL); //Can't be NULL
|
|
||||||
properties[3] = MkIntegerTerm(strstr(props, "nextval") != NULL); //Can't be NULL
|
|
||||||
}
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(functor,4,properties))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c_postgres_get_next_result_set: connection * NextResSet */
|
|
||||||
static Int
|
|
||||||
c_postgres_get_next_result_set( USES_REGS1 ) {
|
|
||||||
//Term arg_db = Deref(ARG1);
|
|
||||||
//Term arg_next_res_set = Deref(ARG2);
|
|
||||||
|
|
||||||
//PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_postgres_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_postgres_change_database( USES_REGS1 ) {
|
|
||||||
/* no-op for now */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_postgres_row_cut( USES_REGS1 ) {
|
|
||||||
struct result_set *res_set=NULL;
|
|
||||||
PGconn *db = res_set->db;
|
|
||||||
|
|
||||||
res_set = AddressOfTerm(EXTRA_CBACK_CUT_ARG(Term,1));
|
|
||||||
PQclear( res_set->res );
|
|
||||||
PQfinish( db );
|
|
||||||
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, ENC_ISO_LATIN1 PASS_REGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_row: ResultSet x Arity_ListOfArgs x ListOfArgs -> */
|
|
||||||
static Int
|
|
||||||
c_postgres_row( USES_REGS1 ) {
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time used by the */
|
|
||||||
/* c_postgres_row function */
|
|
||||||
//MYDDAS_STATS_TIME start,end,total_time,diff;
|
|
||||||
MyddasULInt count = 0;
|
|
||||||
MYDDAS_STATS_TIME start, end;
|
|
||||||
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_postgres_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 = AddressOfTerm(arg_result_set);
|
|
||||||
|
|
||||||
Term head, list, NULL_atom[1];
|
|
||||||
Int arity;
|
|
||||||
list = arg_list_args;
|
|
||||||
arity = IntegerOfTerm(arg_arity);
|
|
||||||
PGconn *db = res_set->db;
|
|
||||||
if (res_set->stmt == NULL ) {
|
|
||||||
CACHE_REGS
|
|
||||||
Int i= IntegerOfTerm(EXTRA_CBACK_CUT_ARG(Term,2)), j;
|
|
||||||
Int rc = true;
|
|
||||||
// data needs to be copied to Prolog
|
|
||||||
// row by row
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
MYDDAS_STATS_TIME diff;
|
|
||||||
|
|
||||||
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy);
|
|
||||||
#endif
|
|
||||||
for (j = 0; j < arity; j++)
|
|
||||||
{
|
|
||||||
/* Ts -> List */
|
|
||||||
const char *field = PQgetvalue(res_set->res, i, j);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
rc = (rc && Yap_unify(head, cvt( field )) );
|
|
||||||
}
|
|
||||||
if (rc) {
|
|
||||||
EXTRA_CBACK_ARG(3,2)= MkIntegerTerm(i+1);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
myddas_stat_transfer_query( diff );
|
|
||||||
#endif
|
|
||||||
cut_fail();
|
|
||||||
}
|
|
||||||
// busy-waiting
|
|
||||||
if (!PQsetnonblocking(res_set->db, 1)) {
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(db));
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!PQsendQueryPrepared(res_set->db, res_set->stmt, 0, NULL, NULL, NULL, 0)) {
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(db));
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
PGresult *res;
|
|
||||||
while((res = PQgetResult(res_set->db)) != NULL);
|
|
||||||
int i;
|
|
||||||
if ((i = res_set->nrows) == 0) {
|
|
||||||
// no more data
|
|
||||||
PQfinish( res_set->db );
|
|
||||||
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 (i < res_set->nrows) {
|
|
||||||
list = arg_list_args;
|
|
||||||
Term tf;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < arity; j++)
|
|
||||||
{
|
|
||||||
/* convert data types here */
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
if (!PQgetisnull(res, i, j)) {
|
|
||||||
const char *col = PQgetvalue(res, i, j);
|
|
||||||
tf = MkAtomTerm(Yap_LookupAtom(col));
|
|
||||||
} else {
|
|
||||||
NULL_atom[0] = MkIntegerTerm(NULL_id++);
|
|
||||||
tf = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("NULL"),1),1,NULL_atom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Yap_unify(head, tf))
|
|
||||||
rc = FALSE;
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
end = myddas_stats_walltime();
|
|
||||||
|
|
||||||
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 */
|
|
||||||
} return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* MYDDAS_PG */
|
|
@ -1,798 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* *
|
|
||||||
* 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_postgres.c *
|
|
||||||
* Last rev: 22/03/05 *
|
|
||||||
* mods: *
|
|
||||||
* comments: Predicates for comunicating with a pq database system *
|
|
||||||
* *
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MYDDAS_POSTGRES
|
|
||||||
|
|
||||||
#include <libpq-fe.h>
|
|
||||||
|
|
||||||
#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_POSTGRES(f) \
|
|
||||||
{ \
|
|
||||||
res = PQ ## f; \
|
|
||||||
if (PQstatus(conn) != CONNECTION_OK) {} \
|
|
||||||
fprintf(stderr, "Error %s when calling %s, line %d\n", \
|
|
||||||
PQerrorMessage(conn), #f,__LINE__); \
|
|
||||||
exit (1); \
|
|
||||||
} \
|
|
||||||
PQclear(res); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#define GET_POSTGRES(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 {
|
|
||||||
PGconn *db;
|
|
||||||
const PGresult *res;
|
|
||||||
int i ;
|
|
||||||
int nrows;
|
|
||||||
int ncols;
|
|
||||||
} resultSet;
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_PGPreds();
|
|
||||||
void Yap_InitBackMYDDAS_PGPreds();
|
|
||||||
|
|
||||||
|
|
||||||
static Int c_PG_connect( USES_REGS1 );
|
|
||||||
static Int c_PG_disconnect( USES_REGS1 );
|
|
||||||
static Int c_PG_number_of_fields( USES_REGS1 );
|
|
||||||
static Int c_PG_get_attributes_types( USES_REGS1 );
|
|
||||||
static Int c_PG_query( USES_REGS1 );
|
|
||||||
static Int c_PG_table_write( USES_REGS1 );
|
|
||||||
static Int c_PG_row( USES_REGS1 );
|
|
||||||
static Int c_PG_row_cut( USES_REGS1 );
|
|
||||||
static Int c_PG_get_fields_properties( USES_REGS1 );
|
|
||||||
static Int c_PG_get_next_result_set( USES_REGS1 );
|
|
||||||
static Int c_PG_get_database( USES_REGS1 );
|
|
||||||
static Int c_PG_change_database( USES_REGS1 );
|
|
||||||
|
|
||||||
void Yap_InitMYDDAS_PGPreds(void)
|
|
||||||
{
|
|
||||||
/* db_dbect: Host x User x Passwd x Database x dbection x ERROR_CODE */
|
|
||||||
Yap_InitCPred("c_PG_connect", 7, c_PG_connect, 0);
|
|
||||||
|
|
||||||
/* db_number_of_fields: Relation x connection x NumberOfFields */
|
|
||||||
Yap_InitCPred("c_PG_number_of_fields",3, c_PG_number_of_fields, 0);
|
|
||||||
|
|
||||||
/* db_get_attributes_types: Relation x TypesList */
|
|
||||||
Yap_InitCPred("c_PG_get_attributes_types", 3, c_PG_get_attributes_types, 0);
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x conection */
|
|
||||||
Yap_InitCPred("c_PG_query", 5, c_PG_query, 0);
|
|
||||||
|
|
||||||
/* db_disconnect: connection */
|
|
||||||
Yap_InitCPred("c_PG_disconnect", 1,c_PG_disconnect, 0);
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
Yap_InitCPred("c_PG_table_write", 1, c_PG_table_write, 0);
|
|
||||||
|
|
||||||
/* db_get_fields_properties: PredName x connection x PropertiesList*/
|
|
||||||
Yap_InitCPred("c_PG_get_fields_properties",3,c_PG_get_fields_properties,0);
|
|
||||||
|
|
||||||
Yap_InitCPred("c_PG_get_next_result_set",2,c_PG_get_next_result_set,0);
|
|
||||||
|
|
||||||
/* c_PG_get_database: connection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_PG_get_database",2,c_PG_get_database,0);
|
|
||||||
|
|
||||||
/* c_PG_change_database: connection x DataBaseName */
|
|
||||||
Yap_InitCPred("c_PG_change_database",2,c_PG_change_database,0);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Yap_InitBackMYDDAS_PGPreds(void)
|
|
||||||
{
|
|
||||||
/* db_row: ResultSet x Arity x ListOfArgs */
|
|
||||||
Yap_InitCPredBackCut("c_PG_row", 3, sizeof(Int),
|
|
||||||
c_PG_row,
|
|
||||||
c_PG_row,
|
|
||||||
c_PG_row_cut, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_PG_connect( USES_REGS1 ) {
|
|
||||||
int i=0;
|
|
||||||
Term arg_host = Deref(ARG1);
|
|
||||||
Term arg_user = Deref(ARG2);
|
|
||||||
Term arg_passwd = Deref(ARG3);
|
|
||||||
Term arg_database = Deref(ARG4);
|
|
||||||
Term arg_port = Deref(ARG5);
|
|
||||||
Term arg_socket = Deref(ARG6);
|
|
||||||
Term arg_conn = ARG7;
|
|
||||||
Term tnone = MkAtomTerm(Yap_LookupAtom(""));
|
|
||||||
Term tzero = MkIntTerm(0);
|
|
||||||
|
|
||||||
char *keywords[8], *values[8], ports[16];
|
|
||||||
|
|
||||||
|
|
||||||
if (IsApplTerm(arg_host)) {
|
|
||||||
keywords[i] = "hostaddr";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(ArgOfTerm(1, arg_host)))->StrOfAE;
|
|
||||||
} else {
|
|
||||||
keywords[i] = "host";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_host))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_user != tnone && IsAtomTerm(arg_user)) {
|
|
||||||
keywords[i] = "user";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_user))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_passwd != tnone && IsAtomTerm(arg_passwd)) {
|
|
||||||
keywords[i] = "password";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_passwd))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_database != tnone && IsAtomTerm(arg_database)) {
|
|
||||||
keywords[i] = "dbase";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_database))->StrOfAE;
|
|
||||||
}
|
|
||||||
if (IsNonVarTerm(arg_user) && arg_port != tzero && IsIntTerm(arg_port)) {
|
|
||||||
keywords[i] = "port";
|
|
||||||
values[i++] = snprintf(ports, sizeof(ports)-1, "%d", IntOfTerm(arg_port));
|
|
||||||
} else if (IsNonVarTerm(arg_socket) && arg_socket != tempty && IsIntTerm(arg_socket)) {
|
|
||||||
keywords[i] = "port";
|
|
||||||
values[i++] = RepAtom(AtomOfTerm(arg_database))->StrOfAE;
|
|
||||||
}
|
|
||||||
keywords[i] = NULL;
|
|
||||||
values[i++] = NULL;
|
|
||||||
|
|
||||||
/* Make a connection to the database */
|
|
||||||
conn = PQconnectdbParams(keywords, values);
|
|
||||||
|
|
||||||
/* Check to see that the backend c onnection was successfully made */
|
|
||||||
if (PQstatus(conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(conn));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Yap_unify(arg_conn, MkAddressTerm(conn)))
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Criar um novo no na lista de ligacoes*/
|
|
||||||
new = myddas_util_add_connection(conn,NULL,MYDDAS_API);
|
|
||||||
|
|
||||||
if (new == NULL){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("ERROR: ** c_db_my_connect ** Error allocating memory\n");
|
|
||||||
#endif
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static MYDDAS_STATS_TIME
|
|
||||||
myddas_stat_init_query( PG *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 PG 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 PG 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* measure transfer time */
|
|
||||||
static void
|
|
||||||
myddas_stat_transfer_query( MYDDAS_STATS_TIME diff )
|
|
||||||
{
|
|
||||||
/* Measure time spent by the PG Server
|
|
||||||
transferring the result of the last query
|
|
||||||
back to the client */
|
|
||||||
start = myddas_stats_walltime();
|
|
||||||
/* Measure time spent by the PG 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, PG_(use or store)_result()
|
|
||||||
returns a NULL pointer*/
|
|
||||||
|
|
||||||
/* This is only works if we use PG_store_result */
|
|
||||||
MyddasUInt numberRows = PG_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 = PG_num_fields(res_set);
|
|
||||||
PG_ROW row;
|
|
||||||
MyddasULInt i;
|
|
||||||
total=0;
|
|
||||||
while ((row = PG_fetch_row(res_set)) != NULL){
|
|
||||||
PG_field_seek(res_set,0);
|
|
||||||
|
|
||||||
for(i=0;i<number_fields;i++){
|
|
||||||
if (row[i] != NULL)
|
|
||||||
total = total + strlen(row[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x connection */
|
|
||||||
static Int
|
|
||||||
c_PQ_query( USES_REGS1 ) {
|
|
||||||
Term arg_sql_query = Deref(ARG1);
|
|
||||||
Term arg_result_set = Deref(ARG2);
|
|
||||||
Term arg_db = Deref(ARG3);
|
|
||||||
Term arg_mode = Deref(ARG4);
|
|
||||||
Term arg_arity = ARG5;
|
|
||||||
|
|
||||||
char *sql = AtomName(AtomOfTerm(arg_sql_query));
|
|
||||||
char *mode = AtomName(AtomOfTerm(arg_mode));
|
|
||||||
PGresult *res;
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
const char *stmt;
|
|
||||||
|
|
||||||
MYDDAS_STATS_TIME start, end;
|
|
||||||
int length=strlen(sql);
|
|
||||||
struct result_set *rs = malloc(sizeof( struct result_set));
|
|
||||||
if (!rs)
|
|
||||||
return FALSE;
|
|
||||||
rs->db = db;
|
|
||||||
rs->i = 0;
|
|
||||||
|
|
||||||
start = myddas_stat_init_query( db );
|
|
||||||
|
|
||||||
char *stmt = new_stmt();
|
|
||||||
|
|
||||||
/* Send query to server and process it */
|
|
||||||
if (strcmp(mode,"store_result")!=0) {
|
|
||||||
// Leave data for extraction
|
|
||||||
CALL_POSTGRES (prepare(db, stmt, sql, 0, NULL) );
|
|
||||||
res = GET_POSTGRES (PQdescribePrepared(db, stmt) );
|
|
||||||
rs->stmt = stmt;
|
|
||||||
rs->res_set = NULL;
|
|
||||||
rs->nrows = -1;
|
|
||||||
rs->length = PQnfields(res);
|
|
||||||
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;
|
|
||||||
|
|
||||||
res = GET_POSTGRES (PGexec(db, sql) );
|
|
||||||
|
|
||||||
end = myddas_stat_end_query( start );
|
|
||||||
length = PGnfields(res);
|
|
||||||
nrows = PGntuples(res);
|
|
||||||
//INSERT statements don't return any res_set
|
|
||||||
if (nrows == 0) {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (!Yap_unify(arg_arity, MkIntegerTerm(nrows))){
|
|
||||||
/*
|
|
||||||
* Should PGclear PGresult whenever it is no longer needed to avoid memory
|
|
||||||
* leaks
|
|
||||||
*/
|
|
||||||
free(rs);
|
|
||||||
PGclear(res);
|
|
||||||
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);
|
|
||||||
PGclear(res);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_PG_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));
|
|
||||||
PG *db = AddressOfTerm(arg_db);
|
|
||||||
PG_stmt *stmt;
|
|
||||||
|
|
||||||
char sql[256];
|
|
||||||
|
|
||||||
snprintf(sql, 255, "SELECT * FROM TABLE `%s`",relation);
|
|
||||||
// Leave data for extraction
|
|
||||||
CALL_POSTGRES (prepare(db, stmt, sql, 0, NULL) );
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
|
|
||||||
int nrows = GET_POSTGRES (PGntuples(stmt) );
|
|
||||||
|
|
||||||
PGClear( stmt );
|
|
||||||
|
|
||||||
return Yap_unify(arg_fields, MkIntegerTerm( nrows ));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* db_get_attributes_types: RelName x connection -> TypesList */
|
|
||||||
static Int
|
|
||||||
c_PG_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));
|
|
||||||
PG *db = AddressOfTerm(arg_db);
|
|
||||||
char sql[256];
|
|
||||||
int row;
|
|
||||||
|
|
||||||
PG_stmt *stmt;
|
|
||||||
Int rc = TRUE;
|
|
||||||
|
|
||||||
sprintf(sql,"SELECT * FROM TABLE `%s`",relation);
|
|
||||||
// Leave data for extraction
|
|
||||||
res = GET_POSTGRES (PGprepare(db, stmt, sql, 0, NULL) );
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
|
|
||||||
|
|
||||||
int cols = PGnfields( res );
|
|
||||||
|
|
||||||
list = arg_types_list;
|
|
||||||
|
|
||||||
for (col = 0; col < cols; col++)
|
|
||||||
{
|
|
||||||
const char *tm;
|
|
||||||
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
rc = (
|
|
||||||
rc && Yap_unify(head, MkAtomTerm(Yap_LookupAtom(PGfname(res, col))) ) );
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
Oid type = PGftype(res, col);
|
|
||||||
switch(type) {
|
|
||||||
case BYTEOID:
|
|
||||||
case CHAROID:
|
|
||||||
case INT2OID:
|
|
||||||
case INT4OID:
|
|
||||||
case INT8OID:
|
|
||||||
tm = "integer";
|
|
||||||
break;
|
|
||||||
case FLOAT4OID:
|
|
||||||
case FLOAT8OID:
|
|
||||||
tm = "real";
|
|
||||||
break;
|
|
||||||
case NAMEOID:
|
|
||||||
tm = "atom";
|
|
||||||
break;
|
|
||||||
case TEXTOID:
|
|
||||||
tm = "string";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tm = "unknown type";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!Yap_unify(head, MkAtomTerm(Yap_LookupAtom(tm))) )
|
|
||||||
rc = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGClear( stmt );
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_disconnect */
|
|
||||||
static Int
|
|
||||||
c_PG_disconnect( USES_REGS1 ) {
|
|
||||||
Term arg_db = Deref(ARG1);
|
|
||||||
|
|
||||||
PG *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
if ((myddas_util_search_connection(db)) != NULL)
|
|
||||||
{
|
|
||||||
myddas_util_delete_connection(db);
|
|
||||||
PGfinish(db);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* db_table_write: Result Set */
|
|
||||||
static Int
|
|
||||||
c_PG_table_write( USES_REGS1 ) {
|
|
||||||
/*
|
|
||||||
Term arg_res_set = Deref(ARG1);
|
|
||||||
PG_RES *res_set = (PG_RES *) IntegerOfTerm(arg_res_set);
|
|
||||||
|
|
||||||
mydas_util_table_write(res_set);
|
|
||||||
PG_free_result(res_set);
|
|
||||||
*/
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_PG_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;
|
|
||||||
PGconn *db = (PG *) (IntegerOfTerm(arg_db));
|
|
||||||
|
|
||||||
sprintf(sql,"\\d+ `%s`",relation);
|
|
||||||
|
|
||||||
res = GET_POSTGRES (PGexec(db, sql) );
|
|
||||||
|
|
||||||
end = myddas_stat_end_query( start );
|
|
||||||
Functor functor = Yap_MkFunctor(Yap_LookupAtom("property"),4);
|
|
||||||
|
|
||||||
Term properties[4];
|
|
||||||
|
|
||||||
list = fields_properties_list;
|
|
||||||
|
|
||||||
num_fields = PGntuples(res);
|
|
||||||
|
|
||||||
if (( coln = PGfnumber(res,"Column")) < 0)
|
|
||||||
return FALSE;
|
|
||||||
if (( propname = PGfname(res,2)) == NULL)
|
|
||||||
return FALSE;
|
|
||||||
if (!strstr(propname, "Table") || !strstr(propname, "Modifiers") )
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (i=0;i<num_fields;i++)
|
|
||||||
{
|
|
||||||
bool not_null, prim, auto_inc;
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
|
|
||||||
if (!PGgetisnull(res, i, coln)) {
|
|
||||||
const char *col = PGgetvalue(res, i, coln);
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(col));
|
|
||||||
}
|
|
||||||
if (!PGgetisnull(res, i, 2)) {
|
|
||||||
const char *props = PGgetvalue(res, i, 2);
|
|
||||||
properties[1] = MkIntegerTerm(strstr(props, "not null") != NULL); //Can't be NULL
|
|
||||||
properties[2] = MkIntegerTerm(strstr(props, "prim") != NULL); //Can't be NULL
|
|
||||||
properties[3] = MkIntegerTerm(strstr(props, "nextval") != NULL); //Can't be NULL
|
|
||||||
}
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(functor,4,properties))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PGclear(res);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c_PG_get_next_result_set: connection * NextResSet */
|
|
||||||
static Int
|
|
||||||
c_PG_get_next_result_set( USES_REGS1 ) {
|
|
||||||
Term arg_db = Deref(ARG1);
|
|
||||||
Term arg_next_res_set = Deref(ARG2);
|
|
||||||
|
|
||||||
PGconn *db = AddressOfTerm(arg_db);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_PG_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_PG_change_database( USES_REGS1 ) {
|
|
||||||
/* no-op for now */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Int
|
|
||||||
c_PG_row_cut( USES_REGS1 ) {
|
|
||||||
struct result_set *res_set=NULL;
|
|
||||||
PG *db = res_set->db;
|
|
||||||
|
|
||||||
res_set = AddressOfTerm(EXTRA_CBACK_CUT_ARG(Term,1));
|
|
||||||
PQclear( res_set->res );
|
|
||||||
PQfinish( db );
|
|
||||||
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_PG_row( USES_REGS1 ) {
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* Measure time used by the */
|
|
||||||
/* c_PG_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_PG_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 = AddressOfTerm(arg_result_set);
|
|
||||||
|
|
||||||
Term head, list, NULL_atom[1];
|
|
||||||
Int arity;
|
|
||||||
list = arg_list_args;
|
|
||||||
arity = IntegerOfTerm(arg_arity);
|
|
||||||
PG *db = res_set->db;
|
|
||||||
if (res_set->stmt == NULL ) {
|
|
||||||
CACHE_REGS
|
|
||||||
Int i= IntegerOfTerm(EXTRA_CBACK_CUT_ARG(Term,2)), j;
|
|
||||||
Int rc = true;
|
|
||||||
// data needs to be copied to Prolog
|
|
||||||
// row by row
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
MYDDAS_STATS_TIME diff;
|
|
||||||
|
|
||||||
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy);
|
|
||||||
#endif
|
|
||||||
for (j = 0; j < arity; j++)
|
|
||||||
{
|
|
||||||
/* 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) {
|
|
||||||
EXTRA_CBACK_ARG(3,2)= MkIntegerTerm(i+1);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
myddas_stat_transfer_query( diff );
|
|
||||||
#endif
|
|
||||||
cut_fail();
|
|
||||||
}
|
|
||||||
// busy-waiting
|
|
||||||
if (!PQsetnonblocking(res_set->db, 1)) {
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(conn));
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!PQsendQueryPrepared(res_set->db, res_set->stmt, 0, NULL, NULL, NULL, 0)) {
|
|
||||||
fprintf(stderr, "Connection to database failed: %s",
|
|
||||||
PQerrorMessage(conn));
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
int res;
|
|
||||||
while((res = PQgetResult(res_set->db)) != NULL);
|
|
||||||
if (i == res_set->nrows) {
|
|
||||||
// no more data
|
|
||||||
PQfinish( res_set->db ) );
|
|
||||||
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 (i < res_ser->nrows) {
|
|
||||||
list = arg_list_args;
|
|
||||||
Term tf;
|
|
||||||
|
|
||||||
for (j = 0; j < arity; j++)
|
|
||||||
{
|
|
||||||
/* convert data types here */
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
|
|
||||||
if (!PGgetisnull(res, i, j)) {
|
|
||||||
const char *col = PGgetvalue(res, i, j);
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(col));
|
|
||||||
} else {
|
|
||||||
NULL_atom[0] = MkIntegerTerm(NULL_id++);
|
|
||||||
tf = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("NULL"),1),1,NULL_atom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Yap_unify(head, tf))
|
|
||||||
rc = FALSE;
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
end = myddas_stats_walltime();
|
|
||||||
|
|
||||||
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_INTERNAL, TermNil, "PG: %s", PG_errmsg( db ) );
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* MYDDAS_PG */
|
|
@ -1,758 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* *
|
|
||||||
* 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 <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#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_SQLITE3Preds(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_SQLITE3Preds(void)
|
|
||||||
{
|
|
||||||
/* db_dbect: Host x User x Passwd x Database x dbection x ERROR_CODE */
|
|
||||||
Yap_InitCPred("c_sqlite3_connect", 4, 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 = ARG4;
|
|
||||||
|
|
||||||
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,API_SQLITE3);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
/* measure transfer time */
|
|
||||||
static void
|
|
||||||
myddas_stat_transfer_query( MYDDAS_STATS_TIME diff )
|
|
||||||
{
|
|
||||||
/* 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_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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* db_query: SQLQuery x ResultSet x connection */
|
|
||||||
static Int
|
|
||||||
c_sqlite3_query( USES_REGS1 ) {
|
|
||||||
Term arg_sql_query = Deref(ARG1);
|
|
||||||
Term arg_result_set = Deref(ARG2);
|
|
||||||
Term arg_db = Deref(ARG3);
|
|
||||||
Term arg_mode = Deref(ARG4);
|
|
||||||
Term arg_arity = Deref(ARG5);
|
|
||||||
|
|
||||||
char *sql = AtomName(AtomOfTerm(arg_sql_query));
|
|
||||||
char *mode = AtomName(AtomOfTerm(arg_mode));
|
|
||||||
sqlite3 *db = AddressOfTerm(arg_db);
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
|
|
||||||
MYDDAS_STATS_TIME start, end;
|
|
||||||
int length=strlen(sql);
|
|
||||||
struct result_set *rs = malloc(sizeof( struct result_set));
|
|
||||||
if (!rs)
|
|
||||||
return FALSE;
|
|
||||||
rs->db = db;
|
|
||||||
|
|
||||||
start = myddas_stat_init_query( db );
|
|
||||||
|
|
||||||
/* Send query to server and process it */
|
|
||||||
if (strcmp(mode,"store_result")!=0) {
|
|
||||||
// Leave data for extraction
|
|
||||||
printf(" SQL 0: %s\n", sql);
|
|
||||||
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 `%s`",relation);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
printf(" SQL 1: %s\n", 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 `%s`",relation);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
printf(" SQL 3: %s\n", 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:
|
|
||||||
default:
|
|
||||||
tm = "";
|
|
||||||
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 `%s`",relation);
|
|
||||||
|
|
||||||
/* executar a query SQL */
|
|
||||||
printf(" SQL 4: %s\n", 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;i<num_fields;i++)
|
|
||||||
{
|
|
||||||
int not_null, prim, auto_inc;
|
|
||||||
|
|
||||||
head = HeadOfTerm(list);
|
|
||||||
|
|
||||||
const char *col = sqlite3_column_name(stmt, i);
|
|
||||||
properties[0] = MkAtomTerm(Yap_LookupAtom(col));
|
|
||||||
|
|
||||||
CALL_SQLITE (table_column_metadata(db, NULL, relation, col, NULL, NULL,
|
|
||||||
¬_null, &prim, &auto_inc) );
|
|
||||||
properties[1] = MkIntegerTerm(not_null); //Can't be NULL
|
|
||||||
|
|
||||||
properties[2] = MkIntegerTerm(prim); //It''s a primary key
|
|
||||||
|
|
||||||
properties[3] = MkIntegerTerm(auto_inc);
|
|
||||||
|
|
||||||
list = TailOfTerm(list);
|
|
||||||
if (!Yap_unify(head, Yap_MkApplTerm(functor,4,properties))){
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c_sqlite3_get_next_result_set: connection * NextResSet */
|
|
||||||
static Int
|
|
||||||
c_sqlite3_get_next_result_set( USES_REGS1 ) {
|
|
||||||
Term arg_db = Deref(ARG1);
|
|
||||||
Term arg_next_res_set = Deref(ARG2);
|
|
||||||
|
|
||||||
sqlite3 *db = (sqlite3 *) (IntegerOfTerm(arg_db));
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
|
|
||||||
if ((stmt = sqlite3_next_stmt(db, NULL)) != NULL){
|
|
||||||
struct result_set *rs = malloc(sizeof( struct result_set));
|
|
||||||
if (!rs)
|
|
||||||
return FALSE;
|
|
||||||
rs->stmt = 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;
|
|
||||||
|
|
||||||
res_set = AddressOfTerm(CBACK_CUT_ARG(1));
|
|
||||||
sqlite3 *db = res_set->db;
|
|
||||||
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 = AddressOfTerm(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_ARG(3,2));
|
|
||||||
Int rc = true;
|
|
||||||
// data needs to be copied to Prolog
|
|
||||||
// row by row
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
MYDDAS_STATS_TIME diff;
|
|
||||||
|
|
||||||
MYDDAS_STATS_INITIALIZE_TIME_STRUCT(diff,time_copy);
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
myddas_stat_transfer_query( diff );
|
|
||||||
#endif
|
|
||||||
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_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_INTERNAL, TermNil, "sqlite3: %s", sqlite3_errmsg( db ) );
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* MYDDAS_sqlite3 */
|
|
@ -1,7 +1,12 @@
|
|||||||
#ifndef __MYDDAS_STRUCTS_H__
|
#ifndef __MYDDAS_STRUCTS_H__
|
||||||
#define __MYDDAS_STRUCTS_H__
|
#define __MYDDAS_STRUCTS_H__
|
||||||
|
|
||||||
#include "myddas.h"
|
#include "myddas_types.h"
|
||||||
|
|
||||||
|
typedef struct myddas_util_query *MYDDAS_UTIL_QUERY;
|
||||||
|
typedef struct myddas_list_connection *MYDDAS_UTIL_CONNECTION;
|
||||||
|
typedef struct myddas_list_preds *MYDDAS_UTIL_PREDICATE;
|
||||||
|
|
||||||
#ifdef MYDDAS_STATS
|
#ifdef MYDDAS_STATS
|
||||||
#include "myddas_statistics_structs.h"
|
#include "myddas_statistics_structs.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#if defined MYDDAS_ODBC || defined MYDDAS_MYSQL || defined MYDDAS_SQLITE3
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifdef MYDDAS_SQLITE3
|
#ifdef MYDDAS_SQLITE3
|
||||||
@ -7,11 +5,6 @@
|
|||||||
#endif /*MYDDAS_MYSQL*/
|
#endif /*MYDDAS_MYSQL*/
|
||||||
#include "Yap.h"
|
#include "Yap.h"
|
||||||
#include "cut_c.h"
|
#include "cut_c.h"
|
||||||
#include "myddas.h"
|
|
||||||
#include "myddas_structs.h"
|
|
||||||
#ifdef MYDDAS_STATS
|
|
||||||
#include "myddas_statistics.h"
|
|
||||||
#endif
|
|
||||||
#ifdef MYDDAS_ODBC
|
#ifdef MYDDAS_ODBC
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#endif /*MYDDAS_ODBC*/
|
#endif /*MYDDAS_ODBC*/
|
||||||
@ -19,18 +12,7 @@
|
|||||||
#include <mysql/mysql.h>
|
#include <mysql/mysql.h>
|
||||||
#endif /*MYDDAS_MYSQL*/
|
#endif /*MYDDAS_MYSQL*/
|
||||||
|
|
||||||
|
#include "myddas_util.h"
|
||||||
|
|
||||||
/* Search for the predicate in the given predicate list*/
|
|
||||||
static MYDDAS_UTIL_PREDICATE
|
|
||||||
myddas_util_find_predicate(const char *, Int , const char *, MYDDAS_UTIL_PREDICATE);
|
|
||||||
/* Deletes a predicate list */
|
|
||||||
static void
|
|
||||||
myddas_util_delete_predicate_list(MYDDAS_UTIL_PREDICATE);
|
|
||||||
|
|
||||||
/* Prints a error message */
|
|
||||||
static void
|
|
||||||
myddas_util_error_message(char *,Int,char *);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MYDDAS_MYSQL
|
#ifdef MYDDAS_MYSQL
|
||||||
@ -221,7 +203,6 @@ n_print(Int n, char c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static
|
|
||||||
void myddas_util_error_message(char *message ,Int line,char *file){
|
void myddas_util_error_message(char *message ,Int line,char *file){
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf ("ERROR: %s at line %d in file %s\n",message,(int)line,file);
|
printf ("ERROR: %s at line %d in file %s\n",message,(int)line,file);
|
||||||
@ -230,7 +211,7 @@ void myddas_util_error_message(char *message ,Int line,char *file){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MYDDAS_UTIL_PREDICATE
|
MYDDAS_UTIL_PREDICATE
|
||||||
myddas_util_find_predicate(const char *pred_name, Int pred_arity,
|
myddas_util_find_predicate(const char *pred_name, Int pred_arity,
|
||||||
const char *pred_module, MYDDAS_UTIL_PREDICATE list){
|
const char *pred_module, MYDDAS_UTIL_PREDICATE list){
|
||||||
|
|
||||||
@ -243,7 +224,7 @@ myddas_util_find_predicate(const char *pred_name, Int pred_arity,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
myddas_util_delete_predicate_list(MYDDAS_UTIL_PREDICATE preds_list){
|
myddas_util_delete_predicate_list(MYDDAS_UTIL_PREDICATE preds_list){
|
||||||
CACHE_REGS
|
CACHE_REGS
|
||||||
MYDDAS_UTIL_PREDICATE to_delete = NULL;
|
MYDDAS_UTIL_PREDICATE to_delete = NULL;
|
||||||
@ -402,8 +383,3 @@ void check_int( void ){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /*defined MYDDAS_ODBC || defined MYDDAS_MYSQL*/
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user