* Calling procedure can be slow, so there is a function alternative */
| 498 | * Calling procedure can be slow, so there is a function alternative |
| 499 | */ |
| 500 | static Datum |
| 501 | bind_variable(PG_FUNCTION_ARGS) |
| 502 | { |
| 503 | CursorData *c; |
| 504 | VariableData *var; |
| 505 | char *varname, *varname_downcase; |
| 506 | Oid valtype; |
| 507 | bool is_unknown = false; |
| 508 | |
| 509 | c = get_cursor(fcinfo, true); |
| 510 | |
| 511 | if (PG_ARGISNULL(1)) |
| 512 | ereport(ERROR, |
| 513 | (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| 514 | errmsg("name of bind variable is NULL"))); |
| 515 | |
| 516 | varname = text_to_cstring(PG_GETARG_TEXT_P(1)); |
| 517 | if (*varname == ':') |
| 518 | varname += 1; |
| 519 | |
| 520 | varname_downcase = downcase_identifier(varname, (int) strlen(varname), false, true); |
| 521 | var = get_var(c, varname_downcase, -1, false); |
| 522 | |
| 523 | valtype = get_fn_expr_argtype(fcinfo->flinfo, 2); |
| 524 | if (valtype == RECORDOID) |
| 525 | ereport(ERROR, |
| 526 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 527 | errmsg("cannot to bind a value of record type"))); |
| 528 | |
| 529 | valtype = getBaseType(valtype); |
| 530 | if (valtype == UNKNOWNOID) |
| 531 | { |
| 532 | is_unknown = true; |
| 533 | valtype = TEXTOID; |
| 534 | } |
| 535 | |
| 536 | if (var->typoid != InvalidOid) |
| 537 | { |
| 538 | if (!var->typbyval && !var->isnull) |
| 539 | { |
| 540 | pfree(DatumGetPointer(var->value)); |
| 541 | var->value = (Datum) 0; |
| 542 | } |
| 543 | |
| 544 | var->isnull = true; |
| 545 | } |
| 546 | |
| 547 | var->typoid = valtype; |
| 548 | |
| 549 | if (!PG_ARGISNULL(2)) |
| 550 | { |
| 551 | MemoryContext oldcxt; |
| 552 | |
| 553 | get_typlenbyval(var->typoid, &var->typlen, &var->typbyval); |
| 554 | |
| 555 | oldcxt = MemoryContextSwitchTo(c->cursor_cxt); |
| 556 | |
| 557 | if (is_unknown) |
no test coverage detected