Parse post-WHERE clauses: additional MATCH, WITH, RETURN, UNION */
| 1952 | |
| 1953 | /* Parse post-WHERE clauses: additional MATCH, WITH, RETURN, UNION */ |
| 1954 | static int parse_post_where(parser_t *p, cbm_query_t *q, // NOLINT(misc-no-recursion) |
| 1955 | int *pat_cap) { |
| 1956 | /* More MATCH / OPTIONAL MATCH after WHERE */ |
| 1957 | if (parse_match_chain(p, q, pat_cap) < 0) { |
| 1958 | return CBM_NOT_FOUND; |
| 1959 | } |
| 1960 | /* Check for unsupported keywords */ |
| 1961 | const char *unsup = unsupported_clause_error(peek(p)->type); |
| 1962 | if (unsup) { |
| 1963 | snprintf(p->error, sizeof(p->error), "%s", unsup); |
| 1964 | return CBM_NOT_FOUND; |
| 1965 | } |
| 1966 | /* Optional WITH clause (standalone, not STARTS WITH) */ |
| 1967 | if (check(p, TOK_WITH) && |
| 1968 | (p->pos < PAIR_LEN || p->tokens[p->pos - SKIP_ONE].type != TOK_STARTS)) { |
| 1969 | if (parse_return_or_with(p, &q->with_clause, true) < 0) { |
| 1970 | return CBM_NOT_FOUND; |
| 1971 | } |
| 1972 | if (parse_where(p, &q->post_with_where) < 0) { |
| 1973 | return CBM_NOT_FOUND; |
| 1974 | } |
| 1975 | } |
| 1976 | /* Optional RETURN */ |
| 1977 | if (parse_return(p, &q->ret) < 0) { |
| 1978 | return CBM_NOT_FOUND; |
| 1979 | } |
| 1980 | /* UNION [ALL] */ |
| 1981 | if (check(p, TOK_UNION)) { |
| 1982 | advance(p); |
| 1983 | q->union_all = match(p, TOK_ALL); |
| 1984 | cbm_parse_result_t sub = {0}; |
| 1985 | if (cbm_parse(&p->tokens[p->pos], p->count - p->pos, &sub) < 0) { |
| 1986 | if (sub.error) { |
| 1987 | snprintf(p->error, sizeof(p->error), "%s", sub.error); |
| 1988 | } |
| 1989 | cbm_parse_free(&sub); |
| 1990 | return CBM_NOT_FOUND; |
| 1991 | } |
| 1992 | q->union_next = sub.query; |
| 1993 | sub.query = NULL; |
| 1994 | cbm_parse_free(&sub); |
| 1995 | } |
| 1996 | return 0; |
| 1997 | } |
| 1998 | |
| 1999 | int cbm_parse(const cbm_token_t *tokens, int token_count, // NOLINT(misc-no-recursion) |
| 2000 | cbm_parse_result_t *out) { |
no test coverage detected