| /* |
| * 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.physical.impl.xsort; |
| |
| import java.io.File; |
| import java.nio.file.Paths; |
| |
| import org.apache.drill.categories.OperatorTest; |
| import org.apache.drill.categories.SlowTest; |
| import org.apache.drill.common.types.TypeProtos; |
| import org.apache.drill.common.types.Types; |
| import org.apache.drill.exec.physical.rowSet.RowSet; |
| import org.apache.drill.exec.physical.rowSet.RowSetBuilder; |
| import org.apache.drill.exec.record.metadata.SchemaBuilder; |
| import org.apache.drill.exec.record.metadata.TupleMetadata; |
| import org.apache.drill.test.BaseTestQuery; |
| import org.apache.drill.test.TestBuilder; |
| import org.apache.drill.test.rowSet.file.JsonFileBuilder; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| |
| import static org.apache.drill.exec.ExecConstants.ENABLE_UNION_TYPE_KEY; |
| import static org.apache.drill.exec.ExecConstants.ENABLE_V2_JSON_READER_KEY; |
| |
| @Category({SlowTest.class, OperatorTest.class}) |
| public class TestExternalSort extends BaseTestQuery { |
| |
| /** |
| * Test union type support in sort using numeric types: BIGINT and FLOAT8 |
| * Drill does not support union types fully. Sort was adapted to handle them. |
| * This test simply verifies that the sort handles these types, even though |
| * Drill does not. |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testNumericTypes() throws Exception { |
| final int record_count = 10000; |
| final String tableDirName = "numericTypes"; |
| |
| { |
| TupleMetadata schema = new SchemaBuilder() |
| .add("a", Types.required(TypeProtos.MinorType.INT)) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 0; i <= record_count; i += 2) { |
| rowSetBuilder.addRow(i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "a.json"); |
| new JsonFileBuilder(rowSet).prettyPrint(false).build(tableFile); |
| rowSet.clear(); |
| } |
| |
| { |
| final TupleMetadata schema = new SchemaBuilder() |
| .add("a", Types.required(TypeProtos.MinorType.FLOAT4)) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 1; i <= record_count; i += 2) { |
| rowSetBuilder.addRow((float) i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "b.json"); |
| new JsonFileBuilder(rowSet) |
| .build(tableFile); |
| rowSet.clear(); |
| } |
| |
| TestBuilder builder = testBuilder() |
| .sqlQuery("select * from dfs.`%s` order by a desc", tableDirName) |
| .optionSettingQueriesForTestQuery("alter session set `exec.enable_union_type` = true") |
| .ordered() |
| .baselineColumns("a"); |
| for (int i = record_count; i >= 0; ) { |
| builder.baselineValues((long) i--); |
| if (i >= 0) { |
| builder.baselineValues((double) i--); |
| } |
| } |
| builder.go(); |
| } |
| |
| @Test |
| @Ignore("Schema changes are disabled in external sort") |
| public void testNumericAndStringTypes() throws Exception { |
| final int record_count = 10000; |
| final String tableDirName = "numericAndStringTypes"; |
| |
| { |
| final TupleMetadata schema = new SchemaBuilder() |
| .add("a", Types.required(TypeProtos.MinorType.INT)) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 0; i <= record_count; i += 2) { |
| rowSetBuilder.addRow(i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "a.json"); |
| new JsonFileBuilder(rowSet).build(tableFile); |
| rowSet.clear(); |
| } |
| |
| { |
| final TupleMetadata schema = new SchemaBuilder() |
| .add("a", Types.required(TypeProtos.MinorType.INT)) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 1; i <= record_count; i += 2) { |
| rowSetBuilder.addRow(i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "b.json"); |
| new JsonFileBuilder(rowSet) |
| .build(tableFile); |
| rowSet.clear(); |
| } |
| |
| TestBuilder builder = testBuilder() |
| .sqlQuery("select * from dfs.`%s` order by a desc", tableDirName) |
| .ordered() |
| .optionSettingQueriesForTestQuery("alter session set `exec.enable_union_type` = true") |
| .baselineColumns("a"); |
| // Strings come first because order by is desc |
| for (int i = record_count; i >= 0;) { |
| i--; |
| if (i >= 0) { |
| builder.baselineValues(String.format("%05d", i--)); |
| } |
| } |
| for (int i = record_count; i >= 0;) { |
| builder.baselineValues((long) i--); |
| i--; |
| } |
| builder.go(); |
| } |
| |
| @Test // V2_UNION |
| public void testNewColumns() throws Exception { |
| final int record_count = 10000; |
| final String tableDirName = "newColumns"; |
| |
| { |
| final TupleMetadata schema = new SchemaBuilder() |
| .add("a", TypeProtos.MinorType.INT) |
| .add("b", TypeProtos.MinorType.INT) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 0; i <= record_count; i += 2) { |
| rowSetBuilder.addRow(i, i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "a.json"); |
| new JsonFileBuilder(rowSet).build(tableFile); |
| rowSet.clear(); |
| } |
| |
| { |
| final TupleMetadata schema = new SchemaBuilder() |
| .add("a", TypeProtos.MinorType.INT) |
| .add("c", TypeProtos.MinorType.INT) |
| .buildSchema(); |
| final RowSetBuilder rowSetBuilder = new RowSetBuilder(allocator, schema); |
| |
| for (int i = 1; i <= record_count; i += 2) { |
| rowSetBuilder.addRow(i, i); |
| } |
| |
| final RowSet rowSet = rowSetBuilder.build(); |
| final File tableFile = createTableFile(tableDirName, "b.json"); |
| new JsonFileBuilder(rowSet).build(tableFile); |
| rowSet.clear(); |
| } |
| try { |
| // Test framework currently doesn't handle changing schema (i.e. new |
| // columns) on the client side |
| TestBuilder builder = testBuilder() |
| .sqlQuery("select a, b, c from dfs.`%s` order by a desc", tableDirName) |
| .ordered() |
| .enableSessionOption(ENABLE_UNION_TYPE_KEY) |
| .disableSessionOption(ENABLE_V2_JSON_READER_KEY) |
| .baselineColumns("a", "b", "c"); |
| for (int i = record_count; i >= 0;) { |
| builder.baselineValues((long) i, (long) i--, null); |
| if (i >= 0) { |
| builder.baselineValues((long) i, null, (long) i--); |
| } |
| } |
| builder.go(); |
| |
| // TODO: Useless test: just dumps to console |
| test("select * from dfs.`%s` order by a desc", tableDirName); |
| } finally { |
| resetSessionOption(ENABLE_UNION_TYPE_KEY); |
| resetSessionOption(ENABLE_V2_JSON_READER_KEY); |
| } |
| } |
| |
| private File createTableFile(final String tableDirName, final String fileName) { |
| return dirTestWatcher |
| .getRootDir() |
| .toPath() |
| .resolve(Paths.get(tableDirName, fileName)) |
| .toFile(); |
| } |
| } |