Parse CASE WHEN ... THEN ... [ELSE ...] END */
| 1396 | |
| 1397 | /* Parse CASE WHEN ... THEN ... [ELSE ...] END */ |
| 1398 | static cbm_case_expr_t *parse_case_expr(parser_t *p) { |
| 1399 | /* CASE already consumed */ |
| 1400 | cbm_case_expr_t *kase = calloc(CBM_ALLOC_ONE, sizeof(cbm_case_expr_t)); |
| 1401 | if (!kase) { |
| 1402 | return NULL; |
| 1403 | } |
| 1404 | int bcap = CYP_INIT_CAP4; |
| 1405 | kase->branches = malloc(bcap * sizeof(cbm_case_branch_t)); |
| 1406 | if (!kase->branches) { |
| 1407 | free(kase); |
| 1408 | return NULL; |
| 1409 | } |
| 1410 | |
| 1411 | while (check(p, TOK_WHEN)) { |
| 1412 | advance(p); |
| 1413 | cbm_expr_t *when = parse_or_expr(p); |
| 1414 | if (!expect(p, TOK_THEN)) { |
| 1415 | expr_free(when); |
| 1416 | break; |
| 1417 | } |
| 1418 | const char *then_val = parse_value_literal(p); |
| 1419 | if (kase->branch_count >= bcap) { |
| 1420 | int new_bcap = bcap * PAIR_LEN; |
| 1421 | void *tmp = realloc(kase->branches, new_bcap * sizeof(cbm_case_branch_t)); |
| 1422 | if (!tmp) { |
| 1423 | expr_free(when); |
| 1424 | safe_str_free(&then_val); |
| 1425 | for (int i = 0; i < kase->branch_count; i++) { |
| 1426 | expr_free(kase->branches[i].when_expr); |
| 1427 | safe_str_free(&kase->branches[i].then_val); |
| 1428 | } |
| 1429 | free(kase->branches); |
| 1430 | free(kase); |
| 1431 | return NULL; |
| 1432 | } |
| 1433 | kase->branches = tmp; |
| 1434 | bcap = new_bcap; |
| 1435 | } |
| 1436 | kase->branches[kase->branch_count++] = |
| 1437 | (cbm_case_branch_t){.when_expr = when, .then_val = then_val}; |
| 1438 | } |
| 1439 | |
| 1440 | if (match(p, TOK_ELSE)) { |
| 1441 | kase->else_val = parse_value_literal(p); |
| 1442 | } |
| 1443 | expect(p, TOK_END); |
| 1444 | return kase; |
| 1445 | } |
| 1446 | |
| 1447 | /* Parse a single RETURN/WITH item (aggregate, string func, CASE, or plain var.prop). |
| 1448 | * Returns 0 on success, -1 on error. */ |
no test coverage detected