📄 executestack.cpp
字号:
if (*value == "LIST") { // values list
while(*value != "EOLIST") {
value = stack->Pop();
if (*value != "EOLIST")
valueStack->Add((CObject*)value);
}
}
value = stack->Pop();
if (*value == "LIST") { // attribute list
while(*value != "EOLIST") {
value = stack->Pop();
if (*value != "EOLIST")
attrStack->Add((CObject*)value);
}
}
if (attrStack->GetSize() != valueStack->GetSize()) {
errorString = "Number of values don't match number of attributes";
goto cleanup;
}
//
// For each attribute, find the column in the table and assign a value to it
// until all the columns are initialized with their values. Note, if you don't
// set the attribute, the last setting will be used
//
for (i=0;i<attrStack->GetSize();i++) {
attr = (CString*)attrStack->GetAt(i);
value = (CString*)valueStack->GetAt(i);
col = tableInQuestion->Column(*attr);
if (col == NULL) {
errorString = "Undefined column " + *attr + " in table " + *table;
goto cleanup;
}
col->SetValueByType(*value); // set the attribute's value
}
tableInQuestion->AddRow(); // add the new row
cleanup: ;
attrStack->Clear();
valueStack->Clear();
delete attrStack;
delete valueStack;
return true;
}
//
// The DELETE execution method.
bool CEStack::ExecuteDelete()
{
CString *value = NULL;
CString *table = NULL;
SCCollection *saveStack = NULL, *copyStack = NULL;
SCCollection deletes;
int *row = NULL;
errorString = ""; // no error, yet
DeleteResult(); // prepare for new result
result = new SCCollection();
table = stack->Pop(); // get the table to use
tableInQuestion = CESql::FindTable(*table);
if (!tableInQuestion) {
errorString = "No such table " + *table;
return true;
}
value = stack->Pop(); // where
if (value == NULL) { // DELETE all records if null
tableInQuestion->DeleteAllRows();
return true;
}
//
// Iterate through each of the records in the table.
// At each record, execute the stack.
// If the result is true, then delete this record, else leave alone
//
saveStack = stack; // save stack at this point
copyStack = stack->Copy();
for (int i=0;i<tableInQuestion->NRows();i++) {
rowInQuestion = tableInQuestion->GetRow(i);
stack = copyStack->Copy(); // restore the stack for each record test
value = stack->Pop();
ExecuteOperator(*value);
value = stack->Pop();
if (Numberize(*value) > 0.0) {
row = new int;
*row = i;
deletes.Add((CObject*)row);
}
stack->Clear();
delete stack;
}
copyStack->Clear();
delete copyStack;
saveStack = stack;
for (i=deletes.GetSize()-1;i>=0;i--) {
row = (int *)deletes.GetAt(i);
tableInQuestion->DeleteRow(*row);
delete row;
}
return true;
}
//
// Execute an operation. Pops 2 productions off the stack and then
// applies the operator. The PopProduction method will call this method
// recursively until the stack is exhausted per the operations
bool CEStack::ExecuteOperator(CString op)
{
char buf[64] = {""};
double c = 0;
int a = 0, b = 0;
errorString = ""; // no error, yet
CString* object1 = PopProduction();
CString* object2 = PopProduction();
if (op == "AND") {
a = (int)Numberize(*object1);
b = (int)Numberize(*object2);
c = a & b;
}
else
if (op == "OR") {
a = (int)Numberize(*object1);
b = (int)Numberize(*object2);
c = a | b;
}
else
c = DoOperation(*object2,*object1,op);
sprintf(buf,"%f",c);
stack->Push(buf);
return true;
}
//
// Evaluate a and b if they need to be looked up in the database, and
// then do the indicated operation. Does the operation based on the type of
// 'a'. If the operation is not defined an error is returned
double CEStack::DoOperation(CString a, CString b, CString op)
{
double ret = 0;
int type = tableInQuestion->Type(a);
CString *valueA = GetValue(a), *valueB = GetValue(b);
if (valueA == NULL) {
errorString = "Can't find symbol: " + a;
return 0;
}
if (valueB == NULL) {
errorString = "Can't find symbol: " + b;
return 0;
}
switch(type) {
case CSTRING:
case CTIME:
if (op == "<") { ret = (*valueA < *valueB); goto end; }
if (op == ">") { ret = (*valueA > *valueB); goto end; }
if (op == "<=") { ret = (*valueA <= *valueB); goto end; }
if (op == ">=") { ret = (*valueA >= *valueB); goto end; }
if (op == "=") { ret = (*valueA == *valueB); goto end; }
if (op == "<>") { ret = (*valueA != *valueB); goto end; }
if (op == "LIKE") { ret = Compare(*valueB, *valueA); goto end; } // reverse order, so wild cards appear on left
errorString = "Error: Operation " + op + " not defined for " + b;
break;
default:
if (op == "<") { ret = (Numberize(*valueA) < Numberize(*valueB)); goto end; }
if (op == ">") { ret = (Numberize(*valueA) > Numberize(*valueB)); goto end; }
if (op == "<=") {ret = (Numberize(*valueA) <= Numberize(*valueB)); goto end; }
if (op == ">=") {ret = (Numberize(*valueA) >= Numberize(*valueB)); goto end; }
if (op == "=") { ret = (Numberize(*valueA) == Numberize(*valueB)); goto end; }
if (op == "<>") { ret = (Numberize(*valueA) != Numberize(*valueB)); goto end; }
if (op == "+") { ret = Numberize(*valueA) + Numberize(*valueB); goto end; }
if (op == "-") { ret = Numberize(*valueA) - Numberize(*valueB); goto end; }
if (op == "/") { ret = Numberize(*valueA) / Numberize(*valueB); goto end; }
if (op == "*") { ret = Numberize(*valueA) * Numberize(*valueB); goto end; }
errorString = "Error: Operation " + op + " not defined for " + b;
break;
}
end: ;
delete valueA;
delete valueB;
return ret;
}
//
// Do LIKE comparison, with wildcards
double CEStack::Compare(CString a, CString b)
{
CString test = "";
int rc = 0;
if ((rc=a.Find("*"))<0) {
if (a == b) return 1.0;
return 0.0;
}
if (rc == 0) { // *blahblah*
test = a.Mid(1,a.GetLength()-1);
rc = test.Find("*"); // look for trailing *
if (rc > 0) {
test = test.Mid(0,a.GetLength()-2);
rc = b.Find(test);
if (rc >= 0) return 1.0;
}
rc = b.Find(test); // test for absolute match on right side
if (rc >= 0 && (rc + test.GetLength() == b.GetLength()) ) return 1.0;
return 0.0;
}
test = a.Mid(0,rc); // test for blah*
rc = b.Find(test);
if (rc == 0) return 1.0;
return 0.0;
}
//
// Look in the table record for this attribute, unless it is a quoted string, then just return it
CString* CEStack::GetValue(CString attr)
{
CString* a = NULL;
int index = 0, type = CUNDEFINED;
if (CESql::IsStringLiteral(attr)) {
attr = attr.Mid(1,attr.GetLength()-2);
a = new CString(attr);
return a;
}
if (CESql::IsNumber(attr)) return new CString(attr);
index = tableInQuestion->Index(attr);
if (index < 0) return NULL;
type = tableInQuestion->Type(index);
a = SCTable::InterpretAsString(type,rowInQuestion[index]);
return a;
}
//
// Assign an expression to an attribute. Pop 2 things off the stack,
// First item is the attribute, second is a production to evaluate and
// assign to the attribute.
// The attributes are an array of void ptrs stored in column order. So,
// by finding the column index of the attribute name, we have the index into
// the array of pointers to use to make the assignment.
bool CEStack::ExecuteAssign()
{
CString *attr = NULL, *value = NULL;
SCColumn *col = NULL;
int index = 0;
errorString = "";
attr = stack->Pop();
if (attr == NULL) {
errorString = "No attribute to assign!";
return false;
}
if (tableInQuestion == NULL) {
errorString = "Table does not exist, can't assign";
return false;
}
index = tableInQuestion->Index(*attr); // find column index
if (index < 0) {
errorString = "No such attribute " + *attr;
return false;
}
value = PopProduction(); // evaluate right hand side
if (value == NULL) {
errorString = "No production to assign to attribute " + *attr;
return false;
}
col = tableInQuestion->Column(index); // get the column object
col->SetValueByType(*value); // assign based on type
shared_free((char*)rowInQuestion[index]); // delete the old value of the attr
rowInQuestion[index] = col->Value(); // assign the new value
return true;
}
//
// Is the string an operator we recognize?
bool CEStack::IsOperator(CString s)
{
char c = s[0];
if (s == "+" || s == "-" || s == '*' || s == '=' || s == '<' || s == '>' ||
s == "<=" || s == ">=" || s == "<>" ||
s == "AND" || s == "OR" || s == "LIKE" || s == "NOT LIKE") return true;
return false;
}
//
// Turn S into a number. If it is an attribute, then look up it's value
double CEStack::Numberize(CString s)
{
double res;
if (CESql::IsNumber(s))
res = atof(s);
else {
errorString = "Error: " + s + " is not a number";
res = -1.0;
}
return res;
}
CString CEStack::TableInQuestion()
{
return tableName;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -