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