mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'JHMH' of github.com:arangodb/arangodb into JHMH
This commit is contained in:
commit
eec9c02a36
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue