first cut at postgres support
This commit is contained in:
parent
9895ec63d0
commit
a24c90334f
@ -47,6 +47,7 @@ MYDDAS_HEADERS= \
|
||||
MYDDAS_SOURCES= \
|
||||
myddas_mysql.c \
|
||||
myddas_odbc.c \
|
||||
myddas_postgres.c \
|
||||
myddas_sqlite3.c \
|
||||
myddas_util.c \
|
||||
myddas_initialization.c \
|
||||
@ -59,8 +60,10 @@ MYDDAS_PROLOG= \
|
||||
$(srcdir)/pl/myddas.ypp \
|
||||
$(srcdir)/pl/myddas_assert_predicates.ypp \
|
||||
$(srcdir)/pl/myddas_mysql.ypp \
|
||||
$(srcdir)/pl/myddas_top_level.ypp \
|
||||
$(srcdir)/pl/myddas_sqlite3.ypp \
|
||||
$(srcdir)/pl/myddas_top_level.ypp \
|
||||
$(srcdir)/pl/myddas_errors.ypp \
|
||||
$(srcdir)/pl/myddas_postgres.ypp \
|
||||
$(srcdir)/pl/myddas_prolog2sql.ypp \
|
||||
$(srcdir)/pl/myddas_util_predicates.ypp \
|
||||
$(srcdir)/pl/myddas_prolog2sql_optimizer.ypp
|
||||
@ -103,4 +106,3 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
|
@ -61,6 +61,20 @@ AC_ARG_WITH(sqlite3,
|
||||
fi,
|
||||
[yap_cv_sqlite3=/usr])
|
||||
|
||||
AC_ARG_WITH(postgres,
|
||||
[ --with-postgres[[=DIR]] with an POSTGRES library],
|
||||
if test "$withval" = yes; then
|
||||
yap_cv_postgres=/usr
|
||||
elif test "$withval" = no; then
|
||||
yap_cv_postgres=no
|
||||
else
|
||||
yap_cv_postgres=$withval
|
||||
LDFLAGS="$LDFLAGS -L${yap_cv_postgres}/lib "
|
||||
CPPFLAGS="$CPPFLAGS -I${yap_cv_postgres}/include "
|
||||
MYDDAS_CPPFLAGS="$MYDDAS_CPPFLAGS -I${yap_cv_postgres}/include "
|
||||
fi,
|
||||
[yap_cv_postgres=/usr])
|
||||
|
||||
AC_ARG_ENABLE(myddas-stats,
|
||||
[ --enable-myddas-stats enable the MYDDAS library statistics support],
|
||||
if test "$yap_cv_myddas" = no; then
|
||||
@ -136,6 +150,18 @@ then
|
||||
YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_SQLITE3"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(pq, PQconnectdbParams,
|
||||
LIBS="-lpq $LIBS"
|
||||
havelib=yes)
|
||||
|
||||
AC_CHECK_HEADERS(libpq-fe.h, [], [yap_cv_postgres="no"])
|
||||
if test "$yap_cv_postgres" != no
|
||||
then
|
||||
use_myddas=true
|
||||
YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_POSTGRES"
|
||||
fi
|
||||
|
||||
|
||||
if test "$myddasstats" = "yes"
|
||||
then
|
||||
YAP_EXTRAS="$YAP_EXTRAS -DMYDDAS_STATS"
|
||||
|
888
packages/myddas/myddas_postgres.c
Normal file
888
packages/myddas/myddas_postgres.c
Normal file
@ -0,0 +1,888 @@
|
||||
/*************************************************************************
|
||||
* *
|
||||
* 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;
|
||||
|
||||
char *sql = AtomName(AtomOfTerm(arg_sql_query));
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
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 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) {
|
||||
// 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 */
|
@ -40,7 +40,8 @@ typedef enum myddas_api {
|
||||
API_MYSQL = 0,
|
||||
API_ODBC = 1,
|
||||
API_SQLITE3 = 2,
|
||||
API_POSTGRES } MYDDAS_API;
|
||||
API_POSTGRES =3
|
||||
} MYDDAS_API;
|
||||
|
||||
struct myddas_list_connection {
|
||||
void *connection;
|
||||
|
@ -884,6 +884,20 @@ db_open(mysql,Connection,Host/Db,User,Password) :-
|
||||
db_open(mysql,Connection,Host/Db/0/_,User,Password). % 0 is default port and Var to be NULL, the default socket
|
||||
#endif
|
||||
|
||||
#ifdef MYDDAS_POSTGRES
|
||||
db_open(postgres,Connection,Host/Db/Port/Socket,User,Password) :- !,
|
||||
'$error_checks'(db_open(postgres,Connection,Host/Db/Port/Socket,User,Password)),
|
||||
c_db_my_connect(Host,User,Password,Db,Port,Socket,Con),
|
||||
set_value(Connection,Con).
|
||||
db_open(postgres,Connection,Host/Db/Port,User,Password) :-
|
||||
integer(Port),!,
|
||||
db_open(postgres,Connection,Host/Db/Port/_,User,Password). % Var to be NULL, the default socket
|
||||
db_open(postgres,Connection,Host/Db/Socket,User,Password) :- !,
|
||||
db_open(postgres,Connection,Host/Db/0/Socket,User,Password). % 0 is default port
|
||||
db_open(postgres,Connection,Host/Db,User,Password) :-
|
||||
db_open(postgres,Connection,Host/Db/0/_,User,Password). % 0 is default port and Var to be NULL, the default socket
|
||||
#endif
|
||||
|
||||
#ifdef MYDDAS_ODBC
|
||||
db_open(odbc,Connection,ODBCEntry,User,Password) :-
|
||||
'$error_checks'(db_open(odbc,Connection,ODBCEntry,User,Password)),
|
||||
@ -916,6 +930,10 @@ db_close(Connection) :-
|
||||
c_db_connection_type(Con,ConType),
|
||||
( ConType == mysql ->
|
||||
c_db_my_disconnect(Con)
|
||||
;ConType == postgres ->
|
||||
c_postgres_disconnect(Con)
|
||||
;ConType == sqlite3 ->
|
||||
c_sqlite3_disconnect(Con)
|
||||
;
|
||||
c_db_odbc_disconnect(Con)
|
||||
),
|
||||
@ -1016,6 +1034,12 @@ db_sql(Connection,SQL,LA):-
|
||||
( ConType == mysql ->
|
||||
db_my_result_set(Mode),
|
||||
c_db_my_query(SQL,ResultSet,Con,Mode,Arity)
|
||||
;ConType == postgres ->
|
||||
postgres_result_set(Mode),
|
||||
c_postgres_query(SQL,ResultSet,Con,Mode,Arity)
|
||||
;ConType == sqlite3 ->
|
||||
sqlite3_result_set(Mode),
|
||||
c_sqlite3_query(SQL,ResultSet,Con,Mode,Arity)
|
||||
;
|
||||
c_db_odbc_number_of_fields_in_query(SQL,Con,Arity)
|
||||
),
|
||||
@ -1119,6 +1143,12 @@ db_assert(Connection,PredName):-
|
||||
( ConType == mysql ->
|
||||
db_my_result_set(Mode),
|
||||
c_db_my_query(SQL,_,Con,Mode,_)
|
||||
;ConType == postgres ->
|
||||
postgres_result_set(Mode),
|
||||
c_postgres_query(SQL,_,Con,Mode,_)
|
||||
;ConType == sqlite3 ->
|
||||
sqlite3_result_set(Mode),
|
||||
c_sqlite3_query(SQL,_,Con,Mode,_)
|
||||
;
|
||||
c_db_odbc_query(SQL,_,_,_,Con)
|
||||
).
|
||||
@ -1142,6 +1172,12 @@ db_create_table(Connection,TableName,FieldsInf):-
|
||||
( ConType == mysql ->
|
||||
db_my_result_set(Mode),
|
||||
c_db_my_query(FinalSQL,_,Con,Mode,_)
|
||||
;ConType == posgres ->
|
||||
postgres_result_set(Mode),
|
||||
c_postsgres_query(FinalSQL,_,Con,Mode,_)
|
||||
;ConType == sqlite3 ->
|
||||
sqlite3_result_set(Mode),
|
||||
c_sqlite3_query(FinalSQL,_,Con,Mode,_)
|
||||
;
|
||||
c_db_odbc_query(FinalSQL,_,_,_,Con)
|
||||
).
|
||||
@ -1248,6 +1284,10 @@ db_number_of_fields(Connection,RelationName,Arity) :-
|
||||
c_db_connection_type(Con,ConType),
|
||||
( ConType == mysql ->
|
||||
c_db_my_number_of_fields(RelationName,Con,Arity)
|
||||
;ConType == postgres ->
|
||||
c_postgres_number_of_fields(RelationName,Con,Arity)
|
||||
;ConType == sqlite3 ->
|
||||
c_sqlite3_number_of_fields(RelationName,Con,Arity)
|
||||
;
|
||||
c_db_odbc_number_of_fields(RelationName,Con,Arity)
|
||||
).
|
||||
|
@ -240,9 +240,12 @@ table_arity( Con, ConType, RelationName, Arity ) :-
|
||||
( ConType == mysql ->
|
||||
c_db_my_number_of_fields(RelationName,Con,Arity)
|
||||
;
|
||||
ConType == odbc ->
|
||||
c_db_odbc_number_of_fields(RelationName,Con,Arity)
|
||||
ConType == postgres ->
|
||||
c_postgres_number_of_fields(RelationName,Con,Arity)
|
||||
;
|
||||
ConType == odbc ->
|
||||
c_db_odbc_number_of_fields(RelationName,Con,Arity)
|
||||
;
|
||||
c_sqlite3_number_of_fields(RelationName,Con,Arity))
|
||||
.
|
||||
|
||||
@ -250,6 +253,9 @@ table_arity( Con, ConType, RelationName, Arity ) :-
|
||||
table_attributes( mysql, Con, RelationName, TypesList ) :-
|
||||
c_db_my_get_attributes_types(RelationName,Con,TypesList).
|
||||
|
||||
table_attributes( postgres, Con, RelationName, TypesList ) :-
|
||||
c_postgres_get_attributes_types(RelationName,Con,TypesList).
|
||||
|
||||
table_attributes( odbc, Con, RelationName, TypesList ) :-
|
||||
c_db_odbc_get_attributes_types(RelationName,Con,TypesList).
|
||||
|
||||
@ -268,6 +274,16 @@ table_access_predicate( mysql, Con, Arity, P, LA, M,
|
||||
!,
|
||||
c_db_my_row(ResultSet,Arity,LA) ))).
|
||||
|
||||
table_access_predicate( postgres, Con, Arity, P, LA, M,
|
||||
( P :- M:('$copy_term_nv'(P,[],G,_),
|
||||
translate(G,G,Code),
|
||||
queries_atom(Code,FinalSQL),
|
||||
db_my_result_set(Mode),
|
||||
'$write_or_not'(FinalSQL),
|
||||
c_postgres_query(FinalSQL,ResultSet,Con,Mode,_),
|
||||
!,
|
||||
c_postgsres_row(ResultSet,Arity,LA) ))).
|
||||
|
||||
table_access_predicate( sqlite3, Con, Arity, P, LA, M,
|
||||
( P :- M:('$copy_term_nv'(P,[],G,_),
|
||||
translate(G,G,Code),
|
||||
@ -299,6 +315,15 @@ table_insert( mysql, Con, RelationName, TypesList, Predicate, LA,
|
||||
c_db_my_query(SQL,_,Con,Mode,_)))
|
||||
).
|
||||
|
||||
table_insert( postgres, Con, RelationName, TypesList, Predicate, LA,
|
||||
( Predicate :- myddas_assert_predicates:
|
||||
( '$get_values_for_insert'(TypesList,LA,ValuesList),
|
||||
'$make_atom'(['INSERT INTO `',RelationName,'` VALUES ('|ValuesList],SQL),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'(SQL),
|
||||
c_postgres_query(SQL,_,Con,Mode,_)))
|
||||
).
|
||||
|
||||
table_insert( sqlite3, Con, RelationName, TypesList, Predicate, LA,
|
||||
( Predicate :- myddas_assert_predicates:
|
||||
( '$get_values_for_insert'(TypesList,LA,ValuesList),
|
||||
@ -329,6 +354,18 @@ table_view( mysql, Con, CopyView, CopyGoal, Arity, LA, M,
|
||||
!,
|
||||
c_db_my_row(ResultSet,Arity,LA) ))).
|
||||
|
||||
table_view( postgres, Con, CopyView, CopyGoal, Arity, LA, M,
|
||||
( CopyView :-
|
||||
M:( '$copy_term_nv'(CopyView,[],ProjT,Dic),
|
||||
'$copy_term_nv'(CopyGoal,Dic,NG,_),
|
||||
translate(ProjT,NG,Code),
|
||||
queries_atom(Code,FinalSQL),
|
||||
db_my_result_set(Mode),
|
||||
'$write_or_not'(FinalSQL),
|
||||
c_postgres_query(FinalSQL,ResultSet,Con,Mode,_),
|
||||
!,
|
||||
c_postgres_row(ResultSet,Arity,LA) ))).
|
||||
|
||||
table_view( odbc, Con, CopyView, CopyGoal, Arity, LA, M,
|
||||
( CopyView :-
|
||||
M:( '$copy_term_nv'(CopyView,[],ProjT,Dic),
|
||||
|
248
packages/myddas/pl/myddas_postgres.ypp
Normal file
248
packages/myddas/pl/myddas_postgres.ypp
Normal file
@ -0,0 +1,248 @@
|
||||
/*************************************************************************
|
||||
* *
|
||||
* 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.yap *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: Postgres Predicates *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef MYDDAS_POSTGRES
|
||||
|
||||
:- module(myddas_postgres,[
|
||||
postgres_result_set/1,
|
||||
postgres_datalog_describe/1,
|
||||
postgres_datalog_describe/2,
|
||||
postgres_describe/3,
|
||||
postgres_describe/2,
|
||||
postgres_datalog_show_tables/1,
|
||||
postgres_datalog_show_tables/0,
|
||||
postgres_show_tables/2,
|
||||
postgres_show_tables/1,
|
||||
postgres_show_database/2,
|
||||
postgres_show_databases/2,
|
||||
postgres_show_databases/1,
|
||||
postgres_change_database/2,
|
||||
postgres_call_procedure/4,
|
||||
postgres_call_procedure/3,
|
||||
postgres_sql_mode/1,
|
||||
postgres_sql_mode/2,
|
||||
postgres_sql_mode/1,
|
||||
postgres_sql_mode/2
|
||||
]).
|
||||
|
||||
:- use_module(myddas,[
|
||||
postgres_sql/3
|
||||
]).
|
||||
|
||||
:- use_module(myddas_errors,[
|
||||
'$error_checks'/1
|
||||
]).
|
||||
|
||||
:- use_module(myddas_util_predicates,[
|
||||
'$get_value'/2,
|
||||
'$make_atom'/2,
|
||||
'$make_atom_args'/2,
|
||||
'$make_a_list'/2,
|
||||
'$write_or_not'/1
|
||||
]).
|
||||
|
||||
|
||||
%--------------------------------------------------------
|
||||
% Public Predicates
|
||||
%--------------------------------------------------------
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_result_set/1
|
||||
%
|
||||
%
|
||||
postgres_result_set(X):-
|
||||
var(X),!,
|
||||
get_value(postgres_result_set,X).
|
||||
postgres_result_set(use_result):-
|
||||
set_value(postgres_result_set,use_result).
|
||||
postgres_result_set(store_result):-
|
||||
set_value(postgres_result_set,store_result).
|
||||
%default value
|
||||
:- postgres_result_set(store_result).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_describe/2
|
||||
%
|
||||
%
|
||||
postgres_datalog_describe(Relation):-
|
||||
postgres_datalog_describe(myddas,Relation).
|
||||
postgres_datalog_describe(Connection,Relation) :-
|
||||
'$error_checks'(postgres_datalog_describe(Relation,Connection)),
|
||||
'$get_value'(Connection,Conn),
|
||||
'$make_atom'(['DESCRIBE ',Relation],SQL),
|
||||
postgres_result_set(Mode),
|
||||
c_postgres_query(SQL,ResultSet,Conn,Mode,_),
|
||||
c_postgres_table_write(ResultSet).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_describe/3
|
||||
% postgres_describe/2
|
||||
% gives the results of the DESCRIBE statement
|
||||
% by backtracking
|
||||
postgres_describe(Relation,TableInfo) :-
|
||||
postgres_describe(myddas,Relation,TableInfo).
|
||||
postgres_describe(Connection,Relation,tableinfo(A1,A2,A3,A4,A5,A6)) :-
|
||||
'$error_checks'(postgres_describe(Relation,Connection,_)),
|
||||
'$get_value'(Connection,Conn),
|
||||
'$make_atom'(['DESCRIBE ',Relation],SQL),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'(SQL),
|
||||
c_postgres_query(SQL,ResultSet,Conn,Mode,_),
|
||||
!,c_postgres_row(ResultSet,6,[A1,A2,A3,A4,A5,A6]).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_datalog_show_tables/1
|
||||
%
|
||||
%
|
||||
postgres_datalog_show_tables:-
|
||||
postgres_datalog_show_tables(myddas).
|
||||
postgres_datalog_show_tables(Connection) :-
|
||||
'$error_checks'(postgres_show_tables(Connection)),
|
||||
'$get_value'(Connection,Conn),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'('SHOW TABLES'),
|
||||
c_postgres_query('SHOW TABLES',ResultSet,Conn,Mode,_),
|
||||
c_postgres_table_write(ResultSet).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_show_tables/2
|
||||
% postgres_show_tables/1
|
||||
% gives the results of the SHOW TABLES statement
|
||||
% by backtracking
|
||||
postgres_show_tables(Table) :-
|
||||
postgres_show_tables(myddas,Table).
|
||||
postgres_show_tables(Connection,table(Table)) :-
|
||||
'$error_checks'(postgres_show_tables(Connection)),
|
||||
'$get_value'(Connection,Conn),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'('SHOW TABLES'),
|
||||
c_postgres_query('SHOW TABLES',ResultSet,Conn,Mode,_),
|
||||
!,c_postgres_row(ResultSet,1,[Table]).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_show_database/2
|
||||
%
|
||||
%
|
||||
postgres_show_database(Connection,Database) :-
|
||||
'$error_checks'(postgres_show_database(Connection,Database)),
|
||||
'$get_value'(Connection,Con),
|
||||
c_postgres_get_database(Con,Database).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_show_databases/2
|
||||
%
|
||||
%
|
||||
postgres_show_databases(Connection,database(Databases)) :-
|
||||
%'$error_checks'(postgres_show_databases(Connection,Database)),
|
||||
'$get_value'(Connection,Conn),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'('SHOW DATABASES'),
|
||||
c_postgres_query('SHOW DATABASES',ResultSet,Conn,Mode,_),
|
||||
!,c_postgres_row(ResultSet,1,[Databases]).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_show_databases/1
|
||||
% TODO Error Checks
|
||||
%
|
||||
postgres_show_databases(Connection) :-
|
||||
'$error_checks'(postgres_show_databases(Connection)),
|
||||
'$get_value'(Connection,Conn),
|
||||
postgres_result_set(Mode),
|
||||
'$write_or_not'('SHOW DATABASES'),
|
||||
c_postgres_query('SHOW DATABASES',ResultSet,Conn,Mode,_),
|
||||
c_postgres_table_write(ResultSet).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_change_database/2
|
||||
%
|
||||
%
|
||||
postgres_change_database(Connection,Database) :-
|
||||
'$error_checks'(postgres_change_database(Connection,Database)),
|
||||
'$get_value'(Connection,Con),
|
||||
'$make_atom'(['USE ',Database],SQL),
|
||||
'$write_or_not'(SQL),
|
||||
c_postgres_change_database(Con,Database).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_call_procedure/4
|
||||
% postgres_call_procedure/3
|
||||
% postgres_call_procedure(+,+,+,?)
|
||||
% Only support in Postgres 5.0 an above
|
||||
% Called procedure must return results via Postgres result set
|
||||
postgres_call_procedure(Procedure,Args,Result) :-
|
||||
postgres_call_procedure(myddas,Procedure,Args,Result).
|
||||
postgres_call_procedure(Connection,Procedure,Args,LA) :-
|
||||
'$error_checks'(postgres_call_procedure(Connection,Procedure,Args,LA)),
|
||||
'$make_atom_args'(Args,ArgsSQL),
|
||||
'$make_atom'(['CALL ',Procedure,'(',ArgsSQL,')'],SQL),
|
||||
postgres_sql(Connection,SQL,LA).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% postgres_sql_mode/1
|
||||
% postgres_sql_mode/2
|
||||
% Possible values : traditional,ansi,strict_trans_tables or '' (empty)
|
||||
postgres_sql_mode(SQLMode):-
|
||||
postgres_sql_mode(SQLMode).
|
||||
postgres_sql_mode(Connection,SQLMode):-
|
||||
postgres_sql_mode(Connection,SQLMode).
|
||||
|
||||
postgres_sql_mode(SQLMode):-
|
||||
postgres_sql_mode(myddas,SQLMode).
|
||||
postgres_sql_mode(Connection,SQLMode):-
|
||||
var(SQLMode),!,
|
||||
'$error_checks'(postgres_sql_mode(Connection,SQLMode)),
|
||||
get_value(Connection,Con),
|
||||
c_postgres_connection_type(Con,postgres), %must be a postgres connection
|
||||
postgres_sql(Connection,'SELECT @@session.sql_mode',[SQLMode]).
|
||||
postgres_sql_mode(Connection,SQLMode):-
|
||||
'$error_checks'(postgres_sql_mode(Connection,SQLMode)),
|
||||
get_value(Connection,Con),
|
||||
c_postgres_connection_type(Con,postgres), %must be a postgres connection
|
||||
'$make_atom'(['SET SESSION sql_mode=`',SQLMode,'`'],FinalSQL),
|
||||
'$write_or_not'(FinalSQL),
|
||||
postgres_result_set(Mode),
|
||||
c_postgres_query(FinalSQL,_,Con,Mode,_).
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
#endif /* MYDDAS_POSTGRES*/
|
Reference in New Issue
Block a user