/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.translator.hive; import static org.junit.Assert.*; import java.math.BigInteger; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Arrays; import java.util.List; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.teiid.cdk.CommandBuilder; import org.teiid.core.types.DataTypeManager; import org.teiid.language.Command; import org.teiid.language.Expression; import org.teiid.language.Function; import org.teiid.language.LanguageFactory; import org.teiid.metadata.Column; import org.teiid.metadata.MetadataFactory; import org.teiid.metadata.MetadataStore; import org.teiid.metadata.Schema; import org.teiid.metadata.Table; import org.teiid.query.mapping.relational.QueryNode; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.metadata.TransformationMetadata; import org.teiid.query.unittest.RealMetadataFactory; import org.teiid.translator.ExecutionContext; import org.teiid.translator.TranslatorException; import org.teiid.translator.TypeFacility; import org.teiid.translator.jdbc.SQLConversionVisitor; import org.teiid.translator.jdbc.TranslatedCommand; @SuppressWarnings("nls") public class TestHiveExecutionFactory { private static HiveExecutionFactory hiveTranslator; private static final LanguageFactory LANG_FACTORY = new LanguageFactory(); private static TransformationMetadata bqt; @BeforeClass public static void setUp() throws TranslatorException { hiveTranslator = new HiveExecutionFactory(); hiveTranslator.setUseBindVariables(false); hiveTranslator.start(); bqt = exampleBQT(); } private void helpTest(Expression srcExpression, String tgtType, String expectedExpression) throws Exception { Function func = LANG_FACTORY.createFunction("convert", Arrays.asList( srcExpression,LANG_FACTORY.createLiteral(tgtType, String.class)),TypeFacility.getDataTypeClass(tgtType)); SQLConversionVisitor sqlVisitor = hiveTranslator.getSQLConversionVisitor(); sqlVisitor.append(func); assertEquals("Error converting from " + srcExpression.getType() + " to " + tgtType, expectedExpression,sqlVisitor.toString()); } private void helpTestVisitor(QueryMetadataInterface metadata, String input, String expectedOutput) throws TranslatorException { // Convert from sql to objects CommandBuilder commandBuilder = new CommandBuilder(metadata); Command obj = commandBuilder.getCommand(input); // Convert back to SQL TranslatedCommand tc = new TranslatedCommand(Mockito.mock(ExecutionContext.class), hiveTranslator); tc.translateCommand(obj); // Check stuff assertEquals("Did not get correct sql", expectedOutput, tc.getSql()); //$NON-NLS-1$ } @Test public void testConvertions() throws Exception { helpTest(LANG_FACTORY.createLiteral(Boolean.TRUE, Boolean.class), TypeFacility.RUNTIME_NAMES.BOOLEAN, "cast(true AS boolean)"); helpTest(LANG_FACTORY.createLiteral(Byte.parseByte("123"), Byte.class), TypeFacility.RUNTIME_NAMES.BYTE, "cast(123 AS tinyint)"); helpTest(LANG_FACTORY.createLiteral(new Integer(12345), Integer.class), TypeFacility.RUNTIME_NAMES.INTEGER, "cast(12345 AS int)"); helpTest(LANG_FACTORY.createLiteral(Short.parseShort("1234"), Short.class), TypeFacility.RUNTIME_NAMES.SHORT, "cast(1234 AS smallint)"); helpTest(LANG_FACTORY.createLiteral(new BigInteger("123451266182"), BigInteger.class), TypeFacility.RUNTIME_NAMES.BIG_INTEGER, "cast(123451266182 AS bigint)"); helpTest(LANG_FACTORY.createLiteral(new String("foo-bar"), String.class), TypeFacility.RUNTIME_NAMES.STRING, "cast('foo-bar' AS string)"); helpTest(LANG_FACTORY.createLiteral(Boolean.TRUE, Boolean.class), TypeFacility.RUNTIME_NAMES.STRING, "cast(true AS string)"); helpTest(LANG_FACTORY.createLiteral(new Integer(12345), Integer.class), TypeFacility.RUNTIME_NAMES.BOOLEAN, "cast(12345 AS boolean)"); } @Test public void testFunction() throws Exception { String input = "SELECT MOD(A.intkey,2) FROM BQT1.SMALLA A"; String output = "SELECT (A.IntKey % 2) FROM SmallA A"; helpTestVisitor(bqt, input, output); } @Test public void testTimeLiterals() throws Exception { String input = "SELECT {ts '1999-01-01 11:11:11'}, {d '2000-02-02'}, {t '00:00:00'} FROM BQT1.SMALLA A"; String output = "SELECT cast('1999-01-01 11:11:11.0' as timestamp), DATE '2000-02-02', cast('1970-01-01 00:00:00.0' as timestamp) FROM SmallA A"; helpTestVisitor(bqt, input, output); } @Test public void testTimeLiteralsINClause() throws Exception { String input = "SELECT intkey FROM BQT1.SMALLA A WHERE A.TimestampValue IN ({ts '1999-01-01 11:11:11'}," + "{ts '1999-02-22 22:22:22'})"; String output = "SELECT A.IntKey FROM SmallA A WHERE A.TimestampValue IN (cast('1999-01-01 11:11:11.0' as timestamp), cast('1999-02-22 22:22:22.0' as timestamp))"; helpTestVisitor(bqt, input, output); input = "SELECT intkey FROM BQT1.SMALLA A WHERE A.DateValue IN (" + "{d '1999-01-01'}, {d '1999-02-22'})"; output = "SELECT A.IntKey FROM SmallA A WHERE A.DateValue IN (DATE '1999-01-01', DATE '1999-02-22')"; helpTestVisitor(bqt, input, output); input = "SELECT intkey FROM BQT1.SMALLA A WHERE A.DateValue IN (" + "convert('1999-01-01',date), convert('1999-02-22', date))"; output = "SELECT A.IntKey FROM SmallA A WHERE A.DateValue IN (DATE '1999-01-01', DATE '1999-02-22')"; helpTestVisitor(bqt, input, output); } @Test public void testEqualityJoinCriteria() throws Exception { String input = "SELECT A.intkey FROM BQT1.SMALLA A JOIN BQT1.SmallB B on A.intkey=B.intkey"; String output = "SELECT A.IntKey FROM SmallA A JOIN SmallB B ON A.IntKey = B.IntKey"; helpTestVisitor(bqt, input, output); } @Test public void testFourWayJoin() throws Exception { String input = "SELECT A.intkey FROM BQT1.SMALLA A JOIN BQT1.SmallB B on A.intkey=B.intkey JOIN BQT1.SMALLA C on A.intkey=C.intkey JOIN BQT1.SMALLB D on A.intkey=D.intkey"; String output = "SELECT A.IntKey FROM SmallA A JOIN SmallB B ON A.IntKey = B.IntKey JOIN SmallA C ON A.IntKey = C.IntKey JOIN SmallB D ON A.IntKey = D.IntKey"; helpTestVisitor(bqt, input, output); } @Test public void testThreeWayJoin() throws Exception { String input = "SELECT A.intkey FROM BQT1.SMALLA A JOIN BQT1.SmallB B on A.intkey=B.intkey JOIN BQT1.SMALLA C on A.intkey=C.intkey"; String output = "SELECT A.IntKey FROM SmallA A JOIN SmallB B ON A.IntKey = B.IntKey JOIN SmallA C ON A.IntKey = C.IntKey"; helpTestVisitor(bqt, input, output); } @Test public void testCrossJoinCriteria() throws Exception { String input = "SELECT A.intkey FROM BQT1.SMALLA A Cross join BQT1.SmallB B"; String output = "SELECT A.IntKey FROM SmallA A CROSS JOIN SmallB B"; helpTestVisitor(bqt, input, output); } @Test public void testMustHaveAliasOnView() throws Exception { String input = "SELECT intkey FROM (select intkey from BQT1.SmallA) as X"; String output = "SELECT X.intkey FROM (SELECT SmallA.IntKey FROM SmallA) X"; helpTestVisitor(bqt, input, output); } @Test public void testUnionAllRewrite() throws Exception { String input = "SELECT intkey, stringkey FROM BQT1.SmallA union all SELECT intkey, stringkey FROM BQT1.Smallb"; String output = "SELECT intkey, stringkey FROM (SELECT SmallA.IntKey, SmallA.StringKey FROM SmallA UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB) X__"; helpTestVisitor(bqt, input, output); } @Test public void testUnionAllRewriteNested() throws Exception { String input = "SELECT intkey, stringkey FROM BQT1.SmallA union all SELECT intkey, stringkey FROM BQT1.Smallb union all SELECT intkey, stringkey FROM BQT1.Smallb"; String output = "SELECT intkey, stringkey FROM (SELECT SmallA.IntKey, SmallA.StringKey FROM SmallA UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB) X__"; helpTestVisitor(bqt, input, output); } @Test public void testUnionAllRewriteNested1() throws Exception { String input = "SELECT intkey, stringkey FROM BQT1.SmallA union all (SELECT intkey, stringkey FROM BQT1.Smallb union SELECT intkey, stringkey FROM BQT1.Smallb)"; String output = "SELECT intkey, stringkey FROM (SELECT SmallA.IntKey, SmallA.StringKey FROM SmallA UNION ALL (SELECT DISTINCT intkey, stringkey FROM (SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB) X__)) X__"; helpTestVisitor(bqt, input, output); } @Test public void testUnionAllExprRewrite() throws Exception { String input = "SELECT count(*) as key, stringkey FROM BQT1.SmallA union all SELECT intkey, stringkey FROM BQT1.Smallb"; String output = "SELECT key, stringkey FROM (SELECT COUNT(*) AS key, SmallA.StringKey FROM SmallA UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB) X__"; helpTestVisitor(bqt, input, output); } @Test public void testUnionRewrite() throws Exception { String input = "SELECT intkey, stringkey FROM BQT1.SmallA union SELECT intkey, stringkey FROM BQT1.Smallb"; String output = "SELECT DISTINCT intkey, stringkey FROM (SELECT SmallA.IntKey, SmallA.StringKey FROM SmallA UNION ALL SELECT SmallB.IntKey, SmallB.StringKey FROM SmallB) X__"; helpTestVisitor(bqt, input, output); } @Test public void testGroupByOrderBy() throws Exception { String input = "SELECT intkey FROM BQT1.SmallA group by intkey order by intkey"; String output = "SELECT SmallA.IntKey FROM SmallA GROUP BY SmallA.IntKey ORDER BY IntKey"; helpTestVisitor(bqt, input, output); } public static TransformationMetadata exampleBQT() { MetadataStore metadataStore = new MetadataStore(); Schema bqt1 = RealMetadataFactory.createPhysicalModel("BQT1", metadataStore); //$NON-NLS-1$ Table bqt1SmallA = RealMetadataFactory.createPhysicalGroup("SmallA", bqt1); //$NON-NLS-1$ Table bqt1SmallB = RealMetadataFactory.createPhysicalGroup("SmallB", bqt1); //$NON-NLS-1$ String[] elemNames = new String[] { "IntKey", "StringKey", //$NON-NLS-1$ //$NON-NLS-2$ "IntNum", "StringNum", //$NON-NLS-1$ //$NON-NLS-2$ "FloatNum", "LongNum", //$NON-NLS-1$ //$NON-NLS-2$ "DoubleNum", "ByteNum", //$NON-NLS-1$ //$NON-NLS-2$ "DateValue", "TimeValue", //$NON-NLS-1$ //$NON-NLS-2$ "TimestampValue", "BooleanValue", //$NON-NLS-1$ //$NON-NLS-2$ "CharValue", "ShortValue", //$NON-NLS-1$ //$NON-NLS-2$ "BigIntegerValue", "BigDecimalValue", //$NON-NLS-1$ //$NON-NLS-2$ "ObjectValue" }; //$NON-NLS-1$ String[] nativeTypes = new String[] { DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.FLOAT, DataTypeManager.DefaultDataTypes.BIG_INTEGER, DataTypeManager.DefaultDataTypes.DOUBLE, DataTypeManager.DefaultDataTypes.BYTE, DataTypeManager.DefaultDataTypes.DATE, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.TIMESTAMP, DataTypeManager.DefaultDataTypes.BOOLEAN, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.SHORT, DataTypeManager.DefaultDataTypes.BIG_INTEGER, DataTypeManager.DefaultDataTypes.BIG_INTEGER, DataTypeManager.DefaultDataTypes.STRING}; String[] runtimeTypes = new String[] { DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.FLOAT, DataTypeManager.DefaultDataTypes.LONG, DataTypeManager.DefaultDataTypes.DOUBLE, DataTypeManager.DefaultDataTypes.BYTE, DataTypeManager.DefaultDataTypes.DATE, DataTypeManager.DefaultDataTypes.TIME, DataTypeManager.DefaultDataTypes.TIMESTAMP, DataTypeManager.DefaultDataTypes.BOOLEAN, DataTypeManager.DefaultDataTypes.CHAR, DataTypeManager.DefaultDataTypes.SHORT, DataTypeManager.DefaultDataTypes.BIG_INTEGER, DataTypeManager.DefaultDataTypes.BIG_DECIMAL, DataTypeManager.DefaultDataTypes.OBJECT }; List<Column> bqt1SmallAe = RealMetadataFactory.createElements(bqt1SmallA, elemNames, nativeTypes); List<Column> bqt1SmallBe = RealMetadataFactory.createElements(bqt1SmallB, elemNames, nativeTypes); Schema vqt = RealMetadataFactory.createVirtualModel("VQT", metadataStore); //$NON-NLS-1$ QueryNode vqtn1 = new QueryNode("SELECT * FROM BQT1.SmallA"); //$NON-NLS-1$ Table vqtg1 = RealMetadataFactory.createUpdatableVirtualGroup("SmallA", vqt, vqtn1); //$NON-NLS-1$ RealMetadataFactory.createElements(vqtg1, elemNames, runtimeTypes); return RealMetadataFactory.createTransformationMetadata(metadataStore, "bqt");//$NON-NLS-1$ } @Test public void testExcludeTables() throws Exception { HiveMetadataProcessor hmp = new HiveMetadataProcessor(); hmp.setExcludeTables("x"); Connection c = Mockito.mock(Connection.class); MetadataFactory mf = Mockito.mock(MetadataFactory.class); Statement stmt = Mockito.mock(Statement.class); Mockito.stub(c.createStatement()).toReturn(stmt); ResultSet rs = Mockito.mock(ResultSet.class); Mockito.stub(stmt.executeQuery("SHOW TABLES")).toReturn(rs); Mockito.stub(rs.next()).toReturn(true).toReturn(false); Mockito.stub(rs.getString(1)).toReturn("x"); hmp.process(mf, c); Mockito.verify(mf, Mockito.times(0)).addTable("x"); } @Test public void testStringLiteral() { CommandBuilder commandBuilder = new CommandBuilder(RealMetadataFactory.example1Cached()); Command obj = commandBuilder.getCommand("select pm1.g1.e2 from pm1.g1 where pm1.g1.e1 = 'a''b\\c'"); SQLConversionVisitor sqlVisitor = hiveTranslator.getSQLConversionVisitor(); sqlVisitor.append(obj); assertEquals("SELECT g1.e2 FROM g1 WHERE g1.e1 = 'a\\'b\\\\c'", sqlVisitor.toString()); } }