/* * Licensed 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 com.facebook.presto.plugin.jdbc; import com.facebook.presto.spi.ColumnHandle; import com.facebook.presto.spi.ConnectorSplitSource; import com.facebook.presto.spi.RecordCursor; import com.facebook.presto.spi.RecordSet; import com.facebook.presto.spi.SchemaTableName; import com.facebook.presto.spi.connector.ConnectorTransactionHandle; import com.facebook.presto.spi.predicate.Domain; import com.facebook.presto.spi.predicate.Range; import com.facebook.presto.spi.predicate.TupleDomain; import com.facebook.presto.spi.predicate.ValueSet; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import static com.facebook.presto.spi.type.BigintType.BIGINT; import static com.facebook.presto.spi.type.VarcharType.VARCHAR; import static com.facebook.presto.spi.type.VarcharType.createVarcharType; import static com.facebook.presto.testing.TestingConnectorSession.SESSION; import static com.google.common.collect.Iterables.getOnlyElement; import static io.airlift.concurrent.MoreFutures.getFutureValue; import static io.airlift.slice.Slices.utf8Slice; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @Test public class TestJdbcRecordSetProvider { private TestingDatabase database; private JdbcClient jdbcClient; private JdbcSplit split; private JdbcTableHandle table; private JdbcColumnHandle textColumn; private JdbcColumnHandle textShortColumn; private JdbcColumnHandle valueColumn; @BeforeClass public void setUp() throws Exception { database = new TestingDatabase(); jdbcClient = database.getJdbcClient(); split = database.getSplit("example", "numbers"); table = jdbcClient.getTableHandle(new SchemaTableName("example", "numbers")); Map<String, JdbcColumnHandle> columns = database.getColumnHandles("example", "numbers"); textColumn = columns.get("text"); textShortColumn = columns.get("text_short"); valueColumn = columns.get("value"); } @AfterClass public void tearDown() throws Exception { database.close(); } @Test public void testGetRecordSet() throws Exception { ConnectorTransactionHandle transaction = new JdbcTransactionHandle(); JdbcRecordSetProvider recordSetProvider = new JdbcRecordSetProvider(jdbcClient); RecordSet recordSet = recordSetProvider.getRecordSet(transaction, SESSION, split, ImmutableList.of(textColumn, textShortColumn, valueColumn)); assertNotNull(recordSet, "recordSet is null"); RecordCursor cursor = recordSet.cursor(); assertNotNull(cursor, "cursor is null"); Map<String, Long> data = new LinkedHashMap<>(); while (cursor.advanceNextPosition()) { data.put(cursor.getSlice(0).toStringUtf8(), cursor.getLong(2)); assertEquals(cursor.getSlice(0), cursor.getSlice(1)); } assertEquals(data, ImmutableMap.<String, Long>builder() .put("one", 1L) .put("two", 2L) .put("three", 3L) .put("ten", 10L) .put("eleven", 11L) .put("twelve", 12L) .build()); } @Test public void testTupleDomain() throws Exception { // single value getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.singleValue(VARCHAR, utf8Slice("foo"))) )); // multiple values (string) getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.union(ImmutableList.of(Domain.singleValue(VARCHAR, utf8Slice("foo")), Domain.singleValue(VARCHAR, utf8Slice("bar"))))) )); // inequality (string) getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.create(ValueSet.ofRanges(Range.greaterThan(VARCHAR, utf8Slice("foo"))), false)) )); getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.create(ValueSet.ofRanges(Range.greaterThan(VARCHAR, utf8Slice("foo"))), false)) )); getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(VARCHAR, utf8Slice("foo"))), false)) )); getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.create(ValueSet.ofRanges(Range.lessThan(VARCHAR, utf8Slice("foo"))), false)) )); // is null getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.onlyNull(VARCHAR)) )); // not null getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.notNull(VARCHAR)) )); // specific value or null getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.union(ImmutableList.of(Domain.singleValue(VARCHAR, utf8Slice("foo")), Domain.onlyNull(VARCHAR)))) )); getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of(textColumn, Domain.create(ValueSet.ofRanges(Range.range(VARCHAR, utf8Slice("bar"), true, utf8Slice("foo"), true)), false)) )); getCursor(table, ImmutableList.of(textColumn, textShortColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of( textColumn, Domain.create(ValueSet.ofRanges( Range.range(VARCHAR, utf8Slice("bar"), true, utf8Slice("foo"), true), Range.range(VARCHAR, utf8Slice("hello"), false, utf8Slice("world"), false)), false ), textShortColumn, Domain.create(ValueSet.ofRanges( Range.range(createVarcharType(32), utf8Slice("bar"), true, utf8Slice("foo"), true), Range.range(createVarcharType(32), utf8Slice("hello"), false, utf8Slice("world"), false)), false ) ) )); getCursor(table, ImmutableList.of(textColumn, valueColumn), TupleDomain.withColumnDomains( ImmutableMap.of( textColumn, Domain.create(ValueSet.ofRanges( Range.range(VARCHAR, utf8Slice("bar"), true, utf8Slice("foo"), true), Range.range(VARCHAR, utf8Slice("hello"), false, utf8Slice("world"), false), Range.equal(VARCHAR, utf8Slice("apple")), Range.equal(VARCHAR, utf8Slice("banana")), Range.equal(VARCHAR, utf8Slice("zoo"))), false ), valueColumn, Domain.create(ValueSet.ofRanges( Range.range(BIGINT, 1L, true, 5L, true), Range.range(BIGINT, 10L, false, 20L, false)), true ) ) )); } private RecordCursor getCursor(JdbcTableHandle jdbcTableHandle, List<JdbcColumnHandle> columns, TupleDomain<ColumnHandle> domain) throws InterruptedException { JdbcTableLayoutHandle layoutHandle = new JdbcTableLayoutHandle(jdbcTableHandle, domain); ConnectorSplitSource splits = jdbcClient.getSplits(layoutHandle); JdbcSplit split = (JdbcSplit) getOnlyElement(getFutureValue(splits.getNextBatch(1000))); ConnectorTransactionHandle transaction = new JdbcTransactionHandle(); JdbcRecordSetProvider recordSetProvider = new JdbcRecordSetProvider(jdbcClient); RecordSet recordSet = recordSetProvider.getRecordSet(transaction, SESSION, split, columns); return recordSet.cursor(); } }