in Unix/wql/wql.c [498:775]
extern int WQL_Eval(
const WQL* wql,
WQL_Lookup lookup,
void* data)
{
size_t i;
WQL_Symbol symbols[WQL_MAX_SYMBOLS];
size_t nsymbols = 0;
if (!wql || !wql->className || !lookup)
return -1;
/* Return success if there is no WHERE clause */
if (wql->nsymbols == 0)
return 0;
/* Perform postfix evaluation */
for (i = 0; i < wql->nsymbols; i++)
{
const WQL_Symbol* sym = &wql->symbols[i];
WQL_Type type = sym->type;
if (nsymbols >= WQL_MAX_SYMBOLS)
return -1;
switch (type)
{
case WQL_TYPE_AND:
case WQL_TYPE_OR:
{
if (nsymbols < 2)
return -1;
{
#if defined(hpux)
#pragma diag_suppress 2549
#endif
WQL_Symbol s2 = symbols[--nsymbols];
WQL_Symbol s1 = symbols[--nsymbols];
#if defined(hpux)
#pragma diag_default 2549
#endif
WQL_Symbol s;
int f;
memset(&s, '\0', sizeof(s));
if (s1.type != WQL_TYPE_BOOLEAN)
return -1;
if (s2.type != WQL_TYPE_BOOLEAN)
return -1;
s.type = WQL_TYPE_BOOLEAN;
if (type == WQL_TYPE_OR)
f = (s1.value.boolean || s2.value.boolean);
else
f = (s1.value.boolean && s2.value.boolean);
s.value.boolean = f ? 1 : 0;
symbols[nsymbols++] = s;
}
break;
}
case WQL_TYPE_NOT:
{
if (nsymbols < 1)
return -1;
{
WQL_Symbol s1 = symbols[--nsymbols];
WQL_Symbol s;
memset(&s, '\0', sizeof(s));
if (s1.type != WQL_TYPE_BOOLEAN)
return -1;
s.type = WQL_TYPE_BOOLEAN;
s.value.boolean = (!s1.value.boolean) ? 1 : 0;
symbols[nsymbols++] = s;
}
break;
}
case WQL_TYPE_EQ:
case WQL_TYPE_NE:
case WQL_TYPE_LT:
case WQL_TYPE_LE:
case WQL_TYPE_GT:
case WQL_TYPE_GE:
case WQL_TYPE_LIKE:
{
if (nsymbols < 2)
return -1;
{
WQL_Symbol s2 = symbols[--nsymbols];
WQL_Symbol s1 = symbols[--nsymbols];
WQL_Symbol s;
int r;
int f;
memset(&s, '\0', sizeof(s));
/* This type only returned by _ValidateLookup() */
if (s2.type == WQL_TYPE_ANY || s1.type == WQL_TYPE_ANY)
{
return 0;
}
/* If either operand is null */
if (s1.type == WQL_TYPE_NULL || s2.type == WQL_TYPE_NULL)
{
/* Set flag non-zero if both operands are null */
int bothNull =
(s1.type==WQL_TYPE_NULL && s2.type==WQL_TYPE_NULL);
if (type == WQL_TYPE_EQ || type == WQL_TYPE_LIKE)
{
s.type = WQL_TYPE_BOOLEAN;
s.value.boolean = bothNull ? 1 : 0;
symbols[nsymbols++] = s;
break;
}
else if (type == WQL_TYPE_NE)
{
s.type = WQL_TYPE_BOOLEAN;
s.value.boolean = bothNull ? 0 : 1;
symbols[nsymbols++] = s;
break;
}
else
return -1;
}
else
{
if (type == WQL_TYPE_LIKE)
r = _CompareLike(&s1, &s2);
else
{
WQL_Symbol lhs = s1;
WQL_Symbol rhs = s2;
if (lhs.type != rhs.type)
{
if (_FixupType(&lhs, &rhs) != 0)
return -1;
}
r = _Compare(&lhs, &rhs);
}
switch (type)
{
case WQL_TYPE_EQ:
case WQL_TYPE_LIKE:
f = (r == 0);
break;
case WQL_TYPE_NE:
f = (r != 0);
break;
case WQL_TYPE_LT:
f = (r < 0);
break;
case WQL_TYPE_LE:
f = (r <= 0);
break;
case WQL_TYPE_GT:
f = (r > 0);
break;
case WQL_TYPE_GE:
f = (r >= 0);
break;
default:
f = 0;
break;
}
s.type = WQL_TYPE_BOOLEAN;
s.value.boolean = f ? 1 : 0;
symbols[nsymbols++] = s;
}
}
break;
}
case WQL_TYPE_IDENTIFIER:
{
WQL_Symbol tmp;
memset(&tmp, 0, sizeof(WQL_Symbol));
if ((*lookup)(
sym->value.string,
sym->value.embeddedClassName,
sym->value.embeddedPropertyName,
&tmp,
wql->batch,
data) != 0)
{
return -1;
}
if (tmp.type != WQL_TYPE_BOOLEAN &&
tmp.type != WQL_TYPE_INTEGER &&
tmp.type != WQL_TYPE_REAL &&
tmp.type != WQL_TYPE_STRING &&
tmp.type != WQL_TYPE_NULL &&
tmp.type != WQL_TYPE_ANY)
{
return -1;
}
symbols[nsymbols++] = tmp;
break;
}
case WQL_TYPE_BOOLEAN:
case WQL_TYPE_INTEGER:
case WQL_TYPE_REAL:
case WQL_TYPE_STRING:
case WQL_TYPE_NULL:
case WQL_TYPE_ANY:
symbols[nsymbols++] = *sym;
break;
case WQL_TYPE_ISA:
{
WQL_Symbol s2;
WQL_Symbol s1;
if (nsymbols < 2)
return -1;
s2 = symbols[--nsymbols];
s1 = symbols[--nsymbols];
if (s1.type != WQL_TYPE_STRING)
return -1;
if (s2.type != WQL_TYPE_STRING)
return -1;
/* Ask lookup() to perform ISA operation */
{
WQL_Symbol tmp = s2;
if ((*lookup)(
s1.value.string, /* Embedded property name */
s2.value.string, /* Embedded class name */
NULL,
&tmp,
wql->batch,
data) != 0)
{
return -1;
}
symbols[nsymbols++] = tmp;
}
break;
}
}
}
/* There should be exactly 1 symbol left on stack */
if (nsymbols != 1)
return -1;
/* There should be exactly 1 symbol left on stack */
/* Final token on stack should be boolean */
if (symbols[0].type != WQL_TYPE_BOOLEAN)
return -1;
/* Return '0' for equal, '1' for not-equal */
if (symbols[0].value.boolean)
return 0;
else
return 1;
}