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

com.googlecode.paradox.planner.plan.SelectUtils Maven / Gradle / Ivy

/*
 * Copyright (c) 2009 Leonardo Alves da Costa
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
 * later version. This program 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 General Public
 * License for more details. You should have received a copy of the GNU General Public License along with this
 * program. If not, see .
 */

package com.googlecode.paradox.planner.plan;

import com.googlecode.paradox.exceptions.ParadoxException;
import com.googlecode.paradox.parser.nodes.AbstractConditionalNode;
import com.googlecode.paradox.parser.nodes.AsteriskNode;
import com.googlecode.paradox.parser.nodes.SQLNode;
import com.googlecode.paradox.planner.nodes.*;
import com.googlecode.paradox.planner.nodes.join.ANDNode;
import com.googlecode.paradox.planner.nodes.join.AbstractJoinNode;
import com.googlecode.paradox.results.Column;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Utility class to reduce Select Plan complexity.
 *
 * @since 1.6.0
 */
public final class SelectUtils {
    /**
     * Utility class, not for use.
     */
    private SelectUtils() {
        // Not using.
    }

    /**
     * Add a AND clause to the plan tree.
     *
     * @param table  the plan table.
     * @param clause the clause to add.
     */
    public static void addAndClause(final PlanTableNode table, SQLNode clause) {
        if (table.getConditionalJoin() instanceof ANDNode) {
            // Exists and it is an AND node.
            table.getConditionalJoin().addChild(clause);
        } else if (table.getConditionalJoin() != null) {
            // Exists, but any other type.
            final ANDNode andNode = new ANDNode(table.getConditionalJoin(), null);
            andNode.addChild(clause);
            table.setConditionalJoin(andNode);
        } else {
            // There is no conditionals in this table.
            table.setConditionalJoin((AbstractConditionalNode) clause);
        }
    }

    /**
     * Add a column to the grouping function.
     *
     * @param column the column to add.
     * @return the function grouping node.
     */
    public static List getGroupingFunctions(final Column column) {
        final FunctionNode function = column.getFunction();
        if (function == null) {
            return Collections.emptyList();
        }

        return function.getGroupingNodes();
    }

    /**
     * Gets the conditional fields.
     *
     * @param table     the plan table.
     * @param condition the condition used to search.
     * @return the column set.
     */
    public static Set getConditionalFields(final PlanTableNode table, final AbstractConditionalNode condition) {
        if (condition != null) {
            return condition.getClauseFields().stream()
                    .filter(node -> table.isThis(node.getTableName()))
                    .map(table::findField)
                    .filter(Objects::nonNull)
                    .map(Column::new)
                    .collect(Collectors.toSet());
        }

        return Collections.emptySet();
    }

    /**
     * Add a JOIN clauses.
     *
     * @param node the node to add.
     * @return the conditional node.
     */
    public static AbstractConditionalNode joinClauses(final AbstractConditionalNode node) {
        AbstractConditionalNode ret = node;

        // It is an 'AND' and 'OR' node?
        if (node instanceof AbstractJoinNode) {
            final List children = node.getChildren();

            // Reduce all children.
            children.replaceAll(sqlNode -> joinClauses((AbstractConditionalNode) sqlNode));

            // Join only 'AND' and 'OR' nodes.
            while (ret instanceof AbstractJoinNode && ret.getChildren().size() <= 1) {
                if (ret.getChildren().isEmpty()) {
                    ret = null;
                } else {
                    ret = (AbstractConditionalNode) ret.getChildren().get(0);
                }
            }
        }

        return ret;
    }

    /**
     * Gets the fields from field node and plan tables.
     *
     * @param node   the field node.
     * @param tables the plan tables.
     * @return the column list.
     * @throws ParadoxException in case of failures.
     */
    public static List getParadoxFields(final FieldNode node, final List tables)
            throws ParadoxException {
        final List ret = new ArrayList<>();

        if (node instanceof FunctionNode) {
            final FunctionNode functionNode = (FunctionNode) node;

            // Create the column for the function.
            ret.add(new Column(functionNode));

            // Parses function fields in function parameters.
            for (final FieldNode field : functionNode.getClauseFields()) {
                ret.addAll(getParadoxFields(field, tables));
            }
        } else if (!(node instanceof ValueNode) && !(node instanceof ParameterNode)
                && !(node instanceof AsteriskNode)) {
            for (final PlanTableNode table : tables) {
                if (node.getTableName() == null || table.isThis(node.getTableName())) {
                    node.setTable(table.getTable());
                    ret.addAll(Arrays.stream(table.getTable().getFields())
                            .filter(f -> f.getName().equalsIgnoreCase(node.getName()))
                            .map(Column::new)
                            .collect(Collectors.toList()));
                }
            }

            if (ret.isEmpty()) {
                throw new ParadoxException(ParadoxException.Error.INVALID_COLUMN, node.getPosition(), node.toString());
            } else if (ret.size() > 1) {
                throw new ParadoxException(ParadoxException.Error.COLUMN_AMBIGUOUS_DEFINED, node.getPosition(),
                        node.toString());
            }
        }

        return ret;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy