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 namespace triagens::aql;
|
||||||
using EN = triagens::aql::ExecutionNode;
|
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();
|
auto node = cn->expression()->node();
|
||||||
std::vector<AstNode const*> currentPath;
|
std::vector<AstNode const*> currentPath;
|
||||||
std::vector<std::vector<AstNode const*>> paths;
|
std::vector<std::vector<AstNode const*>> paths;
|
||||||
|
std::vector<std::vector<AstNode const*>> clonePath;
|
||||||
|
|
||||||
node->findVariableAccess(currentPath, paths, var);
|
node->findVariableAccess(currentPath, paths, var);
|
||||||
|
|
||||||
for (auto onePath : paths) {
|
for (auto onePath : paths) {
|
||||||
size_t len = onePath.size();
|
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) &&
|
if (onePath[len - 2]->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||||
strcmp(onePath[len - 2]->getStringValue(), "edges") &&
|
isEdgeAccess = strcmp(onePath[len - 2]->getStringValue(), "edges") == 0;
|
||||||
strcmp(onePath[len - 2]->getStringValue(), "vertices")) {
|
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.
|
if (!isEdgeAccess && ! isVertexAccess) {
|
||||||
std::string message("TRAVERSAL: path only knows 'edges' and 'vertices', not ");
|
|
||||||
message += onePath[len - 2]->getStringValue();
|
/* We can't catch all cases in which this error would occur, so we don't throw here.
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, message);
|
std::string message("TRAVERSAL: path only knows 'edges' and 'vertices', not ");
|
||||||
*/
|
message += onePath[len - 2]->getStringValue();
|
||||||
return false;
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, message);
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we now need to check for p.edges[n] whether n is >= 0
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
conditionIsImpossible = !tn->isInRange(indexAccessNode->value.value._int);
|
conditionIsImpossible = !tn->isInRange(indexAccessNode->value.value._int);
|
||||||
|
attrAccessTo = indexAccessNode->value.value._int;
|
||||||
}
|
}
|
||||||
else if ((onePath[len - 3]->type == NODE_TYPE_ITERATOR) &&
|
else if ((onePath[len - 3]->type == NODE_TYPE_ITERATOR) &&
|
||||||
(onePath[len - 4]->type == NODE_TYPE_EXPANSION)){
|
(onePath[len - 4]->type == NODE_TYPE_EXPANSION)){
|
||||||
// we now need to check for p.edges[*] which becomes a fancy structure
|
// we now need to check for p.edges[*] which becomes a fancy structure
|
||||||
|
isAsterisc = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OR? don't know howto continue.
|
// OR? don't know howto continue.
|
||||||
|
AstNode const * compareNode = nullptr;
|
||||||
|
AstNode const * accessNodeBranch = nullptr;
|
||||||
for (auto oneNode : onePath) {
|
for (auto oneNode : onePath) {
|
||||||
if (oneNode->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
if (oneNode->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||||
return false;
|
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);
|
int variableType = node->checkIsOutVariable(conditionVar->id);
|
||||||
if (variableType >= 0) {
|
if (variableType >= 0) {
|
||||||
if ((variableType == 2) &&
|
if ((variableType == 2) &&
|
||||||
checkPathVariableAccessFeasible(cn, node, conditionVar, conditionIsImpossible))
|
checkPathVariableAccessFeasible(cn, node, conditionVar, conditionIsImpossible, _plan->getAst()))
|
||||||
{
|
{
|
||||||
condition->andCombine(it.second->expression()->node());
|
condition->andCombine(it.second->expression()->node());
|
||||||
foundCondition = true;
|
foundCondition = true;
|
||||||
|
|
|
@ -32,6 +32,19 @@ using namespace std;
|
||||||
using namespace triagens::basics;
|
using namespace triagens::basics;
|
||||||
using namespace triagens::aql;
|
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,
|
TraversalNode::TraversalNode (ExecutionPlan* plan,
|
||||||
size_t id,
|
size_t id,
|
||||||
TRI_vocbase_t* vocbase,
|
TRI_vocbase_t* vocbase,
|
||||||
|
@ -185,13 +198,13 @@ TraversalNode::TraversalNode (ExecutionPlan* plan,
|
||||||
}
|
}
|
||||||
|
|
||||||
int TraversalNode::checkIsOutVariable(size_t variableId) {
|
int TraversalNode::checkIsOutVariable(size_t variableId) {
|
||||||
if (_vertexOutVariable->id == variableId) {
|
if (_vertexOutVariable != nullptr && _vertexOutVariable->id == variableId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (_edgeOutVariable->id == variableId) {
|
if (_edgeOutVariable != nullptr && _edgeOutVariable->id == variableId) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (_pathOutVariable->id == variableId) {
|
if (_pathOutVariable != nullptr && _pathOutVariable->id == variableId) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -304,6 +317,16 @@ void TraversalNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||||
json("pathOutVariable", pathOutVariable()->toJson());
|
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:
|
// And add it:
|
||||||
nodes(json);
|
nodes(json);
|
||||||
}
|
}
|
||||||
|
@ -380,10 +403,10 @@ void TraversalNode::setCondition(triagens::aql::Condition* condition){
|
||||||
Ast::getReferencedVariables(condition->root(), varsUsedByCondition);
|
Ast::getReferencedVariables(condition->root(), varsUsedByCondition);
|
||||||
|
|
||||||
for (auto oneVar : varsUsedByCondition) {
|
for (auto oneVar : varsUsedByCondition) {
|
||||||
if ((oneVar->id != _vertexOutVariable->id) &&
|
if ((_vertexOutVariable != nullptr && oneVar->id != _vertexOutVariable->id) &&
|
||||||
(oneVar->id != _edgeOutVariable->id) &&
|
(_edgeOutVariable != nullptr && oneVar->id != _edgeOutVariable->id) &&
|
||||||
(oneVar->id != _pathOutVariable->id) &&
|
(_pathOutVariable != nullptr && oneVar->id != _pathOutVariable->id) &&
|
||||||
(oneVar->id != _inVariable->id)) {
|
(_inVariable != nullptr && oneVar->id != _inVariable->id)) {
|
||||||
|
|
||||||
_conditionVariables.push_back(oneVar);
|
_conditionVariables.push_back(oneVar);
|
||||||
}
|
}
|
||||||
|
@ -392,6 +415,22 @@ void TraversalNode::setCondition(triagens::aql::Condition* condition){
|
||||||
_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:
|
// Local Variables:
|
||||||
|
|
|
@ -49,6 +49,18 @@ namespace triagens {
|
||||||
friend class ExecutionBlock;
|
friend class ExecutionBlock;
|
||||||
friend class TraversalCollectionBlock;
|
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
|
/// @brief constructor with a vocbase and a collection name
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -325,6 +337,17 @@ namespace triagens {
|
||||||
return _maxDepth >= _minDepth;
|
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
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -421,6 +444,12 @@ namespace triagens {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::vector<Variable const*> _conditionVariables;
|
std::vector<Variable const*> _conditionVariables;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief store a simple comparator filter
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<simpleTravererExpression> expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace triagens::aql
|
} // namespace triagens::aql
|
||||||
|
|
Loading…
Reference in New Issue