/* * 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.jdbc; import static org.junit.Assert.assertEquals; import java.util.Arrays; import org.junit.Test; import org.teiid.language.Expression; import org.teiid.language.Function; import org.teiid.language.LanguageFactory; import org.teiid.translator.TranslatorException; import org.teiid.translator.SourceSystemFunctions; /** * Test <code>LOCATEFunctionModifier</code> by invoking its methods with varying * parameters to validate it performs as designed and expected. */ public class TestLocateFunctionModifier { private static final LanguageFactory LANG_FACTORY = new LanguageFactory(); /** * Create an expression containing a LOCATE function using <code>args</code> * and pass it to the <code>Translator</code>'s LOCATE function modifier and * compare the resulting expression to <code>expectedStr</code>. * * @param args An array of <code>IExpression</code>'s to use as the * arguments to the LOCATE() function * @param expectedStr A string representing the modified expression * @return On success, the modified expression. * @throws Exception */ public void helpTestLocate(Expression[] args, String expectedStr) throws Exception { this.helpTestLocate(LocateFunctionModifier.LOCATE, false, args, expectedStr); } /** * Create an expression containing a LOCATE function using a function name of * <code>locateFunctionName</code> with the parameter order of * <code>parameterOrder</code> and a string index base of * <code>stringIndexBase</code> and uses the arguments <code>args</code> and * pass it to the <code>Translator</code>'s LOCATE function modifier and * compare the resulting expression to <code>expectedStr</code>. * * @param locateFunctionName the name to use for the function modifier * @param parameterOrder an <code>enum</code> value as defined by * {@link ParameterOrder} which represents the parameter order to use * for the modified LOCATE() function * @param stringIndexBase the string index that represents the first character of a string * @param args an array of <code>IExpression</code>'s to use as the * arguments to the LOCATE() function * @param expectedStr A string representing the modified expression * @return On success, the modified expression. * @throws Exception */ public void helpTestLocate(final String locateFunctionName, final boolean parameterOrder, Expression[] args, String expectedStr) throws Exception { Expression param1 = null; Expression param2 = null; Expression param3 = null; if (args.length > 0 ) param1 = args[0]; if (args.length > 1 ) param2 = args[1]; if (args.length > 2 ) param3 = args[2]; Function func = null; if (param3 != null) { func = LANG_FACTORY.createFunction(SourceSystemFunctions.LOCATE, Arrays.asList(param1, param2, param3), Integer.class); } else { func = LANG_FACTORY.createFunction(SourceSystemFunctions.LOCATE, Arrays.asList(param1, param2), Integer.class); } JDBCExecutionFactory trans = new JDBCExecutionFactory() { @Override public void start() throws TranslatorException { super.start(); registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateFunctionModifier(getLanguageFactory(), locateFunctionName, parameterOrder)); } }; trans.setUseBindVariables(false); trans.start(); SQLConversionVisitor sqlVisitor = trans.getSQLConversionVisitor(); sqlVisitor.append(func); assertEquals("Modified function does not match", expectedStr, sqlVisitor.toString()); //$NON-NLS-1$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str) using constants for both parameters * returns LOCATE(search_str, source_str). * <p> * {@link LocateFunctionModifier} will be constructed without specifying a * function name or parameter order. * * @throws Exception */ @Test public void testModifySimple() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class) //$NON-NLS-1$ }; // default / default helpTestLocate(args, "LOCATE('a', 'abcdefg')"); //$NON-NLS-1$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str) using constants for both parameters * returns locate(search_str, source_str). * <p> * {@link LocateFunctionModifier} will be constructed specifying a function * name of locate but no parameter order. * * @throws Exception */ @Test public void testModifySimple2() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class) //$NON-NLS-1$ }; // locate / default helpTestLocate("locate", false, args, "locate('a', 'abcdefg')"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str) using constants for both parameters * returns INSTR(source_str, search_str). * <p> * {@link LocateFunctionModifier} will be constructed specifying a function * name of INSTR and a parameter order of {@link ParameterOrder#SOURCE_SEARCH_INDEX}. * * @throws Exception */ @Test public void testModifySimple3() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class) //$NON-NLS-1$ }; // INSTR / SOURCE_SEARCH_INDEX helpTestLocate("INSTR", true, args, "INSTR('abcdefg', 'a')"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str) using constants for both parameters * returns locate(search_str, source_str). * <p> * {@link LocateFunctionModifier} will be constructed specifying a function * name of locate and a parameter order of {@link ParameterOrder#DEFAULT}. * * @throws Exception */ @Test public void testModifySimple4() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class) //$NON-NLS-1$ }; // locate / DEFAULT helpTestLocate("locate", false, args, "locate('a', 'abcdefg')"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, 1) using constants for all parameters * returns INSTR(source_str, search_str, 1). * <p> * {@link LocateFunctionModifier} will be constructed specifying a function * name of INSTR and a parameter order of {@link ParameterOrder#SOURCE_SEARCH_INDEX}. * * @throws Exception */ @Test public void testModifyWithStartIndex() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral(1, Integer.class) }; // INSTR / SOURCE_SEARCH_INDEX helpTestLocate("INSTR", true, args, "INSTR('abcdefg', 'a', 1)"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, 4) using constants for all parameters * returns LOCATE(search_str, source_str, 5). * <p> * {@link LocateFunctionModifier} will be constructed specifying no function * name or parameter order. * * @throws Exception */ @Test public void testModifyWithStartIndex2() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral(4, Integer.class) }; // default / default helpTestLocate(args, "LOCATE('a', 'abcdefg', 4)"); //$NON-NLS-1$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, -5) using constants for all parameters * returns LOCATE(search_str, source_str, 1). * <p> * {@link LocateFunctionModifier} will be constructed specifying no function * name or parameter order. * * @throws Exception */ @Test public void testModifyWithStartIndex3() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral(-5, Integer.class) }; // default / default helpTestLocate(args, "LOCATE('a', 'abcdefg', 1)"); //$NON-NLS-1$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, null) using constants for all parameters * returns LOCATE(search_str, source_str, NULL). * <p> * {@link LocateFunctionModifier} will be constructed specifying no function * name or parameter order. * * @throws Exception */ @Test public void testModifyWithStartIndex4() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral(null, Integer.class) }; // default / default helpTestLocate(args, "LOCATE('a', 'abcdefg', NULL)"); //$NON-NLS-1$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, e1) using an element for start index * parameter returns INSTR(source_str, search_str, CASE WHEN e1 < 1 THEN 1 ELSE e1 END). * <p> * {@link LocateFunctionModifier} will be constructed specifying a function * name of INSTR and a parameter order of {@link ParameterOrder#SOURCE_SEARCH_INDEX}. * * @throws Exception */ @Test public void testModifyWithElementStartIndex() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createColumnReference("e1", null, null, Integer.class) //$NON-NLS-1$ }; // INSTR / SOURCE_SEARCH_INDEX helpTestLocate("INSTR", true, args, "INSTR('abcdefg', 'a', CASE WHEN e1 < 1 THEN 1 ELSE e1 END)"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Test {@link LocateFunctionModifier#modify(Function)} to validate a call * to LOCATE(search_str, source_str, e1) using an element for start index * parameter returns LOCATE(search_str, source_str, CASE WHEN e1 < 0 THEN 0 ELSE e1 END). * <p> * {@link LocateFunctionModifier} will be constructed specifying no function * name and no parameter order. * * @throws Exception */ @Test public void testModifyWithElementStartIndex2() throws Exception { Expression[] args = new Expression[] { LANG_FACTORY.createLiteral("a", String.class), //$NON-NLS-1$ LANG_FACTORY.createLiteral("abcdefg", String.class), //$NON-NLS-1$ LANG_FACTORY.createColumnReference("e1", null, null, Integer.class) //$NON-NLS-1$ }; // default / default helpTestLocate(args, "LOCATE('a', 'abcdefg', CASE WHEN e1 < 1 THEN 1 ELSE e1 END)"); //$NON-NLS-1$ } }