Uploaded image for project: 'Couchbase .NET client library'
  1. Couchbase .NET client library
  2. NCBC-3590

Performing sub-doc SetDoc on the entire document should still use the transcoder

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • Critical
    • 3.4.14
    • 3.4.13
    • library
    • None
    • 0

    Description

      Currently, all multi-lookup operations pass through the transcoder to deserialize. However, multi-mutate operations skip the transcoder and go directly to the serializer. This is fine for JSON content, but means that content such as a byte array meant to be written raw is serialized by the JSON serializer. It will then fail to read when performing a multi-lookup "GetFull" operation because that does pass through the transcoder's Decode<T> method.

      When working with true sub-document operations, this is probably fine. You are clearly working with JSON if you're setting a property on a JSON document. However, sub-doc operations are also used for getting/settings XATTRs. This bug means that there is no way to set a byte-array document with XATTRs as a single operation, it would require one traditional SET operation followed by a separate operation to set the XATTRs.

      Additionally, the handling is also inconsistent on nested properties. In this case, the multi-mutate operation is correctly assuming that everything should be serialized as JSON, but the multi-lookup is out of sync because it always uses the Transcoder not just the JSON serializer.

      Repro:

      var transcoder = new LegacyTranscoder(new DefaultSerializer());
       
      var mutateInSpecs = new List<MutateInSpec>(2)
      {
          MutateInSpec.SetDoc(new byte[] { 1, 2, 3, 4 });
          MutateInSpec.Upsert("test_attr", "foo", isXattr: true);
      };
       
      var mutateInOptions = new MutateInOptions()
          .Transcoder(transcoder)
          .StoreSemantics(StoreSemantics.Upsert);
       
      await collection.MutateInAsync("key", mutateInSpecs , mutateInOptions);
       
      var lookupInSpecs = new List<LookupInSpecs>(2)
      {
          builder.GetFull();
          LookupInSpec.Get("test_attr", isXattr: true);
      };
       
      var lookupInOptions = new LookupInOptions()
          .Transcoder(transcoder);
       
      var result = await collection.LookupInAsync("key", lookupInSpecs, lookupInOptions);
       
      // Fails with an exception because the JSON serializer encoded as a Base64 string,
      // but we're decoding as a byte array currently
      var bytes = result.ContentAs<byte[]>(0);
       
      // Fails because "foo" was serialized as a JSON string, with wrapping quotes, but 
      // the deserializer is passing through the LegacyTranscoder which expects raw strings
      // It seems like gets with a path shouldn't pass through the transcoder.
      Assert.Equal("foo", result.ContentAs<string>(1));
      

      Attachments

        For Gerrit Dashboard: NCBC-3590
        # Subject Branch Project Status CR V

        Activity

          People

            btburnett3 Brant Burnett
            btburnett3 Brant Burnett
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes

                PagerDuty