Parse a multi-argument scalar call: coalesce(a, b, ...), substring(s, i[, n]), * replace(s, from, to), left(s, n), right(s, n). */
| 1572 | /* Parse a multi-argument scalar call: coalesce(a, b, ...), substring(s, i[, n]), |
| 1573 | * replace(s, from, to), left(s, n), right(s, n). */ |
| 1574 | static int parse_multiarg_func_item(parser_t *p, cbm_return_item_t *item) { |
| 1575 | const char *canon = multiarg_func_canonical(peek(p)->text); |
| 1576 | advance(p); /* function name */ |
| 1577 | expect(p, TOK_LPAREN); |
| 1578 | int cap = CYP_INIT_CAP4; |
| 1579 | item->args = malloc((size_t)cap * sizeof(cbm_func_arg_t)); |
| 1580 | item->arg_count = 0; |
| 1581 | while (!check(p, TOK_RPAREN) && !check(p, TOK_EOF)) { |
| 1582 | if (item->arg_count > 0 && !match(p, TOK_COMMA)) { |
| 1583 | break; |
| 1584 | } |
| 1585 | if (item->arg_count >= cap) { |
| 1586 | cap *= PAIR_LEN; |
| 1587 | item->args = safe_realloc(item->args, (size_t)cap * sizeof(cbm_func_arg_t)); |
| 1588 | } |
| 1589 | if (parse_func_arg(p, &item->args[item->arg_count]) < 0) { |
| 1590 | return CBM_NOT_FOUND; |
| 1591 | } |
| 1592 | item->arg_count++; |
| 1593 | } |
| 1594 | expect(p, TOK_RPAREN); |
| 1595 | item->func = heap_strdup(canon); |
| 1596 | /* Surface the first variable arg as variable/property for column naming. */ |
| 1597 | if (item->arg_count > 0 && item->args[0].variable) { |
| 1598 | item->variable = heap_strdup(item->args[0].variable); |
| 1599 | if (item->args[0].property) { |
| 1600 | item->property = heap_strdup(item->args[0].property); |
| 1601 | } |
| 1602 | } |
| 1603 | return 0; |
| 1604 | } |
| 1605 | |
| 1606 | /* Parse aggregate function call: COUNT(var.prop) */ |
| 1607 | static int parse_aggregate_item(parser_t *p, cbm_return_item_t *item) { |
no test coverage detected