diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 21f066bbd758b..a0291c62a4cf7 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -1,7 +1,8 @@ # Release History ## 12.9.0-beta.1 (Unreleased) - +- Added support for the 2019-02-10 service version. +- Added support to specify Arrow Output Serialization when querying a blob. ## 12.8.0 (2020-08-13) - Fixed a bug that, when the data length parameter did not match the actual length of the data in BlobClient.upload, caused a zero length blob to be uploaded rather than throwing an exception. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java index 9e9f770b0c014..47ebee34248c9 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java @@ -97,7 +97,7 @@ public AzureBlobStorageImpl build() { if (this.version != null) { client.setVersion(this.version); } else { - client.setVersion("2019-12-12"); + client.setVersion("2020-02-10"); } if (this.pathRenameMode != null) { client.setPathRenameMode(this.pathRenameMode); diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowConfiguration.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowConfiguration.java new file mode 100644 index 0000000000000..2a4056b5b2163 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowConfiguration.java @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. + +package com.azure.storage.blob.implementation.models; + +import com.azure.core.annotation.Fluent; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.List; + +/** + * arrow configuration. + */ +@JacksonXmlRootElement(localName = "ArrowConfiguration") +@Fluent +public final class ArrowConfiguration { + private static final class SchemaWrapper { + @JacksonXmlProperty(localName = "Field") + private final List items; + + @JsonCreator + private SchemaWrapper(@JacksonXmlProperty(localName = "Field") List items) { + this.items = items; + } + } + + /* + * The schema property. + */ + @JsonProperty(value = "Schema", required = true) + private SchemaWrapper schema; + + /** + * Get the schema property: The schema property. + * + * @return the schema value. + */ + public List getSchema() { + if (this.schema == null) { + this.schema = new SchemaWrapper(new ArrayList()); + } + return this.schema.items; + } + + /** + * Set the schema property: The schema property. + * + * @param schema the schema value to set. + * @return the ArrowConfiguration object itself. + */ + public ArrowConfiguration setSchema(List schema) { + this.schema = new SchemaWrapper(schema); + return this; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowField.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowField.java new file mode 100644 index 0000000000000..c93cfd4f43b7f --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/ArrowField.java @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. + +package com.azure.storage.blob.implementation.models; + +import com.azure.core.annotation.Fluent; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +/** + * field of an arrow schema. + */ +@JacksonXmlRootElement(localName = "Field") +@Fluent +public final class ArrowField { + /* + * The type property. + */ + @JsonProperty(value = "Type", required = true) + private String type; + + /* + * The name property. + */ + @JsonProperty(value = "Name") + private String name; + + /* + * The precision property. + */ + @JsonProperty(value = "Precision") + private Integer precision; + + /* + * The scale property. + */ + @JsonProperty(value = "Scale") + private Integer scale; + + /** + * Get the type property: The type property. + * + * @return the type value. + */ + public String getType() { + return this.type; + } + + /** + * Set the type property: The type property. + * + * @param type the type value to set. + * @return the ArrowField object itself. + */ + public ArrowField setType(String type) { + this.type = type; + return this; + } + + /** + * Get the name property: The name property. + * + * @return the name value. + */ + public String getName() { + return this.name; + } + + /** + * Set the name property: The name property. + * + * @param name the name value to set. + * @return the ArrowField object itself. + */ + public ArrowField setName(String name) { + this.name = name; + return this; + } + + /** + * Get the precision property: The precision property. + * + * @return the precision value. + */ + public Integer getPrecision() { + return this.precision; + } + + /** + * Set the precision property: The precision property. + * + * @param precision the precision value to set. + * @return the ArrowField object itself. + */ + public ArrowField setPrecision(Integer precision) { + this.precision = precision; + return this; + } + + /** + * Get the scale property: The scale property. + * + * @return the scale value. + */ + public Integer getScale() { + return this.scale; + } + + /** + * Set the scale property: The scale property. + * + * @param scale the scale value to set. + * @return the ArrowField object itself. + */ + public ArrowField setScale(Integer scale) { + this.scale = scale; + return this; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormat.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormat.java index aa64de56adb19..ec0dc618c7de6 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormat.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormat.java @@ -15,7 +15,7 @@ @Fluent public final class QueryFormat { /* - * Possible values include: 'delimited', 'json' + * Possible values include: 'delimited', 'json', 'arrow' */ @JsonProperty(value = "Type") private QueryFormatType type; @@ -32,8 +32,15 @@ public final class QueryFormat { @JsonProperty(value = "JsonTextConfiguration") private JsonTextConfiguration jsonTextConfiguration; + /* + * The arrowConfiguration property. + */ + @JsonProperty(value = "ArrowConfiguration") + private ArrowConfiguration arrowConfiguration; + /** - * Get the type property: Possible values include: 'delimited', 'json'. + * Get the type property: Possible values include: 'delimited', 'json', + * 'arrow'. * * @return the type value. */ @@ -42,7 +49,8 @@ public QueryFormatType getType() { } /** - * Set the type property: Possible values include: 'delimited', 'json'. + * Set the type property: Possible values include: 'delimited', 'json', + * 'arrow'. * * @param type the type value to set. * @return the QueryFormat object itself. @@ -96,4 +104,24 @@ public QueryFormat setJsonTextConfiguration(JsonTextConfiguration jsonTextConfig this.jsonTextConfiguration = jsonTextConfiguration; return this; } + + /** + * Get the arrowConfiguration property: The arrowConfiguration property. + * + * @return the arrowConfiguration value. + */ + public ArrowConfiguration getArrowConfiguration() { + return this.arrowConfiguration; + } + + /** + * Set the arrowConfiguration property: The arrowConfiguration property. + * + * @param arrowConfiguration the arrowConfiguration value to set. + * @return the QueryFormat object itself. + */ + public QueryFormat setArrowConfiguration(ArrowConfiguration arrowConfiguration) { + this.arrowConfiguration = arrowConfiguration; + return this; + } } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormatType.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormatType.java index 7be7336b27525..d372b3ab69088 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormatType.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/QueryFormatType.java @@ -19,7 +19,12 @@ public enum QueryFormatType { /** * Enum value json. */ - JSON("json"); + JSON("json"), + + /** + * Enum value arrow. + */ + ARROW("arrow"); /** * The actual serialized value for a QueryFormatType instance. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobQueryReader.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobQueryReader.java index b9b68766fcecf..155163cc3e9b9 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobQueryReader.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobQueryReader.java @@ -4,11 +4,15 @@ package com.azure.storage.blob.implementation.util; import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.blob.implementation.models.ArrowConfiguration; +import com.azure.storage.blob.implementation.models.ArrowField; import com.azure.storage.blob.implementation.models.DelimitedTextConfiguration; import com.azure.storage.blob.implementation.models.JsonTextConfiguration; import com.azure.storage.blob.implementation.models.QueryFormat; import com.azure.storage.blob.implementation.models.QueryFormatType; import com.azure.storage.blob.implementation.models.QuerySerialization; +import com.azure.storage.blob.models.BlobQueryArrowField; +import com.azure.storage.blob.models.BlobQueryArrowSerialization; import com.azure.storage.blob.models.BlobQueryDelimitedSerialization; import com.azure.storage.blob.models.BlobQueryError; import com.azure.storage.blob.models.BlobQueryJsonSerialization; @@ -24,6 +28,7 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -201,12 +206,12 @@ private static boolean checkParametersNotNull(Object... data) { } /** - * Transforms a generic BlobQuickQuerySerialization into a QuickQuerySerialization. + * Transforms a generic input BlobQuerySerialization into a QuerySerialization. * @param userSerialization {@link BlobQuerySerialization} * @param logger {@link ClientLogger} * @return {@link QuerySerialization} */ - public static QuerySerialization transformSerialization(BlobQuerySerialization userSerialization, + public static QuerySerialization transformInputSerialization(BlobQuerySerialization userSerialization, ClientLogger logger) { if (userSerialization == null) { return null; @@ -233,6 +238,46 @@ public static QuerySerialization transformSerialization(BlobQuerySerialization u return new QuerySerialization().setFormat(generatedFormat); } + /** + * Transforms a generic input BlobQuerySerialization into a QuerySerialization. + * @param userSerialization {@link BlobQuerySerialization} + * @param logger {@link ClientLogger} + * @return {@link QuerySerialization} + */ + public static QuerySerialization transformOutputSerialization(BlobQuerySerialization userSerialization, + ClientLogger logger) { + if (userSerialization == null) { + return null; + } + + QueryFormat generatedFormat = new QueryFormat(); + if (userSerialization instanceof BlobQueryDelimitedSerialization) { + + generatedFormat.setType(QueryFormatType.DELIMITED); + generatedFormat.setDelimitedTextConfiguration(transformDelimited( + (BlobQueryDelimitedSerialization) userSerialization)); + + } else if (userSerialization instanceof BlobQueryJsonSerialization) { + + generatedFormat.setType(QueryFormatType.JSON); + generatedFormat.setJsonTextConfiguration(transformJson( + (BlobQueryJsonSerialization) userSerialization)); + + } else if (userSerialization instanceof BlobQueryArrowSerialization) { + + generatedFormat.setType(QueryFormatType.ARROW); + generatedFormat.setArrowConfiguration(transformArrow( + (BlobQueryArrowSerialization) userSerialization)); + + } else { + throw logger.logExceptionAsError(new IllegalArgumentException( + String.format("'output' must be one of %s, %s or %s", BlobQueryJsonSerialization.class.getSimpleName(), + BlobQueryDelimitedSerialization.class.getSimpleName(), + BlobQueryArrowSerialization.class.getSimpleName()))); + } + return new QuerySerialization().setFormat(generatedFormat); + } + /** * Transforms a BlobQuickQueryDelimitedSerialization into a DelimitedTextConfiguration. * @@ -266,6 +311,35 @@ private static JsonTextConfiguration transformJson(BlobQueryJsonSerialization js .setRecordSeparator(charToString(jsonSerialization.getRecordSeparator())); } + /** + * Transforms a BlobQueryArrowSerialization into a ArrowConfiguration. + * + * @param arrowSerialization {@link BlobQueryArrowSerialization} + * @return {@link ArrowConfiguration} + */ + private static ArrowConfiguration transformArrow(BlobQueryArrowSerialization arrowSerialization) { + if (arrowSerialization == null) { + return null; + } + List schema = arrowSerialization.getSchema() == null ? null + : new ArrayList<>(arrowSerialization.getSchema().size()); + if (schema != null) { + for (BlobQueryArrowField field : arrowSerialization.getSchema()) { + if (field == null) { + schema.add(null); + } else { + schema.add(new ArrowField() + .setName(field.getName()) + .setPrecision(field.getPrecision()) + .setScale(field.getScale()) + .setType(field.getType().toString()) + ); + } + } + } + return new ArrowConfiguration().setSchema(schema); + } + private static String charToString(char c) { return c == '\0' ? "" : Character.toString(c); } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowField.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowField.java new file mode 100644 index 0000000000000..5607c56cbcead --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowField.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob.models; + +import com.azure.storage.common.implementation.StorageImplUtils; + +/** + * Defines an arrow field for a blob quick query request. + */ +public class BlobQueryArrowField { + + private String name; + private Integer precision; + private Integer scale; + private final BlobQueryArrowFieldType type; + + /** + * @param type {@link BlobQueryArrowFieldType} + */ + public BlobQueryArrowField(BlobQueryArrowFieldType type) { + StorageImplUtils.assertNotNull("type", type); + this.type = type; + } + + /** + * @param name The name of the field. + * @return The updated options. + */ + public BlobQueryArrowField setName(String name) { + this.name = name; + return this; + } + + /** + * @param precision The precision of the field. Required if type is {@link BlobQueryArrowFieldType#DECIMAL} + * @return The updated options. + */ + public BlobQueryArrowField setPrecision(int precision) { + this.precision = precision; + return this; + } + + /** + * @param scale The scale of the field. Required if type is {@link BlobQueryArrowFieldType#DECIMAL} + * @return The updated options. + */ + public BlobQueryArrowField setScale(int scale) { + this.scale = scale; + return this; + } + + /** + * @return The name. + */ + public String getName() { + return name; + } + + /** + * @return The precision. + */ + public Integer getPrecision() { + return precision; + } + + /** + * @return The scale. + */ + public Integer getScale() { + return scale; + } + + /** + * @return {@link BlobQueryArrowFieldType} + */ + public BlobQueryArrowFieldType getType() { + return type; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowFieldType.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowFieldType.java new file mode 100644 index 0000000000000..7ff47f124dee5 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowFieldType.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob.models; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for BlobQueryArrowFieldType. + */ +public enum BlobQueryArrowFieldType { + + /** + * Enum value int64. + */ + INT64("int64"), + + /** + * Enum value bool. + */ + BOOL("bool"), + + /** + * Enum value timestamp[ms]. + */ + TIMESTAMP("timestamp[ms]"), + + /** + * Enum value string. + */ + STRING("string"), + + /** + * Enum value double. + */ + DOUBLE("double"), + + /** + * Enum value decimal. + */ + DECIMAL("decimal"); + + /** + * The actual serialized value for a BlobQueryArrowFieldType instance. + */ + private final String value; + + BlobQueryArrowFieldType(String value) { + this.value = value; + } + + /** + * Parses a serialized value to a BlobQueryArrowFieldType instance. + * + * @param value the serialized value to parse. + * @return the parsed BlobQueryArrowFieldType object, or null if unable to parse. + */ + @JsonCreator + public static BlobQueryArrowFieldType fromString(String value) { + BlobQueryArrowFieldType[] items = BlobQueryArrowFieldType.values(); + for (BlobQueryArrowFieldType item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowSerialization.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowSerialization.java new file mode 100644 index 0000000000000..949cc3ac33854 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQueryArrowSerialization.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob.models; + +import java.util.Collections; +import java.util.List; + +/** + * Defines the output arrow serialization for a blob quick query request. + */ +public class BlobQueryArrowSerialization implements BlobQuerySerialization { + + private List schema; + + /** + * Gets the arrow fields. + * + * @return the arrow fields. + */ + public List getSchema() { + return schema == null ? null : Collections.unmodifiableList(schema); + } + + /** + * Sets the arrow fields. + * + * @param schema the arrow fields. + * @return the updated BlobQueryArrowSerialization object. + */ + public BlobQueryArrowSerialization setSchema(List schema) { + this.schema = schema == null ? null : Collections.unmodifiableList(schema); + return this; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQuerySerialization.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQuerySerialization.java index 3c742d5b07501..e320ba4e60e66 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQuerySerialization.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobQuerySerialization.java @@ -5,7 +5,11 @@ /** * Defines the input and output serialization for a blob quick query request. - * either {@link BlobQueryJsonSerialization} or {@link BlobQueryDelimitedSerialization} + * either {@link BlobQueryJsonSerialization}, {@link BlobQueryDelimitedSerialization}, or + * {@link BlobQueryArrowSerialization}. + *

+ * Note: {@link BlobQueryArrowSerialization} can only be used as an output. + *

*/ public interface BlobQuerySerialization { } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java index 5ef62827229f6..f3895e5b37cca 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java @@ -1764,9 +1764,9 @@ Mono queryWithResponse(BlobQueryOptions queryOptions, Co BlobRequestConditions requestConditions = queryOptions.getRequestConditions() == null ? new BlobRequestConditions() : queryOptions.getRequestConditions(); - QuerySerialization in = BlobQueryReader.transformSerialization(queryOptions.getInputSerialization(), + QuerySerialization in = BlobQueryReader.transformInputSerialization(queryOptions.getInputSerialization(), logger); - QuerySerialization out = BlobQueryReader.transformSerialization(queryOptions.getOutputSerialization(), + QuerySerialization out = BlobQueryReader.transformOutputSerialization(queryOptions.getOutputSerialization(), logger); QueryRequest qr = new QueryRequest() diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlobBaseAPITest.groovy b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlobBaseAPITest.groovy index 36b7aa15d772f..6eff27cc1a39a 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlobBaseAPITest.groovy +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlobBaseAPITest.groovy @@ -372,6 +372,43 @@ class BlobBaseAPITest extends APISpec { } } + @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation + def "Query Input csv Output arrow"() { + setup: + BlobQueryDelimitedSerialization inSer = new BlobQueryDelimitedSerialization() + .setRecordSeparator('\n' as char) + .setColumnSeparator(',' as char) + .setEscapeChar('\0' as char) + .setFieldQuote('\0' as char) + .setHeadersPresent(false) + uploadCsv(inSer, 32) + List schema = new ArrayList<>() + schema.add(new BlobQueryArrowField(BlobQueryArrowFieldType.DECIMAL).setName("Name").setPrecision(4).setScale(2)) + BlobQueryArrowSerialization outSer = new BlobQueryArrowSerialization().setSchema(schema) + def expression = "SELECT _2 from BlobStorage WHERE _1 > 250;" + String expectedData = "/////4AAAAAQAAAAAAAKAAwABgAFAAgACgAAAAABAwAMAAAACAAIAAAABAAIAAAABAAAAAEAAAAUAAAAEAAUAAgABgAHAAwAAAAQABAAAAAAAAEHJAAAABQAAAAEAAAAAAAAAAgADAAEAAgACAAAAAQAAAACAAAABAAAAE5hbWUAAAAAAAAAAP////9wAAAAEAAAAAAACgAOAAYABQAIAAoAAAAAAwMAEAAAAAAACgAMAAAABAAIAAoAAAAwAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAP////+IAAAAFAAAAAAAAAAMABYABgAFAAgADAAMAAAAAAMDABgAAAAAAgAAAAAAAAAACgAYAAwABAAIAAoAAAA8AAAAEAAAACAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAABAAAAIAAAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAA" + OutputStream os = new ByteArrayOutputStream() + BlobQueryOptions options = new BlobQueryOptions(expression, os).setInputSerialization(inSer).setOutputSerialization(outSer) + + /* Input Stream. */ + when: + InputStream qqStream = bc.openQueryInputStreamWithResponse(options).getValue() + byte[] queryData = readFromInputStream(qqStream, 912) + + then: + notThrown(IOException) + Base64.getEncoder().encodeToString(queryData) == expectedData + + /* Output Stream. */ + when: + bc.queryWithResponse(options, null, null) + byte[] osData = os.toByteArray() + + then: + notThrown(BlobStorageException) + Base64.getEncoder().encodeToString(osData) == expectedData + } + @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation def "Query non fatal error"() { setup: @@ -606,6 +643,29 @@ class BlobBaseAPITest extends APISpec { false | true || _ } +// @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation + def "Query arrow input IA"() { + setup: + def inSer = new BlobQueryArrowSerialization() + def expression = "SELECT * from BlobStorage" + BlobQueryOptions options = new BlobQueryOptions(expression) + .setInputSerialization(inSer) + + when: + InputStream stream = bc.openQueryInputStreamWithResponse(options).getValue() /* Don't need to call read. */ + + then: + thrown(IllegalArgumentException) + + when: + options = new BlobQueryOptions(expression, new ByteArrayOutputStream()) + .setInputSerialization(inSer) + bc.queryWithResponse(options, null, null) + + then: + thrown(IllegalArgumentException) + } + @Unroll @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation def "Query AC"() { diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryarrowinputia.json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryarrowinputia.json new file mode 100644 index 0000000000000..9c803387aa64c --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryarrowinputia.json @@ -0,0 +1,86 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryarrowinputia0blobbaseapitestqueryarrowinputia47a792753?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "11f8f93f-d71e-42c5-af8e-c907c52b95d6" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D8494722AEEC76", + "Last-Modified" : "Tue, 25 Aug 2020 22:35:14 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "83bee4bf-501e-0005-7330-7beaf9000000", + "Date" : "Tue, 25 Aug 2020 22:35:14 GMT", + "x-ms-client-request-id" : "11f8f93f-d71e-42c5-af8e-c907c52b95d6" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryarrowinputia0blobbaseapitestqueryarrowinputia47a792753/javablobqueryarrowinputia13646815a561dd87f9495a", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "1678200f-e4e6-4c8f-b879-9ea964860f78", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D8494722DBDEE4", + "x-ms-content-crc64" : "AAAAAAAAAAA=", + "Last-Modified" : "Tue, 25 Aug 2020 22:35:14 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "83bee4c3-501e-0005-7430-7beaf9000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 25 Aug 2020 22:35:14 GMT", + "x-ms-client-request-id" : "1678200f-e4e6-4c8f-b879-9ea964860f78", + "Content-MD5" : "1B2M2Y8AsgTpgAmY7PhCfg==" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcqueryarrowinputia&comp=list", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "139c2c52-d129-4bfe-b41c-a2a74360e315" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "83bee4c4-501e-0005-7530-7beaf9000000", + "Body" : "jtcqueryarrowinputiajtcqueryarrowinputia0blobbaseapitestqueryarrowinputia47a792753Tue, 25 Aug 2020 22:35:14 GMT\"0x8D8494722AEEC76\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 25 Aug 2020 22:35:14 GMT", + "x-ms-client-request-id" : "139c2c52-d129-4bfe-b41c-a2a74360e315", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryarrowinputia0blobbaseapitestqueryarrowinputia47a792753?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "ebc4f286-14cf-499a-8b00-97c7be5bac3c" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "83bee4c5-501e-0005-7630-7beaf9000000", + "Date" : "Tue, 25 Aug 2020 22:35:14 GMT", + "x-ms-client-request-id" : "ebc4f286-14cf-499a-8b00-97c7be5bac3c" + }, + "Exception" : null + } ], + "variables" : [ "jtcqueryarrowinputia0blobbaseapitestqueryarrowinputia47a792753", "javablobqueryarrowinputia13646815a561dd87f9495a" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryinputcsvoutputarrow.json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryinputcsvoutputarrow.json new file mode 100644 index 0000000000000..efc564c6b8170 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobBaseAPITestqueryinputcsvoutputarrow.json @@ -0,0 +1,166 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "b98b8ca5-bbda-48f7-9628-1a89f859cc43" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D8491E8AFA0907", + "Last-Modified" : "Tue, 25 Aug 2020 17:44:40 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "7817cf11-d01e-0000-7007-7bff58000000", + "Date" : "Tue, 25 Aug 2020 17:44:39 GMT", + "x-ms-client-request-id" : "b98b8ca5-bbda-48f7-9628-1a89f859cc43" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f/javablobqueryinputcsvoutputarrow1728602615190a44aa", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "c8d9c873-b1bd-46c6-950d-1afb1284a2d2", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D8491E8B327087", + "x-ms-content-crc64" : "AAAAAAAAAAA=", + "Last-Modified" : "Tue, 25 Aug 2020 17:44:40 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "7817cf15-d01e-0000-7107-7bff58000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 25 Aug 2020 17:44:39 GMT", + "x-ms-client-request-id" : "c8d9c873-b1bd-46c6-950d-1afb1284a2d2", + "Content-MD5" : "1B2M2Y8AsgTpgAmY7PhCfg==" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f/javablobqueryinputcsvoutputarrow1728602615190a44aa", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "dd808953-3b9b-4c41-a6ec-6e6adc99b95a", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D8491E8B407A50", + "x-ms-content-crc64" : "qWWGs5Hamvo=", + "Last-Modified" : "Tue, 25 Aug 2020 17:44:40 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "7817cf16-d01e-0000-7207-7bff58000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 25 Aug 2020 17:44:39 GMT", + "x-ms-client-request-id" : "dd808953-3b9b-4c41-a6ec-6e6adc99b95a", + "Content-MD5" : "vDCMhAvvo34oZHeMW+ZcXg==" + }, + "Exception" : null + }, { + "Method" : "POST", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f/javablobqueryinputcsvoutputarrow1728602615190a44aa?comp=query", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "7f060a29-4667-465a-9294-cef21bea9cdb", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2020-02-10", + "x-ms-lease-state" : "available", + "Last-Modified" : "Tue, 25 Aug 2020 17:44:40 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 25 Aug 2020 17:44:39 GMT", + "x-ms-blob-type" : "BlockBlob", + "Accept-Ranges" : "bytes", + "ETag" : "0x8D8491E8B407A50", + "x-ms-creation-time" : "Tue, 25 Aug 2020 17:44:40 GMT", + "x-ms-request-id" : "7817cf17-d01e-0000-7307-7bff58000000", + "Body" : "T2JqAQIWYXZyby5zY2hlbWG+HlsKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLnJlc3VsdERhdGEiLAogICAgImRvYyI6ICJIb2xkcyByZXN1bHQgZGF0YSBpbiB0aGUgZm9ybWF0IHNwZWNpZmllZCBmb3IgdGhpcyBxdWVyeSAoQ1NWLCBKU09OLCBldGMuKS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImRhdGEiLAogICAgICAgICJ0eXBlIjogImJ5dGVzIgogICAgICB9CiAgICBdCiAgfSwKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLmVycm9yIiwKICAgICJkb2MiOiAiQW4gZXJyb3IgdGhhdCBvY2N1cnJlZCB3aGlsZSBwcm9jZXNzaW5nIHRoZSBxdWVyeS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImZhdGFsIiwKICAgICAgICAidHlwZSI6ICJib29sZWFuIiwKICAgICAgICAiZG9jIjogIklmIHRydWUsIHRoaXMgZXJyb3IgcHJldmVudHMgZnVydGhlciBxdWVyeSBwcm9jZXNzaW5nLiAgTW9yZSByZXN1bHQgZGF0YSBtYXkgYmUgcmV0dXJuZWQsIGJ1dCB0aGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgb2YgdGhlIG9yaWdpbmFsIGRhdGEgd2lsbCBiZSBwcm9jZXNzZWQuICBJZiBmYWxzZSwgdGhpcyBlcnJvciBkb2VzIG5vdCBwcmV2ZW50IGZ1cnRoZXIgcXVlcnkgcHJvY2Vzc2luZy4iCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJuYW1lIiwKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJkb2MiOiAiVGhlIG5hbWUgb2YgdGhlIGVycm9yIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAiZGVzY3JpcHRpb24iLAogICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgImRvYyI6ICJBIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvciIKICAgICAgfSwKICAgICAgewogICAgICAgICJuYW1lIjogInBvc2l0aW9uIiwKICAgICAgICAidHlwZSI6ICJsb25nIiwKICAgICAgICAiZG9jIjogIlRoZSBibG9iIG9mZnNldCBhdCB3aGljaCB0aGUgZXJyb3Igb2NjdXJyZWQiCiAgICAgIH0KICAgIF0KICB9LAogIHsKICAgICJ0eXBlIjogInJlY29yZCIsCiAgICAibmFtZSI6ICJjb20ubWljcm9zb2Z0LmF6dXJlLnN0b3JhZ2UucXVlcnlCbG9iQ29udGVudHMucHJvZ3Jlc3MiLAogICAgImRvYyI6ICJJbmZvcm1hdGlvbiBhYm91dCB0aGUgcHJvZ3Jlc3Mgb2YgdGhlIHF1ZXJ5IiwKICAgICJmaWVsZHMiOiBbCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJieXRlc1NjYW5uZWQiLAogICAgICAgICJ0eXBlIjogImxvbmciLAogICAgICAgICJkb2MiOiAiVGhlIG51bWJlciBvZiBieXRlcyB0aGF0IGhhdmUgYmVlbiBzY2FubmVkIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0sCiAgewogICAgInR5cGUiOiAicmVjb3JkIiwKICAgICJuYW1lIjogImNvbS5taWNyb3NvZnQuYXp1cmUuc3RvcmFnZS5xdWVyeUJsb2JDb250ZW50cy5lbmQiLAogICAgImRvYyI6ICJTZW50IGFzIHRoZSBmaW5hbCBtZXNzYWdlIG9mIHRoZSByZXNwb25zZSwgaW5kaWNhdGluZyB0aGF0IGFsbCByZXN1bHRzIGhhdmUgYmVlbiBzZW50LiIsCiAgICAiZmllbGRzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0KXQoA86yNoNoIdkuH4Oppm6W9NgKGBACABP////+AAAAAEAAAAAAACgAMAAYABQAIAAoAAAAAAQMADAAAAAgACAAAAAQACAAAAAQAAAABAAAAFAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABByQAAAAUAAAABAAAAAAAAAAIAAwABAAIAAgAAAAEAAAAAgAAAAQAAABOYW1lAAAAAAAAAAD/////cAAAABAAAAAAAAoADgAGAAUACAAKAAAAAAMDABAAAAAAAAoADAAAAAQACAAKAAAAMAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAADzrI2g2gh2S4fg6mmbpb02AqYKAKAK/////4gAAAAUAAAAAAAAAAwAFgAGAAUACAAMAAwAAAAAAwMAGAAAAAACAAAAAAAAAAAKABgADAAEAAgACgAAADwAAAAQAAAAIAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAEAAAAgAAAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAADzrI2g2gh2S4fg6mmbpb02AgoEgBCAEPOsjaDaCHZLh+DqaZulvTYCBgaAEPOsjaDaCHZLh+DqaZulvTY=", + "x-ms-client-request-id" : "7f060a29-4667-465a-9294-cef21bea9cdb", + "Content-Type" : "avro/binary" + }, + "Exception" : null + }, { + "Method" : "POST", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f/javablobqueryinputcsvoutputarrow1728602615190a44aa?comp=query", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "f0370564-128a-485d-848e-109ba34d4486", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2020-02-10", + "x-ms-lease-state" : "available", + "Last-Modified" : "Tue, 25 Aug 2020 17:44:40 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 25 Aug 2020 17:44:41 GMT", + "x-ms-blob-type" : "BlockBlob", + "Accept-Ranges" : "bytes", + "ETag" : "0x8D8491E8B407A50", + "x-ms-creation-time" : "Tue, 25 Aug 2020 17:44:40 GMT", + "x-ms-request-id" : "7817cf18-d01e-0000-7407-7bff58000000", + "Body" : "T2JqAQIWYXZyby5zY2hlbWG+HlsKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLnJlc3VsdERhdGEiLAogICAgImRvYyI6ICJIb2xkcyByZXN1bHQgZGF0YSBpbiB0aGUgZm9ybWF0IHNwZWNpZmllZCBmb3IgdGhpcyBxdWVyeSAoQ1NWLCBKU09OLCBldGMuKS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImRhdGEiLAogICAgICAgICJ0eXBlIjogImJ5dGVzIgogICAgICB9CiAgICBdCiAgfSwKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLmVycm9yIiwKICAgICJkb2MiOiAiQW4gZXJyb3IgdGhhdCBvY2N1cnJlZCB3aGlsZSBwcm9jZXNzaW5nIHRoZSBxdWVyeS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImZhdGFsIiwKICAgICAgICAidHlwZSI6ICJib29sZWFuIiwKICAgICAgICAiZG9jIjogIklmIHRydWUsIHRoaXMgZXJyb3IgcHJldmVudHMgZnVydGhlciBxdWVyeSBwcm9jZXNzaW5nLiAgTW9yZSByZXN1bHQgZGF0YSBtYXkgYmUgcmV0dXJuZWQsIGJ1dCB0aGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgb2YgdGhlIG9yaWdpbmFsIGRhdGEgd2lsbCBiZSBwcm9jZXNzZWQuICBJZiBmYWxzZSwgdGhpcyBlcnJvciBkb2VzIG5vdCBwcmV2ZW50IGZ1cnRoZXIgcXVlcnkgcHJvY2Vzc2luZy4iCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJuYW1lIiwKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJkb2MiOiAiVGhlIG5hbWUgb2YgdGhlIGVycm9yIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAiZGVzY3JpcHRpb24iLAogICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgImRvYyI6ICJBIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvciIKICAgICAgfSwKICAgICAgewogICAgICAgICJuYW1lIjogInBvc2l0aW9uIiwKICAgICAgICAidHlwZSI6ICJsb25nIiwKICAgICAgICAiZG9jIjogIlRoZSBibG9iIG9mZnNldCBhdCB3aGljaCB0aGUgZXJyb3Igb2NjdXJyZWQiCiAgICAgIH0KICAgIF0KICB9LAogIHsKICAgICJ0eXBlIjogInJlY29yZCIsCiAgICAibmFtZSI6ICJjb20ubWljcm9zb2Z0LmF6dXJlLnN0b3JhZ2UucXVlcnlCbG9iQ29udGVudHMucHJvZ3Jlc3MiLAogICAgImRvYyI6ICJJbmZvcm1hdGlvbiBhYm91dCB0aGUgcHJvZ3Jlc3Mgb2YgdGhlIHF1ZXJ5IiwKICAgICJmaWVsZHMiOiBbCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJieXRlc1NjYW5uZWQiLAogICAgICAgICJ0eXBlIjogImxvbmciLAogICAgICAgICJkb2MiOiAiVGhlIG51bWJlciBvZiBieXRlcyB0aGF0IGhhdmUgYmVlbiBzY2FubmVkIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0sCiAgewogICAgInR5cGUiOiAicmVjb3JkIiwKICAgICJuYW1lIjogImNvbS5taWNyb3NvZnQuYXp1cmUuc3RvcmFnZS5xdWVyeUJsb2JDb250ZW50cy5lbmQiLAogICAgImRvYyI6ICJTZW50IGFzIHRoZSBmaW5hbCBtZXNzYWdlIG9mIHRoZSByZXNwb25zZSwgaW5kaWNhdGluZyB0aGF0IGFsbCByZXN1bHRzIGhhdmUgYmVlbiBzZW50LiIsCiAgICAiZmllbGRzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0KXQoA4VNL221Di0m75nYkd1H7RQKGBACABP////+AAAAAEAAAAAAACgAMAAYABQAIAAoAAAAAAQMADAAAAAgACAAAAAQACAAAAAQAAAABAAAAFAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABByQAAAAUAAAABAAAAAAAAAAIAAwABAAIAAgAAAAEAAAAAgAAAAQAAABOYW1lAAAAAAAAAAD/////cAAAABAAAAAAAAoADgAGAAUACAAKAAAAAAMDABAAAAAAAAoADAAAAAQACAAKAAAAMAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAADhU0vbbUOLSbvmdiR3UftFAqYKAKAK/////4gAAAAUAAAAAAAAAAwAFgAGAAUACAAMAAwAAAAAAwMAGAAAAAACAAAAAAAAAAAKABgADAAEAAgACgAAADwAAAAQAAAAIAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAEAAAAgAAAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAADhU0vbbUOLSbvmdiR3UftFAgoEgBCAEOFTS9ttQ4tJu+Z2JHdR+0UCBgaAEOFTS9ttQ4tJu+Z2JHdR+0U=", + "x-ms-client-request-id" : "f0370564-128a-485d-848e-109ba34d4486", + "Content-Type" : "avro/binary" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcqueryinputcsvoutputarrow&comp=list", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "d8571b30-dcb5-4ded-acb1-c31b206b898d" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "7817cf19-d01e-0000-7507-7bff58000000", + "Body" : "jtcqueryinputcsvoutputarrowjtcqueryinputcsvoutputarrow0172025f01ff1d6b1848fTue, 25 Aug 2020 17:44:40 GMT\"0x8D8491E8AFA0907\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 25 Aug 2020 17:44:41 GMT", + "x-ms-client-request-id" : "d8571b30-dcb5-4ded-acb1-c31b206b898d", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "c9f4572a-3753-4eff-8a98-95e81dd41e5f" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "7817cf1a-d01e-0000-7607-7bff58000000", + "Date" : "Tue, 25 Aug 2020 17:44:41 GMT", + "x-ms-client-request-id" : "c9f4572a-3753-4eff-8a98-95e81dd41e5f" + }, + "Exception" : null + } ], + "variables" : [ "jtcqueryinputcsvoutputarrow0172025f01ff1d6b1848f", "javablobqueryinputcsvoutputarrow1728602615190a44aa" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-file-datalake/CHANGELOG.md b/sdk/storage/azure-storage-file-datalake/CHANGELOG.md index 6a80c56d4edbd..c3aac689c5c74 100644 --- a/sdk/storage/azure-storage-file-datalake/CHANGELOG.md +++ b/sdk/storage/azure-storage-file-datalake/CHANGELOG.md @@ -3,6 +3,7 @@ ## 12.3.0-beta.1 (Unreleased) - Added support for the 2019-02-10 service version. - Added support to schedule file expiration. +- Added support to specify Arrow Output Serialization when querying a file. ## 12.2.0 (2020-08-13) - Fixed bug where Query Input Stream would throw when a ByteBuffer of length 0 was encountered. diff --git a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/Transforms.java b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/Transforms.java index 686e2895acc19..d7850a81a66bd 100644 --- a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/Transforms.java +++ b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/Transforms.java @@ -14,6 +14,9 @@ import com.azure.storage.blob.models.BlobDownloadResponse; import com.azure.storage.blob.models.BlobHttpHeaders; import com.azure.storage.blob.models.BlobProperties; +import com.azure.storage.blob.models.BlobQueryArrowField; +import com.azure.storage.blob.models.BlobQueryArrowFieldType; +import com.azure.storage.blob.models.BlobQueryArrowSerialization; import com.azure.storage.blob.models.BlobQueryAsyncResponse; import com.azure.storage.blob.models.BlobQueryDelimitedSerialization; import com.azure.storage.blob.models.BlobQueryError; @@ -39,6 +42,8 @@ import com.azure.storage.file.datalake.models.DataLakeRequestConditions; import com.azure.storage.file.datalake.models.DataLakeSignedIdentifier; import com.azure.storage.file.datalake.models.DownloadRetryOptions; +import com.azure.storage.file.datalake.models.FileQueryArrowField; +import com.azure.storage.file.datalake.models.FileQueryArrowSerialization; import com.azure.storage.file.datalake.models.FileQueryAsyncResponse; import com.azure.storage.file.datalake.models.FileQueryDelimitedSerialization; import com.azure.storage.file.datalake.models.FileQueryError; @@ -489,12 +494,36 @@ static BlobQuerySerialization toBlobQuerySerialization(FileQuerySerialization se .setFieldQuote(delSer.getFieldQuote()) .setHeadersPresent(delSer.isHeadersPresent()) .setRecordSeparator(delSer.getRecordSeparator()); + } else if (ser instanceof FileQueryArrowSerialization) { + FileQueryArrowSerialization arrSer = (FileQueryArrowSerialization) ser; + return new BlobQueryArrowSerialization().setSchema(toBlobQueryArrowSchema(arrSer.getSchema())); } else { - throw new IllegalArgumentException("serialization must be FileQueryJsonSerialization or " - + "FileQueryDelimitedSerialization"); + throw new IllegalArgumentException("serialization must be FileQueryJsonSerialization, " + + "FileQueryDelimitedSerialization, or FileQueryArrowSerialization"); } } + private static List toBlobQueryArrowSchema(List schema) { + if (schema == null) { + return null; + } + List blobSchema = new ArrayList<>(schema.size()); + for (FileQueryArrowField field : schema) { + blobSchema.add(toBlobQueryArrowField(field)); + } + return blobSchema; + } + + private static BlobQueryArrowField toBlobQueryArrowField(FileQueryArrowField field) { + if (field == null) { + return null; + } + return new BlobQueryArrowField(BlobQueryArrowFieldType.fromString(field.getType().toString())) + .setName(field.getName()) + .setPrecision(field.getPrecision()) + .setScale(field.getScale()); + } + static Consumer toBlobQueryErrorConsumer(Consumer er) { if (er == null) { return null; diff --git a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowField.java b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowField.java new file mode 100644 index 0000000000000..105e6ca947a8e --- /dev/null +++ b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowField.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.datalake.models; + +import com.azure.storage.common.implementation.StorageImplUtils; + +/** + * Defines an arrow field for a file quick query request. + */ +public class FileQueryArrowField { + + private String name; + private Integer precision; + private Integer scale; + private final FileQueryArrowFieldType type; + + /** + * @param type {@link FileQueryArrowFieldType} + */ + public FileQueryArrowField(FileQueryArrowFieldType type) { + StorageImplUtils.assertNotNull("type", type); + this.type = type; + } + + /** + * @param name The name of the field. + * @return The updated options. + */ + public FileQueryArrowField setName(String name) { + this.name = name; + return this; + } + + /** + * @param precision The precision of the field. Required if type is {@link FileQueryArrowFieldType#DECIMAL} + * @return The updated options. + */ + public FileQueryArrowField setPrecision(int precision) { + this.precision = precision; + return this; + } + + /** + * @param scale The scale of the field. Required if type is {@link FileQueryArrowFieldType#DECIMAL} + * @return The updated options. + */ + public FileQueryArrowField setScale(int scale) { + this.scale = scale; + return this; + } + + /** + * @return The name. + */ + public String getName() { + return name; + } + + /** + * @return The precision. + */ + public Integer getPrecision() { + return precision; + } + + /** + * @return The scale. + */ + public Integer getScale() { + return scale; + } + + /** + * @return {@link FileQueryArrowFieldType} + */ + public FileQueryArrowFieldType getType() { + return type; + } +} diff --git a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowFieldType.java b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowFieldType.java new file mode 100644 index 0000000000000..b7625fe6957ff --- /dev/null +++ b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowFieldType.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.datalake.models; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for FileQueryArrowFieldType. + */ +public enum FileQueryArrowFieldType { + + /** + * Enum value int64. + */ + INT64("int64"), + + /** + * Enum value bool. + */ + BOOL("bool"), + + /** + * Enum value timestamp[ms]. + */ + TIMESTAMP("timestamp[ms]"), + + /** + * Enum value string. + */ + STRING("string"), + + /** + * Enum value double. + */ + DOUBLE("double"), + + /** + * Enum value decimal. + */ + DECIMAL("decimal"); + + /** + * The actual serialized value for a FileQueryArrowFieldType instance. + */ + private final String value; + + FileQueryArrowFieldType(String value) { + this.value = value; + } + + /** + * Parses a serialized value to a FileQueryArrowFieldType instance. + * + * @param value the serialized value to parse. + * @return the parsed FileQueryArrowFieldType object, or null if unable to parse. + */ + @JsonCreator + public static FileQueryArrowFieldType fromString(String value) { + FileQueryArrowFieldType[] items = FileQueryArrowFieldType.values(); + for (FileQueryArrowFieldType item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowSerialization.java b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowSerialization.java new file mode 100644 index 0000000000000..cc2c20c54749b --- /dev/null +++ b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/models/FileQueryArrowSerialization.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.datalake.models; + +import java.util.Collections; +import java.util.List; + +/** + * Defines the output arrow serialization for a file quick query request. + */ +public class FileQueryArrowSerialization implements FileQuerySerialization { + + private List schema; + + /** + * Gets the arrow fields. + * + * @return the arrow fields. + */ + public List getSchema() { + return schema == null ? null : Collections.unmodifiableList(schema); + } + + /** + * Sets the arrow fields. + * + * @param schema the arrow fields. + * @return the updated FileQueryArrowSerialization object. + */ + public FileQueryArrowSerialization setSchema(List schema) { + this.schema = schema == null ? null : Collections.unmodifiableList(schema); + return this; + } +} diff --git a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy index cfd4ecdf9e609..6c7d366d27033 100644 --- a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy +++ b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy @@ -15,6 +15,9 @@ import com.azure.storage.file.datalake.models.AccessTier import com.azure.storage.file.datalake.models.DataLakeRequestConditions import com.azure.storage.file.datalake.models.DataLakeStorageException import com.azure.storage.file.datalake.models.FileExpirationOffset +import com.azure.storage.file.datalake.models.FileQueryArrowField +import com.azure.storage.file.datalake.models.FileQueryArrowFieldType +import com.azure.storage.file.datalake.models.FileQueryArrowSerialization import com.azure.storage.file.datalake.models.FileQueryDelimitedSerialization import com.azure.storage.file.datalake.models.FileQueryError import com.azure.storage.file.datalake.models.FileQueryJsonSerialization @@ -3088,6 +3091,43 @@ class FileAPITest extends APISpec { } } + @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation + def "Query Input csv Output arrow"() { + setup: + FileQueryDelimitedSerialization inSer = new FileQueryDelimitedSerialization() + .setRecordSeparator('\n' as char) + .setColumnSeparator(',' as char) + .setEscapeChar('\0' as char) + .setFieldQuote('\0' as char) + .setHeadersPresent(false) + uploadCsv(inSer, 32) + List schema = new ArrayList<>() + schema.add(new FileQueryArrowField(FileQueryArrowFieldType.DECIMAL).setName("Name").setPrecision(4).setScale(2)) + FileQueryArrowSerialization outSer = new FileQueryArrowSerialization().setSchema(schema) + def expression = "SELECT _2 from BlobStorage WHERE _1 > 250;" + String expectedData = "/////4AAAAAQAAAAAAAKAAwABgAFAAgACgAAAAABAwAMAAAACAAIAAAABAAIAAAABAAAAAEAAAAUAAAAEAAUAAgABgAHAAwAAAAQABAAAAAAAAEHJAAAABQAAAAEAAAAAAAAAAgADAAEAAgACAAAAAQAAAACAAAABAAAAE5hbWUAAAAAAAAAAP////9wAAAAEAAAAAAACgAOAAYABQAIAAoAAAAAAwMAEAAAAAAACgAMAAAABAAIAAoAAAAwAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAP////+IAAAAFAAAAAAAAAAMABYABgAFAAgADAAMAAAAAAMDABgAAAAAAgAAAAAAAAAACgAYAAwABAAIAAoAAAA8AAAAEAAAACAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAABAAAAIAAAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAA" + OutputStream os = new ByteArrayOutputStream() + FileQueryOptions options = new FileQueryOptions(expression, os).setInputSerialization(inSer).setOutputSerialization(outSer) + + /* Input Stream. */ + when: + InputStream qqStream = fc.openQueryInputStreamWithResponse(options).getValue() + byte[] queryData = readFromInputStream(qqStream, 912) + + then: + notThrown(IOException) + Base64.getEncoder().encodeToString(queryData) == expectedData + + /* Output Stream. */ + when: + fc.queryWithResponse(options, null, null) + byte[] osData = os.toByteArray() + + then: + notThrown(BlobStorageException) + Base64.getEncoder().encodeToString(osData) == expectedData + } + @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation def "Query non fatal error"() { setup: @@ -3288,6 +3328,29 @@ class FileAPITest extends APISpec { false | true || _ } + @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation + def "Query arrow input IA"() { + setup: + def inSer = new FileQueryArrowSerialization() + def expression = "SELECT * from BlobStorage" + FileQueryOptions options = new FileQueryOptions(expression) + .setInputSerialization(inSer) + + when: + InputStream stream = fc.openQueryInputStreamWithResponse(options).getValue() /* Don't need to call read. */ + + then: + thrown(IllegalArgumentException) + + when: + options = new FileQueryOptions(expression, new ByteArrayOutputStream()) + .setInputSerialization(inSer) + fc.queryWithResponse(options, null, null) + + then: + thrown(IllegalArgumentException) + } + @Unroll @Requires({ playbackMode() }) // TODO (rickle-msft): Remove annotation def "Query AC"() { diff --git a/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryarrowinputia.json b/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryarrowinputia.json new file mode 100644 index 0000000000000..75a2ea3385961 --- /dev/null +++ b/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryarrowinputia.json @@ -0,0 +1,86 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryarrowinputia0fileapitestqueryarrowinputiaef2880751b?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "85aebad2-7051-409f-86a3-fb58603d4282" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D8494689453920", + "Last-Modified" : "Tue, 25 Aug 2020 22:30:57 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "4eb14628-801e-0055-422f-7b5d2b000000", + "Date" : "Tue, 25 Aug 2020 22:30:57 GMT", + "x-ms-client-request-id" : "85aebad2-7051-409f-86a3-fb58603d4282" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.dfs.core.windows.net/jtfsqueryarrowinputia0fileapitestqueryarrowinputiaef2880751b/javapathqueryarrowinputia1fileapitestqueryarrowinputiaef224848?resource=file", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-file-datalake/12.3.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0c70ad77-0c03-4539-b528-328a2d4e2611" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "Server" : "Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D8494689CF4ED1", + "Last-Modified" : "Tue, 25 Aug 2020 22:30:58 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "3f2b3850-901f-0004-202f-7bc0a7000000", + "Date" : "Tue, 25 Aug 2020 22:30:57 GMT", + "x-ms-client-request-id" : "0c70ad77-0c03-4539-b528-328a2d4e2611" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtfsqueryarrowinputia&comp=list", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "ab5d3fce-68ae-4bce-a46c-3690097a948e" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "4eb146c5-801e-0055-3b2f-7b5d2b000000", + "Body" : "jtfsqueryarrowinputiajtfsqueryarrowinputia0fileapitestqueryarrowinputiaef2880751bTue, 25 Aug 2020 22:30:57 GMT\"0x8D8494689453920\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 25 Aug 2020 22:30:58 GMT", + "x-ms-client-request-id" : "ab5d3fce-68ae-4bce-a46c-3690097a948e", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryarrowinputia0fileapitestqueryarrowinputiaef2880751b?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "eb004eb9-fe90-4433-85c7-9abf30b3bcb9" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "4eb146d0-801e-0055-452f-7b5d2b000000", + "Date" : "Tue, 25 Aug 2020 22:30:58 GMT", + "x-ms-client-request-id" : "eb004eb9-fe90-4433-85c7-9abf30b3bcb9" + }, + "Exception" : null + } ], + "variables" : [ "jtfsqueryarrowinputia0fileapitestqueryarrowinputiaef2880751b", "javapathqueryarrowinputia1fileapitestqueryarrowinputiaef224848" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryinputcsvoutputarrow.json b/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryinputcsvoutputarrow.json new file mode 100644 index 0000000000000..804cebb513efa --- /dev/null +++ b/sdk/storage/azure-storage-file-datalake/src/test/resources/session-records/FileAPITestqueryinputcsvoutputarrow.json @@ -0,0 +1,199 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "915a1b62-6fea-422f-a790-67dabc6a76c0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D84921A6A86E9D", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:55 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "9ffd6b02-901e-0004-400a-7b14f4000000", + "Date" : "Tue, 25 Aug 2020 18:06:54 GMT", + "x-ms-client-request-id" : "915a1b62-6fea-422f-a790-67dabc6a76c0" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.dfs.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?resource=file", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-file-datalake/12.3.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "4bbb2b25-b4e7-4d0b-a067-6a567e8d2fed" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D84921A6E99977", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:55 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "00044a5b-501f-0003-4d0a-7b0c38000000", + "Date" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-client-request-id" : "4bbb2b25-b4e7-4d0b-a067-6a567e8d2fed" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.dfs.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?resource=file", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-file-datalake/12.3.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "63cf61f7-bec9-4e85-826a-f43a28712171" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D84921A6FAB1A0", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:55 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "00044a5c-501f-0003-4e0a-7b0c38000000", + "Date" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-client-request-id" : "63cf61f7-bec9-4e85-826a-f43a28712171" + }, + "Exception" : null + }, { + "Method" : "PATCH", + "Uri" : "https://REDACTED.dfs.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?position=0&action=append", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-file-datalake/12.3.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "fb5eaace-4686-48be-a449-4b44fcb0e72e", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-server-encrypted" : "true", + "x-ms-request-id" : "00044a5d-501f-0003-4f0a-7b0c38000000", + "Date" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-client-request-id" : "fb5eaace-4686-48be-a449-4b44fcb0e72e" + }, + "Exception" : null + }, { + "Method" : "PATCH", + "Uri" : "https://REDACTED.dfs.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?position=1024&retainUncommittedData=false&close=false&action=flush", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-file-datalake/12.3.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "96fbabcd-3552-4818-b8f0-6223136ca288" + }, + "Response" : { + "x-ms-version" : "2020-02-10", + "ETag" : "0x8D84921A7287887", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:56 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-server-encrypted" : "false", + "x-ms-request-id" : "00044a5e-501f-0003-500a-7b0c38000000", + "Date" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-client-request-id" : "96fbabcd-3552-4818-b8f0-6223136ca288" + }, + "Exception" : null + }, { + "Method" : "POST", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?comp=query", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "c9006573-e83f-4e56-bfc0-0310922270d3", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2020-02-10", + "x-ms-lease-state" : "available", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:56 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 25 Aug 2020 18:06:56 GMT", + "x-ms-blob-type" : "BlockBlob", + "Accept-Ranges" : "bytes", + "ETag" : "0x8D84921A7287887", + "x-ms-creation-time" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-request-id" : "9ffd6b05-901e-0004-410a-7b14f4000000", + "Body" : "T2JqAQIWYXZyby5zY2hlbWG+HlsKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLnJlc3VsdERhdGEiLAogICAgImRvYyI6ICJIb2xkcyByZXN1bHQgZGF0YSBpbiB0aGUgZm9ybWF0IHNwZWNpZmllZCBmb3IgdGhpcyBxdWVyeSAoQ1NWLCBKU09OLCBldGMuKS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImRhdGEiLAogICAgICAgICJ0eXBlIjogImJ5dGVzIgogICAgICB9CiAgICBdCiAgfSwKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLmVycm9yIiwKICAgICJkb2MiOiAiQW4gZXJyb3IgdGhhdCBvY2N1cnJlZCB3aGlsZSBwcm9jZXNzaW5nIHRoZSBxdWVyeS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImZhdGFsIiwKICAgICAgICAidHlwZSI6ICJib29sZWFuIiwKICAgICAgICAiZG9jIjogIklmIHRydWUsIHRoaXMgZXJyb3IgcHJldmVudHMgZnVydGhlciBxdWVyeSBwcm9jZXNzaW5nLiAgTW9yZSByZXN1bHQgZGF0YSBtYXkgYmUgcmV0dXJuZWQsIGJ1dCB0aGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgb2YgdGhlIG9yaWdpbmFsIGRhdGEgd2lsbCBiZSBwcm9jZXNzZWQuICBJZiBmYWxzZSwgdGhpcyBlcnJvciBkb2VzIG5vdCBwcmV2ZW50IGZ1cnRoZXIgcXVlcnkgcHJvY2Vzc2luZy4iCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJuYW1lIiwKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJkb2MiOiAiVGhlIG5hbWUgb2YgdGhlIGVycm9yIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAiZGVzY3JpcHRpb24iLAogICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgImRvYyI6ICJBIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvciIKICAgICAgfSwKICAgICAgewogICAgICAgICJuYW1lIjogInBvc2l0aW9uIiwKICAgICAgICAidHlwZSI6ICJsb25nIiwKICAgICAgICAiZG9jIjogIlRoZSBibG9iIG9mZnNldCBhdCB3aGljaCB0aGUgZXJyb3Igb2NjdXJyZWQiCiAgICAgIH0KICAgIF0KICB9LAogIHsKICAgICJ0eXBlIjogInJlY29yZCIsCiAgICAibmFtZSI6ICJjb20ubWljcm9zb2Z0LmF6dXJlLnN0b3JhZ2UucXVlcnlCbG9iQ29udGVudHMucHJvZ3Jlc3MiLAogICAgImRvYyI6ICJJbmZvcm1hdGlvbiBhYm91dCB0aGUgcHJvZ3Jlc3Mgb2YgdGhlIHF1ZXJ5IiwKICAgICJmaWVsZHMiOiBbCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJieXRlc1NjYW5uZWQiLAogICAgICAgICJ0eXBlIjogImxvbmciLAogICAgICAgICJkb2MiOiAiVGhlIG51bWJlciBvZiBieXRlcyB0aGF0IGhhdmUgYmVlbiBzY2FubmVkIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0sCiAgewogICAgInR5cGUiOiAicmVjb3JkIiwKICAgICJuYW1lIjogImNvbS5taWNyb3NvZnQuYXp1cmUuc3RvcmFnZS5xdWVyeUJsb2JDb250ZW50cy5lbmQiLAogICAgImRvYyI6ICJTZW50IGFzIHRoZSBmaW5hbCBtZXNzYWdlIG9mIHRoZSByZXNwb25zZSwgaW5kaWNhdGluZyB0aGF0IGFsbCByZXN1bHRzIGhhdmUgYmVlbiBzZW50LiIsCiAgICAiZmllbGRzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0KXQoAU52CWBoqwkC2fH2Z2/qYwwKGBACABP////+AAAAAEAAAAAAACgAMAAYABQAIAAoAAAAAAQMADAAAAAgACAAAAAQACAAAAAQAAAABAAAAFAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABByQAAAAUAAAABAAAAAAAAAAIAAwABAAIAAgAAAAEAAAAAgAAAAQAAABOYW1lAAAAAAAAAAD/////cAAAABAAAAAAAAoADgAGAAUACAAKAAAAAAMDABAAAAAAAAoADAAAAAQACAAKAAAAMAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAABTnYJYGirCQLZ8fZnb+pjDAqYKAKAK/////4gAAAAUAAAAAAAAAAwAFgAGAAUACAAMAAwAAAAAAwMAGAAAAAACAAAAAAAAAAAKABgADAAEAAgACgAAADwAAAAQAAAAIAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAEAAAAgAAAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAABTnYJYGirCQLZ8fZnb+pjDAgoEgBCAEFOdglgaKsJAtnx9mdv6mMMCBgaAEFOdglgaKsJAtnx9mdv6mMM=", + "x-ms-client-request-id" : "c9006573-e83f-4e56-bfc0-0310922270d3", + "Content-Type" : "avro/binary" + }, + "Exception" : null + }, { + "Method" : "POST", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47/javapathqueryinputcsvoutputarrow157523d21919db6a7d?comp=query", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "12e1d6c3-da56-4cef-b1e8-2e0fce8d372c", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2020-02-10", + "x-ms-lease-state" : "available", + "Last-Modified" : "Tue, 25 Aug 2020 18:06:56 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 25 Aug 2020 18:06:56 GMT", + "x-ms-blob-type" : "BlockBlob", + "Accept-Ranges" : "bytes", + "ETag" : "0x8D84921A7287887", + "x-ms-creation-time" : "Tue, 25 Aug 2020 18:06:55 GMT", + "x-ms-request-id" : "9ffd6b06-901e-0004-420a-7b14f4000000", + "Body" : "T2JqAQIWYXZyby5zY2hlbWG+HlsKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLnJlc3VsdERhdGEiLAogICAgImRvYyI6ICJIb2xkcyByZXN1bHQgZGF0YSBpbiB0aGUgZm9ybWF0IHNwZWNpZmllZCBmb3IgdGhpcyBxdWVyeSAoQ1NWLCBKU09OLCBldGMuKS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImRhdGEiLAogICAgICAgICJ0eXBlIjogImJ5dGVzIgogICAgICB9CiAgICBdCiAgfSwKICB7CiAgICAidHlwZSI6ICJyZWNvcmQiLAogICAgIm5hbWUiOiAiY29tLm1pY3Jvc29mdC5henVyZS5zdG9yYWdlLnF1ZXJ5QmxvYkNvbnRlbnRzLmVycm9yIiwKICAgICJkb2MiOiAiQW4gZXJyb3IgdGhhdCBvY2N1cnJlZCB3aGlsZSBwcm9jZXNzaW5nIHRoZSBxdWVyeS4iLAogICAgImZpZWxkcyI6IFsKICAgICAgewogICAgICAgICJuYW1lIjogImZhdGFsIiwKICAgICAgICAidHlwZSI6ICJib29sZWFuIiwKICAgICAgICAiZG9jIjogIklmIHRydWUsIHRoaXMgZXJyb3IgcHJldmVudHMgZnVydGhlciBxdWVyeSBwcm9jZXNzaW5nLiAgTW9yZSByZXN1bHQgZGF0YSBtYXkgYmUgcmV0dXJuZWQsIGJ1dCB0aGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgb2YgdGhlIG9yaWdpbmFsIGRhdGEgd2lsbCBiZSBwcm9jZXNzZWQuICBJZiBmYWxzZSwgdGhpcyBlcnJvciBkb2VzIG5vdCBwcmV2ZW50IGZ1cnRoZXIgcXVlcnkgcHJvY2Vzc2luZy4iCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJuYW1lIiwKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJkb2MiOiAiVGhlIG5hbWUgb2YgdGhlIGVycm9yIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAiZGVzY3JpcHRpb24iLAogICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgImRvYyI6ICJBIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvciIKICAgICAgfSwKICAgICAgewogICAgICAgICJuYW1lIjogInBvc2l0aW9uIiwKICAgICAgICAidHlwZSI6ICJsb25nIiwKICAgICAgICAiZG9jIjogIlRoZSBibG9iIG9mZnNldCBhdCB3aGljaCB0aGUgZXJyb3Igb2NjdXJyZWQiCiAgICAgIH0KICAgIF0KICB9LAogIHsKICAgICJ0eXBlIjogInJlY29yZCIsCiAgICAibmFtZSI6ICJjb20ubWljcm9zb2Z0LmF6dXJlLnN0b3JhZ2UucXVlcnlCbG9iQ29udGVudHMucHJvZ3Jlc3MiLAogICAgImRvYyI6ICJJbmZvcm1hdGlvbiBhYm91dCB0aGUgcHJvZ3Jlc3Mgb2YgdGhlIHF1ZXJ5IiwKICAgICJmaWVsZHMiOiBbCiAgICAgIHsKICAgICAgICAibmFtZSI6ICJieXRlc1NjYW5uZWQiLAogICAgICAgICJ0eXBlIjogImxvbmciLAogICAgICAgICJkb2MiOiAiVGhlIG51bWJlciBvZiBieXRlcyB0aGF0IGhhdmUgYmVlbiBzY2FubmVkIgogICAgICB9LAogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0sCiAgewogICAgInR5cGUiOiAicmVjb3JkIiwKICAgICJuYW1lIjogImNvbS5taWNyb3NvZnQuYXp1cmUuc3RvcmFnZS5xdWVyeUJsb2JDb250ZW50cy5lbmQiLAogICAgImRvYyI6ICJTZW50IGFzIHRoZSBmaW5hbCBtZXNzYWdlIG9mIHRoZSByZXNwb25zZSwgaW5kaWNhdGluZyB0aGF0IGFsbCByZXN1bHRzIGhhdmUgYmVlbiBzZW50LiIsCiAgICAiZmllbGRzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAidG90YWxCeXRlcyIsCiAgICAgICAgInR5cGUiOiAibG9uZyIsCiAgICAgICAgImRvYyI6ICJUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGJlIHNjYW5uZWQgaW4gdGhpcyBxdWVyeSIKICAgICAgfQogICAgXQogIH0KXQoA52bU6U5oN02k2+nUYeV9owKGBACABP////+AAAAAEAAAAAAACgAMAAYABQAIAAoAAAAAAQMADAAAAAgACAAAAAQACAAAAAQAAAABAAAAFAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABByQAAAAUAAAABAAAAAAAAAAIAAwABAAIAAgAAAAEAAAAAgAAAAQAAABOYW1lAAAAAAAAAAD/////cAAAABAAAAAAAAoADgAGAAUACAAKAAAAAAMDABAAAAAAAAoADAAAAAQACAAKAAAAMAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAADnZtTpTmg3TaTb6dRh5X2jAqYKAKAK/////4gAAAAUAAAAAAAAAAwAFgAGAAUACAAMAAwAAAAAAwMAGAAAAAACAAAAAAAAAAAKABgADAAEAAgACgAAADwAAAAQAAAAIAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAEAAAAgAAAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAAAAADnZtTpTmg3TaTb6dRh5X2jAgoEgBCAEOdm1OlOaDdNpNvp1GHlfaMCBgaAEOdm1OlOaDdNpNvp1GHlfaM=", + "x-ms-client-request-id" : "12e1d6c3-da56-4cef-b1e8-2e0fce8d372c", + "Content-Type" : "avro/binary" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtfsqueryinputcsvoutputarrow&comp=list", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0df7eeba-aed7-41a8-bb03-9c7d360cbfec" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "9ffd6b08-901e-0004-430a-7b14f4000000", + "Body" : "jtfsqueryinputcsvoutputarrowjtfsqueryinputcsvoutputarrow028875933422012e0e47Tue, 25 Aug 2020 18:06:55 GMT\"0x8D84921A6A86E9D\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 25 Aug 2020 18:06:56 GMT", + "x-ms-client-request-id" : "0df7eeba-aed7-41a8-bb03-9c7d360cbfec", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtfsqueryinputcsvoutputarrow028875933422012e0e47?restype=container", + "Headers" : { + "x-ms-version" : "2020-02-10", + "User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "a8f33aea-2908-477b-a76d-000798361056" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-02-10", + "retry-after" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "9ffd6b09-901e-0004-440a-7b14f4000000", + "Date" : "Tue, 25 Aug 2020 18:06:56 GMT", + "x-ms-client-request-id" : "a8f33aea-2908-477b-a76d-000798361056" + }, + "Exception" : null + } ], + "variables" : [ "jtfsqueryinputcsvoutputarrow028875933422012e0e47", "javapathqueryinputcsvoutputarrow157523d21919db6a7d" ] +} \ No newline at end of file