/* SQLINS.C - implement shsql INSERT
 * Copyright 1998-2001 Stephen C. Grubb  (www.sgpr.net) .
 * This code is covered under the GNU General Public License (GPL);
 * see the file ./Copyright for details. */

#include "tdhkit.h"
#include "shsql.h"

int
SHSQL_insert( frag, nfrag )
char *frag[];
int nfrag;
{
int k;
char data[MAXITEMS][DATAMAXLEN+1];
char buf[MAXRECORDLEN+1];
int i, j, ix, stat;
char tok[DATAMAXLEN+1];
int nreq;
char table[ MAXPATH ];
char reqname[MAXITEMS][40];
char filename[ MAXPATH ];
int nfdf;
int len;
int req_use_fdf;
int ifld;
FILE *fp;


k = 0;
nreq = 0;
strcpy( table, "" );
req_use_fdf = 0;

/* TDH_valuesubst_settings( "shieldquotedvars", 1 ); */ /* don't evaluate vars within quoted strings 
							in insert statements */


/* INSERT INTO.. */
/* 1st frag holds "insert"; 2nd holds "into table" */
k = 1;
ix = 0;
strcpy( tok, GL_getok( frag[k], &ix ) ); /* into */
if( stricmp( tok, "into" ) != 0 ) return( SHSQL_err( 240, "sql insert: 'into' expected", "" ) );
GL_getchunk( table, frag[k], &ix, " " );

/* get field names */
for( i = 0; i < MAXITEMS; i++ ) {
	GL_getchunk( reqname[i], frag[k], &ix, ", " );
	if( reqname[i][0] == '\0' ) break;
	}
nreq = i;


TDH_altfmap( 1 );
stat = SHSQL_loadfieldmap( table );
if( stat != 0 ) return( stat );
nfdf = fieldmap( "" );
TDH_altfmap( 0 );



if( nreq == 0 ) {
	req_use_fdf = 1;
	nreq = nfdf;
	}

for( i = 0; i < nfdf; i++ ) strcpy( data[i], TDH_dbnull );




/* VALUES */
k++;
if( k >= nfrag ) return( SHSQL_err( 242, "sql insert: 'values' expected", "" ) );
ix = 0;
GL_getchunk( tok, frag[k], &ix, ", " );
if( stricmp( tok, "values" )!= 0 ) return( SHSQL_err( 243, "sql insert: 'values' expected", "" ) );

for( i = 0; i < nreq; i++ ) {
	GL_getchunk( tok, frag[k], &ix, ", " ); /* get value */
	if( strncmp( tok, "@_QS", 4 )==0 ) TDH_getvar( &tok[1], tok );
	if( strcmp( tok, "" )==0 || stricmp( tok, TDH_dbnull )==0 ) strcpy( tok, TDH_dbnull ); /* avoid case probs w/ null */
	if( req_use_fdf ) ifld = i;
	else	{
		TDH_altfmap( 1 );
		ifld = fieldmap( reqname[i] );
		TDH_altfmap( 0 );
		if( ifld < 0 ) return( SHSQL_err( 244, "sql insert: unrecognized field name", reqname[i] ) );
		}
	for( j = 0, len = strlen( tok ); j < len; j++ ) if( isdelim( tok[j] ) ) tok[j] = '_';	/* datadelim */

	strcpy( data[ifld], tok );
	}

/* lock table */
stat = SHSQL_lock( table );
if( stat != 0 ) return( SHSQL_err( SHSQL_TABLELOCKED, "update refused.. try again in a few minutes", table ) );


/* open the data file.. */
sprintf( filename, "%s/data/%s", SHSQL_projdir, table );
fp = fopen( filename, "a" );
if( fp == NULL ) return( SHSQL_err( 245, "sql insert: cannot open data file to write", table ) ); 

/* now insert the new record */
stat = SHSQL_newrec( table, fp, data, nfdf, buf, 1 );
fclose( fp );
if( stat != 0 ) return( SHSQL_err( stat, "sql insert: error on insert of new data record", table ) );
SHSQL_nrows = 1;

/* unlock table */
SHSQL_unlock( );

return( 0 );
}

/* ============================================== */
/* SHSQL_NEWREC - append a new data record.  Returns 0 if ok; otherwise an error code */

int
SHSQL_newrec( table, fp, data, size, buf, logtrans )
char *table;
FILE *fp;	
char data[][DATAMAXLEN+1];  /* if NULL, content is already in buf, and size is size of buf */
int size;	/* number of items in data array, or else size of buf */
char *buf;	/* buf of size MAXRECORDLEN - holds output record (may be built here or passed in) */
int logtrans;   /* 1 = log it,   0 = don't */
{
int i, nitems;
int reclen, nextlen, padlen;

if( logtrans ) SHSQL_log( "add", table, data, size, buf );

if( data != NULL ) {
	nitems = size;
	reclen = 0;
	for( i = 0; i < nitems; i++ ) {
		nextlen = reclen + strlen( data[i] );
		if( nextlen >= (MAXRECORDLEN-2) ) return( 246 ); /* SHSQL_err - record will be too long */
		strcpy( &buf[ reclen ], data[i] );
		reclen = nextlen;
		strcpy( &buf[ reclen++ ], SHSQL_delims );
		}
	}
else reclen = size;

/* compute appropriate padding length and add padding to end of record.. */
padlen = reclen * 0.2; /* 20% */
if( padlen < RECPADLEN ) padlen = RECPADLEN;
if ( reclen+padlen > (MAXRECORDLEN-2) ) padlen = 0;
for( i = 0; i < padlen; i++ ) buf[reclen++] = SHSQL_delim;
buf[reclen++] = '\n';
buf[reclen] = '\0';

/* output the record */
fseek( fp, 0, SEEK_END );
fputs( buf, fp );
fflush( fp );

return( 0 );
}
