Response BlobClient::Query()

in sdk/storage/azure-storage-blobs/src/rest_client.cpp [5348:5670]


    Response<Models::QueryBlobResult> BlobClient::Query(
        Core::Http::_internal::HttpPipeline& pipeline,
        const Core::Url& url,
        const QueryBlobOptions& options,
        const Core::Context& context)
    {
      std::string xmlBody;
      {
        _internal::XmlWriter writer;
        writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "QueryRequest"});
        writer.Write(_internal::XmlNode{
            _internal::XmlNodeType::StartTag,
            "QueryType",
            options.QueryRequest.QueryType.ToString()});
        writer.Write(_internal::XmlNode{
            _internal::XmlNodeType::StartTag, "Expression", options.QueryRequest.Expression});
        if (options.QueryRequest.InputSerialization.HasValue())
        {
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "InputSerialization"});
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Format"});
          writer.Write(_internal::XmlNode{
              _internal::XmlNodeType::StartTag,
              "Type",
              options.QueryRequest.InputSerialization.Value().Format.Type.ToString()});
          if (options.QueryRequest.InputSerialization.Value()
                  .Format.DelimitedTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "DelimitedTextConfiguration"});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "ColumnSeparator",
                options.QueryRequest.InputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .ColumnSeparator});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "FieldQuote",
                options.QueryRequest.InputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .FieldQuote});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "RecordSeparator",
                options.QueryRequest.InputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .RecordSeparator});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "EscapeChar",
                options.QueryRequest.InputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .EscapeChar});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "HasHeaders",
                options.QueryRequest.InputSerialization.Value()
                        .Format.DelimitedTextConfiguration.Value()
                        .HeadersPresent
                    ? "true"
                    : "false"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.InputSerialization.Value()
                  .Format.JsonTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "JsonTextConfiguration"});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "RecordSeparator",
                options.QueryRequest.InputSerialization.Value()
                    .Format.JsonTextConfiguration.Value()
                    .RecordSeparator});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.InputSerialization.Value().Format.ArrowConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "ArrowConfiguration"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Schema"});
            for (const auto& i1 : options.QueryRequest.InputSerialization.Value()
                                      .Format.ArrowConfiguration.Value()
                                      .Schema)
            {
              writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Field"});
              writer.Write(
                  _internal::XmlNode{_internal::XmlNodeType::StartTag, "Type", i1.Type.ToString()});
              if (i1.Name.HasValue())
              {
                writer.Write(
                    _internal::XmlNode{_internal::XmlNodeType::StartTag, "Name", i1.Name.Value()});
              }
              if (i1.Precision.HasValue())
              {
                writer.Write(_internal::XmlNode{
                    _internal::XmlNodeType::StartTag,
                    "Precision",
                    std::to_string(i1.Precision.Value())});
              }
              if (i1.Scale.HasValue())
              {
                writer.Write(_internal::XmlNode{
                    _internal::XmlNodeType::StartTag, "Scale", std::to_string(i1.Scale.Value())});
              }
              writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
            }
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.InputSerialization.Value()
                  .Format.ParquetTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "ParquetTextConfiguration"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
        }
        if (options.QueryRequest.OutputSerialization.HasValue())
        {
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "OutputSerialization"});
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Format"});
          writer.Write(_internal::XmlNode{
              _internal::XmlNodeType::StartTag,
              "Type",
              options.QueryRequest.OutputSerialization.Value().Format.Type.ToString()});
          if (options.QueryRequest.OutputSerialization.Value()
                  .Format.DelimitedTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "DelimitedTextConfiguration"});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "ColumnSeparator",
                options.QueryRequest.OutputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .ColumnSeparator});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "FieldQuote",
                options.QueryRequest.OutputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .FieldQuote});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "RecordSeparator",
                options.QueryRequest.OutputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .RecordSeparator});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "EscapeChar",
                options.QueryRequest.OutputSerialization.Value()
                    .Format.DelimitedTextConfiguration.Value()
                    .EscapeChar});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "HasHeaders",
                options.QueryRequest.OutputSerialization.Value()
                        .Format.DelimitedTextConfiguration.Value()
                        .HeadersPresent
                    ? "true"
                    : "false"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.OutputSerialization.Value()
                  .Format.JsonTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "JsonTextConfiguration"});
            writer.Write(_internal::XmlNode{
                _internal::XmlNodeType::StartTag,
                "RecordSeparator",
                options.QueryRequest.OutputSerialization.Value()
                    .Format.JsonTextConfiguration.Value()
                    .RecordSeparator});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.OutputSerialization.Value().Format.ArrowConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "ArrowConfiguration"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Schema"});
            for (const auto& i2 : options.QueryRequest.OutputSerialization.Value()
                                      .Format.ArrowConfiguration.Value()
                                      .Schema)
            {
              writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Field"});
              writer.Write(
                  _internal::XmlNode{_internal::XmlNodeType::StartTag, "Type", i2.Type.ToString()});
              if (i2.Name.HasValue())
              {
                writer.Write(
                    _internal::XmlNode{_internal::XmlNodeType::StartTag, "Name", i2.Name.Value()});
              }
              if (i2.Precision.HasValue())
              {
                writer.Write(_internal::XmlNode{
                    _internal::XmlNodeType::StartTag,
                    "Precision",
                    std::to_string(i2.Precision.Value())});
              }
              if (i2.Scale.HasValue())
              {
                writer.Write(_internal::XmlNode{
                    _internal::XmlNodeType::StartTag, "Scale", std::to_string(i2.Scale.Value())});
              }
              writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
            }
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          if (options.QueryRequest.OutputSerialization.Value()
                  .Format.ParquetTextConfiguration.HasValue())
          {
            writer.Write(
                _internal::XmlNode{_internal::XmlNodeType::StartTag, "ParquetTextConfiguration"});
            writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          }
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
          writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
        }
        writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
        writer.Write(_internal::XmlNode{_internal::XmlNodeType::End});
        xmlBody = writer.GetDocument();
      }
      Core::IO::MemoryBodyStream requestBody(
          reinterpret_cast<const uint8_t*>(xmlBody.data()), xmlBody.length());
      auto request = Core::Http::Request(Core::Http::HttpMethod::Post, url, &requestBody, false);
      request.SetHeader("Content-Type", "application/xml; charset=UTF-8");
      request.SetHeader("Content-Length", std::to_string(requestBody.Length()));
      request.GetUrl().AppendQueryParameter("comp", "query");
      if (options.Snapshot.HasValue() && !options.Snapshot.Value().empty())
      {
        request.GetUrl().AppendQueryParameter(
            "snapshot", _internal::UrlEncodeQueryParameter(options.Snapshot.Value()));
      }
      if (options.LeaseId.HasValue() && !options.LeaseId.Value().empty())
      {
        request.SetHeader("x-ms-lease-id", options.LeaseId.Value());
      }
      if (options.EncryptionKey.HasValue() && !options.EncryptionKey.Value().empty())
      {
        request.SetHeader("x-ms-encryption-key", options.EncryptionKey.Value());
      }
      if (options.EncryptionKeySha256.HasValue()
          && !Core::Convert::Base64Encode(options.EncryptionKeySha256.Value()).empty())
      {
        request.SetHeader(
            "x-ms-encryption-key-sha256",
            Core::Convert::Base64Encode(options.EncryptionKeySha256.Value()));
      }
      if (options.EncryptionAlgorithm.HasValue() && !options.EncryptionAlgorithm.Value().empty())
      {
        request.SetHeader("x-ms-encryption-algorithm", options.EncryptionAlgorithm.Value());
      }
      if (options.IfModifiedSince.HasValue())
      {
        request.SetHeader(
            "If-Modified-Since",
            options.IfModifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123));
      }
      if (options.IfUnmodifiedSince.HasValue())
      {
        request.SetHeader(
            "If-Unmodified-Since",
            options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123));
      }
      if (options.IfMatch.HasValue() && !options.IfMatch.ToString().empty())
      {
        request.SetHeader("If-Match", options.IfMatch.ToString());
      }
      if (options.IfNoneMatch.HasValue() && !options.IfNoneMatch.ToString().empty())
      {
        request.SetHeader("If-None-Match", options.IfNoneMatch.ToString());
      }
      if (options.IfTags.HasValue() && !options.IfTags.Value().empty())
      {
        request.SetHeader("x-ms-if-tags", options.IfTags.Value());
      }
      request.SetHeader("x-ms-version", "2024-08-04");
      if (options.EncryptionScope.HasValue() && !options.EncryptionScope.Value().empty())
      {
        request.SetHeader("x-ms-encryption-scope", options.EncryptionScope.Value());
      }
      auto pRawResponse = pipeline.Send(request, context);
      auto httpStatusCode = pRawResponse->GetStatusCode();
      if (!(httpStatusCode == Core::Http::HttpStatusCode::Ok
            || httpStatusCode == Core::Http::HttpStatusCode::PartialContent))
      {
        throw StorageException::CreateFromResponse(std::move(pRawResponse));
      }
      Models::QueryBlobResult response;
      response.BodyStream = pRawResponse->ExtractBodyStream();
      if (pRawResponse->GetHeaders().count("Last-Modified") != 0)
      {
        response.LastModified = DateTime::Parse(
            pRawResponse->GetHeaders().at("Last-Modified"), Azure::DateTime::DateFormat::Rfc1123);
      }
      if (pRawResponse->GetHeaders().count("ETag") != 0)
      {
        response.ETag = ETag(pRawResponse->GetHeaders().at("ETag"));
      }
      if (pRawResponse->GetHeaders().count("x-ms-lease-duration") != 0)
      {
        response.LeaseDuration
            = Models::LeaseDurationType(pRawResponse->GetHeaders().at("x-ms-lease-duration"));
      }
      if (pRawResponse->GetHeaders().count("x-ms-lease-state") != 0)
      {
        response.LeaseState = Models::LeaseState(pRawResponse->GetHeaders().at("x-ms-lease-state"));
      }
      if (pRawResponse->GetHeaders().count("x-ms-lease-status") != 0)
      {
        response.LeaseStatus
            = Models::LeaseStatus(pRawResponse->GetHeaders().at("x-ms-lease-status"));
      }
      response.IsServerEncrypted
          = pRawResponse->GetHeaders().at("x-ms-server-encrypted") == std::string("true");
      return Response<Models::QueryBlobResult>(std::move(response), std::move(pRawResponse));
    }