/*
tclsql.c -- Release 2
sql commands for informix database support
*/

#ifndef lint
static char rcsid[] = "$Header: /u/kumar/:w/RCS/tclsql.c,v 2.1 1993/06/17 17:41:50 kumar Exp kumar $ SPRITE (Berkeley)";
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "tcl.h"

int tcl_informix_cmds();
int tcl_system();
isql_init(interp) Tcl_Interp *interp; {
    Tcl_CreateCommand(interp, "sql", tcl_informix_cmds, 
        (ClientData)0L,(void (*)()) NULL);
    Tcl_CreateCommand(interp, "tcl_system", tcl_system, 
        (ClientData)0L,(void (*)()) NULL);
    return TCL_OK;
}

static int tcl_sql_usage(interp) Tcl_Interp *interp; {
	Tcl_AppendResult(interp, "wrong args to sql: should be one of open,\n\
        fetch,close,run,exists,reopen,explain,geterror,sqlca,sqlda,\n\
        sqld,database,getdatabase,finish", (char *)NULL);
    return TCL_ERROR;
}

int tcl_informix_cmds(dummy, interp, argc, argv) 
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *minor = argv[1];
    int mlen;

    if (!minor) return tcl_sql_usage(interp);
    mlen = strlen(minor);
    if (*minor == 'c' && strncmp(minor, "close", mlen) == 0)
        return tcl_sql_close(dummy, interp, --argc, ++argv);
    if (*minor == 'd' && strncmp(minor, "database", mlen) == 0)
        return tcl_sql_database(dummy, interp, --argc, ++argv);
    if (*minor == 'e') {
		if (mlen < 3) mlen = 3;
		if (strncmp(minor, "exists", mlen) == 0)
        	return tcl_sql_exists(dummy, interp, --argc, ++argv);
    	if (strncmp(minor, "explain", mlen) == 0)
        	return tcl_sql_explain(dummy, interp, --argc, ++argv);
		return tcl_sql_usage(interp);
	}
    if (*minor == 'f') {
		if (mlen < 2) mlen = 2;
		if (strncmp(minor, "fetch", mlen) == 0)
        	return tcl_sql_fetch(dummy, interp, --argc, ++argv);
    	if (strncmp(minor, "finish", mlen) == 0)
        	return tcl_sql_finish(dummy, interp, --argc, ++argv);
		return tcl_sql_usage(interp);
	}
    if (*minor == 'g') {
		if (mlen < 4) mlen = 4;
		if (strncmp(minor, "geterror", mlen) == 0)
        	return tcl_sql_geterror(dummy, interp, --argc, ++argv);
    	if (strncmp(minor, "getdatabase", mlen) == 0)
        	return tcl_sql_getdatabase(dummy, interp, --argc, ++argv);
		return tcl_sql_usage(interp);
	}
    if (*minor == 'o' && strncmp(minor, "open", mlen) == 0)
        return tcl_sql_open(dummy, interp, --argc, ++argv);
    if (*minor == 'r') {
		if (mlen < 2) mlen = 2;
		if (strncmp(minor, "run", mlen) == 0)
        	return tcl_sql_run(dummy, interp, --argc, ++argv);
    	if (strncmp(minor, "reopen", mlen) == 0)
        	return tcl_sql_reopen(dummy, interp, --argc, ++argv);
		return tcl_sql_usage(interp);
	}
    if (*minor == 's') {
		if (mlen < 4) mlen = 4;
		if (strncmp(minor, "sqlca", mlen) == 0)
        	return tcl_sqlca(dummy, interp, --argc, ++argv);
		mlen = 5;
    	if (strncmp(minor, "sqlda", mlen) == 0)
        	return tcl_sqlda(dummy, interp, --argc, ++argv);
    	if (strncmp(minor, "sqld", mlen) == 0)
        	return tcl_sqld(dummy, interp, --argc, ++argv);
		return tcl_sql_usage(interp);
	}
	return tcl_sql_usage(interp);
}
        
int
tcl_sql_run(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    char *sql_geterror();
    int ret;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    stmt = argv[0];
    argc--;
    argv++;
    ret = sql_run(stmt, argc, argv);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_open(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int ret;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    stmt = argv[0];
    argc--;
    argv++;
    ret = sql_open(stmt, argc, argv);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}
int
tcl_sql_close(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int ret;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &ret, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql close not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    ret = sql_close(ret);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    /*sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);*/
    return TCL_OK;
}
int
tcl_sql_fetch(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int fd, ret, retargc, dostrip;
    char **retargv, **sql_values();
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &fd, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql fetch not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    if (argc >= 2 && argv[1] && sscanf(argv[1], "%d", &ret) == 1 && ret == 1)
        dostrip = 1;
    else dostrip = 0;
    ret = sql_fetch(fd);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    if (ret == 0) {
        retargv = sql_values(fd, &retargc, dostrip);
        if (!retargv) {
            Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
            "\"", (char *) NULL);
            return TCL_ERROR;
        }
        interp->result = Tcl_Merge(retargc, retargv);
        interp->freeProc = (Tcl_FreeProc *) free;
        return TCL_OK;
    }
    return TCL_OK;
}
int
tcl_sql_exists(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *arg0, *table, *column, *value = NULL, *where = NULL;
    char buf[25];
    int ret;
    if (argc < 3) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " table column ?value ?where?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    table = argv[0];
    column = argv[1];
    if (argv[2]) {
        value = argv[2];
        if (argv[3])
            where = argv[3];
    }
    ret = sql_exists(table, column, value, where);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_reopen(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int ret;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &ret, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql reopen not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    ret = sql_reopen(ret);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_explain(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int ret;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &ret, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql explain not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    ret = sql_explain(ret);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_getenv(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    int ret;
    char *p;
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " arg ?arg ...?\"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    p = getenv(argv[0]);
    if (!p) p = "";
    Tcl_SetResult(interp, p, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_geterror(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *p, *sql_geterror();
    int ret;
    p = sql_geterror();
    if (!p) p = "";
    Tcl_SetResult(interp, p, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sqlca(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    int retargc;
    char **retargv, **sql_sqlca();
    char *arg0 = argv[0];

    retargv = sql_sqlca(&retargc);
    if (!retargv) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    interp->result = Tcl_Merge(retargc, retargv);
    interp->freeProc = (Tcl_FreeProc *) free;
    return TCL_OK;
}

int
tcl_sqld(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    char buf[25];
    int ret, type_ld;
    if (argc < 3) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " <fd> <in> \"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &ret, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql sqld not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &type_ld, buf) != 1) {
        Tcl_AppendResult(interp, "argument 2 to sql sqld not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    ret = sql_sqld(ret, type_ld);
    if (ret == -2) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sqlda(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    int retargc;
    char **retargv, **sql_sqlda();
    char *stmt, *arg0;
    char buf[25];
    int ret, fd, num, type_ld;
    if (argc < 4) {
        Tcl_AppendResult(interp, "wrong # args: should be \"sql ", argv[0],
                " <fd> <in> <num> \"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &fd, buf) != 1) {
        Tcl_AppendResult(interp, "argument to sql sqld not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &type_ld, buf) != 1) {
        Tcl_AppendResult(interp, "argument 2 to sql sqld not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    argc--;
    argv++;
    if (sscanf(argv[0], "%d%1s", &num, buf) != 1) {
        Tcl_AppendResult(interp, "argument 2 to sql sqld not an integer ==>",
            argv[0], (char *) NULL);
        return TCL_ERROR;
    }
    retargv = sql_sqlda(fd, type_ld, num, &retargc);
    if (!retargv) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    interp->result = Tcl_Merge(retargc, retargv);
    interp->freeProc = (Tcl_FreeProc *) free;
    return TCL_OK;
}

int
tcl_sql_getdatabase(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *p, *sql_getdatabase();
    int ret;
    p = sql_getdatabase();
    if (!p) p = "";
    Tcl_SetResult(interp, p, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_finish(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *p, *sql_getdatabase();
    int ret;
    char buf[25];

    ret = sql_finish();
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_sql_database(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    int ret;
    char *p = NULL;
    char buf[25];

    arg0 = argv[0];
    if (argc >= 2) p = argv[1];
    ret = sql_database(p);
    if (ret < 0) {
        Tcl_AppendResult(interp, "\"sql ", arg0, ":", sql_geterror(), 
        "\"", (char *) NULL);
        return TCL_ERROR;
    }
    sprintf(buf, "%d", ret);

    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}

int
tcl_system(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
{
    char *stmt, *arg0;
    int ret;
    char *p;
    char buf[25];
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                " arg \"", (char *) NULL);
        return TCL_ERROR;
    }
    arg0 = argv[0];
    argc--;
    argv++;
    ret = system(argv[0]);
    sprintf(buf, "%d", ret);
    Tcl_SetResult(interp, buf, TCL_VOLATILE);
    return TCL_OK;
}
