* bson_repath_and_build take an array of paths and an array of bsons and constructs a bson where * the root paths of each bson become the corresponding text in the array of paths and are merged into one object * ["l1", "l2"] [{"":x}, {"":y}] becomes {"l1":x, "l2":y} * * If the value is an empty document, it is treated as an EOD value and is not written. For example: * ["l1", "l2"] [{"":x}, {}
| 403 | * ["l1", "l2"] [{"":x}, {}] becomes {"l1":x} |
| 404 | */ |
| 405 | static Datum |
| 406 | BsonRepathAndBuildCore(PG_FUNCTION_ARGS, bool isBuildDocument) |
| 407 | { |
| 408 | Datum *args; |
| 409 | bool *nulls; |
| 410 | Oid *types; |
| 411 | |
| 412 | /* fetch argument values to build the object */ |
| 413 | int nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls); |
| 414 | if (nargs < 0) |
| 415 | { |
| 416 | PG_RETURN_NULL(); |
| 417 | } |
| 418 | if (nargs % 2 != 0) |
| 419 | { |
| 420 | ereport(ERROR, |
| 421 | (errcode(ERRCODE_DOCUMENTDB_BADVALUE), |
| 422 | errmsg("argument list must have an even number of elements"), |
| 423 | errdetail( |
| 424 | "The arguments of bson_repath_and_build() must consist of alternating keys and values."))); |
| 425 | } |
| 426 | |
| 427 | pgbson_writer writer; |
| 428 | PgbsonWriterInit(&writer); |
| 429 | for (int i = 0; i < nargs; i += 2) |
| 430 | { |
| 431 | if (nulls[i]) |
| 432 | { |
| 433 | ereport(ERROR, |
| 434 | (errcode(ERRCODE_DOCUMENTDB_BADVALUE), |
| 435 | errmsg("The specified argument %d must not be null", i + 1), |
| 436 | errdetail("Object keys should be text."))); |
| 437 | } |
| 438 | |
| 439 | char *path; |
| 440 | int len; |
| 441 | if (types[i] != TEXTOID) |
| 442 | { |
| 443 | if (isBuildDocument) |
| 444 | { |
| 445 | Oid outputFunction; |
| 446 | bool isVarlena; |
| 447 | getTypeOutputInfo(types[i], &outputFunction, &isVarlena); |
| 448 | |
| 449 | FmgrInfo info; |
| 450 | LOCAL_FCINFO(innerFcinfo, 1); |
| 451 | fmgr_info(outputFunction, &info); |
| 452 | |
| 453 | InitFunctionCallInfoData(*innerFcinfo, &info, 1, fcinfo->fncollation, |
| 454 | fcinfo->context, fcinfo->resultinfo); |
| 455 | innerFcinfo->args->value = args[i]; |
| 456 | innerFcinfo->args->isnull = nulls[i]; |
| 457 | |
| 458 | Datum result = FunctionCallInvoke(innerFcinfo); |
| 459 | if (innerFcinfo->isnull) |
| 460 | { |
| 461 | ereport(ERROR, |
| 462 | (errcode(ERRCODE_DOCUMENTDB_BADVALUE), |
no test coverage detected