/* SQLDEL.C - DELETE
 * Copyright 1998-2002 Stephen C. Grubb  
 * This code is covered under the GNU General Public License (GPL);
 * see the file ./Copyright for details. */

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


/* Note: it is not considered an error if where clause does not match any records -- 
	caller should check affected row count */
int
SHSQL_delete( frag, nfrag )
char *frag[];
int nfrag;
{
int i, j, k;
char buf[MAXRECORDLEN+1];
int ix, stat;
char tok[DATAMAXLEN+1];
char table[MAXPATH];
FILE *fp;
char **rows;
struct selectparms sp;
long physloc;
int reclen;
int ilt, ilo, doing_recordlock, recordlock_error, errorflag;


strcpy( table, "" );

k = 0;


/* DELETE.. */
/* "delete" is in 1st chunk;  "from table" is in 2nd chunk */
k = 1;
ix = 0;
strcpy( tok, GL_getok( frag[k], &ix ) ); /* from */
if( stricmp( tok, "from" ) != 0 ) return( SHSQL_err( 230, "sql delete: 'from' expected", "" ) );
strcpy( table, GL_getok( frag[k], &ix ) ); 
strcpy( tok, GL_getok( frag[k], &ix ) ); 


/* WHERE */
k++;
if( k >= nfrag ) return( SHSQL_err( 231, "sql delete: 'where' expected", "" ) );
ix = 0;
strcpy( tok, GL_getok( frag[k], &ix ) );
if( stricmp( tok, "where" )!= 0 ) return( SHSQL_err( 232, "sql delete: 'where' clause expected", "" ) );

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

/* build a select command to locate eligible records.. */
sprintf( buf, "select * from %s %s %s", table, frag[ k ], ((nfrag-1)>k)? frag[k+1]:"" );
SHSQL_loclistmode( 1 ); /* turn on loclist mode */
SHSQL_command( buf );
stat = SHSQL_fetchrows( &rows, SHSQL_maxrows_update, &sp ); 
SHSQL_free( rows, &sp ); /* we can free the rows right away because all we are after is the physloc list.. */
SHSQL_loclistmode( 0 ); /* turn off loclist mode */

if( stat != 0 ) return( stat ); /* any error on retrieval (including MAXROWS exceeded) cancels the delete operation */
else if( stat == 1 ) return( 0 ); /* no matching rows found - not an error */

TDH_altfmap( 1 );
ilt = fieldmap( "_locktime" );  /* fieldmap filled by select done above */
ilo = fieldmap( "_lockowner" );
TDH_altfmap( 0 );
if( ilt >= 0 && ilo >= 0 ) doing_recordlock = 1;
else doing_recordlock = 0;
recordlock_error = 0;

sprintf( buf, "%s/data/%s", SHSQL_projdir, table );
fp = fopen( buf, "r+" );
if( fp == NULL ) return( SHSQL_err( 234, "sql delete: cannot open table file ", table ) );


/* loop across all records found.. */
errorflag = 0;
for( i = 0; ; i++ ) {
	stat = SHSQL_nextloc( &physloc, &reclen );
	if( stat ) break;
	stat = fseek( fp, physloc, SEEK_SET );
	fgets( buf, MAXRECORDLEN, fp );
	if( doing_recordlock ) {
		stat = SHSQL_check_rlock_rec( buf, ilt, ilo );
		if( stat != 0 ) { recordlock_error = 1; continue; } /* record is locked */ 
		}

	stat = fseek( fp, physloc, SEEK_SET );
	if( stat ) { errorflag = 235; continue; }  /* SHSQL_err - write seek error */

	SHSQL_log( "delete", table, NULL, 0, buf );

	/* rub out the record.. */
	for( j = 0; j < reclen-1; j++ ) buf[j] = SHSQL_delim;
	buf[j] = '\0';
	fputs( buf, fp );
	fflush( fp );
	}

if( SHSQL_debug ) fprintf( stderr, "%d rows deleted\n", i );

SHSQL_freeloclist();
fclose( fp );
SHSQL_nrows = i;


SHSQL_unlock( );

if( recordlock_error ) return( SHSQL_RECORDLOCKED );
return( errorflag );
}
