2009-02-16 12:23:29 +00:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L . Damas , V . S . Costa and Universidade do Porto 1985 - 1997 *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* File : myddas_odbc . c *
* Last rev : 22 / 03 / 05 *
* mods : *
* comments : Predicates for comunicating with ODBC drivers *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-11 15:15:39 +00:00
# if defined MYDDAS_ODBC
2009-02-16 12:23:29 +00:00
# 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 ;
2013-04-25 23:15:04 +01:00
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 ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
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 ;
}
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
static int SQLCLOSECURSOR ( SQLHSTMT sthandle ,
char * print )
{
SQLRETURN retcode ;
retcode = SQLCloseCursor ( sthandle ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( retcode ! = SQL_SUCCESS & & retcode ! = SQL_SUCCESS_WITH_INFO )
return odbc_error ( SQL_HANDLE_STMT , sthandle , " SQLCloseCursor " , print ) ;
return TRUE ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
2009-02-16 12:23:29 +00:00
# define SQLFETCH(A,print) \
{ \
SQLRETURN retcode ; \
retcode = SQLFetch ( A ) ; \
if ( retcode = = SQL_NO_DATA ) \
break ; \
if ( retcode ! = SQL_SUCCESS & & retcode ! = SQL_SUCCESS_WITH_INFO ) \
{ \
2010-05-23 18:22:00 +01:00
printf ( " Error in SQLFETCH: %s \n " , print ) ; \
2009-02-16 12:23:29 +00:00
return FALSE ; \
} \
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
static int SQLDISCONNECT ( SQLHSTMT sthandle ,
char * print )
{
SQLRETURN retcode ;
retcode = SQLDisconnect ( sthandle ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( retcode ! = SQL_SUCCESS & & retcode ! = SQL_SUCCESS_WITH_INFO )
return odbc_error ( SQL_HANDLE_DBC , sthandle , " SQLDisconnect " , print ) ;
return TRUE ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
static int SQLFREEHANDLE ( SQLSMALLINT HandleType ,
SQLHANDLE Handle ,
char * print )
{
SQLRETURN retcode ;
retcode = SQLFreeHandle ( HandleType , Handle ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( retcode ! = SQL_SUCCESS & & retcode ! = SQL_SUCCESS_WITH_INFO )
return odbc_error ( HandleType , Handle , " SQLDisconnect " , print ) ;
return TRUE ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
}
2010-05-23 18:22:00 +01:00
/********************************************
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 ;
}
2009-02-16 12:23:29 +00:00
/* 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
2011-03-07 16:02:55 +00:00
c_db_odbc_connect ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
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 ;
char * driver = AtomName ( AtomOfTerm ( arg_driver ) ) ;
char * user = AtomName ( AtomOfTerm ( arg_user ) ) ;
char * passwd = AtomName ( AtomOfTerm ( arg_passwd ) ) ;
SQLHENV henv ;
SQLHDBC hdbc ;
/*Allocate environment handle */
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_ENV , SQL_NULL_HANDLE , & henv , " connect " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Set the ODBC version environment attribute */
2010-05-23 18:22:00 +01:00
if ( ! SQLSETENVATTR ( henv , SQL_ATTR_ODBC_VERSION , ( SQLPOINTER ) SQL_OV_ODBC3 , 0 , " connect " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Allocate connection handle */
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_DBC , henv , & hdbc , " connect " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Set login timeout to 6 seconds. */
2010-05-23 18:22:00 +01:00
if ( ! SQLSETCONNECTATTR ( hdbc , SQL_LOGIN_TIMEOUT , ( SQLPOINTER ) 6 , 0 , " connect " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Connect to data source */
2010-05-23 18:22:00 +01:00
if ( ! SQLCONNECT ( hdbc ,
( SQLCHAR * ) driver ,
( SQLCHAR * ) user ,
( SQLCHAR * ) passwd , " connect " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
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 ) ;
if ( new = = NULL ) {
2010-05-23 18:22:00 +01:00
fprintf ( stderr , " Error: could not allocate list memory \n " ) ;
2009-02-16 12:23:29 +00:00
return FALSE ;
}
return TRUE ;
}
}
/* db_query: SQLQuery x ResultSet x Arity x BindList x Connection */
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_query ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
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 ) ;
2010-05-23 18:22:00 +01:00
SQLCHAR * sql = ( SQLCHAR * ) AtomName ( AtomOfTerm ( arg_sql_query ) ) ;
2009-02-16 12:23:29 +00:00
SQLHDBC hdbc = ( SQLHDBC ) ( IntegerOfTerm ( arg_conn ) ) ;
SQLHSTMT hstmt ;
SQLSMALLINT type ;
2010-05-23 18:22:00 +01:00
Int arity ;
Int i ;
2009-02-16 12:23:29 +00:00
/*Allocate an handle for the query*/
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_STMT , hdbc , & hstmt , " db_query " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Executes the query*/
2010-05-23 18:22:00 +01:00
if ( ! SQLEXECDIRECT ( hstmt , sql , " db_query " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
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 ;
2010-05-23 18:22:00 +01:00
SQLULEN ColumnSizePtr ;
SQLLEN * data_info = NULL ;
2009-02-16 12:23:29 +00:00
for ( i = 1 ; i < = arity ; i + + )
{
head = HeadOfTerm ( list ) ;
list = TailOfTerm ( list ) ;
2010-05-23 18:22:00 +01:00
if ( ! SQLDESCRIBECOL ( hstmt , i , NULL , 0 , NULL , & type , & ColumnSizePtr , NULL , NULL , " db_query " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* +1 because of '\0' */
bind_space = malloc ( sizeof ( char ) * ( ColumnSizePtr + 1 ) ) ;
data_info = malloc ( sizeof ( SQLINTEGER ) ) ;
2011-07-21 10:24:08 +01:00
if ( ! SQLBINDCOL ( hstmt , i , SQL_C_CHAR , bind_space , ( ColumnSizePtr + 1 ) , data_info , " db_query " ) ) {
2010-05-23 18:22:00 +01:00
return FALSE ;
2011-07-21 10:24:08 +01:00
}
2009-02-16 12:23:29 +00:00
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 ) ) )
{
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_query " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_query " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
return FALSE ;
}
return TRUE ;
}
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_number_of_fields ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
Term arg_relation = Deref ( ARG1 ) ;
Term arg_conn = Deref ( ARG2 ) ;
Term arg_fields = Deref ( ARG3 ) ;
char * relation = AtomName ( AtomOfTerm ( arg_relation ) ) ;
SQLHDBC hdbc = ( SQLHDBC ) ( IntegerOfTerm ( arg_conn ) ) ;
SQLHSTMT hstmt ;
char sql [ 256 ] ;
SQLSMALLINT number_fields ;
2014-11-25 16:42:35 +00:00
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 ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_STMT , hdbc , & hstmt , " db_number_of_fields " ) )
return FALSE ;
if ( ! SQLEXECDIRECT ( hstmt , ( SQLCHAR * ) sql , " db_number_of_fields " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Calcula o numero de campos*/
number_fields = 0 ;
while ( TRUE ) {
SQLFETCH ( hstmt , " db_number_of_fields " ) ;
number_fields + + ;
}
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_number_of_fields " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_number_of_fields " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
if ( ! Yap_unify ( arg_fields , MkIntegerTerm ( number_fields ) ) )
return FALSE ;
return TRUE ;
}
/* db_get_attributes_types: RelName x Connection -> TypesList */
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_get_attributes_types ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
Term arg_relation = Deref ( ARG1 ) ;
Term arg_conn = Deref ( ARG2 ) ;
Term arg_types_list = Deref ( ARG3 ) ;
char * relation = AtomName ( AtomOfTerm ( arg_relation ) ) ;
SQLHDBC hdbc = ( SQLHDBC ) ( IntegerOfTerm ( arg_conn ) ) ;
SQLHSTMT hstmt ;
char sql [ 256 ] ;
Term head , list ;
list = arg_types_list ;
2014-11-25 16:42:35 +00:00
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 ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_STMT , hdbc , & hstmt , " db_get_attributes_types " ) )
return FALSE ;
if ( ! SQLEXECDIRECT ( hstmt , ( SQLCHAR * ) sql , " db_get_attributes_types " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
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 ' ;
2010-05-23 18:22:00 +01:00
if ( ! SQLGETDATA ( hstmt , 1 , SQL_C_CHAR , sql , 256 , NULL , " db_get_attributes_types " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
head = HeadOfTerm ( list ) ;
Yap_unify ( head , MkAtomTerm ( Yap_LookupAtom ( sql ) ) ) ;
list = TailOfTerm ( list ) ;
head = HeadOfTerm ( list ) ;
list = TailOfTerm ( list ) ;
sql [ 0 ] = ' \0 ' ;
2010-05-23 18:22:00 +01:00
if ( ! SQLGETDATA ( hstmt , 2 , SQL_C_CHAR , sql , 256 , NULL , " db_get_attributes_types " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
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 " ) ) ) ;
}
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_get_attributes_types " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_get_attributes_types " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
return TRUE ;
}
/* db_disconnect */
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_disconnect ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
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 */
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
return TRUE ;
}
else
return FALSE ;
}
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_row_cut ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
SQLHSTMT hstmt = ( SQLHSTMT ) IntegerOfTerm ( EXTRA_CBACK_CUT_ARG ( Term , 1 ) ) ;
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_row_cut " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_row_cut " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
return TRUE ;
}
2011-07-21 10:24:08 +01:00
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 ;
}
2009-02-16 12:23:29 +00:00
/* db_row: ResultSet x BindList x ListOfArgs -> */
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_row ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
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 )
{
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_row " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_row " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! release_list_args ( arg_list_args , arg_bind_list , " db_row " ) ) {
return FALSE ;
}
2009-02-16 12:23:29 +00:00
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 " ) )
{
2010-10-08 14:42:55 +01:00
if ( ! Yap_unify ( head , MkIntegerTerm ( atol ( bind_value ) ) ) )
2009-02-16 12:23:29 +00:00
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
2011-03-07 16:02:55 +00:00
c_db_odbc_number_of_fields_in_query ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
Term arg_query = Deref ( ARG1 ) ;
Term arg_conn = Deref ( ARG2 ) ;
Term arg_fields = Deref ( ARG3 ) ;
char * sql = AtomName ( AtomOfTerm ( arg_query ) ) ;
SQLHDBC hdbc = ( SQLHDBC ) ( IntegerOfTerm ( arg_conn ) ) ;
SQLHSTMT hstmt ;
SQLSMALLINT number_cols = 0 ;
2010-05-23 18:22:00 +01:00
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 ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( ! SQLNUMRESULTCOLS ( hstmt , & number_cols ,
" db_number_of_fields_in_query " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
if ( ! Yap_unify ( arg_fields , MkIntegerTerm ( number_cols ) ) ) {
2010-10-08 14:42:55 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_number_of_fields_in_query " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_number_of_fields_in_query " ) )
2010-10-08 14:42:55 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
return FALSE ;
}
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_number_of_fields_in_query " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt , " db_number_of_fields_in_query " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
return TRUE ;
}
static Int
2011-03-07 16:02:55 +00:00
c_db_odbc_get_fields_properties ( USES_REGS1 ) {
2009-02-16 12:23:29 +00:00
Term nome_relacao = Deref ( ARG1 ) ;
Term arg_conn = Deref ( ARG2 ) ;
Term fields_properties_list = Deref ( ARG3 ) ;
Term head , list ;
2010-05-23 18:22:00 +01:00
SQLCHAR * relacao = ( SQLCHAR * ) AtomName ( AtomOfTerm ( nome_relacao ) ) ;
2009-02-16 12:23:29 +00:00
char sql [ 256 ] ;
char name [ 200 ] ;
Int i ;
SQLSMALLINT num_fields = 0 ;
SQLSMALLINT NullablePtr = 0 ;
2010-05-23 18:22:00 +01:00
SQLLEN AutoIncrementPointer = 0 ;
2009-02-16 12:23:29 +00:00
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*/
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_STMT , hdbc , & hstmt , " db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Executes the query*/
2010-05-23 18:22:00 +01:00
if ( ! SQLEXECDIRECT ( hstmt , ( SQLCHAR * ) sql , " db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
Functor functor = Yap_MkFunctor ( Yap_LookupAtom ( " property " ) , 4 ) ;
Term properties [ 4 ] ;
2010-05-23 18:22:00 +01:00
if ( ! SQLNUMRESULTCOLS ( hstmt , & num_fields ,
" db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
list = fields_properties_list ;
SQLSMALLINT bind_prim_key ;
2014-10-02 23:24:04 +01:00
// rows in odbc start at 1 :)
2010-05-23 18:22:00 +01:00
Short * null = ( Short * ) malloc ( sizeof ( Short ) * ( 1 + num_fields ) ) ;
2009-02-16 12:23:29 +00:00
2010-05-23 18:22:00 +01:00
if ( ! SQLALLOCHANDLE ( SQL_HANDLE_STMT , hdbc , & hstmt2 , " db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Executes the query*/
2010-05-23 18:22:00 +01:00
if ( ! SQLPRIMARYKEYS ( hstmt2 , NULL , 0 , NULL , 0 , relacao , SQL_NTS , " db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
/* Associates bind value for the 5 column*/
2010-05-23 18:22:00 +01:00
if ( ! SQLBINDCOL ( hstmt2 , 5 , SQL_C_SSHORT , & bind_prim_key , sizeof ( SQLSMALLINT ) , NULL ,
" db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
while ( 1 )
{
SQLFETCH ( hstmt2 , " db_get_fields_properties " ) ;
null [ bind_prim_key ] = 1 ;
}
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt2 , " db_get_fields_properties " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt2 , " db_get_fields_properties " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
for ( i = 1 ; i < = num_fields ; i + + )
{
head = HeadOfTerm ( list ) ;
name [ 0 ] = ' \0 ' ;
2010-05-23 18:22:00 +01:00
SQLDESCRIBECOL ( hstmt , i , ( SQLCHAR * ) name , 200 , NULL , NULL , NULL , NULL , & NullablePtr ,
2009-02-16 12:23:29 +00:00
" db_get_fields_properties " ) ;
2010-05-23 18:22:00 +01:00
if ( ! SQLCOLATTRIBUTE ( hstmt , i , SQL_DESC_AUTO_UNIQUE_VALUE , NULL , 0 , NULL , & AutoIncrementPointer ,
" db_get_fields_properties " ) )
return FALSE ;
2009-02-16 12:23:29 +00:00
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 ;
}
}
2010-05-23 18:22:00 +01:00
if ( ! SQLCLOSECURSOR ( hstmt , " db_get_fields_properties " ) )
return FALSE ;
2011-07-21 10:24:08 +01:00
if ( ! SQLFREEHANDLE ( SQL_HANDLE_STMT , hstmt2 , " db_get_fields_properties " ) )
2010-05-23 18:22:00 +01:00
return FALSE ;
2009-02-16 12:23:29 +00:00
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*/