blob: 128333741030691665f776c2d5468ce25e1f7f84 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.drill.exec.store.xml;
import org.apache.drill.categories.RowSetTest;
import org.apache.drill.common.exceptions.UserException;
import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.physical.rowSet.RowSet;
import org.apache.drill.exec.record.metadata.SchemaBuilder;
import org.apache.drill.exec.record.metadata.TupleMetadata;
import org.apache.drill.test.ClusterFixture;
import org.apache.drill.test.ClusterTest;
import org.apache.drill.test.rowSet.RowSetComparison;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import static org.apache.drill.test.QueryTestUtil.generateCompressedFile;
import static org.apache.drill.test.rowSet.RowSetUtilities.mapArray;
import static org.apache.drill.test.rowSet.RowSetUtilities.objArray;
import static org.apache.drill.test.rowSet.RowSetUtilities.strArray;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@Category(RowSetTest.class)
public class TestXMLReader extends ClusterTest {
@BeforeClass
public static void setup() throws Exception {
ClusterTest.startCluster(ClusterFixture.builder(dirTestWatcher));
XMLFormatConfig formatConfig = new XMLFormatConfig(null, 2, true);
cluster.defineFormat("cp", "xml", formatConfig);
cluster.defineFormat("dfs", "xml", formatConfig);
// Needed for compressed file unit test
dirTestWatcher.copyResourceToRoot(Paths.get("xml/"));
}
/**
* This unit test tests a simple XML file with no nesting or attributes
* @throws Exception Throw exception if anything goes wrong
*/
@Test
public void testWildcard() throws Exception {
String sql = "SELECT * FROM cp.`xml/simple.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(3, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP)
.addNullable("groupID", MinorType.VARCHAR)
.addNullable("artifactID", MinorType.VARCHAR)
.addNullable("version", MinorType.VARCHAR)
.addNullable("classifier", MinorType.VARCHAR)
.addNullable("scope", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), "org.apache.drill.exec", "drill-java-exec", "${project.version}", null, null)
.addRow(mapArray(),"org.apache.drill.exec", "drill-java-exec", "${project.version}", "tests", "test")
.addRow(mapArray(),"org.apache.drill", "drill-common", "${project.version}", "tests", "test")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testAttributesOnRoot() throws Exception {
String sql = "SELECT * FROM table(cp.`xml/no_nest.xml` (type => 'xml', dataLevel => 1))";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(1, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addMap("attributes")
.addNullable("PPP_Version", MinorType.VARCHAR)
.addNullable("PPP_TimeStamp", MinorType.VARCHAR)
.addNullable("P1_SubVersion", MinorType.VARCHAR)
.addNullable("P1_MID", MinorType.VARCHAR)
.addNullable("P1_PN", MinorType.VARCHAR)
.addNullable("P1_SL", MinorType.VARCHAR)
.addNullable("P2_SubVersion", MinorType.VARCHAR)
.resumeSchema()
.addNullable("P1", MinorType.VARCHAR)
.addMap("P2")
.addNullable("Color", MinorType.VARCHAR)
.resumeSchema()
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(strArray("2023-001", "2023-06-09T21:17:14.416+02:00", "a1", "XX003", "156", "3", "b1"), null, strArray("blue"))
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testXXE() throws Exception {
String sql = "SELECT * FROM cp.`xml/bad.xml`";
try {
client.queryBuilder().sql(sql).rowSet();
fail();
} catch (UserException e) {
assertTrue(e.getMessage().contains("DATA_READ ERROR: Error parsing XML file"));
}
}
@Test
public void testAllTextMode() throws Exception {
String sql = "SELECT attributes, int_field, bigint_field, float_field, double_field, " +
"boolean_field, date_field, time_field, timestamp_field, string_field" +
" FROM table(cp.`xml/simple_with_datatypes" +
".xml` (type => 'xml', " +
"allTextMode => 'false'))";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(2, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP)
.addNullable("int_field", MinorType.FLOAT8)
.addNullable("bigint_field", MinorType.FLOAT8)
.addNullable("float_field", MinorType.FLOAT8)
.addNullable("double_field", MinorType.FLOAT8)
.addNullable("boolean_field", MinorType.BIT)
.addNullable("date_field", MinorType.DATE)
.addNullable("time_field", MinorType.VARCHAR)
.addNullable("timestamp_field", MinorType.TIMESTAMP)
.addNullable("string_field", MinorType.VARCHAR)
.buildSchema();
//DateUtility.parseLocalDateTime
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), 1.0, 1000.0, 1.3, 3.3, true, LocalDate.parse("2022-01-01"),
"12:04:34", Instant.parse("2022-01-06T12:30" +
":30Z"),
"string")
.addRow(mapArray(), 2.0, 2000.0, 2.3, 4.3, false, LocalDate.parse("2022-02-01"),
"13:04:34", Instant.parse("2022-03-06T12:30:30Z"), null)
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testSimpleProvidedSchema() throws Exception {
String sql = "SELECT * FROM table(cp.`xml/simple_with_datatypes.xml` (type => 'xml', schema " +
"=> 'inline=(`int_field` INT, `bigint_field` BIGINT, `float_field` FLOAT, `double_field` DOUBLE, `boolean_field` " +
"BOOLEAN, `date_field` DATE, `time_field` TIME, `timestamp_field` TIMESTAMP, `string_field`" +
" VARCHAR, `date2_field` DATE properties {`drill.format` = `MM/dd/yyyy`})'))";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(2, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("int_field", MinorType.INT)
.addNullable("bigint_field", MinorType.BIGINT)
.addNullable("float_field", MinorType.FLOAT4)
.addNullable("double_field", MinorType.FLOAT8)
.addNullable("boolean_field", MinorType.BIT)
.addNullable("date_field", MinorType.DATE)
.addNullable("time_field", MinorType.TIME)
.addNullable("timestamp_field", MinorType.TIMESTAMP)
.addNullable("string_field", MinorType.VARCHAR)
.addNullable("date2_field", MinorType.DATE)
.add("attributes", MinorType.MAP)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(1, 1000L, 1.2999999523162842, 3.3, true, LocalDate.parse("2022-01-01"),
LocalTime.parse("12:04:34"), Instant.parse("2022-01-06T12:30:30Z"), "string",
LocalDate.parse("2022-03-02"), mapArray())
.addRow(2, 2000L, 2.299999952316284, 4.3, false, LocalDate.parse("2022-02-01"),
LocalTime.parse("13:04:34"), Instant.parse("2022-03-06T12:30:30Z"), null,
LocalDate.parse("2022-03-01"), mapArray())
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testSelfClosingTags() throws Exception {
String sql = "SELECT * FROM cp.`xml/weather.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(1, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addMap("attributes")
.addNullable("weather_module_id", MinorType.VARCHAR)
.addNullable("weather_tab_id", MinorType.VARCHAR)
.addNullable("weather_mobile_row", MinorType.VARCHAR)
.addNullable("weather_mobile_zipped", MinorType.VARCHAR)
.addNullable("weather_row", MinorType.VARCHAR)
.addNullable("weather_section", MinorType.VARCHAR)
.addNullable("forecast_information_city_data", MinorType.VARCHAR)
.addNullable("forecast_information_postal_code_data", MinorType.VARCHAR)
.addNullable("forecast_information_latitude_e6_data", MinorType.VARCHAR)
.addNullable("forecast_information_longitude_e6_data", MinorType.VARCHAR)
.addNullable("forecast_information_forecast_date_data", MinorType.VARCHAR)
.addNullable("forecast_information_current_date_time_data", MinorType.VARCHAR)
.addNullable("forecast_information_unit_system_data", MinorType.VARCHAR)
.addNullable("current_conditions_condition_data", MinorType.VARCHAR)
.addNullable("current_conditions_temp_f_data", MinorType.VARCHAR)
.addNullable("current_conditions_temp_c_data", MinorType.VARCHAR)
.addNullable("current_conditions_humidity_data", MinorType.VARCHAR)
.addNullable("current_conditions_icon_data", MinorType.VARCHAR)
.addNullable("current_conditions_wind_condition_data", MinorType.VARCHAR)
.resumeSchema()
.addNullable("city", MinorType.VARCHAR)
.addNullable("postal_code", MinorType.VARCHAR)
.addNullable("latitude_e6", MinorType.VARCHAR)
.addNullable("longitude_e6", MinorType.VARCHAR)
.addNullable("forecast_date", MinorType.VARCHAR)
.addNullable("current_date_time", MinorType.VARCHAR)
.addNullable("unit_system", MinorType.VARCHAR)
.addNullable("condition", MinorType.VARCHAR)
.addNullable("temp_f", MinorType.VARCHAR)
.addNullable("temp_c", MinorType.VARCHAR)
.addNullable("humidity", MinorType.VARCHAR)
.addNullable("icon", MinorType.VARCHAR)
.addNullable("wind_condition", MinorType.VARCHAR)
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(strArray("0", "0", "0", "1", "0", "0","Seattle, WA", "Seattle WA", "", "", "2011-09-29", "2011-09-29 17:53:00 +0000", "US", "Clear",
"62", "17", "Humidity: 62%", "/ig/images/weather" +
"/sunny.gif", "Wind: N at 4 mph"), null, null, null, null, null, null, null, null, null, null, null, null, null)
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
/**
* This unit test tests a simple XML file with no nesting or attributes, but with explicitly selected fields.
* @throws Exception Throw exception if anything goes wrong
*/
@Test
public void testExplicitWithSimpleXMLFile() throws Exception {
String sql = "SELECT groupID, artifactID, version, classifier, scope FROM cp.`xml/simple.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(3, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("groupID", MinorType.VARCHAR)
.addNullable("artifactID", MinorType.VARCHAR)
.addNullable("version", MinorType.VARCHAR)
.addNullable("classifier", MinorType.VARCHAR)
.addNullable("scope", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("org.apache.drill.exec", "drill-java-exec", "${project.version}", null, null)
.addRow("org.apache.drill.exec", "drill-java-exec", "${project.version}", "tests", "test")
.addRow("org.apache.drill", "drill-common", "${project.version}", "tests", "test")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testWildcardWithFilter() throws Exception {
String sql = "SELECT * FROM cp.`xml/simple.xml` WHERE scope='test'";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(2, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP)
.addNullable("groupID", MinorType.VARCHAR)
.addNullable("artifactID", MinorType.VARCHAR)
.addNullable("version", MinorType.VARCHAR)
.addNullable("classifier", MinorType.VARCHAR)
.addNullable("scope", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(),"org.apache.drill.exec", "drill-java-exec", "${project.version}", "tests", "test")
.addRow(mapArray(),"org.apache.drill", "drill-common", "${project.version}", "tests", "test")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testWildcardWithSingleNestedDataField() throws Exception {
String sql = "SELECT * FROM cp.`xml/really-simple-nested.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(3, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP, DataMode.REQUIRED)
.addMap("field1")
.addNullable("key1", MinorType.VARCHAR)
.addNullable("key2", MinorType.VARCHAR)
.resumeSchema()
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), strArray("value1", "value2"))
.addRow(mapArray(), strArray("value3", "value4"))
.addRow(mapArray(), strArray("value5", "value6"))
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testExplicitWithSingleNestedDataField() throws Exception {
String sql = "SELECT t1.field1.key1 as key1, t1.field1.key2 as key2 FROM cp.`xml/really-simple-nested.xml` as t1";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(3, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("key1", MinorType.VARCHAR)
.addNullable("key2", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("value1", "value2")
.addRow("value3", "value4")
.addRow("value5", "value6")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testSerDe() throws Exception {
String sql = "SELECT COUNT(*) FROM cp.`xml/simple.xml`";
String plan = queryBuilder().sql(sql).explainJson();
long cnt = queryBuilder().physical(plan).singletonLong();
assertEquals("Counts should match", 3L, cnt);
}
@Test
public void testExplicitWithCompressedSimpleXMLFile() throws Exception {
generateCompressedFile("xml/simple.xml", "zip", "xml/simple.xml.zip");
String sql = "SELECT groupID, artifactID, version, classifier, scope FROM dfs.`xml/simple.xml.zip`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(3, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("groupID", MinorType.VARCHAR)
.addNullable("artifactID", MinorType.VARCHAR)
.addNullable("version", MinorType.VARCHAR)
.addNullable("classifier", MinorType.VARCHAR)
.addNullable("scope", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("org.apache.drill.exec", "drill-java-exec", "${project.version}", null, null)
.addRow("org.apache.drill.exec", "drill-java-exec", "${project.version}", "tests", "test")
.addRow("org.apache.drill", "drill-common", "${project.version}", "tests", "test")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testDeepNestedSpecificFields() throws Exception {
String sql = "select xml.level2.level3.level4.level5.level6.level7.field1 as field1, xml.level2.level3.level4.level5.level6.level7.field2 as field2, xml.level2.level3.level4" +
".level5.level6.level7.field3 as field3 FROM cp.`xml/deep-nested.xml` as xml";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(2, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("field1", MinorType.VARCHAR)
.addNullable("field2", MinorType.VARCHAR)
.addNullable("field3", MinorType.VARCHAR)
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("f1", "f2", "f3")
.addRow("f4", "f5", "f6")
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testDeepNesting() throws Exception {
String sql = "SELECT * FROM cp.`xml/deep-nested.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
assertEquals(2, results.rowCount());
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP, DataMode.REQUIRED)
.addMap("level2")
.addNullable("field1-level2", MinorType.VARCHAR)
.addMap("level3")
.addNullable("field1-level3", MinorType.VARCHAR)
.addMap("level4")
.addNullable("field1-level4", MinorType.VARCHAR)
.addMap("level5")
.addNullable("field1-level5", MinorType.VARCHAR)
.addMap("level6")
.addNullable("field1-level6", MinorType.VARCHAR)
.addMap("level7")
.addNullable("field1", MinorType.VARCHAR)
.addNullable("field2", MinorType.VARCHAR)
.addNullable("field3", MinorType.VARCHAR)
.resumeMap() // End level 7
.resumeMap() // End level 6
.resumeMap() // End level 5
.resumeMap() // End level 4
.resumeMap() // End level 3
.resumeSchema()
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), objArray(
objArray(
"l2",
objArray("l3",
objArray("l4",
objArray("l5",
objArray("l6",
strArray("f1", "f2", "f3")
)
)
)
)
)
))
.addRow(mapArray(), objArray(
objArray(
null,
objArray(null,
objArray(null,
objArray(null,
objArray(null,
strArray("f4", "f5", "f6")
)
)
)
)
)
))
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testDataLevel() throws Exception {
String sql = "SELECT * FROM table(cp.`xml/deep-nested2.xml` (type => 'xml', dataLevel => 8))";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP, DataMode.REQUIRED)
.addNullable("field1", MinorType.VARCHAR)
.addNullable("field2", MinorType.VARCHAR)
.addNullable("field3", MinorType.VARCHAR)
.addNullable("field1-level6", MinorType.VARCHAR)
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), "f4", "f5", "f6", null)
.addRow(mapArray(), "f1", "f2", "f3", "l6")
.build();
assertEquals(2, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testExplicitDataLevel() throws Exception {
String sql = "SELECT field1, field2, field3 FROM table(cp.`xml/deep-nested2.xml` (type => 'xml', dataLevel => 8))";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("field1", MinorType.VARCHAR)
.addNullable("field2", MinorType.VARCHAR)
.addNullable("field3", MinorType.VARCHAR)
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("f4", "f5", "f6")
.addRow("f1", "f2", "f3")
.build();
assertEquals(2, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testComplexWildcardStar() throws Exception {
String sql = "SELECT * FROM cp.`xml/nested.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.add("attributes", MinorType.MAP, DataMode.REQUIRED)
.addMap("field1")
.addNullable("key1", MinorType.VARCHAR)
.addNullable("key2", MinorType.VARCHAR)
.resumeSchema()
.addMap("field2")
.addNullable("key3", MinorType.VARCHAR)
.addMap("nestedField1")
.addNullable("nk1", MinorType.VARCHAR)
.addNullable("nk2", MinorType.VARCHAR)
.addNullable("nk3", MinorType.VARCHAR)
.resumeMap()
.resumeSchema()
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), strArray("value1", "value2"), objArray("k1", strArray("nk_value1", "nk_value2", "nk_value3")))
.addRow(mapArray(), strArray("value3", "value4"), objArray("k2", strArray("nk_value4", "nk_value5", "nk_value6")))
.addRow(mapArray(), strArray("value5", "value6"), objArray("k3", strArray("nk_value7", "nk_value8", "nk_value9")))
.build();
assertEquals(3, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testComplexNestedExplicit() throws Exception {
String sql = "SELECT xml.field2.nestedField1.nk1 as nk1, xml.field2.nestedField1.nk2 as nk2, xml.field2.nestedField1.nk3 as nk3 FROM cp.`xml/nested.xml` AS xml";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("nk1", MinorType.VARCHAR)
.addNullable("nk2", MinorType.VARCHAR)
.addNullable("nk3", MinorType.VARCHAR)
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("nk_value1", "nk_value2", "nk_value3")
.addRow("nk_value4", "nk_value5", "nk_value6")
.addRow("nk_value7", "nk_value8", "nk_value9")
.build();
assertEquals(3, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testAttributes() throws Exception {
String sql = "SELECT attributes FROM cp.`xml/attributes.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addMap("attributes")
.addNullable("title_binding", MinorType.VARCHAR)
.addNullable("title_subcategory", MinorType.VARCHAR)
.resumeSchema()
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow((Object) mapArray(null, null))
.addRow((Object) strArray("paperback", null))
.addRow((Object) strArray("hardcover", "non-fiction"))
.build();
assertEquals(3, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testNestedAttributes() throws Exception {
String sql = "SELECT * FROM cp.`xml/nested-with-attributes.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addMap("attributes")
.addNullable("field1_f1", MinorType.VARCHAR)
.addNullable("field2_f2", MinorType.VARCHAR)
.addNullable("field2_key3_f3", MinorType.VARCHAR)
.addNullable("field2_nestedField1_f4", MinorType.VARCHAR)
.addNullable("field2_nestedField1_f5", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk1_f6", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk1_f7", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk3_f8", MinorType.VARCHAR)
.resumeSchema()
.addMap("field1")
.addNullable("key1", MinorType.VARCHAR)
.addNullable("key2", MinorType.VARCHAR)
.resumeSchema()
.addMap("field2")
.addNullable("key3", MinorType.VARCHAR)
.addMap("nestedField1")
.addNullable("nk1", MinorType.VARCHAR)
.addNullable("nk2", MinorType.VARCHAR)
.addNullable("nk3", MinorType.VARCHAR)
.resumeMap()
.resumeSchema()
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(strArray("k1", "k2", "k3", "k4", "k5", "k6", "k7", null), strArray("value1", "value2"), objArray("k1", strArray("nk_value1", "nk_value2", "nk_value3")))
.addRow(strArray(null, null, null, null, null, null, null, null), strArray("value3", "value4"), objArray("k2", strArray("nk_value4", "nk_value5", "nk_value6")))
.addRow(strArray(null, null, null, null, null, null, null, "k8"), strArray("value5", "value6"), objArray("k3", strArray("nk_value7", "nk_value8", "nk_value9")))
.build();
assertEquals(3, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testExplicitNestedAttributes() throws Exception {
String sql = "SELECT data.attributes.field1_f1 AS field1_f1," +
"data.attributes.field2_f2 AS field2_f2, " +
"data.attributes.field2_key3_f3 AS field2_key3_f3," +
"data.attributes.field2_nestedField1_f4 AS field2_nestedField1_f4," +
"data.attributes.field2_nestedField1_f5 AS field2_nestedField1_f5, " +
"data.attributes.field2_nestedField1_nk1_f6 AS field2_nestedField1_nk1_f6, " +
"data.attributes.field2_nestedField1_nk1_f7 AS field2_nestedField1_nk1_f7," +
"data.attributes.field2_nestedField1_nk3_f8 AS field2_nestedField1_nk3_f8 " +
"FROM cp.`xml/nested-with-attributes.xml` AS data";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addNullable("field1_f1", MinorType.VARCHAR)
.addNullable("field2_f2", MinorType.VARCHAR)
.addNullable("field2_key3_f3", MinorType.VARCHAR)
.addNullable("field2_nestedField1_f4", MinorType.VARCHAR)
.addNullable("field2_nestedField1_f5", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk1_f6", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk1_f7", MinorType.VARCHAR)
.addNullable("field2_nestedField1_nk3_f8", MinorType.VARCHAR)
.buildSchema();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow("k1", "k2", "k3", "k4", "k5", "k6", "k7", null)
.addRow(null, null, null, null, null, null, null, null)
.addRow(null, null, null, null, null, null, null, "k8")
.build();
assertEquals(3, results.rowCount());
new RowSetComparison(expected).verifyAndClearAll(results);
}
@Test
public void testLimitPushdown() throws Exception {
String sql = "SELECT * FROM cp.`xml/simple.xml` LIMIT 2";
queryBuilder()
.sql(sql)
.planMatcher()
.include("Limit", "limit=2")
.match();
}
@Test
public void testMapError() throws Exception {
String sql = "SELECT * FROM cp.`xml/schemaChange.xml`";
RowSet results = client.queryBuilder().sql(sql).rowSet();
TupleMetadata expectedSchema = new SchemaBuilder()
.addMap("attributes")
.resumeSchema()
.addMap("parent")
.addNullable("link", MinorType.VARCHAR)
.addNullable("value", MinorType.VARCHAR)
.resumeSchema()
.build();
RowSet expected = client.rowSetBuilder(expectedSchema)
.addRow(mapArray(), mapArray(null, null))
.addRow(mapArray(), strArray("https://dev57595.service-now.com/api/now/table/task/46eaa7c9a9fe198100bbe282da0d4b7d", "46eaa7c9a9fe198100bbe282da0d4b7d"))
.build();
new RowSetComparison(expected).verifyAndClearAll(results);
}
}