"Fossies" - the Fresh Open Source Software archive 
Member "leap-1.2.6.1/src/cond.c" of archive leap-1.2.6.1.tar.gz:
/*
* Name: cond.c
* Description: Routines for evaluating conditions against tuples.
* Version: cond.c,v 1.9.2.1 2004/02/09 20:05:20 rleyton Exp
*
* LEAP RDBMS - An extensible and free RDBMS
* Copyright (C) 1995-2004 Richard Leyton
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* See the file COPYING for more information.
*
* Richard Leyton
* leap@leyton.org
* http://leap.sourceforge.net
* http://www.leyton.org
*
*/
#ifdef HAVE_CONFIG_H
# include "defines.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "consts.h"
#include "globals.h"
#include "dtypes.h"
#include "errors.h"
#include "cond.h"
#include "tuples.h"
#include "util.h"
#include "relation.h"
#include "leapio.h"
#include "regexp.h"
boolean do_int_eval(int boolval,
attribute left_attr, char *lptr,
attribute right_attr, char *rptr,
boolean *errorflag) {
/* do_int_eval
* Performs an integer based evaluation of the data
*/
int lint=0,rint=0,errs=-1, err= 0;
boolean cresult=FALSE;
regexp *regresult;
do_debug(DEBUG_ENTER,"Start: do_int_eval\n");
/* Mark no error. */
*errorflag=FALSE;
/* Convert the left attribute to a number */
errs=sscanf(lptr,"%d",&lint);
/* Check for conversion errors */
if (errs==EOF) {
/* An error occured */
*errorflag=TRUE;
raise_error(ERROR_TYPE_CONVERSION,NONFATAL,lptr);
do_debug(DEBUG_ENTER,"End (Error): do_int_eval\n");
} else {
/* No error occured */
/* Convert the right attribute to a number */
errs=sscanf(rptr,"%d",&rint);
/* If an error occured during conversion */
if (errs==EOF) {
/* Mark the error, and abort */
*errorflag=TRUE;
raise_error(ERROR_TYPE_CONVERSION,NONFATAL,rptr);
do_debug(DEBUG_ENTER,"End (Error): do_int_eval\n");
} else {
/* Depending on the type of evaluation... */
switch (boolval) {
/* Calculate the result */
case BOOLEAN_EQUAL : cresult=(lint==rint);
break;
case BOOLEAN_NOT_EQUAL : cresult=(lint!=rint);
break;
case BOOLEAN_GREATER_THAN : cresult=(lint>rint);
break;
case BOOLEAN_GREATER_EQUAL_THAN : cresult=(lint>=rint);
break;
case BOOLEAN_LESS_THAN : cresult=(lint<rint);
break;
case BOOLEAN_LESS_EQUAL_THAN : cresult=(lint<=rint);
break;
case BOOLEAN_LIKE:
regresult=regcomp(rptr);
if (regresult==NULL) {
raise_error( ERROR_REGEXP,NONFATAL,rptr);
}
do_debug(DEBUG_ENTER,"Start (LEAP): regexec\n");
err=regexec(regresult, lptr);
do_debug(DEBUG_ENTER,"End (LEAP): regexec\n");
do_debug(DEBUG_INFO,"err: [%d]\n",err);
if (err==0) {
cresult=FALSE;
} else {
cresult=TRUE;
}
do_debug(DEBUG_INFO,"cresult: [%d]\n",cresult);
free(regresult);
break;
default : raise_error(ERROR_UNDEFINED,NONFATAL,"Something Strange has happenened (Query evaluation)");
*errorflag=TRUE;
do_debug(DEBUG_ENTER,"End (Error): do_int_eval\n");
break;
}
}
}
do_debug(DEBUG_ENTER,"End (Ok): do_int_eval\n");
/* Return the result */
return(cresult);
}
boolean do_string_eval(int boolval,
attribute left_attr, char *lptr,
attribute right_attr, char *rptr,
boolean *errorflag) {
boolean cresult=FALSE;
regexp *regresult;
int err;
do_debug(DEBUG_ENTER,"Start: do_string_eval\n");
*errorflag=FALSE;
if ( (status_debug) && (lptr) && (rptr) ){
do_debug(DEBUG_MODERATE,"STR COMP: Left==[%s] Right==[%s]\n",lptr,rptr);
}
/* Convert to upper case if case sensitivity is on */
if (status_case==TRUE) {
upcase(lptr);
upcase(rptr);
}
switch (boolval) {
case BOOLEAN_EQUAL : cresult=(strcmp(lptr,rptr)==0);
break;
case BOOLEAN_NOT_EQUAL : cresult=(strcmp(lptr,rptr)!=0);
break;
case BOOLEAN_GREATER_THAN : cresult=(strcmp(lptr,rptr)>0);
break;
case BOOLEAN_GREATER_EQUAL_THAN : cresult=(strcmp(lptr,rptr)>=0);
break;
case BOOLEAN_LESS_THAN : cresult=(strcmp(lptr,rptr)<0);
break;
case BOOLEAN_LESS_EQUAL_THAN : cresult=(strcmp(lptr,rptr)<=0);
break;
case BOOLEAN_LIKE:
do_debug(DEBUG_INFO,"Regular expression string comparison\n");
do_debug(DEBUG_ENTER,"Start (LEAP): regcomp\n");
regresult=regcomp(rptr);
do_debug(DEBUG_ENTER,"End (LEAP): regcomp\n");
if (regresult==NULL) {
raise_error( ERROR_REGEXP,NONFATAL,rptr);
do_debug(DEBUG_ENTER,"End (LEAP-Err): regcomp\n");
}
do_debug(DEBUG_ENTER,"Start (LEAP): regexec\n");
err=regexec(regresult, lptr);
do_debug(DEBUG_ENTER,"End (LEAP): regexec\n");
do_debug(DEBUG_INFO,"err: [%d]\n",err);
if (err==0) {
cresult=FALSE;
} else {
cresult=TRUE;
}
do_debug(DEBUG_INFO,"cresult: [%d]\n",cresult);
free(regresult);
break;
default : raise_error(ERROR_UNDEFINED,NONFATAL,"Something Strange has happenened (Query evaluation)");
do_debug(DEBUG_ENTER,"End (Error): do_string_eval\n");
*errorflag=TRUE;
break;
}
do_debug(DEBUG_ENTER,"End (Ok): do_string_eval\n");
return(cresult);
}
boolean evaluate( condp condition,
tuple ltuple, tuple rtuple ) {
/* evaluate
* Evaluates a condition based on condition structure, and
* specified tuple, and returns TRUE or FALSE
*/
condp ccond;
boolean errorflag=FALSE,cresult=FALSE,final_result=FALSE;
int booleanops[MAXIMUM_ATTRIBUTES]; /* For boolean operators */
boolean allresults[MAXIMUM_ATTRIBUTES]; /* For results */
int counter,noresults;
char *lptr,*rptr;
int ldtype=DT_UNDEFINED, rdtype=DT_UNDEFINED;
do_debug(DEBUG_ENTER,"Start: evaluate\n");
ccond=condition;
counter=0;
while ( (errorflag==FALSE) && (ccond!=NULL) ) {
if (ccond->left_field==TRUE) {
lptr=ccond->left_attribute_val;
} else {
lptr=ccond->left;
}
if (ccond->right_field==TRUE) {
rptr=ccond->right_attribute_val;
} else {
rptr=ccond->right;
}
if (ccond->left_field == TRUE) {
ldtype=ccond->left_attribute->data_type;
} else {
ldtype=DT_UNDEFINED;
}
if (ccond->right_field == TRUE) {
rdtype=ccond->right_attribute->data_type;
} else {
rdtype=DT_UNDEFINED;
}
if ( (ldtype!=DT_UNDEFINED) && (rdtype!=DT_UNDEFINED) ) {
if ( (ldtype!=rdtype) ) {
raise_error(ERROR_TYPE_INCOMPATIBLE,NONFATAL,"");
return(FALSE);
}
}
if ( (ldtype==DT_NUMBER) || (rdtype==DT_NUMBER) ) {
cresult=do_int_eval(ccond->boolval, ccond->left_attribute, lptr, ccond->right_attribute, rptr, &errorflag);
} else
if ( (ldtype==DT_STRING) || (rdtype==DT_STRING) ) {
cresult=do_string_eval(ccond->boolval, ccond->left_attribute, lptr, ccond->right_attribute, rptr, &errorflag);
} else
if ( (ldtype==DT_BOOLEAN) || (rdtype==DT_BOOLEAN) ) {
cresult=do_string_eval(ccond->boolval, ccond->left_attribute, lptr, ccond->right_attribute, rptr, &errorflag);
} else
cresult=do_string_eval(ccond->boolval, ccond->left_attribute, lptr, ccond->right_attribute, rptr, &errorflag);
/* Capture information to save repassing Condition structure */
allresults[counter]=cresult;
booleanops[counter]=ccond->boolean_condition;
/* Move onto the next item */
counter++;
ccond=ccond->next_condition;
}
noresults=counter;
final_result=allresults[0];
for (counter=1; counter<noresults; counter++) {
switch (booleanops[counter-1]) {
case BOOLEAN_AND : final_result=(final_result && allresults[counter]);
break;
case BOOLEAN_OR : final_result=(final_result || allresults[counter]);
break;
case BOOLEAN_XOR : raise_error(ERROR_UNIMPLEMENTED, NONFATAL, "XOR - Sorry to have lead you on...");
do_debug(DEBUG_ENTER,"End (Unimplemented=Err): evaluate\n");
break;
case BOOLEAN_END_MARKER : break; /* Do nothing. The end is nigh */
default : raise_error(ERROR_UNIMPLEMENTED,NONFATAL,"Unsupported boolean operator.");
do_debug(DEBUG_ENTER,"End (Unsupported=Err): evaluate\n");
break;
}
}
do_debug(DEBUG_ENTER,"End (Ok): evaluate\n");
return(final_result);
}
boolean string_position_ok(int cpos, int string_length, char *text) {
/* check_string_position
* Check the current position (cpos) in the string (string_length),
* whilst evaluating text
*/
/* If cposition = string_length at this stage, we're missing
* some important features!
*/
if (cpos>=string_length) {
raise_error(ERROR_EVALUATING_EXPR,NONFATAL,text);
return(FALSE);
} else {
return(TRUE);
}
}
int get_first_expression(char *text,
condp cond) {
/* get_first_expression
* Takes an expression from the string specified (text), where
* a string is seperated by boolean expressions in the bool array
* REWRITE: This needs to be tidied up somewhat.
*/
int start=0,cposition=0,boolean_start=0,boolean_end=0,endpos=0,string_length=0;
int start_end=0, end_start=0;
boolean errorflag=FALSE,sposok;
char temp[MAXIMUM_EXPRESSION],*lptr,*rptr;
string_length=strlen(text);
cond->left_always=ALWAYS_UNKNOWN;
cond->right_always=ALWAYS_UNKNOWN;
#ifdef FULL_DEBUG
fprintf(stderr,"About to process (%d): %s\n",string_length,text);
#endif
/* This section here locates the start and end of the appropriate
* sections of the expression: left bool right
*/
/* Locate the first text */
while ( (cposition<string_length) && ( ( (text[cposition]==' ') || (text[cposition]=='(') )
&& ( (text[cposition]<'A') || (text[cposition]>'Z') )
&& ( (text[cposition]<'a') || (text[cposition]>'z') ) ) ) {
cposition++;
}
/* Store the start of the text */
start=cposition;
/* Check the string position. Return early if things don't work */
sposok=string_position_ok(cposition,string_length,text);
if ( sposok != TRUE ) {
return(RETURN_ERROR);
}
/* Scan through the string to locate the first non
* character, ie. condition - <, <=, =, >=, >, <>
* OR SPACE! or TILDE
*/
/* Locate the start of the condition */
while ( (cposition<string_length) && (text[cposition]!='=') && (text[cposition]!='<')
&& (text[cposition]!='>') && (text[cposition]!=' ') && (text[cposition]!='~')) {
cposition++;
}
/* Check the string position. Return early if things don't work */
sposok=string_position_ok(cposition,string_length,text);
/* Record END of STARTing section */
start_end=cposition;
if (text[cposition]==' ') {
/* Skip over any spaces between left val and condition */
while ( (cposition<string_length) && (text[cposition]==' ')) {
cposition++;
}
}
/* Store the start of the condition */
boolean_start=cposition;
/* Locate the end of the condition */
while ( (cposition<string_length) && ( (text[cposition]=='=') || (text[cposition]=='<')
|| (text[cposition]=='>') || (text[cposition]=='~') ) ){
cposition++;
}
/* Check the string position. Return early if things don't work */
sposok=string_position_ok(cposition,string_length,text);
if ( sposok != TRUE ) {
return(RETURN_ERROR);
}
/* boolean_end is also the start of the next field */
boolean_end=cposition;
if (text[cposition]==' ') {
/* Skip over any spaces between left val and condition */
while ( (cposition<string_length) && (text[cposition]==' ')) {
cposition++;
}
}
end_start=cposition;
while ( (cposition<string_length) && (text[cposition]!=')')) {
cposition++;
}
endpos=cposition;
/* Populate the string fields with all the details */
/* Second bit is placing a NULL char at the end, to make
* sure it is properly terminated.
*/
strncpy(cond->left,&text[start],start_end-start);
cond->left[start_end-start]='\0';
strncpy(cond->bool,&text[boolean_start],boolean_end-boolean_start);
cond->bool[boolean_end-boolean_start]='\0';
strncpy(cond->right,&text[end_start],endpos-end_start);
cond->right[endpos-end_start]='\0';
do_debug( DEBUG_MODERATE,"Left: >%s< Bool: >%s< Right: >%s<\n",cond->left, cond->bool, cond->right);
/* Check the first character of the left item, if it is
* a quote, then it is a value, otherwise it is a field
* that will need to be resolved each time
*/
if ( (lptr=strpbrk(cond->left,VALUES))!=NULL) {
cond->left_field=FALSE;
lptr++;
strcpy(temp,lptr);
strcpy(cond->left,temp);
rptr=strpbrk(cond->left,VALUES);
if (rptr!=NULL) {
/* Make the quote the end of the string */
*rptr='\0';
} else {
raise_error(ERROR_NO_CLOSING_QUOTE,NONFATAL,cond->left);
errorflag=TRUE;
}
} else {
/* Check that the left string is not TRUE or FALSE */
if (strcmp(cond->left,TRUE_STRING)==0) {
cond->left_always=ALWAYS_TRUE;
} else if (strcmp(cond->left,FALSE_STRING)==0) {
cond->left_always=ALWAYS_FALSE;
} else {
cond->left_field=TRUE;
}
}
/* Check the first character of the right item, if it is
* a quote, then it is a value, otherwise it is a field
* that will need to be resolved each time
*/
if ( (lptr=strpbrk(cond->right,VALUES))!=NULL) {
cond->right_field=FALSE;
lptr++;
strcpy(temp,lptr);
strcpy(cond->right,temp);
rptr=strpbrk(cond->right,VALUES);
if (rptr!=NULL) {
/* Make the quote the end of the string */
*rptr='\0';
} else {
raise_error(ERROR_NO_CLOSING_QUOTE,NONFATAL,cond->right);
errorflag=TRUE;
}
} else {
/* Check that the right string is not TRUE or FALSE */
if (strcmp(cond->right,TRUE_STRING)==0) {
cond->right_always=ALWAYS_TRUE;
} else if (strcmp(cond->right,FALSE_STRING)==0) {
cond->right_always=ALWAYS_FALSE;
} else {
cond->right_field=TRUE;
}
}
switch (cond->bool[0]) {
case L_EQUAL : cond->boolval=BOOLEAN_EQUAL;
break;
case L_LIKE : cond->boolval=BOOLEAN_LIKE;
break;
case L_LESSTHAN : switch (cond->bool[1]) {
case L_END : cond->boolval=BOOLEAN_LESS_THAN;
break;
case L_EQUAL: cond->boolval=BOOLEAN_LESS_EQUAL_THAN;
break;
case L_GREATERTHAN: cond->boolval=BOOLEAN_NOT_EQUAL;
break;
default: raise_error(ERROR_UNEXPECTED_CONDITION_CHAR,NONFATAL,cond->bool);
errorflag=TRUE;
break;
}
break;
case L_GREATERTHAN : switch (cond->bool[1]) {
case L_END : cond->boolval=BOOLEAN_GREATER_THAN;
break;
case L_EQUAL : cond->boolval=BOOLEAN_GREATER_EQUAL_THAN;
break;
default: raise_error(ERROR_UNEXPECTED_CONDITION_CHAR,NONFATAL,cond->bool);
errorflag=TRUE;
break;
}
break;
default:
raise_error(ERROR_UNEXPECTED_CONDITION_CHAR,NONFATAL,cond->bool);
errorflag=TRUE;
break;
}
if (errorflag==FALSE) {
return(RETURN_SUCCESS);
} else {
return(RETURN_ERROR);
}
}
void print_condition( condp condition ) {
/* Displays the condition structure
*/
condp currentc;
currentc=condition;
while (currentc!=NULL) {
printf("( %s %s %s )\n",
currentc->left, currentc->bool, currentc->right);
switch (currentc->boolean_condition) {
case BOOLEAN_END_MARKER : printf("<END>\n");
break;
case BOOLEAN_AND : printf("AND\n");
break;
case BOOLEAN_OR : printf("OR\n");
break;
case BOOLEAN_XOR : printf("XOR\n");
break;
default: printf(">UNKNOWN<");
break;
}
currentc=currentc->next_condition;
}
}
int matchup( condp ccondition, int leftorright, tuple ltuple, tuple rtuple ) {
/* matchup
* Performs the work of matching the condition to the appropriate
* tuple, fetching ptrs to data, and so on.
*/
boolean *lr_field;
char *datumptr,*lr_condition,**lr_attribute_val;
char object_name[ATTRIBUTE_NAME_SIZE+1],*sptr;
attribute lr_attribute;
int source;
switch (leftorright) {
case DIR_LEFT: lr_field=&ccondition->left_field;
lr_condition=ccondition->left;
lr_attribute_val=&ccondition->left_attribute_val;
break;
case DIR_RIGHT: lr_field=&ccondition->right_field;
lr_condition=ccondition->right;
lr_attribute_val=&ccondition->right_attribute_val;
break;
default:raise_error(ERROR_UNKNOWN,NONFATAL,"Something strange has happened (Tuple matchup, can't determine left/right)");
return(RETURN_ERROR);
/* Lint-ified */
/* break; */
}
/* If the item is a field, then process it */
if (*lr_field==TRUE) {
/* Get the pointer to the data string */
source=DIR_LEFT;
/* Check that the attribute specified does not contain a
* relation name.
*/
sptr=strchr(lr_condition,'.');
if (sptr!=NULL) {
/* Get the relation and attribute seperate */
strcpy(object_name,lr_condition);
sptr=strchr(object_name,'.');
*sptr='\0';
sptr++;
/* Now object_name contains the relation name, and
* sptr point to the attribute name
*/
/* Check that the object is actually a relation */
if (strcmp(object_name,relation_name(get_relation(ltuple)))==0) {
datumptr=tuple_find_attribute_val(ltuple,sptr);
if (datumptr==NULL) {
raise_error(ERROR_CANTFIND_ATTR,NONFATAL,sptr);
return(RETURN_ERROR);
}
*lr_attribute_val=datumptr;
lr_attribute=tuple_find_attribute(ltuple,sptr);
} else
if (strcmp(object_name,relation_name(get_relation(rtuple)))==0) {
datumptr=tuple_find_attribute_val(rtuple,sptr);
if (datumptr==NULL) {
raise_error(ERROR_CANTFIND_ATTR,NONFATAL,sptr);
return(RETURN_ERROR);
}
*lr_attribute_val=datumptr;
lr_attribute=tuple_find_attribute(rtuple,sptr);
} else {
/* Not a valid object! Abort with an error */
raise_error(ERROR_CANNOT_FIND_REL,NONFATAL,object_name);
return(RETURN_ERROR);
}
} else {
datumptr=tuple_find_attribute_val(ltuple,lr_condition);
/* If it was not in the "left" source tuple, and there is a
* "right" source tuple, then search that one.
*/
if ( (rtuple!=NULL) && (datumptr==NULL) ) {
source=DIR_RIGHT;
datumptr=tuple_find_attribute_val(rtuple,lr_condition);
}
/* If there is no such thing, then raise an error of some sort */
if (datumptr==NULL) {
/* Report an error */
raise_error(ERROR_CANTFIND_ATTR,NONFATAL,lr_condition);
return(RETURN_ERROR);
} else {
/* Set values to point to the located data */
*lr_attribute_val=datumptr;
switch (source) {
case DIR_LEFT:*lr_attribute_val=datumptr;
lr_attribute=tuple_find_attribute(ltuple,lr_condition);
break;
case DIR_RIGHT:*lr_attribute_val=datumptr;
lr_attribute=tuple_find_attribute(rtuple,lr_condition);
break;
default:raise_error(ERROR_CANTFIND_ATTR,NONFATAL,lr_condition);
return(RETURN_ERROR);
/* Lintified */
/* break; */
}
}
}
/* Do an assignment that is easier this way */
switch (leftorright) {
case DIR_LEFT: ccondition->left_attribute=lr_attribute;
break;
case DIR_RIGHT: ccondition->right_attribute=lr_attribute;
break;
default:raise_error(ERROR_UNKNOWN,NONFATAL,"Something strange has happened (Tuple matchup, can't determine 2nd 2nd left/right)");
return(RETURN_ERROR);
/* Lintified */
/* break; */
}
}
return(RETURN_SUCCESS);
}
int match_tuples( condp condition, tuple left_tuple, tuple right_tuple) {
/* Match up condition fields to tuples, so references can quickly
* be made when evaluating if a condition is TRUE or FALSE
*/
condp ccondition;
boolean errorflag=FALSE;
/* Start at the top of the condition list */
ccondition=condition;
/* While the condition has nodes to be processed */
while ( (errorflag==FALSE) && (ccondition!=NULL) ) {
errorflag=(matchup(ccondition, DIR_LEFT , left_tuple, right_tuple)!=RETURN_SUCCESS);
if (errorflag!=TRUE) {
errorflag=(matchup(ccondition, DIR_RIGHT, left_tuple, right_tuple)!=RETURN_SUCCESS);
}
/* While the condition list has nodes to be processed! */
ccondition=ccondition->next_condition;
}
if (errorflag==FALSE) {
return(RETURN_SUCCESS);
} else {
return(RETURN_ERROR);
}
}
int destroy_condition( condp *condition ) {
/* Dispose of a condition structure. Returns SUCCESS. Could this possibly
* fail?
*/
condp previousc,currentc;
/* Get the condition into a local ptr */
currentc=*condition;
/* Whilst it is valid */
while (currentc!=NULL) {
/* Put it into a backup */
previousc=currentc;
/* Move to the next condition */
currentc=currentc->next_condition;
/* Dispose of the old condition */
free(previousc);
}
/* Dispose of the holder memory
if ((condition!=NULL) && (*condition!=NULL)) {
free(*condition);
}
*/
*condition=NULL;
return(RETURN_SUCCESS);
}
condp create_condition() {
condp ccondition;
ccondition=(ncond_struct *) malloc (sizeof(ncond_struct));
strcpy(ccondition->left,"");
ccondition->left_field=FALSE;
ccondition->left_attribute_val=NULL;
ccondition->left_attribute=NULL;
ccondition->left_always=0;
strcpy(ccondition->bool,"");
ccondition->boolval=0;
strcpy(ccondition->right,"");
ccondition->right_field=FALSE;
ccondition->right_attribute_val=NULL;
ccondition->right_attribute=NULL;
ccondition->right_always=0;
ccondition->boolean_condition=0;
ccondition->next_condition=NULL;
ccondition->eval_result=FALSE;
return(ccondition);
}
condp build_condition( char *qualification, tuple left_tuple, tuple right_tuple) {
/* Takes a qualification, and builds a linked list structure with
* the qualification built.
* Return NULL If fails, ptr to first condition if success
*/
int counter,result,matchupres=0;
char booleanexp[MAXIMUM_EXPRESSION+1],currentexp[MAXIMUM_EXPRESSION+1],*stringptr;
condp pcondition,ccondition,rcondition;
boolean errorflag=FALSE;
/* Initialise ptrs to conditions */
pcondition=NULL;
ccondition=create_condition();
/* Set return condition, ie. first item on list */
rcondition=ccondition;
/* Cut out the first set of brackets */
(void) cut_to_right_bracket(qualification,1,TRUE,currentexp);
/* Reset the counter */
counter=0;
/* Process each of the conditions */
while ( (errorflag!=TRUE) && (strlen(currentexp)!=0) ) {
/* Load the expressions */
result=get_first_expression(currentexp, ccondition);
/* If the function was NOT successful... */
if (result!=RETURN_SUCCESS) {
/* Release memory, and set an error flag */
if (ccondition!=NULL) free(ccondition);
ccondition=NULL;
errorflag=TRUE;
} else {
/* If an expression was returned */
/* Is there a previous condition? */
if (pcondition!=NULL) {
/* Link the previous condition to the new condition */
pcondition->next_condition=ccondition;
}
/* Move the previous condition to the current condition */
pcondition=ccondition;
/* Create a new condition node */
ccondition=create_condition();
/* Mark it as if it were the last. */
ccondition->boolean_condition=BOOLEAN_END_MARKER;
}
/* Increment the counter */
counter++;
/* Locate the first non-space */
stringptr=find_start_of_data(qualification);
/* If something was found */
if (stringptr!=NULL) {
qualification=stringptr;
/* Get the token, ie. the linking "and, or, xor"... */
cut_token(qualification,'\0',booleanexp);
#ifdef DEBUG
fprintf(stderr,"Boolean seperator is: >%s<\n",booleanexp);
#endif
/* Determine what sort of condition it is... */
/* TODO: Is there maybe a better way of doing this? */
/* Worst case it involves searching the string 3 times */
if (strcmp(booleanexp,BOOLEAN_AND_STRING)==0) {
pcondition->boolean_condition=BOOLEAN_AND;
} else if (strcmp(booleanexp,BOOLEAN_OR_STRING)==0) {
pcondition->boolean_condition=BOOLEAN_OR;
} else if (strcmp(booleanexp,BOOLEAN_XOR_STRING)==0) {
pcondition->boolean_condition=BOOLEAN_XOR;
} else {
pcondition->boolean_condition=BOOLEAN_UNDETERMINED;
raise_error(ERROR_UNSUPPORTED_BOOLEAN_OPERATOR,NONFATAL,booleanexp);
errorflag=TRUE;
}
/* Cut out the next set of brackets */
(void) cut_to_right_bracket(qualification,1,TRUE,currentexp);
} else {
/* Nothing was found in the string. So force an end. */
/* Make the currentexp zero length, to end the loop */
strcpy(currentexp,"");
}
}
/* At this point, the conditions should be loaded,
* or an error occured. */
if (pcondition!=NULL) {
/* Make sure the previous condition is tidied up */
pcondition->next_condition=NULL;
pcondition->boolean_condition=BOOLEAN_END_MARKER;
}
/* Free up the tailing condition */
if (ccondition!=NULL) free(ccondition);
ccondition=NULL;
if (errorflag==FALSE) {
/* Match the condition list up against the source
* tuple, so attribute names are paired with
* ptrs to the attribute in the tuple, to speed
* up evaluation
*/
matchupres=match_tuples(rcondition,left_tuple,right_tuple);
/* If matching was successful... */
if (matchupres==RETURN_SUCCESS) {
/* Return the complete condition */
return(rcondition);
} else {
/* If it wasn't - destory the condition structure,
* and return NULL
*/
(void) destroy_condition(&rcondition);
return(NULL);
}
} else {
/* An error occured... */
/* TODO - Free up condition list... */
return(NULL);
}
}