/* SQLBUILD.C
 *
 * Build SQL 'update' or 'insert' code chunk ...
 *
 * This has to be a sinterp module so that generated SQL can be captured by #sql ...
 *
 * Copyright 1998-2004 Stephen C. Grubb  (quisp.sourceforge.net)
 * This code is covered under the GNU General Public License (GPL);
 * see the file ./Copyright for details. 
 */

#include "tdhkit.h"

extern int TDH_sqltabdef();


static char *fnames[MAXITEMS];
static char omitlist[DATAMAXLEN];
static char qexceplist[DATAMAXLEN];
static int nsqlfields;
static char smode, qmode;
static int nlinesout;
static char commandstart[128];

/* syntax: #sqlbuild  insert|update  table  quotemode  [omit=fieldnamelist]  [noquote=fieldnamelist]  [quote=fieldnamelist] */

int
sqlbuild0( line, ss )
char *line;
struct sinterpstate *ss;
{
int i, ix, stat;
char table[MAXPATH], tok[DATAMAXLEN];

strcpy( omitlist, "" );
strcpy( qexceplist, "" );
nlinesout = 0;


/* parse the #sqlbuild line.. */
ix = 0;
strcpy( tok, GL_getok( line, &ix ));	/* skip over #sqlbuild.. */

strcpy( tok, GL_getok( line, &ix ));	/* type of sql to build, either insert or update */
smode = tok[0]; /* i or u */
if( smode == 'n' ) smode = 'i';  
if( smode != 'i' && smode != 'u' ) return( err( 2750, "sqlbuild: expecting command mode of 'insert' or 'update'", "" ));

strcpy( table, GL_getok( line, &ix )); 	/* table */

strcpy( tok, GL_getok( line, &ix )); 	/* quotemode */
if( tok[0] == '\0' ) return( err( 2750, "sqlbuild: not enough parameters", "" ));
qmode = tok[0];
if( qmode != 'q' && qmode != 'n' ) return( err( 2750, "sqlbuild: expecting quote mode of 'quote' or 'noquote'", "" ));

while( 1 ) {
	strcpy( tok, GL_getok( line, &ix ));  	
	if( tok[0] == '\0' ) break;

	if( strncmp( tok, "noquote=", 8 )==0 || strncmp( tok, "quote=", 6 )==0 ) {
		strcpy( qexceplist, &tok[8] );
		for( i = 0; qexceplist[i] != '\0'; i++ ) if( qexceplist[i] == ',' ) qexceplist[i] = ' ';
		}

	else if( strncmp( tok, "omit=", 5 )==0 ) {
		strcpy( omitlist, &tok[5] );
		for( i = 0; omitlist[i] != '\0'; i++ ) if( omitlist[i] == ',' ) omitlist[i] = ' ';
		}
	}

TDH_altfmap( 1 );
stat = TDH_sqltabdef( table, fnames, &nsqlfields );	/* caution - fnames points to info which is overwritten upon next
							   processed shsql command.  Even tho fnames are stored static herein,
							   it's safe because sqlbuild0 and sqlbuild1 are tightly 
							   coupled (guaranteed to be invoked one after the other) with
							   no chance for a shsql command to be submitted in between. */
TDH_altfmap( 0 );

if( stat != 0 ) return( err( stat, "sqlbuild: invalid table", table ));

ss->sqlbuildi = 1;
if( smode == 'i' ) sprintf( commandstart, "insert into %s values ( ", table );
else sprintf( commandstart, "update %s set ", table );
return( 0 );
}

/* ===================================== */
/* generate sql code for one item */
int
sqlbuild1( line, ss )
char *line;			/* built here and sent back.. */
struct sinterpstate *ss;
{
int i, itemi, doquote, stat;
char val[DATAMAXLEN];

/* ss->sqlbuildi-1 points to the item that we are to generate code for here */
itemi = ss->sqlbuildi - 1;
if( itemi < 0 ) return( 1 ); /* sanity */

while( 1 ) {
	if( GL_smember( fnames[itemi], omitlist )) {
		(ss->sqlbuildi)++;
		if( ss->sqlbuildi > nsqlfields ) {
			ss->sqlbuildi = 0; /* indicate we're done */
			return( 0 );
			}
		itemi++;
		}
	else break;
	}

/* process the item */

doquote = 1;
if( GL_smember( fnames[itemi], qexceplist ) && qmode == 'q' ) doquote = 0;
else if( ! GL_smember( fnames[itemi], qexceplist ) && qmode == 'n' ) doquote = 0;

/* enclose val in double quotes, except for NULL .. */
if( doquote ) {
	stat = TDH_getvar( fnames[itemi], &val[1] );
	if( stat != 0 ) strcpy( val, DBNULL );
	else if( val[1] == '\0' || stricmp( &val[1], DBNULL )==0 ) strcpy( val, DBNULL );
	else	{
		/* convert embedded double quotes to single quotes */
		for( i = 1; val[i] != '\0'; i++ ) if( val[i] == '"' ) val[i] = '\''; 
		val[0] = '"';
		val[i] = '"';
		val[i+1] = '\0';
		}
	}

/* don't enclose val in quotes */
else	{
	stat = TDH_getvar( fnames[itemi], val );
	if( stat != 0 ) strcpy( val, DBNULL );
	else if( val[0] == '\0' ) strcpy( val, DBNULL );
	}

/* now build an output line, either part of an 'update' chunk, or part of an 'insert' chunk.. */
if( smode == 'u' ) sprintf( line, "  %s %s = %s\n", (nlinesout>0)?",":commandstart, fnames[itemi], val );
else sprintf( line, "  %s %s\n", (nlinesout>0)?",":commandstart, val );

nlinesout++;

(ss->sqlbuildi)++;
if( ss->sqlbuildi > nsqlfields ) {
	ss->sqlbuildi = 0;
	if( smode == 'i' ) strcat( line, " )" ); /* finish up the insert command.. */
	}
return( 0 );
}
