validate a CALL clause
| 1082 | |
| 1083 | // validate a CALL clause |
| 1084 | static VISITOR_STRATEGY _Validate_CALL_Clause |
| 1085 | ( |
| 1086 | const cypher_astnode_t *n, // ast-node |
| 1087 | bool start, // first traversal |
| 1088 | ast_visitor *visitor // visitor |
| 1089 | ) { |
| 1090 | validations_ctx *vctx = AST_Visitor_GetContext(visitor); |
| 1091 | |
| 1092 | if(start) { |
| 1093 | vctx->clause = cypher_astnode_type(n); |
| 1094 | // introduce aliases in the clause to the bounded vars environment |
| 1095 | _AST_GetProcCallAliases(n, vctx->defined_identifiers); |
| 1096 | |
| 1097 | /* Make sure procedure calls are valid: |
| 1098 | * 1. procedure exists |
| 1099 | * 2. number of arguments to procedure is as expected |
| 1100 | * 3. yield refers to procedure output */ |
| 1101 | |
| 1102 | ProcedureCtx *proc = NULL; |
| 1103 | rax *rax = NULL; |
| 1104 | |
| 1105 | // Make sure procedure exists. |
| 1106 | const char *proc_name = cypher_ast_proc_name_get_value(cypher_ast_call_get_proc_name(n)); |
| 1107 | proc = Proc_Get(proc_name); |
| 1108 | |
| 1109 | if(proc == NULL) { |
| 1110 | ErrorCtx_SetError("Procedure `%s` is not registered", proc_name); |
| 1111 | goto cleanup; |
| 1112 | } |
| 1113 | |
| 1114 | // Validate num of arguments. |
| 1115 | if(proc->argc != PROCEDURE_VARIABLE_ARG_COUNT) { |
| 1116 | unsigned int given_arg_count = cypher_ast_call_narguments(n); |
| 1117 | if(Procedure_Argc(proc) != given_arg_count) { |
| 1118 | ErrorCtx_SetError("Procedure `%s` requires %d arguments, got %d", proc_name, proc->argc, |
| 1119 | given_arg_count); |
| 1120 | goto cleanup; |
| 1121 | } |
| 1122 | } |
| 1123 | |
| 1124 | rax = raxNew(); |
| 1125 | |
| 1126 | // validate projections |
| 1127 | uint proj_count = cypher_ast_call_nprojections(n); |
| 1128 | // collect call projections |
| 1129 | for(uint j = 0; j < proj_count; j++) { |
| 1130 | const cypher_astnode_t *proj = cypher_ast_call_get_projection(n, j); |
| 1131 | const cypher_astnode_t *ast_exp = cypher_ast_projection_get_expression(proj); |
| 1132 | ASSERT(cypher_astnode_type(ast_exp) == CYPHER_AST_IDENTIFIER); |
| 1133 | const char *identifier = cypher_ast_identifier_get_name(ast_exp); |
| 1134 | |
| 1135 | // make sure each yield output is mentioned only once |
| 1136 | if(!raxInsert(rax, (unsigned char *)identifier, strlen(identifier), NULL, NULL)) { |
| 1137 | ErrorCtx_SetError("Variable `%s` already declared", identifier); |
| 1138 | goto cleanup; |
| 1139 | } |
| 1140 | |
| 1141 | // make sure procedure is aware of output |
nothing calls this directly
no test coverage detected