All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hpccsystems.commons.filter.SQLFragment Maven / Gradle / Ivy

package org.hpccsystems.commons.filter;

/*******************************************************************************
 * HPCC SYSTEMS software Copyright (C) 2018 HPCC Systems®.
 *
 * 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.
 *******************************************************************************/

import java.util.List;
import java.util.StringTokenizer;

import org.hpccsystems.commons.utils.Utils;

public class SQLFragment
{
    public enum FragmentType
    {
        UNKNOWN_TYPE, NUMERIC_FRAGMENT, LITERAL_STRING, PARAMETERIZED, FIELD, LIST, CONTENT_MODIFIER, FIELD_CONTENT_MODIFIER, AGGREGATE_FUNCTION, BOOLEAN;
    }

    private String       fnname = null;
    private String       parent = null;
    private String       value  = null;
    private FragmentType type   = FragmentType.UNKNOWN_TYPE;

    /**
     * Instantiates a new SQL fragment.
     */
    public SQLFragment()
    {
    }

    /**
     * Instantiates a new SQL fragment.
     *
     * @param framentStr
     *            the frament str
     */
    public SQLFragment(String framentStr)
    {
        parseExpressionFragment(framentStr);
    }

    /**
     * Checks if is parameterized.
     *
     * @return true, if is parameterized
     */
    public boolean isParameterized()
    {
        return type == FragmentType.PARAMETERIZED;
    }

    /**
     * Gets the parent.
     *
     * @return the parent
     */
    public String getParent()
    {
        return parent;
    }

    /**
     * Sets the parent.
     *
     * @param parent
     *            the new parent
     */
    public void setParent(String parent)
    {
        this.parent = parent.toUpperCase();
    }

    /**
     * Gets the value.
     *
     * @return the value
     */
    public String getValue()
    {
        if (type == FragmentType.CONTENT_MODIFIER || type == FragmentType.FIELD_CONTENT_MODIFIER)
            return fnname + "( " + value + " )";
        else
            return value;
    }

    /**
     * Sets the value.
     *
     * @param value
     *            the new value
     */
    public void setValue(String value)
    {
        this.value = value;
    }

    /**
     * Gets the type.
     *
     * @return the type
     */
    public FragmentType getType()
    {
        return type;
    }

    /**
     * Sets the type.
     *
     * @param type
     *            the new type
     */
    public void setType(FragmentType type)
    {
        this.type = type;
    }

    /**
     * Handle field type.
     *
     * @param fragment
     *            the fragment
     */
    private void handleFieldType(String fragment)
    {
        String fragsplit[] = fragment.split(Utils.DOTSEPERATORREGEX, 2);
        if (fragsplit.length == 1)
        {
            setValue(Utils.handleQuotedString(fragsplit[0]));
        }
        else
        {
            setParent(Utils.handleQuotedString(fragsplit[0]));
            setValue(Utils.handleQuotedString(fragsplit[1]));
        }
    }

    private void handleSQLFieldType(String fragment)
    {
        String fragsplit[] = fragment.split(Utils.DOTSEPERATORREGEX, 2);
        if (fragsplit.length == 1)
        {
            setValue(Utils.handleQuotedIdentifier(fragsplit[0]));
        }
        else
        {
            setParent(Utils.handleQuotedIdentifier(fragsplit[0]));
            setValue(Utils.handleQuotedIdentifier(fragsplit[1]));
        }
    }
    /**
     * Parses the expression fragment.
     *
     * @param fragment
     *            the fragment
     */
    public void parseExpressionFragment(String fragment)
    {
        try
        {
            this.type = determineFragmentType(fragment);

            switch (type)
            {
                case LITERAL_STRING:
                    fragment = Utils.replaceSQLwithECLEscapeChar(fragment);
                case NUMERIC_FRAGMENT:
                case PARAMETERIZED:
                case BOOLEAN:
                    setValue(fragment);
                    break;
                case FIELD:
                    handleSQLFieldType(fragment);
                    break;
                case LIST:

                    if (Utils.hasPossibleEscapedQuoteLiteral(fragment))
                    {
                        StringBuilder tmp = new StringBuilder();

                        StringTokenizer comatokens = new StringTokenizer(Utils.getParenContents(fragment), ",");

                        while (comatokens.hasMoreTokens())
                        {
                            if (tmp.length() == 0)
                                tmp.append("[");
                            else
                                tmp.append(", ");

                            tmp.append(Utils.replaceSQLwithECLEscapeChar(comatokens.nextToken().trim()));
                        }
                        tmp.append("]");

                        setValue(tmp.toString());
                    }
                    else
                        setValue("[" + Utils.getParenContents(fragment) + "]");

                    break;
                /*
                 * case AGGREGATE_FUNCTION:
                 * Matcher matcher = HPCCJDBCUtils.AGGFUNCPATTERN.matcher(fragment);
                 * 
                 * if (matcher.matches())
                 * {
                 * ECLFunction func = ECLFunctions.getEclFunction(matcher.group(1));
                 * 
                 * if (func == null)
                 * HPCCJDBCUtils.traceoutln(Level.WARNING, "Function found in HAVING clause might not be supported.");
                 * else
                 * {
                 * if (func.getFunctionType() == FunctionType.CONTENT_MODIFIER)
                 * {
                 * this.type = FragmentType.CONTENT_MODIFIER;
                 * 
                 * setFnname(func.getEclFunction());
                 * String subfragment = matcher.group(3).trim();
                 * FragmentType subfragtype = determineFragmentType(subfragment);
                 * switch (subfragtype)
                 * {
                 * case FIELD:
                 * handleFieldType(subfragment);
                 * this.type = FragmentType.FIELD_CONTENT_MODIFIER;
                 * break;
                 * case LITERAL_STRING:
                 * case NUMERIC_FRAGMENT:
                 * case PARAMETERIZED:
                 * case BOOLEAN:
                 * setValue(subfragment);
                 * break;
                 * }
                 * }
                 * else
                 * {
                 * String fnname = matcher.group(1).trim();
                 * setParent(fnname);
                 * setValue(fnname+"out");
                 * }
                 * }
                 * }
                 * break;
                 */
                default:
                    break;
            }
        }
        catch (Exception e)
        {
            System.out.println("Error while parsing SQL fragment: " + fragment);
        }
    }

    /**
     * Creates the expression fragment.
     *
     * @param fragment
     *            the fragment
     * @return the SQL fragment
     */
    public static SQLFragment createExpressionFragment(String fragment)
    {
        SQLFragment frag = new SQLFragment();

        frag.parseExpressionFragment(fragment);

        return frag;
    }

    /**
     * Determine fragment type.
     *
     * @param fragStr
     *            the frag str
     * @return the fragment type
     */
    public static FragmentType determineFragmentType(String fragStr)
    {
        if (fragStr == null || fragStr.length() <= 0)
        {
            return FragmentType.UNKNOWN_TYPE;
        }
        else if (Utils.isParameterizedStr(fragStr))
        {
            return FragmentType.PARAMETERIZED;
        }
        else if (Utils.isSQLLiteralString(fragStr))
        {
            return FragmentType.LITERAL_STRING;
        }
        else if (Utils.isBooleanKeyWord(fragStr))
        {
            return FragmentType.BOOLEAN;
        }
        else if (Utils.isNumeric(fragStr))
        {
            return FragmentType.NUMERIC_FRAGMENT;
        }
        else if (Utils.isInParenthesis(fragStr) || Utils.isCommaList(fragStr))
        {
            return FragmentType.LIST;
        }
        else if (Utils.isAggFunction(fragStr))
        {
            return FragmentType.AGGREGATE_FUNCTION;
        }
        else
        {
            return FragmentType.FIELD;
        }
    }

    /**
     * Gets the full column name.
     *
     * @return the full column name
     */
    public String getFullColumnName()
    {
        if (type == FragmentType.FIELD)
            return getParent() + "." + getValue();
        else
            return getValue();
    }

    /**
     * Update fragment colum parent.
     *
     * @param sqlTables
     *            the sql tables
     * @throws Exception
     *             the exception
     */
    public void updateFragmentColumParent(List sqlTables) throws Exception
    {
        if (type == FragmentType.FIELD || type == FragmentType.FIELD_CONTENT_MODIFIER)
        {
            if (parent != null && parent.length() > 0)
            {
                setParent(searchForPossibleTableName(sqlTables));
            }
            else if (sqlTables.size() == 1)
            {
                setParent(sqlTables.get(0).getName());
            }
            else
            {
                throw new Exception("Ambiguous field found: " + getValue());
            }
        }
    }

    /**
     * Returns table name if the tablename or alias match Otherwise
     * throw exception.
     *
     * @param sqlTables
     *            the sql tables
     * @return the string
     * @throws Exception
     *             the exception
     */
    private String searchForPossibleTableName(List sqlTables) throws Exception
    {
        for (int i = 0; i < sqlTables.size(); i++)
        {
            SQLTable currTable = sqlTables.get(i);
            if (parent.equalsIgnoreCase(currTable.getAlias()) || parent.equalsIgnoreCase(currTable.getName())) return currTable.getName();
        }

        throw new Exception("Invalid field found: " + getFullColumnName());
    }

    /**
     * Gets the fnname.
     *
     * @return the fnname
     */
    public String getFnname()
    {
        return fnname;
    }

    /**
     * Sets the fnname.
     *
     * @param fnname
     *            the new fnname
     */
    public void setFnname(String fnname)
    {
        this.fnname = fnname;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy