/* * 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.flink.api.java.io.jdbc; import org.apache.flink.api.java.io.jdbc.split.GenericParameterValuesProvider; import org.apache.flink.api.java.io.jdbc.split.NumericBetweenParametersProvider; import org.apache.flink.api.java.io.jdbc.split.ParameterValuesProvider; import org.apache.flink.core.io.InputSplit; import org.apache.flink.types.Row; import org.junit.After; import org.junit.Assert; import org.junit.Test; import java.io.IOException; import java.io.Serializable; import java.sql.ResultSet; public class JDBCInputFormatTest extends JDBCTestBase { private JDBCInputFormat jdbcInputFormat; @After public void tearDown() throws IOException { if (jdbcInputFormat != null) { jdbcInputFormat.close(); jdbcInputFormat.closeInputFormat(); } jdbcInputFormat = null; } @Test(expected = IllegalArgumentException.class) public void testUntypedRowInfo() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername("org.apache.derby.jdbc.idontexist") .setDBUrl(DB_URL) .setQuery(SELECT_ALL_BOOKS) .finish(); jdbcInputFormat.openInputFormat(); } @Test(expected = IllegalArgumentException.class) public void testInvalidDriver() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername("org.apache.derby.jdbc.idontexist") .setDBUrl(DB_URL) .setQuery(SELECT_ALL_BOOKS) .setRowTypeInfo(rowTypeInfo) .finish(); jdbcInputFormat.openInputFormat(); } @Test(expected = IllegalArgumentException.class) public void testInvalidURL() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl("jdbc:der:iamanerror:mory:ebookshop") .setQuery(SELECT_ALL_BOOKS) .setRowTypeInfo(rowTypeInfo) .finish(); jdbcInputFormat.openInputFormat(); } @Test(expected = IllegalArgumentException.class) public void testInvalidQuery() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery("iamnotsql") .setRowTypeInfo(rowTypeInfo) .finish(); jdbcInputFormat.openInputFormat(); } @Test(expected = IllegalArgumentException.class) public void testIncompleteConfiguration() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setQuery(SELECT_ALL_BOOKS) .setRowTypeInfo(rowTypeInfo) .finish(); } @Test public void testJDBCInputFormatWithoutParallelism() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery(SELECT_ALL_BOOKS) .setRowTypeInfo(rowTypeInfo) .setResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) .finish(); //this query does not exploit parallelism Assert.assertEquals(1, jdbcInputFormat.createInputSplits(1).length); jdbcInputFormat.openInputFormat(); jdbcInputFormat.open(null); Row row = new Row(5); int recordCount = 0; while (!jdbcInputFormat.reachedEnd()) { Row next = jdbcInputFormat.nextRecord(row); assertEquals(TEST_DATA[recordCount], next); recordCount++; } jdbcInputFormat.close(); jdbcInputFormat.closeInputFormat(); Assert.assertEquals(TEST_DATA.length, recordCount); } @Test public void testJDBCInputFormatWithParallelismAndNumericColumnSplitting() throws IOException { final int fetchSize = 1; final long min = TEST_DATA[0].id; final long max = TEST_DATA[TEST_DATA.length - fetchSize].id; ParameterValuesProvider pramProvider = new NumericBetweenParametersProvider(fetchSize, min, max); jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery(JDBCTestBase.SELECT_ALL_BOOKS_SPLIT_BY_ID) .setRowTypeInfo(rowTypeInfo) .setParametersProvider(pramProvider) .setResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) .finish(); jdbcInputFormat.openInputFormat(); InputSplit[] splits = jdbcInputFormat.createInputSplits(1); //this query exploit parallelism (1 split for every id) Assert.assertEquals(TEST_DATA.length, splits.length); int recordCount = 0; Row row = new Row(5); for (InputSplit split : splits) { jdbcInputFormat.open(split); while (!jdbcInputFormat.reachedEnd()) { Row next = jdbcInputFormat.nextRecord(row); assertEquals(TEST_DATA[recordCount], next); recordCount++; } jdbcInputFormat.close(); } jdbcInputFormat.closeInputFormat(); Assert.assertEquals(TEST_DATA.length, recordCount); } @Test public void testJDBCInputFormatWithoutParallelismAndNumericColumnSplitting() throws IOException { final long min = TEST_DATA[0].id; final long max = TEST_DATA[TEST_DATA.length - 1].id; final long fetchSize = max + 1;//generate a single split ParameterValuesProvider pramProvider = new NumericBetweenParametersProvider(fetchSize, min, max); jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery(JDBCTestBase.SELECT_ALL_BOOKS_SPLIT_BY_ID) .setRowTypeInfo(rowTypeInfo) .setParametersProvider(pramProvider) .setResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) .finish(); jdbcInputFormat.openInputFormat(); InputSplit[] splits = jdbcInputFormat.createInputSplits(1); //assert that a single split was generated Assert.assertEquals(1, splits.length); int recordCount = 0; Row row = new Row(5); for (InputSplit split : splits) { jdbcInputFormat.open(split); while (!jdbcInputFormat.reachedEnd()) { Row next = jdbcInputFormat.nextRecord(row); assertEquals(TEST_DATA[recordCount], next); recordCount++; } jdbcInputFormat.close(); } jdbcInputFormat.closeInputFormat(); Assert.assertEquals(TEST_DATA.length, recordCount); } @Test public void testJDBCInputFormatWithParallelismAndGenericSplitting() throws IOException { Serializable[][] queryParameters = new String[2][1]; queryParameters[0] = new String[]{TEST_DATA[3].author}; queryParameters[1] = new String[]{TEST_DATA[0].author}; ParameterValuesProvider paramProvider = new GenericParameterValuesProvider(queryParameters); jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery(JDBCTestBase.SELECT_ALL_BOOKS_SPLIT_BY_AUTHOR) .setRowTypeInfo(rowTypeInfo) .setParametersProvider(paramProvider) .setResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) .finish(); jdbcInputFormat.openInputFormat(); InputSplit[] splits = jdbcInputFormat.createInputSplits(1); //this query exploit parallelism (1 split for every queryParameters row) Assert.assertEquals(queryParameters.length, splits.length); verifySplit(splits[0], TEST_DATA[3].id); verifySplit(splits[1], TEST_DATA[0].id + TEST_DATA[1].id); jdbcInputFormat.closeInputFormat(); } private void verifySplit(InputSplit split, int expectedIDSum) throws IOException { int sum = 0; Row row = new Row(5); jdbcInputFormat.open(split); while (!jdbcInputFormat.reachedEnd()) { row = jdbcInputFormat.nextRecord(row); int id = ((int) row.getField(0)); int testDataIndex = id - 1001; assertEquals(TEST_DATA[testDataIndex], row); sum += id; } Assert.assertEquals(expectedIDSum, sum); } @Test public void testEmptyResults() throws IOException { jdbcInputFormat = JDBCInputFormat.buildJDBCInputFormat() .setDrivername(DRIVER_CLASS) .setDBUrl(DB_URL) .setQuery(SELECT_EMPTY) .setRowTypeInfo(rowTypeInfo) .setResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) .finish(); try { jdbcInputFormat.openInputFormat(); jdbcInputFormat.open(null); Assert.assertTrue(jdbcInputFormat.reachedEnd()); } finally { jdbcInputFormat.close(); jdbcInputFormat.closeInputFormat(); } } private static void assertEquals(TestEntry expected, Row actual) { Assert.assertEquals(expected.id, actual.getField(0)); Assert.assertEquals(expected.title, actual.getField(1)); Assert.assertEquals(expected.author, actual.getField(2)); Assert.assertEquals(expected.price, actual.getField(3)); Assert.assertEquals(expected.qty, actual.getField(4)); } }