1
0
Fork 0

Merge branch 'JHMH' of github.com:arangodb/arangodb into JHMH

This commit is contained in:
Michael Hackstein 2015-11-13 17:12:36 +01:00
commit eec9c02a36
3 changed files with 161 additions and 19 deletions

View File

@ -34,26 +34,38 @@
using namespace triagens::aql;
using EN = triagens::aql::ExecutionNode;
bool checkPathVariableAccessFeasible(CalculationNode const* cn, TraversalNode * tn, Variable const* var, bool &conditionIsImpossible) {
bool checkPathVariableAccessFeasible(CalculationNode const* cn,
TraversalNode * tn,
Variable const* var,
bool &conditionIsImpossible,
Ast* ast) {
auto node = cn->expression()->node();
std::vector<AstNode const*> currentPath;
std::vector<std::vector<AstNode const*>> paths;
std::vector<std::vector<AstNode const*>> clonePath;
node->findVariableAccess(currentPath, paths, var);
for (auto onePath : paths) {
size_t len = onePath.size();
bool isEdgeAccess = false;
bool isVertexAccess = false;
bool isAsterisc = false;
size_t attrAccessTo = 0;
if ((onePath[len - 2]->type == NODE_TYPE_ATTRIBUTE_ACCESS) &&
strcmp(onePath[len - 2]->getStringValue(), "edges") &&
strcmp(onePath[len - 2]->getStringValue(), "vertices")) {
if (onePath[len - 2]->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
isEdgeAccess = strcmp(onePath[len - 2]->getStringValue(), "edges") == 0;
isVertexAccess = strcmp(onePath[len - 2]->getStringValue(), "vertices") == 0;
/* We can't catch all cases in which this error would occur, so we don't throw here.
std::string message("TRAVERSAL: path only knows 'edges' and 'vertices', not ");
message += onePath[len - 2]->getStringValue();
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, message);
*/
return false;
if (!isEdgeAccess && ! isVertexAccess) {
/* We can't catch all cases in which this error would occur, so we don't throw here.
std::string message("TRAVERSAL: path only knows 'edges' and 'vertices', not ");
message += onePath[len - 2]->getStringValue();
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, message);
*/
return false;
}
}
// we now need to check for p.edges[n] whether n is >= 0
@ -65,21 +77,83 @@ bool checkPathVariableAccessFeasible(CalculationNode const* cn, TraversalNode *
return false;
}
conditionIsImpossible = !tn->isInRange(indexAccessNode->value.value._int);
attrAccessTo = indexAccessNode->value.value._int;
}
else if ((onePath[len - 3]->type == NODE_TYPE_ITERATOR) &&
(onePath[len - 4]->type == NODE_TYPE_EXPANSION)){
// we now need to check for p.edges[*] which becomes a fancy structure
isAsterisc = true;
}
else {
return false;
}
// OR? don't know howto continue.
AstNode const * compareNode = nullptr;
AstNode const * accessNodeBranch = nullptr;
for (auto oneNode : onePath) {
if (oneNode->type == NODE_TYPE_OPERATOR_BINARY_OR) {
return false;
}
if (compareNode != nullptr && accessNodeBranch == nullptr) {
accessNodeBranch = oneNode;
}
if (oneNode->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
compareNode = oneNode;
}
}
if (compareNode != NULL) {
AstNode const * pathAccessNode;
AstNode const * filterByNode;
if (compareNode->getMember(0) == accessNodeBranch) {
pathAccessNode = accessNodeBranch;
filterByNode = compareNode->getMember(1);
}
else {
pathAccessNode = accessNodeBranch;
filterByNode = compareNode->getMember(0);
}
if (accessNodeBranch->isSimple() && filterByNode->type == NODE_TYPE_VALUE) {
AstNode *newNode = accessNodeBranch->clone(ast);
// since we just copied one path, we should only find one.
newNode->findVariableAccess(currentPath, clonePath, var);
newNode->dump(20);
if (isAsterisc) {
}
else {
auto len = clonePath[0].size();
/// todo len < 4
AstNode* firstRefNode = (AstNode*) clonePath[0][len - 4];
TRI_ASSERT(firstRefNode->type == NODE_TYPE_ATTRIBUTE_ACCESS);
auto varRefNode = new AstNode(NODE_TYPE_REFERENCE);
ast->query()->addNode(varRefNode);
varRefNode->setData(isEdgeAccess ? tn->edgeOutVariable(): tn->vertexOutVariable());
firstRefNode->changeMember(0, varRefNode);
tn->storeSimpleExpression(isAsterisc,
isEdgeAccess,
attrAccessTo,
NODE_TYPE_OPERATOR_BINARY_EQ,
newNode,
filterByNode);
printf("\n xxxxx: %s\n", newNode->toString().c_str());
printf("\n yyyy: %s\n", accessNodeBranch->toString().c_str());
printf("\n yyyy: %s\n", filterByNode->toString().c_str());
}
}
printf("\na: %s\n", compareNode->toString().c_str());
printf("\na: %s\n", accessNodeBranch->toString().c_str());
triagens::basics::Json j(TRI_UNKNOWN_MEM_ZONE, accessNodeBranch->toJson(TRI_UNKNOWN_MEM_ZONE, true));
printf("sanotuh %s\n", j.toString().c_str());
}
}
@ -189,7 +263,7 @@ bool TraversalConditionFinder::before (ExecutionNode* en) {
int variableType = node->checkIsOutVariable(conditionVar->id);
if (variableType >= 0) {
if ((variableType == 2) &&
checkPathVariableAccessFeasible(cn, node, conditionVar, conditionIsImpossible))
checkPathVariableAccessFeasible(cn, node, conditionVar, conditionIsImpossible, _plan->getAst()))
{
condition->andCombine(it.second->expression()->node());
foundCondition = true;

View File

@ -32,6 +32,19 @@ using namespace std;
using namespace triagens::basics;
using namespace triagens::aql;
void TraversalNode::simpleTravererExpression::toJson(triagens::basics::Json& json,
TRI_memory_zone_t* zone) const
{
json("isAsteriscAccess", triagens::basics::Json(isAsteriscAccess))
("isEdgeAccess", triagens::basics::Json(isEdgeAccess))
("indexAccess", triagens::basics::Json((int32_t)indexAccess))
("comparisonType", triagens::basics::Json("==")) /// TODO more comparison types?
("varAccess", varAccess->toJson(zone, true))
("compareTo", compareTo->toJson(zone, true));
}
TraversalNode::TraversalNode (ExecutionPlan* plan,
size_t id,
TRI_vocbase_t* vocbase,
@ -185,13 +198,13 @@ TraversalNode::TraversalNode (ExecutionPlan* plan,
}
int TraversalNode::checkIsOutVariable(size_t variableId) {
if (_vertexOutVariable->id == variableId) {
if (_vertexOutVariable != nullptr && _vertexOutVariable->id == variableId) {
return 0;
}
if (_edgeOutVariable->id == variableId) {
if (_edgeOutVariable != nullptr && _edgeOutVariable->id == variableId) {
return 1;
}
if (_pathOutVariable->id == variableId) {
if (_pathOutVariable != nullptr && _pathOutVariable->id == variableId) {
return 2;
}
return -1;
@ -304,6 +317,16 @@ void TraversalNode::toJsonHelper (triagens::basics::Json& nodes,
json("pathOutVariable", pathOutVariable()->toJson());
}
if (expressions.size() > 0) {
triagens::basics::Json expressionArray = triagens::basics::Json(triagens::basics::Json::Array,
expressions.size());
for (auto x : expressions) {
triagens::basics::Json exp(zone, triagens::basics::Json::Object);
x.toJson(exp, zone);
expressionArray(exp);
}
json("simpleExpressions", expressionArray);
}
// And add it:
nodes(json);
}
@ -380,10 +403,10 @@ void TraversalNode::setCondition(triagens::aql::Condition* condition){
Ast::getReferencedVariables(condition->root(), varsUsedByCondition);
for (auto oneVar : varsUsedByCondition) {
if ((oneVar->id != _vertexOutVariable->id) &&
(oneVar->id != _edgeOutVariable->id) &&
(oneVar->id != _pathOutVariable->id) &&
(oneVar->id != _inVariable->id)) {
if ((_vertexOutVariable != nullptr && oneVar->id != _vertexOutVariable->id) &&
(_edgeOutVariable != nullptr && oneVar->id != _edgeOutVariable->id) &&
(_pathOutVariable != nullptr && oneVar->id != _pathOutVariable->id) &&
(_inVariable != nullptr && oneVar->id != _inVariable->id)) {
_conditionVariables.push_back(oneVar);
}
@ -392,6 +415,22 @@ void TraversalNode::setCondition(triagens::aql::Condition* condition){
_condition = condition;
}
void TraversalNode::storeSimpleExpression(bool isAsteriscAccess,
bool isEdgeAccess,
size_t indexAccess,
AstNodeType comparisonType,
AstNode const* varAccess,
AstNode const* compareTo) {
simpleTravererExpression e {
isAsteriscAccess,
isEdgeAccess,
indexAccess,
comparisonType,
varAccess,
compareTo};
expressions.emplace_back(e);
}
// Local Variables:

View File

@ -49,6 +49,18 @@ namespace triagens {
friend class ExecutionBlock;
friend class TraversalCollectionBlock;
struct simpleTravererExpression {
bool isAsteriscAccess;
bool isEdgeAccess;
size_t indexAccess;
AstNodeType comparisonType;
AstNode const* varAccess;
AstNode const* compareTo;
void toJson(triagens::basics::Json& json,
TRI_memory_zone_t* zone) const;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor with a vocbase and a collection name
////////////////////////////////////////////////////////////////////////////////
@ -325,6 +337,17 @@ namespace triagens {
return _maxDepth >= _minDepth;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Remember a simple comparator filter
////////////////////////////////////////////////////////////////////////////////
void storeSimpleExpression(bool isAsteriscAccess,
bool isEdgeAccess,
size_t indexAccess,
AstNodeType comparisonType,
AstNode const* varAccess,
AstNode const* compareTo);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
@ -421,6 +444,12 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
std::vector<Variable const*> _conditionVariables;
////////////////////////////////////////////////////////////////////////////////
/// @brief store a simple comparator filter
////////////////////////////////////////////////////////////////////////////////
std::vector<simpleTravererExpression> expressions;
};
} // namespace triagens::aql