* Given an update spec that is a replace document, writes the replacement document * processing the necessary update. This covers scenarios around _id validation, and ensuring * the _id is propagated from source to target document. It also means for upserts, extracting the _id * from the filters into the target document. */
| 731 | * from the filters into the target document. |
| 732 | */ |
| 733 | static pgbson * |
| 734 | ProcessReplaceDocument(pgbson *sourceDoc, const bson_value_t *updateSpec, |
| 735 | bool isUpsert) |
| 736 | { |
| 737 | bson_iter_t sourceDocIterator; |
| 738 | bson_iter_t replaceDocumentIterator; |
| 739 | pgbson_writer writer; |
| 740 | if (updateSpec->value_type != BSON_TYPE_DOCUMENT) |
| 741 | { |
| 742 | ereport(ERROR, (errcode(ERRCODE_DOCUMENTDB_BADVALUE), errmsg( |
| 743 | "Expected value to contain 'document' type but found '%s' type", |
| 744 | BsonTypeName(updateSpec->value_type)))); |
| 745 | } |
| 746 | |
| 747 | uint32_t documentLength = updateSpec->value.v_doc.data_len; |
| 748 | const uint8_t *documentBytes = updateSpec->value.v_doc.data; |
| 749 | |
| 750 | /* validate the replace document. */ |
| 751 | ValidateInputBsonBytes(documentBytes, |
| 752 | documentLength, |
| 753 | BSON_VALIDATE_NONE); |
| 754 | |
| 755 | PgbsonWriterInit(&writer); |
| 756 | |
| 757 | /* write the object_id of the document. */ |
| 758 | const bson_value_t *sourceIdValue = NULL; |
| 759 | if (!isUpsert) |
| 760 | { |
| 761 | if (!PgbsonInitIteratorAtPath(sourceDoc, "_id", &sourceDocIterator)) |
| 762 | { |
| 763 | ereport(ERROR, (errmsg( |
| 764 | "Unexpected: Document to update did not have an _id"))); |
| 765 | } |
| 766 | |
| 767 | sourceIdValue = bson_iter_value(&sourceDocIterator); |
| 768 | PgbsonWriterAppendValue(&writer, "_id", 3, sourceIdValue); |
| 769 | } |
| 770 | else |
| 771 | { |
| 772 | /* first we look up the _id from the document. */ |
| 773 | const bson_value_t *idFromReplaceDocument = NULL; |
| 774 | bson_iter_init_from_data(&replaceDocumentIterator, documentBytes, documentLength); |
| 775 | |
| 776 | if (bson_iter_find_w_len(&replaceDocumentIterator, "_id", 3)) |
| 777 | { |
| 778 | idFromReplaceDocument = bson_iter_value(&replaceDocumentIterator); |
| 779 | } |
| 780 | |
| 781 | /* next we look up the id value from the query document. */ |
| 782 | bson_iter_t queryDocumentIterator; |
| 783 | bson_value_t idFromQueryDocument = { 0 }; |
| 784 | if (PgbsonInitIteratorAtPath(sourceDoc, "_id", |
| 785 | &queryDocumentIterator)) |
| 786 | { |
| 787 | idFromQueryDocument = *bson_iter_value(&queryDocumentIterator); |
| 788 | } |
| 789 | |
| 790 | /* if both are specified make sure they're equal */ |
no test coverage detected