Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load CSV #592

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/ast/ast_validations.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,23 @@ static VISITOR_STRATEGY _Validate_pattern_comprehension
return VISITOR_CONTINUE;
}

// validate LOAD CSV clause
static VISITOR_STRATEGY _Validate_load_csv
(
const cypher_astnode_t *n, // ast-node (LOAD CSV)
bool start, // first traversal
ast_visitor *visitor // visitor
) {
validations_ctx *vctx = AST_Visitor_GetContext(visitor);

const cypher_astnode_t *node = cypher_ast_load_csv_get_identifier(n);
const char *alias = cypher_ast_identifier_get_name(node);

_IdentifierAdd(vctx, alias, NULL);

return VISITOR_CONTINUE;
}

// validate that an identifier is bound
static VISITOR_STRATEGY _Validate_identifier
(
Expand Down Expand Up @@ -2253,6 +2270,7 @@ bool AST_ValidationsMappingInit(void) {
validations_mapping[CYPHER_AST_REMOVE] = _Validate_REMOVE_Clause;
validations_mapping[CYPHER_AST_REDUCE] = _Validate_reduce;
validations_mapping[CYPHER_AST_FOREACH] = _Validate_FOREACH_Clause;
validations_mapping[CYPHER_AST_LOAD_CSV] = _Validate_load_csv;
validations_mapping[CYPHER_AST_IDENTIFIER] = _Validate_identifier;
validations_mapping[CYPHER_AST_PROJECTION] = _Validate_projection;
validations_mapping[CYPHER_AST_NAMED_PATH] = _Validate_named_path;
Expand All @@ -2276,7 +2294,6 @@ bool AST_ValidationsMappingInit(void) {
validations_mapping[CYPHER_AST_FILTER] = _visit_break;
validations_mapping[CYPHER_AST_EXTRACT] = _visit_break;
validations_mapping[CYPHER_AST_COMMAND] = _visit_break;
validations_mapping[CYPHER_AST_LOAD_CSV] = _visit_break;
validations_mapping[CYPHER_AST_MATCH_HINT] = _visit_break;
validations_mapping[CYPHER_AST_USING_JOIN] = _visit_break;
validations_mapping[CYPHER_AST_USING_SCAN] = _visit_break;
Expand Down
12 changes: 6 additions & 6 deletions src/errors/error_msgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#define EMSG_SHORTESTPATH_SINGLE_RELATIONSHIP "shortestPath requires a path containing a single relationship"
#define EMSG_SHORTESTPATH_MINIMAL_LENGTH "shortestPath does not support a minimal length different from 0 or 1"
#define EMSG_SHORTESTPATH_MAX_HOPS "Maximum number of hops must be greater than or equal to minimum number of hops"
#define EMSG_SHORTESTPATH_UNDIRECTED "RedisGraph does not currently support undirected shortestPath traversals"
#define EMSG_SHORTESTPATH_RELATIONSHIP_FILTERS "RedisGraph does not currently support filters on relationships in shortestPath"
#define EMSG_SHORTESTPATH_UNDIRECTED "FalkorDB does not currently support undirected shortestPath traversals"
#define EMSG_SHORTESTPATH_RELATIONSHIP_FILTERS "FalkorDB does not currently support filters on relationships in shortestPath"
#define EMSG_SHORTESTPATH_NODE_FILTERS "Node filters may not be introduced in shortestPath"
#define EMSG_FUNCTION_REQUIER_PREDICATE "'%s' function requires a WHERE predicate"
#define EMSG_NESTED_AGGREGATION "Can't use aggregate functions inside of aggregate functions."
Expand Down Expand Up @@ -65,7 +65,7 @@
#define EMSG_CALLSUBQUERY_INVALID_REFERENCES "WITH imports in CALL {} must consist of only simple references to outside variables"
#define EMSG_VAIABLE_ALREADY_DECLARED_IN_OUTER_SCOPE "Variable `%s` already declared in outer scope"
#define EMSG_DELETE_INVALID_ARGUMENTS "DELETE can only be called on nodes, paths and relationships"
#define EMSG_SET_LHS_NON_ALIAS "RedisGraph does not currently support non-alias references on the left-hand side of SET expressions"
#define EMSG_SET_LHS_NON_ALIAS "FalkorDB does not currently support non-alias references on the left-hand side of SET expressions"
#define EMSG_UNION_COMBINATION "Invalid combination of UNION and UNION ALL."
#define EMSG_FOREACH_INVALID_BODY "Error: Only updating clauses may reside in FOREACH"
#define EMSG_QUERY_INVALID_LAST_CLAUSE "Query cannot conclude with %s (must be a RETURN clause, an update clause, a procedure call or a non-returning subquery)"
Expand All @@ -75,8 +75,8 @@
#define EMSG_MISSING_WITH_AFTER_MATCH "A WITH clause is required to introduce a MATCH clause after an OPTIONAL MATCH."
#define EMSG_UNSUPPORTED_QUERY_TYPE "Encountered unsupported query type '%s'"
#define EMSG_EMPTY_QUERY "Error: empty query."
#define EMSG_ALLSHORTESTPATH_SUPPORT "RedisGraph support allShortestPaths only in match clauses"
#define EMSG_SHORTESTPATH_SUPPORT "RedisGraph currently only supports shortestPaths in WITH or RETURN clauses"
#define EMSG_ALLSHORTESTPATH_SUPPORT "FalkorDB support allShortestPaths only in match clauses"
#define EMSG_SHORTESTPATH_SUPPORT "FalkorDB currently only supports shortestPaths in WITH or RETURN clauses"
#define EMSG_EXPLAIN_PROFILE_USAGE "Please use GRAPH.%s 'key' 'query' command instead of GRAPH.QUERY 'key' '%s query'"
#define EMSG_DUPLICATE_PARAMETERS "Duplicated parameter: %s"
#define EMSG_PARSER_ERROR "errMsg: %s line: %u, column: %u, offset: %zu errCtx: %s errCtxOffset: %zu"
Expand All @@ -87,7 +87,7 @@
#define EMSG_COULD_NOT_PARSE_QUERY "Error: could not parse query"
#define EMSG_UNABLE_TO_RESOLVE_FILTER_ALIAS "Unable to resolve filtered alias '%s'"
#define EMSG_TYPE_MISMATCH "Type mismatch: expected %s but was %s"
#define EMSG_REDISGRAPH_SUPPORT "RedisGraph does not currently support %s"
#define EMSG_FALKORDB_SUPPORT "FalkorDB does not currently support %s"
#define EMSG_INVALID_PROPERTY_VALUE "Property values can only be of primitive types or arrays of primitive types"
#define EMSG_DIVISION_BY_ZERO "Division by zero"
#define EMSG_ALLSHORTESTPATH_SRC_DST_RESLOVED "Source and destination must already be resolved to call allShortestPaths"
Expand Down
4 changes: 2 additions & 2 deletions src/errors/errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,13 @@ void Error_UnsupportedASTNodeType(const cypher_astnode_t *node) {

cypher_astnode_type_t type = cypher_astnode_type(node);
const char *type_str = cypher_astnode_typestr(type);
ErrorCtx_SetError(EMSG_REDISGRAPH_SUPPORT, type_str);
ErrorCtx_SetError(EMSG_FALKORDB_SUPPORT, type_str);
}

void Error_UnsupportedASTOperator(const cypher_operator_t *op) {
ASSERT(op != NULL);

ErrorCtx_SetError(EMSG_REDISGRAPH_SUPPORT, op->str);
ErrorCtx_SetError(EMSG_FALKORDB_SUPPORT, op->str);
}

inline void Error_InvalidPropertyValue(void) {
Expand Down
27 changes: 27 additions & 0 deletions src/execution_plan/execution_plan_build/execution_plan_construct.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,31 @@ static inline void _buildUnwindOp(ExecutionPlan *plan, const cypher_astnode_t *c
ExecutionPlan_UpdateRoot(plan, op);
}

static void _buildLoadCSVOp
(
ExecutionPlan *plan,
const cypher_astnode_t *clause
) {
ASSERT(plan != NULL);
ASSERT(clause != NULL);

// extract information from AST

// with headers
bool with_headers = cypher_ast_load_csv_has_with_headers(clause);

// URI expression
const cypher_astnode_t *node = cypher_ast_load_csv_get_url(clause);
AR_ExpNode *exp = AR_EXP_FromASTNode(node);

// alias
node = cypher_ast_load_csv_get_identifier(clause);
const char *alias = cypher_ast_identifier_get_name(node);

OpBase *op = NewLoadCSVOp(plan, exp, alias, with_headers);
ExecutionPlan_UpdateRoot(plan, op);
}

static inline void _buildUpdateOp(GraphContext *gc, ExecutionPlan *plan,
const cypher_astnode_t *clause) {
rax *update_exps = AST_PrepareUpdateOp(gc, clause);
Expand Down Expand Up @@ -368,6 +393,8 @@ void ExecutionPlanSegment_ConvertClause
_buildForeachOp(plan, clause, gc);
} else if(t == CYPHER_AST_CALL_SUBQUERY) {
buildCallSubqueryPlan(plan, clause);
} else if(t == CYPHER_AST_LOAD_CSV) {
_buildLoadCSVOp(plan, clause);
} else {
assert(false && "unhandeled clause");
}
Expand Down
5 changes: 3 additions & 2 deletions src/execution_plan/ops/op.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ typedef enum {
OPType_OR_APPLY_MULTIPLEXER,
OPType_AND_APPLY_MULTIPLEXER,
OPType_OPTIONAL,
OPType_LOAD_CSV,
} OPType;

typedef enum {
Expand Down Expand Up @@ -204,8 +205,8 @@ uint OpBase_ChildCount
// returns the i'th child of the op
OpBase *OpBase_GetChild
(
OpBase *join, // op
uint i // child index
OpBase *op, // op
uint i // child index
);

// mark alias as being modified by operation
Expand Down