/* See the copyright notice (COPYRIGHT) in this directory. */

/*
 * FILE
 *	pg_parse()	- Given a query string, determine what it is.
 *	pg_query()	- Construct a final query to execute on a portal.
 *
 * SYNOPSIS
 *	int
 *	pg_parse()
 *	char	*query;	 (i)	syntactically complete query
 *	char	*pq;	 (i/o)	short postquel command (retrieve, append, etc.)
 *	int	pq_len;  (i)    size of pq
 *
 *	int
 *	pg_query()
 *	dbConn  *d;      (i) database connector
 *	int     chan;    (i) query channel
 *	char    *q_in;   (i) original query
 *	char    *q_out;  (o) final query
 *	int	q_len;   (i) size of q_out
 *	char    *portal; (i/o) final portal name, gets filled here
 *
 * DESCRIPTION
 * 	pg_parse() stores what a query is (retrieve? append?) in the pq
 *	parameter. It returns the integer code from gdi_postgres.h that 
 *	corresponds to that query type.
 *
 *	pg_query() writes the final query and determines the final
 *	portal name since that can be part of the query. We are forcing
 *	use of a portal to put in hooks for a future gdi_resubmit. 
 *
 * CALLER
 *	Called by pg_submit().
 *
 * DIAGNOSTICS
 *	Returns GDI_FAILURE or GDI_SUCCESS;
 *
 * AUTHOR
 *	J. T. Anderson
 */

#ifndef lint
static char SccsId[] = "@(#)pg_parse.c	16.1 8/3/93 Copyright (c) 1992-1993 Science Applications International Corporation";
#endif

#include "gdi_postgres.h"

extern char *strtok();

/* ===============================  pg_parse() ================================
 *
 * Public.
 */
dbStatus
pg_parse(d, query, pq, pq_len)
dbConn	*d;
char	*query;		/* (i)   complete query string */
char	*pq;		/* (i/o) postquel command (retrieve, create, etc.) */
int	pq_len;		/* (i)   size of pq */
{
	char	*p=NULL, *q=NULL;
	char	command[PG_SHORT_COMMAND_SIZE];
	char	sub_command[PG_SHORT_COMMAND_SIZE];
	int	pcode;
        int     query_size;

        query_size=strlen(query);

		/* copy the query */
	if (( q = UCALLOC(char, query_size + 1)) == NULL ) {
		(void) gdi_error_unix (d, "pg_parse");
		return(PG_ALLOC_FAIL);
	}

	(void) pg_strncpy(q, query, query_size, query_size);

	p = strtok(q, " \n\t");
	(void) pg_strncpy(command, p, sizeof(command) - 1, strlen(p));
	(void) pg_strncpy(pq, command, pq_len - 1, strlen(command));

	switch(command[0])
	{
	   case 'a':
		if (STREQL (command, "abort"))
			pcode = PG_ABORT;
		else if (STREQL (command, "addattr")) 
			pcode = PG_ADDATTR;
		else if (STREQL (command, "append"))
			pcode = PG_APPEND;
		else if (STREQL (command, "attachas")) 
			pcode = PG_ATTACHAS;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'b':
		if (STREQL (command, "begin")) 
			pcode = PG_BEGIN;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'c':
		if (STREQL (command, "change")) {
			pcode = PG_CHANGE_ACL;
			strncat(pq, " acl", pq_len - 1 );
		}

		else if (STREQL (command, "close"))
			pcode = PG_CLOSE;
		else if (STREQL (command, "cluster"))
			pcode = PG_CLUSTER;
		else if (STREQL (command, "copy")) 
			pcode = PG_COPY;
		else if (STREQL (command, "create")) 
		{
			p = strtok((char *)NULL," \n\t");
			(void) pg_strncpy(sub_command, p, 
				sizeof(sub_command) - 1, strlen(p));
			if (STREQL (sub_command, "version")) {
				pcode = PG_CREATE_VERSION;
				strncat(pq, " version", pq_len - 1 );
			}
			else
				pcode = PG_CREATE;
		}
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'd':
		if (STREQL (command, "define")) 
		{
			p = strtok((char *)NULL," \n\t");

			(void) pg_strncpy(sub_command, p,
				sizeof(sub_command) - 1, strlen(p));
			sub_command[sizeof(sub_command) - 1] = '\0';

			strncat(pq, " ", pq_len - 1 );
			strncat(pq, sub_command, pq_len - 1 );

			if (STREQL (sub_command, "aggregate"))
			   pcode = PG_DEFINE_AGGREGATE;
			else if (STREQL (sub_command, "function"))
			   pcode = PG_DEFINE_FUNCTION;
			else if (STREQL (sub_command, "index"))
			   pcode = PG_DEFINE_INDEX;
			else if (STREQL (sub_command, "operator"))
			   pcode = PG_DEFINE_OPERATOR;
			else if (STREQL (sub_command, "rule")) 
			   pcode = PG_DEFINE_RULE;
			else if (STREQL (sub_command, "type"))
			   pcode = PG_DEFINE_TYPE;
			else if (STREQL (sub_command, "view"))
			   pcode = PG_DEFINE_VIEW;
			else
			   pcode = PG_UNKNOWN_QUERY;
		}
		else if (STREQL (command, "delete")) 
			pcode = PG_DELETE;
		else if (STREQL (command, "destroy"))
			pcode = PG_DESTROY;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'e':
		if (STREQL (command, "extend")) 
			pcode = PG_EXTEND;
		else if (STREQL (command, "end"))
			pcode = PG_END;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'f':
		if (STREQL (command, "fetch")) 
			pcode = PG_FETCH;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'l':
		if (STREQL (command, "listen")) 
			pcode = PG_LISTEN;
		else if (STREQL (command, "load")) 
			pcode = PG_LOAD;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'm':
		if (STREQL (command, "merge")) 
			pcode = PG_MERGE;
		else if (STREQL (command, "move")) 
			pcode = PG_MOVE;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'n':
		if (STREQL (command, "notify")) 
			pcode = PG_NOTIFY;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'p':
		if (STREQL (command, "purge")) 
			pcode = PG_PURGE;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'r':
		if (STREQL (command, "remove")) 
		{
			p = strtok((char *)NULL," \n\t");
			(void) pg_strncpy(sub_command, p, 
				sizeof(sub_command) - 1, strlen(p));

			strncat(pq, " ", pq_len - 1 );
			strncat(pq, sub_command, pq_len - 1 );

			if (STREQL (sub_command, "aggregate"))
			   pcode = PG_REMOVE_AGGREGATE;
			else if (STREQL (sub_command, "function"))
			   pcode = PG_REMOVE_FUNCTION;
			else if (STREQL (sub_command, "index"))
			   pcode = PG_REMOVE_INDEX;
			else if (STREQL (sub_command, "operator"))
			   pcode = PG_REMOVE_OPERATOR;
			else if (STREQL (sub_command, "rule")) 
			   pcode = PG_REMOVE_RULE;
			else if (STREQL (sub_command, "type"))
			   pcode = PG_REMOVE_TYPE;
			else if (STREQL (sub_command, "view"))
			   pcode = PG_REMOVE_VIEW;
			else
			   pcode = PG_UNKNOWN_QUERY;
		}
		else if (STREQL (command, "rename")) 
			pcode = PG_RENAME;
		else if (STREQL (command, "replace")) 
			pcode = PG_REPLACE;
		else if (STREQL (command, "retrieve")) 
		{
			p = strtok((char *)NULL," \n\t");
			(void) pg_strncpy(sub_command, p, 
				sizeof(sub_command) - 1, strlen(p));

			if (STREQL (sub_command, "into")) {
			   strncat(pq, " into", pq_len - 1 );
			   pcode = PG_RETRIEVE_INTO;
			}
			else
			   pcode = PG_RETRIEVE;
		}
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   case 'v':
		if (STREQL (command, "vacuum")) 
			pcode = PG_VACUUM;
		else	pcode = PG_UNKNOWN_QUERY;
		break;
	   default:
		pcode = PG_UNKNOWN_QUERY;
		break;
	}

	pq[pq_len - 1] = '\0';

	UFREE(q);
	return(pcode);
}

/* ===============================  pg_query() ================================
 *
 * Public.
 */
dbStatus
pg_query(d, chan, q_in, q_out, q_len, portal )
dbConn	*d;		/* (i) database connector */
int	chan;		/* (i) query channel      */
char	*q_in;		/* (i) original query */
char	*q_out;		/* (i/o) final query */
int	q_len;		/* (i) size of q_out */
char	*portal;	/* (i/o) final portal name, gets filled here */
{
	char	*q=NULL, *c=NULL;
        int     query_size;

	if( ( q_out == NULL ) || (q_len <= 0 ) ) {
		gdi_error_app(d, GDI_BADDATA, 
			"pg_query: output query buffer is NULL: ");
		return (GDI_FAILURE);
	}

        query_size = strlen(q_in);

		/* Copy the original query */
	if (( q = UCALLOC(char, query_size + 1)) == NULL )
		return ( gdi_error_unix (d, "pg_query") );

	(void) pg_strncpy(q, q_in, query_size, query_size);
	(void) pg_strncpy (q_out, "retrieve portal ", q_len - 1, 16);

	c = strtok(q, " \n\t");               /* "retrieve" */
	c = strtok((char *)NULL," \n\t");     /* "portal", maybe   */

	if (STREQL (c, "portal") )
	{		/* Use the portal name specified by the user */
		c = strtok((char *)NULL," \n\t");	/* get portal name */
		(void) pg_strncpy (portal, c, 
			PG_PORTAL_NAME_SIZE - 1, strlen(c));
		strncat(q_out, portal, q_len - 1);
		strncat(q_out, " ", q_len - 1);
		q_out[q_len - 1] = '\0';
	}
	else
	{               /* Use default portal name */
		(void) pg_strncpy(portal, PG_PORT_NAME(d,chan), 
			PG_PORTAL_NAME_SIZE - 1, strlen(PG_PORT_NAME(d,chan)));

		strncat (q_out, portal, q_len - 1);
		strncat(q_out, " ", q_len - 1);
		strncat (q_out, c, q_len - 1);
		strncat(q_out, " ", q_len - 1);
		q_out[q_len - 1] = '\0';
	}

		/* fill in the rest of the query */
        while ( (c = strtok((char *)NULL," \n\t")) != NULL) {
                strncat (q_out, c, q_len - 1);
                strncat (q_out, " ", q_len - 1);
		q_out[q_len - 1] = '\0';
        }

	q_out[q_len - 1] = '\0';

	UFREE(q);
	return(GDI_SUCCESS);
}
