#include <stdio.h>
#include "onyx_config.h"

/* 
 *	some neccesary engine related stuff
 */

EXEC SQL BEGIN DECLARE SECTION;
#include "sqltypes.h"
EXEC SQL END DECLARE SECTION;

#define MAX_DATE_LEN    10
#define MAX_COL_LEN     18

/* 
 *	check,connect,commit,rollback,error,disconnect.
 *
 *	uses 	BEGIN DECLARE SECTION
 *		END DECLARE SECTION
 *		CONNECT :yard_user
 *		DATABASE :yard_db
 *		COMMIT WORK
 *		ROLLBACK WORK
 *		CLOSE DATABASE
 *		DISCONNECT
 */

char *yard_act;
int   yard_code;
#define yard_check(ACT,CHECK) { yard_code = SQLCODE; if (SQLCODE < 0) { int sc=SQLCODE; yard_act = ACT; yard_error(CHECK); return (sc); } }
extern void yard_error(int rollback);

int yard_connect(char *user,char *db)
{	
	EXEC SQL BEGIN DECLARE SECTION;
	char *yard_user;
	char *yard_db;
	EXEC SQL END DECLARE SECTION;

	char env[1024];

	sprintf(env,"YARDHOME=%s",YARD_HOME);
	putenv(strdup(env));
	sprintf(env,"PATH=%s:%s/bin",getenv("PATH"),YARD_HOME);
	putenv(strdup(env));
	sprintf(env,"YARDDBS=%s",YARD_DBS);
	putenv(strdup(env));
	putenv(strdup("YARDDELIM=\t"));

	yard_user = user;
	yard_db   = db;

	EXEC SQL CONNECT :yard_user;
	yard_check("connect",0);

	EXEC SQL DATABASE :yard_db;
	yard_check("database",0);

	return (SQLCODE);
	}

int yard_commit()
{	EXEC SQL COMMIT WORK;
	yard_check("commit",1);

	return (SQLCODE);
	}

int yard_rollback()
{	EXEC SQL ROLLBACK WORK;
	return (SQLCODE);
	}

void yard_error(int rollback)
{	if (rollback) {
		yard_rollback();
		}
	}

int yard_disconnect()
{	EXEC SQL COMMIT WORK;

	EXEC SQL CLOSE DATABASE;
	EXEC SQL DISCONNECT;
	return (SQLCODE);
	}

/* 
 *	command for sending all what is not select !
 *
 *	uses 	BEGIN DECLARE SECTION
 *		END DECLARE SECTION
 *		PREPARE p_output FROM :yard_cmd
 *		EXECUTE p_output
 */

int yard_command(char *cmd)
{	EXEC SQL BEGIN DECLARE SECTION;
	char *yard_cmd;
	EXEC SQL END DECLARE SECTION;

	yard_cmd = cmd;

	EXEC SQL PREPARE p_cmd FROM :yard_cmd;
	yard_check("prepare",1);

	EXEC SQL EXECUTE p_cmd;
	yard_check("execute",1);

	EXEC SQL FREE STATEMENT p_cmd;
	yard_check("free",1);

	return (SQLCODE);
	}

/*
 *	select for selecting stuff.
 *
 *	uses 	BEGIN DECLARE SECTION
 *		END DECLARE SECTION
 *		PREPARE p_output FROM :yard_cmd
 *
 *	warning	maxdesc = sqlca.sqlerrd[4]
 */

int yard_select_prep(char *cmd)
{	EXEC SQL BEGIN DECLARE SECTION;
	char *descname = "outdesc";
	char *yard_cmd;
	int maxdesc;
	int desccount;
	int desctype;
	int desclen;
	int i;
	EXEC SQL END DECLARE SECTION;

	yard_cmd = cmd;

	EXEC SQL PREPARE p_output FROM :yard_cmd;
	yard_check("prepare",1);

	maxdesc = sqlca.sqlerrd[4];

	EXEC SQL ALLOCATE DESCRIPTOR :descname WITH MAX :maxdesc;
	yard_check("allocat",1);
	EXEC SQL DESCRIBE p_output USING SQL DESCRIPTOR :descname;
	yard_check("describe",1);
	EXEC SQL GET DESCRIPTOR :descname :desccount = COUNT;
	yard_check("get count",1);

	for (i = 1; i <= desccount; i++) {
		EXEC SQL GET DESCRIPTOR :descname VALUE :i
			:desctype = TYPE;

		switch(desctype) {
			case DATETYPE:
				desclen = MAX_DATE_LEN + 1;
				EXEC SQL SET DESCRIPTOR :descname VALUE :i
					TYPE = CHARTYPE,
					LENGTH = :desclen;
				break;
			case DECIMALTYPE:
			case MONEYTYPE:
				EXEC SQL GET DESCRIPTOR :descname VALUE :i
					:desclen = PRECISION;

				EXEC SQL SET DESCRIPTOR :descname VALUE :i
					TYPE = CHARTYPE,
					LENGTH = :desclen;
				break;
			case INTTYPE:
				EXEC SQL SET DESCRIPTOR :descname VALUE :i
					TYPE = LONGTYPE;
				break;
			case FLOATTYPE:
				EXEC SQL SET DESCRIPTOR :descname VALUE :i
					TYPE = DOUBLETYPE;
				break;
			}
		}

	EXEC SQL DECLARE c_output CURSOR FOR p_output;
	yard_check("declare",1);
	EXEC SQL OPEN c_output;
	yard_check("open",1);

	return(SQLCODE);
	}

int yard_select_fetch(char *result)
{	EXEC SQL BEGIN DECLARE SECTION;
	char *descname = "outdesc";
	int desccount;
	int i;
	short dummy; /* Hier ist ein BUG im Yard sonst wird i ueberschrieben */
	short ind;
	int desctype;
	int charlen;
	char *charval;
	long longval;
	double floatval;
	EXEC SQL END DECLARE SECTION;
	char strval[256];

	EXEC SQL GET DESCRIPTOR :descname :desccount = COUNT;
	yard_check("get count",1);

	EXEC SQL FETCH c_output INTO SQL DESCRIPTOR :descname;
	if (SQLCODE == SQLNOTFOUND) {
		return(SQLCODE);
		}

	yard_check("fetch",1);

	for (i = 1; i <= desccount; i++) {
		if (i == 1)
			*result=0;
		else	strcat(result,"\t");

		EXEC SQL GET DESCRIPTOR :descname VALUE :i
			:ind = INDICATOR;
		yard_check("get ind",1);

		if (ind != -1) {
			EXEC SQL GET DESCRIPTOR :descname VALUE :i
				:desctype = TYPE;
			yard_check("get type",1);

			switch(desctype) {
			    case VCHARTYPE:
			    case CHARTYPE:
			    case DECIMALTYPE:
			    case MONEYTYPE:
			    case DATETYPE:
				EXEC SQL GET DESCRIPTOR :descname 
					VALUE :i
					:charlen = LENGTH;
				yard_check("get len",1);

				charval = (char *)malloc(charlen + 1);

				EXEC SQL GET DESCRIPTOR :descname 
					VALUE :i
					 :charval = DATA;
				yard_check("get data",1);
				strcat(result,charval);
				break;
			    case SERIALTYPE:
			    case LONGTYPE:
			    case INTTYPE:
				EXEC SQL GET DESCRIPTOR :descname 
					VALUE :i
					:longval = DATA;
				sprintf(result+strlen(result),"%ld", longval);
				break;
			    case DOUBLETYPE:
			    case FLOATTYPE:
				EXEC SQL GET DESCRIPTOR :descname 
					VALUE :i
					:floatval = DATA;
				yard_check("get float data",1);
				sprintf(result+strlen(result),"%f", floatval);
				break;
			    }
			}
		}
	return(SQLCODE);
	}

int yard_select_close()
{	EXEC SQL BEGIN DECLARE SECTION;
	char *descname = "outdesc";
	EXEC SQL END DECLARE SECTION;

	EXEC SQL CLOSE c_output;
	yard_check("close",1);
	EXEC SQL FREE STATEMENT p_output;
	yard_check("free statement",1);
	EXEC SQL FREE CURSOR c_output;
	yard_check("free cursor",1);
	EXEC SQL DEALLOCATE DESCRIPTOR :descname;
	yard_check("deallocat",1);

	return (SQLCODE);
	}
