// ---------------------------- -*- Mode: C++ -*- ----------------------------
// PQTcl.cc - Tcl extensions for Postgres.
// 
// %W%
// 
// Written by
// Robin J. Maxwell
// Open Systems Solutions, Inc
// Collaboration Software Group.
// 
// Copyright (c) 1992 Open Systems Solutions, Inc
// 
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose and without fee is hereby granted, provided
// that the above copyright notice appear in all copies.  
// Open Systems Solutions, Inc. and Robin J. Maxwell make no representations 
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// 
// Author          : Robin J. Maxwell
// Created On      : Wed Jul 29 10:41:42 1992
// Last Modified By: Robin J. Maxwell
// Last Modified On: Wed Oct 28 11:15:25 1992
// Update Count    : 14
// Status          : Tested.
// ---------------------------------------------------------------------------


#include "PQTcl.hpp"
#include <string.h>

//
//
PQTcl::PQTcl(TclInterp_cl &tclI):
Interp(tclI),
handles("PQPortal", sizeof (PBuffer_pt), MAXPORTALS),
dbname(NULL)
{
    Interp.CreateCommand ("PQsetdb", PQTcl::PQsetdbCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQdb", PQTcl::PQdbCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQreset", PQTcl::PQresetCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQfinish", PQTcl::PQFinishCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQexec", PQTcl::PQexecCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQnportals", PQTcl::PQnportalsCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQnames", PQTcl::PQnamesCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQparray", PQTcl::PQparrayCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQclear", PQTcl::PQclearCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQrulep", PQTcl::PQrulepCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQntuples", PQTcl::PQntuplesCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQngroups", PQTcl::PQngroupsCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQntuplesGroup", 
			   PQTcl::PQntuplesGroupCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQnfieldsGroup", 
			   PQTcl::PQnfieldsGroupCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQfnameGroup", PQTcl::PQfnameGroupCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQfnumberGroup", 
			   PQTcl::PQfnumberGroupCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQgetgroup", PQTcl::PQgetgroupCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQnfields", PQTcl::PQnfieldsCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQfnumber", PQTcl::PQfnumberCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQfname", PQTcl::PQfnameCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQftype", PQTcl::PQftypeCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQsametype", PQTcl::PQsametypeCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQgetvalue", PQTcl::PQgetvalueCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQtrace", PQTcl::PQtraceCmd_S,
			   (ClientData)this, NULL);
    Interp.CreateCommand ("PQuntrace", PQTcl::PQuntraceCmd_S,
			   (ClientData)this, NULL);
}
PQTcl::~PQTcl()
{
    Interp.DeleteCommand ("PQsetdb");
    Interp.DeleteCommand ("PQdb");
    Interp.DeleteCommand ("PQreset");
    Interp.DeleteCommand ("PQfinish");
    Interp.DeleteCommand ("PQexec");
    Interp.DeleteCommand ("PQnportals");
    Interp.DeleteCommand ("PQnames");
    Interp.DeleteCommand ("PQparray");
    Interp.DeleteCommand ("PQclear");
    Interp.DeleteCommand ("PQrulep");
    Interp.DeleteCommand ("PQntuples");
    Interp.DeleteCommand ("PQngroups");
    Interp.DeleteCommand ("PQntuplesGroup");
    Interp.DeleteCommand ("PQnfieldsGroup");
    Interp.DeleteCommand ("PQfnameGroup");
    Interp.DeleteCommand ("PQfnumberGroup");
    Interp.DeleteCommand ("PQgetgroup");
    Interp.DeleteCommand ("PQnfields");
    Interp.DeleteCommand ("PQfnumber");
    Interp.DeleteCommand ("PQfname");
    Interp.DeleteCommand ("PQftype");
    Interp.DeleteCommand ("PQsametype");
    Interp.DeleteCommand ("PQgetvalue");
    Interp.DeleteCommand ("PQtrace");
    Interp.DeleteCommand ("PQuntrace");
    if (dbname)
	free(dbname);
}

/*----------------------------------------------------------------------------
 * Make the specified database the current database.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQsetdbCmd_S (ClientData clientData, Tcl_Interp *,
			 int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQsetdbCmd(argc, argv);
}

int
PQTcl::PQsetdbCmd (int argc, char *argv[])
{
    if (argc != 2)
	return AppendArgCountError(argv[0], " dbname");

    dbname = strdup(argv[1]);
    PQsetdb(dbname);
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the current database being accessed.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQdbCmd_S (ClientData clientData, Tcl_Interp *,
		      int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQdbCmd(argc, argv);
}

/*----------------------------------------------------------------------------
 * Reset the communication port with the back-end in case of errors.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQresetCmd_S (ClientData clientData, Tcl_Interp *,
			 int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQresetCmd(argc, argv);
}

/*----------------------------------------------------------------------------
 * Close communications ports with the back-end.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQFinishCmd_S (ClientData clientData, Tcl_Interp *,
			      int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQFinishCmd(argc, argv);
}

/*----------------------------------------------------------------------------
 * Submit a query to POSTGRES.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQexecCmd_S (ClientData clientData, Tcl_Interp *,
			    int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQexecCmd(argc, argv);
}

int
PQTcl::PQexecCmd (int argc, char *argv[])
{
    if (argc != 2)
	return AppendArgCountError(argv[0], " query");

    Interp.SetResult(PQexec(argv[1]), TCL_STATIC);
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of open portals.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQnportalsCmd_S (ClientData clientData, Tcl_Interp *,
				int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQnportalsCmd(argc, argv);
}

int
PQTcl::PQnportalsCmd (int argc, char *argv[])
{
    int rule_p;
    
    if (argc != 2)
	return AppendArgCountError(argv[0], " rule_p");
    
    if (Interp.GetInt (argv[1], &rule_p) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQnportals(rule_p));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return all portal names.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQnamesCmd_S (ClientData clientData, Tcl_Interp *,
			     int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQnamesCmd(argc, argv);
}

int
PQTcl::PQnamesCmd (int argc, char *argv[])
{
    register int i;
    int rule_p;
    char *pnames[MAXPORTALS];
    char arrayref[20];
    
    if (argc != 3)
	return AppendArgCountError(argv[0], " pnames rule_p");
    
    if (Interp.GetInt (argv[1], &rule_p) != TCL_OK)
	return TCL_ERROR;
    
    PQpnames(pnames, rule_p);
    for (i=0;i<MAXPORTALS;i++){
	sprintf(arrayref, "%d", i);
	if (!Interp.SetVar2(argv[1], arrayref, pnames[i], TCL_LEAVE_ERR_MSG))
	    return TCL_ERROR;
    }
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the portal buffer handle given a portal name.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQparrayCmd_S (ClientData clientData, Tcl_Interp *,
			      int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQparrayCmd(argc, argv);
}

int
PQTcl::PQparrayCmd (int argc, char *argv[])
{
    if (argc != 2)
	return AppendArgCountError(argv[0], " pname");

    int walkKey = -1;
    PBuffer_pt PBufferPtr;
    PortalBuffer *pbuff = (PortalBuffer *)PQparray(argv[1]);
    while ((PBufferPtr = (PBuffer_pt)handles.HandleWalk (&walkKey)) != NULL){
	if (*PBufferPtr == pbuff)
	    break;
    }
    if (PBufferPtr)
	handles.WalkKeyToHandle(walkKey, Interp.Result());
    else{
	PBufferPtr = (PBuffer_pt)handles.HandleAlloc(Interp.Result());
	*PBufferPtr = pbuff;
    }

    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Free storage claimed by named portal.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQclearCmd_S (ClientData clientData, Tcl_Interp *,
			     int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQclearCmd(argc, argv);
}

int
PQTcl::PQclearCmd (int argc, char *argv[])
{
    if (argc != 2)
	return AppendArgCountError(argv[0], " pname");
    
    PQclear(argv[1]);
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return 1 if an asynchronous portal.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQrulepCmd_S (ClientData clientData, Tcl_Interp *,
			     int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQrulepCmd(argc, argv);
}

int
PQTcl::PQrulepCmd (int argc, char *argv[])
{
    PBuffer_pt PBufferPtr;
    
    if (argc != 2)
	return AppendArgCountError(argv[0], " hPortal");

    if (!(PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(),
						      argv[1])))
	return AppendHandleError(argv[0],argv[1]);

    sprintf (Interp.Result(), "%d", PQrulep(*PBufferPtr));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of instances in a portal buffer.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQntuplesCmd_S (ClientData clientData, Tcl_Interp *,
			       int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQntuplesCmd(argc, argv);
}

int
PQTcl::PQntuplesCmd (int argc, char *argv[])
{
    PBuffer_pt PBufferPtr;
    
    if (argc != 2)
	return AppendArgCountError(argv[0], " hPortal");

    if (!(PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						       argv[1])))
	return AppendHandleError(argv[0],argv[1]);
    
    sprintf (Interp.Result(), "%d", PQntuples(*PBufferPtr));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of instance groups in a portal buffer.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQngroupsCmd_S (ClientData clientData, Tcl_Interp *,
			       int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQngroupsCmd(argc, argv);
}

int
PQTcl::PQngroupsCmd (int argc, char *argv[])
{
    PBuffer_pt PBufferPtr;
    
    if (argc != 2)
	return AppendArgCountError(argv[0], " hPortal");

    if (!(PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1])))
	return AppendHandleError(argv[0],argv[1]);
    
    sprintf (Interp.Result(), "%d", PQngroups(*PBufferPtr));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of instances in an instance group.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQntuplesGroupCmd_S (ClientData clientData, Tcl_Interp *,
				    int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQntuplesGroupCmd(argc, argv);
}

int
PQTcl::PQntuplesGroupCmd (int argc, char *argv[])
{
    int group_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 3)
	return AppendArgCountError(argv[0], " hPortal group_index");

    if (Interp.GetInt (argv[2], &group_index) != TCL_OK)
	return TCL_ERROR;

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);
    
    sprintf (Interp.Result(), "%d", PQntuplesGroup(*PBufferPtr, group_index));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of fields in an instance group.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQnfieldsGroupCmd_S (ClientData clientData, Tcl_Interp *,
				    int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQnfieldsGroupCmd(argc, argv);
}

int
PQTcl::PQnfieldsGroupCmd (int argc, char *argv[])
{
    int group_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 3)
	return AppendArgCountError(argv[0], " hPortal group_index");

    if (Interp.GetInt (argv[2], &group_index) != TCL_OK)
        return TCL_ERROR;

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    sprintf(Interp.Result(), "%d", PQnfieldsGroup(*PBufferPtr, group_index));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the field name given the group and field index.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQfnameGroupCmd_S (ClientData clientData, Tcl_Interp *,
				  int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQfnameGroupCmd(argc, argv);
}

int
PQTcl::PQfnameGroupCmd (int argc, char *argv[])
{
    int group_index;
    int field_number;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0], 
				   " hPortal group_index field_number");

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &group_index) != TCL_OK)
        return TCL_ERROR;

    if (Interp.GetInt (argv[3], &field_number) != TCL_OK)
        return TCL_ERROR;
    
    Interp.SetResult(PQfnameGroup(*PBufferPtr, group_index, field_number));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the field number (index) given the group index and field name.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQfnumberGroupCmd_S (ClientData clientData, Tcl_Interp *,
				    int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQfnumberGroupCmd(argc, argv);
}

int
PQTcl::PQfnumberGroupCmd (int argc, char *argv[])
{
    int group_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0], " hPortal group_index field_name");

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &group_index) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQfnumberGroup(*PBufferPtr, group_index,
						  argv[3]));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Returns the index of the group that a particular instance is in.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQgetgroupCmd_S (ClientData clientData, Tcl_Interp *,
				int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQgetgroupCmd(argc, argv);
}

int
PQTcl::PQgetgroupCmd (int argc, char *argv[])
{
    int tuple_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 3)
	return AppendArgCountError(argv[0], " hPortal tuple_index");

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);
    
    if (Interp.GetInt (argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQgetgroup(*PBufferPtr,tuple_index));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the number of fields in an instance.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQnfieldsCmd_S (ClientData clientData, Tcl_Interp *,
			       int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQnfieldsCmd(argc, argv);
}

int
PQTcl::PQnfieldsCmd (int argc, char *argv[])
{
    int tuple_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 3)
	return AppendArgCountError(argv[0], " hPortal tuple_index");

    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQnfields(*PBufferPtr,tuple_index));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the field index of a given field name within and instance.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQfnumberCmd_S (ClientData clientData, Tcl_Interp *,
			       int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQfnumberCmd(argc, argv);
}

int
PQTcl::PQfnumberCmd (int argc, char *argv[])
{
    int tuple_index;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0],
				   " hPortal tuple_index field_name");
    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQfnumber(*PBufferPtr, tuple_index, argv[3]));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the name of a field.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQfnameCmd_S (ClientData clientData, Tcl_Interp *,
			     int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQfnameCmd(argc, argv);
}

int
PQTcl::PQfnameCmd (int argc, char *argv[])
{
    int tuple_index;
    int field_number;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0], 
			  " hPortal tuple_index field_number");
    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt ( argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    if (Interp.GetInt (argv[3], &field_number) != TCL_OK)
        return TCL_ERROR;
    
    strcpy(Interp.Result(), PQfname(*PBufferPtr, tuple_index, field_number));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return the type of a field.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQftypeCmd_S (ClientData clientData, Tcl_Interp *,
			     int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQftypeCmd(argc, argv);
}

int
PQTcl::PQftypeCmd (int argc, char *argv[])
{
    int tuple_index;
    int field_number;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0], 
				   " hPortal tuple_index field_number");
    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    if (Interp.GetInt (argv[3], &field_number) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQftype(*PBufferPtr,tuple_index,					     field_number)); 
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return 1 if two instances have the same attributes.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQsametypeCmd_S (ClientData clientData, Tcl_Interp *,
				int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQsametypeCmd(argc, argv);
}

int
PQTcl::PQsametypeCmd (int argc, char *argv[])
{
    int tuple_index1;
    int tuple_index2;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0], 
				   " hPortal tuple_index1 tuple_index2");
    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &tuple_index1) != TCL_OK)
        return TCL_ERROR;
    if (Interp.GetInt (argv[3], &tuple_index2) != TCL_OK)
        return TCL_ERROR;
    
    sprintf (Interp.Result(), "%d", PQsametype(*PBufferPtr, tuple_index1, 
					      tuple_index2)); 
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Return an attribute (field) value.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQgetvalueCmd_S (ClientData clientData, Tcl_Interp *,
				int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQgetvalueCmd(argc, argv);
}

int
PQTcl::PQgetvalueCmd (int argc, char *argv[])
{
    int tuple_index;
    int field_number;
    PBuffer_pt PBufferPtr;
    
    if (argc != 4)
	return AppendArgCountError(argv[0],
				   " hPortal tuple_index field_number");
    if ((PBufferPtr = (PBuffer_pt)handles.HandleXlate(Interp.GetInterp(), 
						      argv[1]))==NULL)
	return AppendHandleError(argv[0],argv[1]);

    if (Interp.GetInt (argv[2], &tuple_index) != TCL_OK)
        return TCL_ERROR;
    if (Interp.GetInt (argv[3], &field_number) != TCL_OK)
        return TCL_ERROR;
    
    Interp.SetResult(PQgetvalue(*PBufferPtr, tuple_index,field_number));
    return TCL_OK;
}

/*----------------------------------------------------------------------------
 * Make the specified database the current database.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQtraceCmd_S (ClientData clientData, Tcl_Interp *,
			 int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQtraceCmd(argc, argv);
}

/*----------------------------------------------------------------------------
 * Disable tracing.
 *----------------------------------------------------------------------------
 */
int
PQTcl::PQuntraceCmd_S (ClientData clientData, Tcl_Interp *,
			   int argc, char *argv[])
{
    return ((PQTcl *)clientData)->PQuntraceCmd(argc, argv);
}

int
PQTcl::AppendArgCountError(const char *cname, const char *arglist)
{
    Interp.AppendResult ("wrong # args: ", cname, arglist, NULL);
    return TCL_ERROR;
}

int
PQTcl::AppendHandleError(const char *cname, const char *handle)
{
    Interp.AppendResult (" bad handle: ", cname, " ", handle, NULL);
    return TCL_ERROR;
}






