Package org.teiid.translator.jdbc

Source Code of org.teiid.translator.jdbc.LocateFunctionModifier

/*
* 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 java.util.Arrays;
import java.util.List;

import org.teiid.language.Comparison;
import org.teiid.language.Expression;
import org.teiid.language.Function;
import org.teiid.language.LanguageFactory;
import org.teiid.language.Literal;
import org.teiid.language.Comparison.Operator;
import org.teiid.translator.TypeFacility;


/**
* A modifier class that can be used to translate the scalar function
* <code>locate(search_string, source_string)</code> and
* <code>locate(search_string, source_string, start_index)</code> to a function
* or expression that can be used at the data source.
* <p>
* If the default implementation is used, a function name of LOCATE will be used
* for the function name.
* <p>
* If the default implementation is used, the expression will not be modified if:
* <li><code>locate(search_string, source_string)</code> is used</li>
* <li><code>locate(search_string, source_string, start_index)</code> is used
* and <code>start_index</code> is a literal integer greater then 0</li>
* <li>the default function parameter order is used or unspecified</li>
* <p>
* If the default implementation is used, the expression will be modified if:
* <li><code>locate(search_string, source_string, start_index)</code> is used
* and <code>start_index</code> is a literal integer less then 1</li> 
* <li><code>locate(search_string, source_string, start_index)</code> is used
* and <code>start_index</code> is not a literal integer</li>
* <li>the function parameter order is something other than the default</li>
* <p>
* If the default implementation is used and the expression is modified, it is
* modified to ensure that any literal integer value less than 1 is made equal
* to 1 and any non literal value is wrapped by a searched case expression
* to ensure that a value of less then 1 will be equal to 1 and the parameter
* order matches that of what the data source expects.
* <p>
* For example:
* <li><code>locate('a', 'abcdef')</code> --> <code>LOCATE('a', 'abcdef')</code></li>
* <li><code>locate('a', 'abcdef', 2)</code> --> <code>LOCATE('a', 'abcdef', 2)</code></li>
* <li><code>locate('a', 'abcdef', 0)</code> --> <code>LOCATE('a', 'abcdef', 1)</code></li>
* <li><code>locate('a', 'abcdef', intCol)</code> --> <code>LOCATE('a', 'abcdef', CASE WHEN intCol < 1 THEN 1 ELSE intCol END)</code></li>
*
* @since 6.2
*/
public class LocateFunctionModifier extends AliasModifier {

  public static String LOCATE = "LOCATE"; //$NON-NLS-1$
 
    private LanguageFactory langFactory;
    private boolean sourceStringFirst;
   
  /**
   * Translates the scalar function LOCATE() to a source specific scalar
   * function or expression.
   *
   * @param langFactory the language factory associated with translation
   */
    public LocateFunctionModifier(LanguageFactory langFactory) {
      this(langFactory, LOCATE, false);
    }

  /**
   * Translates the scalar function LOCATE() to a source specific scalar
   * function or expression.
   *
   * @param langFactory the language factory associated with translation
   * @param functionName the function name or alias to be used instead of LOCATE
   * @param sourceStringFirst
   */
    public LocateFunctionModifier(LanguageFactory langFactory, final String functionName, boolean sourceStringFirst) {
      super(functionName);
      this.langFactory = langFactory;
      this.sourceStringFirst = sourceStringFirst;
    }

  /**
   * Returns a version of <code>function</code> suitable for executing at the
   * data source.
   * <p>
   * For example:
   * <ul>
   * <code>locate('a', 'abcdefg')  --->  LOCATE('a', 'abcdefg')</code><br />
   * <code>locate('a', 'abcdefg', 1)  --->  LOCATE('a', 'abcdefg', 1)</code><br />
   * <code>locate('a', 'abcdefg', 1)  --->  INSTR('abcdefg', 'a', 1)</code><br />
   * <code>locate('a', 'abcdefg', -5)  --->  INSTR('abcdefg', 'a', 1)</code><br />
   * <code>locate('a', 'abcdefg', 1)  --->  FINDSTR('a', 'abcdefg', 1)</code><br />
   * <code>locate('a', 'abcdefg', myCol)  --->  LOCATE('a', 'abcdefg', CASE WHEN myCol < 1 THEN 1 ELSE myCol END)</code>
   * </ul>
   *
   * @param function the LOCATE function that may need to be modified
   */
    public void modify(Function function) {
      super.modify(function);
        List<Expression> args = function.getParameters();
        Expression searchStr = args.get(0);
        Expression sourceStr = args.get(1);

        // if startIndex was given then we may need to do additional work
        if (args.size() > 2) {
          args.set(2, ensurePositiveStartIndex(args.get(2)));
        }
        if (sourceStringFirst) {
      args.set(0, sourceStr);
      args.set(1, searchStr);
        }
    }

  private Expression ensurePositiveStartIndex(Expression startIndex) {
    if (startIndex instanceof Literal) {
      Literal literal = (Literal)startIndex; 
      if (literal.getValue() instanceof Integer && ((Integer)literal.getValue() < 1)) {
        literal.setValue(1);
      }
    } else {
      Comparison whenExpr = langFactory.createCompareCriteria(
          Operator.LT,
          startIndex,
          langFactory.createLiteral(1, Integer.class)
        );
      Literal thenExpr = langFactory.createLiteral(1, Integer.class);
      startIndex = langFactory.createSearchedCaseExpression(Arrays.asList(langFactory.createSearchedWhenCondition(whenExpr, thenExpr)), startIndex, TypeFacility.RUNTIME_TYPES.INTEGER);
    }
    return startIndex;
  }
 
  /**
     * Get the instance of {@link LanguageFactory} set during construction.
     *
     * @return the <code>ILanguageFactory</code> instance
     */
  protected LanguageFactory getLanguageFactory() {
    return this.langFactory;
  }

}
TOP

Related Classes of org.teiid.translator.jdbc.LocateFunctionModifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.