feat(Query): Support computation in SELECT clause

This commit is contained in:
SoftlySpoken 2020-07-18 09:25:16 +00:00
parent c92a22fecf
commit 4f571b24bf
9 changed files with 611 additions and 91 deletions

View File

@ -320,98 +320,188 @@ void QueryParser::parseSelectAggregateFunction(SPARQLParser::ExpressionContext *
conditionalAndexpression(0)->valueLogical(0)->relationalexpression()-> \
numericexpression(0)->additiveexpression()->multiplicativeexpression(0)-> \
unaryexpression(0)->primaryexpression()->builtInCall();
if (!bicCtx)
throw runtime_error("[ERROR] Currently only support selecting variables, "
"the aggregate function COUNT, and path-associated built-in calls");
antlr4::tree::ParseTree *curr = expCtx;
for (int i = 0; i < 10; i++)
{
// Make sure only one children along the way
if (curr->children.size() > 1)
throw runtime_error("[ERROR] Currently only support selecting variables, "
"the aggregate function COUNT, and path-associated built-in calls");
curr = curr->children[0];
}
SPARQLParser::AggregateContext *aggCtx = bicCtx->aggregate();
if (aggCtx)
{
string tmp = aggCtx->children[0]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
if (tmp != "COUNT")
throw runtime_error("[ERROR] The supported aggregate function now is COUNT only");
// if (!bicCtx)
// throw runtime_error("[ERROR] Currently only support selecting variables, "
// "the aggregate function COUNT, and path-associated built-in calls");
if (bicCtx)
{
antlr4::tree::ParseTree *curr = expCtx;
for (int i = 0; i < 10; i++)
{
// Make sure only one children along the way
if (curr->children.size() > 1)
throw runtime_error("[ERROR] Currently only support selecting variables, "
"the aggregate function COUNT, and path-associated built-in calls");
curr = curr->children[0];
}
SPARQLParser::AggregateContext *aggCtx = bicCtx->aggregate();
if (aggCtx)
{
string tmp = aggCtx->children[0]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
if (tmp != "COUNT")
throw runtime_error("[ERROR] The supported aggregate function now is COUNT only");
query_tree_ptr->addProjectionVar();
QueryTree::ProjectionVar &proj_var = query_tree_ptr->getLastProjectionVar();
proj_var.aggregate_type = QueryTree::ProjectionVar::Count_type;
proj_var.aggregate_var = aggCtx->expression()->getText(); // Error would have been dealt with
tmp = aggCtx->children[2]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
proj_var.distinct = aggCtx->children[2]->children.size() == 0 && tmp == "DISTINCT";
proj_var.var = varCtx->getText();
}
else
{
string tmp = bicCtx->children[0]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
if (tmp != "SIMPLECYCLEPATH" && tmp != "SIMPLECYCLEBOOLEAN"
&& tmp != "CYCLEPATH" && tmp != "CYCLEBOOLEAN"
&& tmp != "SHORTESTPATH" && tmp != "SHORTESTPATHLEN"
&& tmp != "KHOPREACHABLE" && tmp != "KHOPENUMERATE")
throw runtime_error("[ERROR] Currently only support selecting variables, "
"the aggregate function COUNT, and path-associated built-in calls");
query_tree_ptr->addProjectionVar();
QueryTree::ProjectionVar &proj_var = query_tree_ptr->getLastProjectionVar();
if (tmp == "SIMPLECYCLEPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::simpleCyclePath_type;
else if (tmp == "SIMPLECYCLEBOOLEAN")
proj_var.aggregate_type = QueryTree::ProjectionVar::simpleCycleBoolean_type;
else if (tmp == "CYCLEPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::cyclePath_type;
else if (tmp == "CYCLEBOOLEAN")
proj_var.aggregate_type = QueryTree::ProjectionVar::cycleBoolean_type;
else if (tmp == "SHORTESTPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::shortestPath_type;
else if (tmp == "SHORTESTPATHLEN")
proj_var.aggregate_type = QueryTree::ProjectionVar::shortestPathLen_type;
else if (tmp == "KHOPREACHABLE")
proj_var.aggregate_type = QueryTree::ProjectionVar::kHopReachable_type;
else if (tmp == "KHOPENUMERATE")
proj_var.aggregate_type = QueryTree::ProjectionVar::kHopEnumerate_type;
proj_var.path_args.src = bicCtx->varOrIri(0)->getText();
replacePrefix(proj_var.path_args.src);
proj_var.path_args.dst = bicCtx->varOrIri(1)->getText();
replacePrefix(proj_var.path_args.dst);
auto predSet = bicCtx->predSet()->iri();
for (auto pred : predSet)
{
string prefixedPred = pred->getText();
replacePrefix(prefixedPred);
proj_var.path_args.pred_set.push_back(prefixedPred);
}
if (tmp == "KHOPREACHABLE" || tmp == "KHOPENUMERATE")
{
if (bicCtx->num_integer())
proj_var.path_args.k = stoi(bicCtx->num_integer()->getText());
else if (bicCtx->integer_positive())
proj_var.path_args.k = stoi(bicCtx->integer_positive()->getText());
else if (bicCtx->integer_negative())
proj_var.path_args.k = stoi(bicCtx->integer_negative()->getText());
if (bicCtx->numericLiteral())
proj_var.path_args.confidence = stof(bicCtx->numericLiteral()->getText());
else
proj_var.path_args.confidence = 1;
}
if (bicCtx->booleanLiteral()->getText() == "true")
proj_var.path_args.directed = true;
else
proj_var.path_args.directed = false;
proj_var.var = varCtx->getText();
}
}
else // For multi-layer computation, only consider vars, literals, and bracketted expressions for now
{
query_tree_ptr->addProjectionVar();
QueryTree::ProjectionVar &proj_var = query_tree_ptr->getLastProjectionVar();
proj_var.aggregate_type = QueryTree::ProjectionVar::Count_type;
proj_var.aggregate_var = aggCtx->expression()->getText(); // Error would have been dealt with
tmp = aggCtx->children[2]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
proj_var.distinct = aggCtx->children[2]->children.size() == 0 && tmp == "DISTINCT";
proj_var.aggregate_type = QueryTree::ProjectionVar::CompTree_type;
proj_var.var = varCtx->getText();
proj_var.comp_tree_root = new QueryTree::CompTreeNode;
buildCompTree(expCtx, -1, proj_var.comp_tree_root);
}
}
void QueryParser::buildCompTree(antlr4::tree::ParseTree *root, int oper_pos, QueryTree::CompTreeNode *curr_node)
{
cout << root->getText() << endl;
cout << "#children = " << root->children.size() << endl;
if (root->children.size() == 1)
{
if (((SPARQLParser::PrimaryexpressionContext *)root)->rDFLiteral())
{
curr_node->oprt = "";
curr_node->lchild = NULL;
curr_node->rchild = NULL;
curr_node->val = root->getText();
}
else if (((SPARQLParser::PrimaryexpressionContext *)root)->numericLiteral())
{
curr_node->oprt = "";
curr_node->lchild = NULL;
curr_node->rchild = NULL;
auto numericLiteral = ((SPARQLParser::PrimaryexpressionContext *)root)->numericLiteral();
curr_node->val = getNumeric(numericLiteral);
}
else if (((SPARQLParser::PrimaryexpressionContext *)root)->booleanLiteral())
{
curr_node->oprt = "";
curr_node->lchild = NULL;
curr_node->rchild = NULL;
curr_node->val = "\"" + root->getText() + "\"" + "^^<http://www.w3.org/2001/XMLSchema#boolean>";
}
else if (((SPARQLParser::PrimaryexpressionContext *)root)->var())
{
curr_node->oprt = "";
curr_node->lchild = NULL;
curr_node->rchild = NULL;
curr_node->val = root->getText();
}
else
buildCompTree(root->children[0], -1, curr_node);
}
else if (root->children.size() == 2)
{
if (root->children[0]->getText()[0] != '!' \
&& root->children[0]->getText()[0] != '+' \
&& root->children[0]->getText()[0] != '-')
throw runtime_error("[ERROR] Unary operator not supported");
curr_node->oprt = root->children[0]->getText();
curr_node->lchild = new QueryTree::CompTreeNode;
curr_node->rchild = NULL;
curr_node->val = "";
buildCompTree(root->children[1], -1, curr_node->lchild);
}
else if (root->children.size() % 2 == 1) // >= 3, odd #children
{
if (root->children[0]->getText() == "(")
buildCompTree(root->children[1], -1, curr_node);
else
{
int rightmostOprtPos = (root->children.size() - 1) / 2;
// if (oper_pos == -1)
// oper_pos = 1;
if (oper_pos < rightmostOprtPos)
{
int new_oper_pos = oper_pos + 2;
curr_node->oprt = root->children[oper_pos + 2]->getText();
curr_node->lchild = new QueryTree::CompTreeNode;
curr_node->rchild = new QueryTree::CompTreeNode;
curr_node->val = "";
buildCompTree(root->children[oper_pos + 1], -1, curr_node->lchild);
buildCompTree(root, oper_pos + 2, curr_node->rchild);
}
else // oper_pos == rightmostOprtPos, the last operator on this level has been handled
buildCompTree(root->children[oper_pos + 1], -1, curr_node);
}
}
else
{
string tmp = bicCtx->children[0]->getText();
transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
if (tmp != "SIMPLECYCLEPATH" && tmp != "SIMPLECYCLEBOOLEAN"
&& tmp != "CYCLEPATH" && tmp != "CYCLEBOOLEAN"
&& tmp != "SHORTESTPATH" && tmp != "SHORTESTPATHLEN"
&& tmp != "KHOPREACHABLE" && tmp != "KHOPENUMERATE")
throw runtime_error("[ERROR] Currently only support selecting variables, "
"the aggregate function COUNT, and path-associated built-in calls");
query_tree_ptr->addProjectionVar();
QueryTree::ProjectionVar &proj_var = query_tree_ptr->getLastProjectionVar();
if (tmp == "SIMPLECYCLEPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::simpleCyclePath_type;
else if (tmp == "SIMPLECYCLEBOOLEAN")
proj_var.aggregate_type = QueryTree::ProjectionVar::simpleCycleBoolean_type;
else if (tmp == "CYCLEPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::cyclePath_type;
else if (tmp == "CYCLEBOOLEAN")
proj_var.aggregate_type = QueryTree::ProjectionVar::cycleBoolean_type;
else if (tmp == "SHORTESTPATH")
proj_var.aggregate_type = QueryTree::ProjectionVar::shortestPath_type;
else if (tmp == "SHORTESTPATHLEN")
proj_var.aggregate_type = QueryTree::ProjectionVar::shortestPathLen_type;
else if (tmp == "KHOPREACHABLE")
proj_var.aggregate_type = QueryTree::ProjectionVar::kHopReachable_type;
else if (tmp == "KHOPENUMERATE")
proj_var.aggregate_type = QueryTree::ProjectionVar::kHopEnumerate_type;
proj_var.path_args.src = bicCtx->varOrIri(0)->getText();
replacePrefix(proj_var.path_args.src);
proj_var.path_args.dst = bicCtx->varOrIri(1)->getText();
replacePrefix(proj_var.path_args.dst);
auto predSet = bicCtx->predSet()->iri();
for (auto pred : predSet)
{
string prefixedPred = pred->getText();
replacePrefix(prefixedPred);
proj_var.path_args.pred_set.push_back(prefixedPred);
}
if (tmp == "KHOPREACHABLE" || tmp == "KHOPENUMERATE")
{
if (bicCtx->num_integer())
proj_var.path_args.k = stoi(bicCtx->num_integer()->getText());
else if (bicCtx->integer_positive())
proj_var.path_args.k = stoi(bicCtx->integer_positive()->getText());
else if (bicCtx->integer_negative())
proj_var.path_args.k = stoi(bicCtx->integer_negative()->getText());
if (bicCtx->numericLiteral())
proj_var.path_args.confidence = stof(bicCtx->numericLiteral()->getText());
else
proj_var.path_args.confidence = 1;
}
if (bicCtx->booleanLiteral()->getText() == "true")
proj_var.path_args.directed = true;
else
proj_var.path_args.directed = false;
proj_var.var = varCtx->getText();
}
throw runtime_error("[ERROR] Computation type not supported (an even #children > 2)");
}
/**

View File

@ -56,6 +56,7 @@ public:
void parseSelectAggregateFunction(SPARQLParser::ExpressionContext *expCtx, \
SPARQLParser::VarContext *varCtx);
void buildCompTree(antlr4::tree::ParseTree *root, int oper_pos, QueryTree::CompTreeNode *curr_node);
void buildFilterTree(antlr4::tree::ParseTree *root, \
QueryTree::GroupPattern::FilterTree::FilterTreeNode::FilterTreeChild *currChild, \
QueryTree::GroupPattern::FilterTree::FilterTreeNode &filter, std::string tp);

View File

@ -1190,7 +1190,8 @@ void GeneralEvaluation::getFinalResult(ResultSet &ret_result)
if (result0_size == 0 && proj.size() == 1 && \
proj[0].aggregate_type != QueryTree::ProjectionVar::None_type && \
proj[0].aggregate_type != QueryTree::ProjectionVar::Count_type)
proj[0].aggregate_type != QueryTree::ProjectionVar::Count_type && \
proj[0].aggregate_type != QueryTree::ProjectionVar::CompTree_type)
{
// Path query, both nodes are IRI
@ -1427,6 +1428,22 @@ void GeneralEvaluation::getFinalResult(ResultSet &ret_result)
ss << "\"^^<http://www.w3.org/2001/XMLSchema#integer>";
ss >> new_result0.result.back().str[proj2new[i] - new_result0_id_cols];
}
else if (proj[i].aggregate_type == QueryTree::ProjectionVar::CompTree_type)
{
// Strictly speaking, not an aggregate; each original line will produce a line of results
for (int j = begin; j <= end; j++)
{
new_result0.result.back().str[proj2new[i] - new_result0_id_cols] = \
result0.doComp(proj[i].comp_tree_root, result0.result[j], result0_id_cols, stringindex, \
query_tree.getGroupPattern().group_pattern_subject_object_maximal_varset).term_value;
if (j < end)
{
new_result0.result.push_back(TempResult::ResultPair());
new_result0.result.back().id = new unsigned[new_result0_id_cols];
new_result0.result.back().str.resize(new_result0_str_cols);
}
}
}
else // Path query
{
prepPathQuery();

View File

@ -875,7 +875,8 @@ bool QueryTree::checkWellDesigned()
|| proj.aggregate_type == ProjectionVar::shortestPath_type
|| proj.aggregate_type == ProjectionVar::shortestPathLen_type
|| proj.aggregate_type == ProjectionVar::kHopReachable_type
|| proj.aggregate_type == ProjectionVar::kHopEnumerate_type)
|| proj.aggregate_type == ProjectionVar::kHopEnumerate_type
|| proj.aggregate_type == ProjectionVar::CompTree_type)
{
check_condition = false;
break;
@ -973,6 +974,11 @@ void QueryTree::print()
printf("kHopReachable(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::kHopEnumerate_type)
printf("kHopEnumerate(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::CompTree_type)
{
cout << endl;
projection[i].comp_tree_root->print(0);
}
if (this->projection[i].distinct)
printf("DISTINCT ");
@ -1079,3 +1085,33 @@ void QueryTree::print()
for (int j = 0; j < 80; j++) printf("="); printf("\n");
}
void QueryTree::CompTreeNode::print(int dep)
{
if (!lchild && !rchild)
{
for (int i = 0; i < dep; i++)
cout << '\t';
cout << "Value: " << val << endl;
}
else
{
for (int i = 0; i < dep; i++)
cout << '\t';
cout << "Operator " << oprt << endl;
if (lchild)
{
for (int i = 0; i < dep; i++)
cout << '\t';
cout << "lchild:" << endl;
lchild->print(dep + 1);
}
if (rchild)
{
for (int i = 0; i < dep; i++)
cout << '\t';
cout << "rchild:" << endl;
rchild->print(dep + 1);
}
}
}

View File

@ -104,6 +104,17 @@ class QueryTree
float confidence;
};
class CompTreeNode
{
public:
std::string oprt; // operator
CompTreeNode *lchild;
CompTreeNode *rchild; // child nodes
std::string val; // variable, or literal followed by datatype suffix
void print(int dep); // Print subtree rooted at this node
};
class GroupPattern::FilterTree
{
public:
@ -195,7 +206,8 @@ class QueryTree
public:
enum AggregateType {None_type, Count_type, Sum_type, Min_type, Max_type, Avg_type,
simpleCyclePath_type, simpleCycleBoolean_type, cyclePath_type, cycleBoolean_type,
shortestPath_type, shortestPathLen_type, kHopReachable_type, kHopEnumerate_type};
shortestPath_type, shortestPathLen_type, kHopReachable_type, kHopEnumerate_type,
CompTree_type};
AggregateType aggregate_type;
std::string var, aggregate_var;
@ -203,6 +215,8 @@ class QueryTree
PathArgs path_args;
CompTreeNode *comp_tree_root;
ProjectionVar():aggregate_type(None_type), distinct(false){}
};

View File

@ -889,6 +889,85 @@ EvalMultitypeValue
return ret_femv;
}
EvalMultitypeValue
TempResult::doComp(QueryTree::CompTreeNode *root, ResultPair &row, int id_cols, StringIndex *stringindex, Varset &entity_literal_varset)
{
if (root->lchild == NULL && root->rchild == NULL) // leaf node
{
EvalMultitypeValue x;
x.datatype = EvalMultitypeValue::rdf_term;
if (root->val[0] == '?') // variable
{
int pos;
pos = Varset(root->val).mapTo(entity_literal_varset)[0];
if (pos == -1)
{
x.datatype = EvalMultitypeValue::xsd_boolean;
x.bool_value = EvalMultitypeValue::EffectiveBooleanValue::error_value;
return x;
}
if (pos < id_cols)
{
int id = row.id[pos];
bool isel = entity_literal_varset.findVar(root->val);
stringindex->randomAccess(id, &x.term_value, isel);
}
else
x.term_value = row.str[pos - id_cols];
}
else // literal
x.term_value = root->val;
x.deduceTypeValue();
cout << "x.term_value = " << x.term_value << endl;
return x;
}
else
{
EvalMultitypeValue lRes, rRes;
if (root->lchild)
lRes = doComp(root->lchild, row, id_cols, stringindex, entity_literal_varset);
if (root->rchild)
rRes = doComp(root->rchild, row, id_cols, stringindex, entity_literal_varset);
if (root->oprt == "||")
return lRes || rRes;
else if (root->oprt == "&&")
return lRes && rRes;
else if (root->oprt == "=")
return lRes == rRes;
else if (root->oprt == "!=")
return lRes != rRes;
else if (root->oprt == "<")
return lRes < rRes;
else if (root->oprt == ">")
return lRes > rRes;
else if (root->oprt == "<=")
return lRes <= rRes;
else if (root->oprt == ">=")
return lRes >= rRes;
else if (root->oprt == "+")
{
if (!root->rchild) // unary
return lRes;
else // binary
return lRes + rRes;
}
else if (root->oprt == "-")
{
if (!root->rchild) // unary
return -lRes;
else // binary
return lRes - rRes;
}
else if (root->oprt == "*")
return lRes * rRes;
else if (root->oprt == "/")
return lRes / rRes;
else if (root->oprt == "!")
return !lRes;
}
}
void TempResult::doFilter(QueryTree::GroupPattern::FilterTree::FilterTreeNode &filter, TempResult &r, StringIndex *stringindex, Varset &entity_literal_varset)
{
Varset this_varset = this->getAllVarset();

View File

@ -50,6 +50,8 @@ class TempResult
EvalMultitypeValue matchFilterTree(QueryTree::GroupPattern::FilterTree::FilterTreeNode &filter, ResultPair &row, int id_cols, StringIndex *stringindex);
void doFilter(QueryTree::GroupPattern::FilterTree::FilterTreeNode &filter, TempResult &r, StringIndex *stringindex, Varset &entity_literal_varset);
EvalMultitypeValue doComp(QueryTree::CompTreeNode *root, ResultPair &row, int id_cols, StringIndex *stringindex, Varset &entity_literal_varset);
void print(int no=-1);
};

View File

@ -226,6 +226,8 @@ EvalMultitypeValue
return ret_femv;
ret_femv.bool_value = !this->bool_value;
ret_femv.deduceTermValue();
return ret_femv;
}
@ -240,6 +242,8 @@ EvalMultitypeValue
return ret_femv;
ret_femv.bool_value = (this->bool_value || x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -254,6 +258,8 @@ EvalMultitypeValue
return ret_femv;
ret_femv.bool_value = (this->bool_value && x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -267,6 +273,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value == x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -278,6 +286,8 @@ EvalMultitypeValue
return ret_femv;
ret_femv.bool_value = EffectiveBooleanValue::false_value;
ret_femv.deduceTermValue();
return ret_femv;
}
@ -294,28 +304,37 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value == x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value == x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value == x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value == x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.bool_value = (this->term_value == x.term_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -329,6 +348,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value != x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -340,6 +361,8 @@ EvalMultitypeValue
return ret_femv;
ret_femv.bool_value = EffectiveBooleanValue::true_value;
ret_femv.deduceTermValue();
return ret_femv;
}
@ -356,28 +379,37 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value != x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value != x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value != x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value != x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.bool_value = (this->term_value != x.term_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -391,6 +423,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value < x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -407,27 +441,35 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value < x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value < x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value < x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value < x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.deduceTermValue();
return ret_femv;
}
@ -441,6 +483,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value <= x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -457,27 +501,35 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value <= x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value <= x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value <= x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value <= x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.deduceTermValue();
return ret_femv;
}
@ -491,6 +543,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value > x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -507,27 +561,35 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value > x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value > x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value > x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value > x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.deduceTermValue();
return ret_femv;
}
@ -541,6 +603,8 @@ EvalMultitypeValue
if (this->datatype == xsd_boolean && x.datatype == xsd_boolean)
{
ret_femv.bool_value = (this->bool_value >= x.bool_value);
ret_femv.deduceTermValue();
return ret_femv;
}
@ -557,30 +621,240 @@ EvalMultitypeValue
if (this->datatype == xsd_double && x.datatype == xsd_double)
ret_femv.bool_value = (this->dbl_value >= x.dbl_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->isSimpleLiteral() && x.isSimpleLiteral())
{
ret_femv.bool_value = (this->str_value >= x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_string && x.datatype == xsd_string)
{
ret_femv.bool_value = (this->str_value >= x.str_value);
ret_femv.deduceTermValue();
return ret_femv;
}
if (this->datatype == xsd_datetime && x.datatype == xsd_datetime)
{
ret_femv.bool_value = (this->dt_value >= x.dt_value);
ret_femv.deduceTermValue();
return ret_femv;
}
ret_femv.deduceTermValue();
return ret_femv;
}
EvalMultitypeValue
EvalMultitypeValue::operator + (EvalMultitypeValue &x)
{
EvalMultitypeValue ret_femv;
ret_femv.datatype = xsd_boolean;
ret_femv.bool_value = EffectiveBooleanValue::error_value;
if (datatype != xsd_integer && datatype != xsd_decimal && datatype != xsd_float && datatype != xsd_double \
&& x.datatype != xsd_integer && x.datatype != xsd_decimal && x.datatype != xsd_float && x.datatype != xsd_double)
return ret_femv;
this->getSameNumericType(x);
if (datatype == xsd_integer)
{
ret_femv.datatype = xsd_integer;
ret_femv.int_value = int_value + x.int_value;
}
else if (datatype == xsd_decimal)
{
ret_femv.datatype = xsd_decimal;
ret_femv.flt_value = flt_value + x.flt_value;
}
else if (datatype == xsd_float)
{
ret_femv.datatype = xsd_float;
ret_femv.flt_value = flt_value + x.flt_value;
}
else if (datatype == xsd_double)
{
ret_femv.datatype = xsd_double;
ret_femv.dbl_value = dbl_value + x.dbl_value;
}
ret_femv.deduceTermValue();
return ret_femv;
}
EvalMultitypeValue
EvalMultitypeValue::operator - ()
{
EvalMultitypeValue ret_femv;
ret_femv.datatype = xsd_boolean;
ret_femv.bool_value = EffectiveBooleanValue::error_value;
if (datatype != xsd_integer && datatype != xsd_decimal && datatype != xsd_float && datatype != xsd_double)
return ret_femv;
if (datatype == xsd_integer)
{
ret_femv.datatype = xsd_integer;
ret_femv.int_value = -int_value;
}
else if (datatype == xsd_decimal)
{
ret_femv.datatype = xsd_decimal;
ret_femv.flt_value = -flt_value;
}
else if (datatype == xsd_float)
{
ret_femv.datatype = xsd_float;
ret_femv.flt_value = -flt_value;
}
else if (datatype == xsd_double)
{
ret_femv.datatype = xsd_double;
ret_femv.dbl_value = -dbl_value;
}
ret_femv.deduceTermValue();
return ret_femv;
}
EvalMultitypeValue
EvalMultitypeValue::operator - (EvalMultitypeValue &x)
{
EvalMultitypeValue ret_femv;
ret_femv.datatype = xsd_boolean;
ret_femv.bool_value = EffectiveBooleanValue::error_value;
if (datatype != xsd_integer && datatype != xsd_decimal && datatype != xsd_float && datatype != xsd_double \
&& x.datatype != xsd_integer && x.datatype != xsd_decimal && x.datatype != xsd_float && x.datatype != xsd_double)
return ret_femv;
this->getSameNumericType(x);
if (datatype == xsd_integer)
{
ret_femv.datatype = xsd_integer;
ret_femv.int_value = int_value - x.int_value;
}
else if (datatype == xsd_decimal)
{
ret_femv.datatype = xsd_decimal;
ret_femv.flt_value = flt_value - x.flt_value;
}
else if (datatype == xsd_float)
{
ret_femv.datatype = xsd_float;
ret_femv.flt_value = flt_value - x.flt_value;
}
else if (datatype == xsd_double)
{
ret_femv.datatype = xsd_double;
ret_femv.dbl_value = dbl_value - x.dbl_value;
}
ret_femv.deduceTermValue();
return ret_femv;
}
EvalMultitypeValue
EvalMultitypeValue::operator * (EvalMultitypeValue &x)
{
EvalMultitypeValue ret_femv;
ret_femv.datatype = xsd_boolean;
ret_femv.bool_value = EffectiveBooleanValue::error_value;
if (datatype != xsd_integer && datatype != xsd_decimal && datatype != xsd_float && datatype != xsd_double \
&& x.datatype != xsd_integer && x.datatype != xsd_decimal && x.datatype != xsd_float && x.datatype != xsd_double)
return ret_femv;
this->getSameNumericType(x);
if (datatype == xsd_integer)
{
ret_femv.datatype = xsd_integer;
ret_femv.int_value = int_value * x.int_value;
}
else if (datatype == xsd_decimal)
{
ret_femv.datatype = xsd_decimal;
ret_femv.flt_value = flt_value * x.flt_value;
}
else if (datatype == xsd_float)
{
ret_femv.datatype = xsd_float;
ret_femv.flt_value = flt_value * x.flt_value;
}
else if (datatype == xsd_double)
{
ret_femv.datatype = xsd_double;
ret_femv.dbl_value = dbl_value * x.dbl_value;
}
ret_femv.deduceTermValue();
return ret_femv;
}
EvalMultitypeValue
EvalMultitypeValue::operator / (EvalMultitypeValue &x)
{
EvalMultitypeValue ret_femv;
ret_femv.datatype = xsd_boolean;
ret_femv.bool_value = EffectiveBooleanValue::error_value;
if (datatype != xsd_integer && datatype != xsd_decimal && datatype != xsd_float && datatype != xsd_double \
&& x.datatype != xsd_integer && x.datatype != xsd_decimal && x.datatype != xsd_float && x.datatype != xsd_double)
return ret_femv;
this->getSameNumericType(x);
if (datatype == xsd_integer)
{
ret_femv.datatype = xsd_integer;
ret_femv.int_value = int_value / x.int_value;
}
else if (datatype == xsd_decimal)
{
ret_femv.datatype = xsd_decimal;
ret_femv.flt_value = flt_value / x.flt_value;
}
else if (datatype == xsd_float)
{
ret_femv.datatype = xsd_float;
ret_femv.flt_value = flt_value / x.flt_value;
}
else if (datatype == xsd_double)
{
ret_femv.datatype = xsd_double;
ret_femv.dbl_value = dbl_value / x.dbl_value;
}
ret_femv.deduceTermValue();
return ret_femv;
}
void EvalMultitypeValue::deduceTermValue()
{
if (datatype == xsd_integer)
term_value = "\"" + to_string(int_value) + "\"^^<http://www.w3.org/2001/XMLSchema#integer>";
else if (datatype == xsd_decimal)
term_value = "\"" + to_string(flt_value) + "\"^^<http://www.w3.org/2001/XMLSchema#decimal>";
else if (datatype == xsd_float)
term_value = "\"" + to_string(flt_value) + "\"^^<http://www.w3.org/2001/XMLSchema#float>";
else if (datatype == xsd_double)
term_value = "\"" + to_string(dbl_value) + "\"^^<http://www.w3.org/2001/XMLSchema#double>";
else if (datatype == xsd_boolean)
{
if (bool_value.value == EvalMultitypeValue::EffectiveBooleanValue::true_value)
term_value = "\"true\"^^<http://www.w3.org/2001/XMLSchema#boolean>";
else if (bool_value.value == EvalMultitypeValue::EffectiveBooleanValue::false_value)
term_value = "\"false\"^^<http://www.w3.org/2001/XMLSchema#boolean>";
}
}
void EvalMultitypeValue::deduceTypeValue()
{
if (term_value[0] == '<' && term_value[term_value.length() - 1] == '>')

View File

@ -69,7 +69,7 @@ class EvalMultitypeValue
std::string str_value;
EffectiveBooleanValue bool_value;
int int_value;
float flt_value;
float flt_value; // xsd_decimal and xsd_float
double dbl_value;
DateTime dt_value;
@ -85,9 +85,16 @@ class EvalMultitypeValue
EvalMultitypeValue operator > (EvalMultitypeValue &x);
EvalMultitypeValue operator >= (EvalMultitypeValue &x);
EvalMultitypeValue operator + (EvalMultitypeValue &x);
EvalMultitypeValue operator - ();
EvalMultitypeValue operator - (EvalMultitypeValue &x);
EvalMultitypeValue operator * (EvalMultitypeValue &x);
EvalMultitypeValue operator / (EvalMultitypeValue &x);
EvalMultitypeValue():datatype(rdf_term), int_value(0), flt_value(0), dbl_value(0){}
void deduceTypeValue(); // Set datatype and value according to term_value
void deduceTermValue(); // Set term value according to datatype and essential value
void deduceTypeValue(); // Set datatype and value according to term_value, for numeric & boolean
};
#endif //_UTIL_EVALMULTITYPEVALUE_H