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

org.eclipse.persistence.internal.expressions.ExtractOperator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     07/29/2022-4.0.0 Tomas Kraus - 1573: Fixed types returned by JPQL EXTRACT()
package org.eclipse.persistence.internal.expressions;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.helper.ClassConstants;

import java.util.ArrayList;
import java.util.List;

/**
 * Expression operator customization for {@code EXTRACT( FROM )}.
 * Contains support for platform specific native SQL override for individual {@code }
 * values.
 */
public class ExtractOperator extends ExpressionOperator {

    // Default native database Strings to be printed for EXTRACT expression
    private static List defaultDbStrings() {
        final List dbStrings = new ArrayList<>(5);
        dbStrings.add("EXTRACT(");
        dbStrings.add(" FROM ");
        dbStrings.add(")");
        return dbStrings;
    }

    /**
     * Creates an instance of {@link ExtractOperator} expression.
     * Default native database Strings are set for EXTRACT expression.
     */
    public ExtractOperator() {
        this(defaultDbStrings());
    }

    /**
     * Creates an instance of {@link ExtractOperator} expression.
     * Custom native database Strings are set for EXTRACT expression.
     *
     * @param dbStrings native database Strings
     */
    protected ExtractOperator(List dbStrings) {
        this.setType(ExpressionOperator.FunctionOperator);
        this.setSelector(ExpressionOperator.Extract);
        this.setName("EXTRACT");
        this.printsAs(dbStrings);
        this.setArgumentIndices(new int[] {1, 0});
        this.bePrefix();
        this.setNodeClass(ClassConstants.FunctionExpression_Class);
    }

    /**
     * Default SQL printer for {@code EXTRACT( FROM )}.
     * It expects 2 arguments (first, second), argument indices array of size 2
     * and 3 database Strings (prefix, arguments separator and suffix).
     * Indices swap first and second expression order by default.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    private void printPartSql(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        if (printer.getPlatform().isDynamicSQLRequiredForFunctions() && Boolean.FALSE.equals(isBindingSupported())) {
            printer.getCall().setUsesBinding(false);
        }
        final int[] indices = getArgumentIndices(2);
        final String[] dbString = getDatabaseStrings();
        int dbStringPos = 0;
        // Print 1st database String (prefix) if defined
        if (isPrefix() && dbString.length > dbStringPos) {
            printer.printString(dbString[dbStringPos++]);
        }
        // Print first or second argument depending on indices
        if (indices[0] == 0) {
            first.printSQL(printer);
        }
        if (indices[0] == 1) {
            second.printSQL(printer);
        }
        // Print 2nd database String (arguments separator) if defined
        if (dbString.length > dbStringPos) {
            printer.printString(dbString[dbStringPos++]);
        }
        // Print first or second argument depending on indices
        if (indices[1] == 0) {
            first.printSQL(printer);
        }
        if (indices[1] == 1) {
            second.printSQL(printer);
        }
        // Print 3rd database String (suffix) if defined
        if (dbString.length > dbStringPos) {
            printer.printString(dbString[dbStringPos]);
        }
    }

    /**
     * Printer for YEAR ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printYearSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for QUARTER ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printQuarterSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for MONTH ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printMonthSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for WEEK ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printWeekSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for DAY ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printDaySQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for HOUR ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printHourSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for MINUTE ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printMinuteSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    /**
     * Printer for SECOND ({@code } argument.
     * This method shall be overriden to implement platform specific SQL printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printSecondSQL(final Expression first, Expression second, final ExpressionSQLPrinter printer) {
        printPartSql(first, second, printer);
    }

    @Override
    public void printDuo(Expression first, Expression second, ExpressionSQLPrinter printer) {
        if (second.isLiteralExpression()) {
            switch (((LiteralExpression) second).getValue().toUpperCase()) {
                case "YEAR":
                    printYearSQL(first, second, printer);
                    return;
                case "QUARTER":
                    printQuarterSQL(first, second, printer);
                    return;
                case "MONTH":
                    printMonthSQL(first, second, printer);
                    return;
                case "WEEK":
                    printWeekSQL(first, second, printer);
                    return;
                case "DAY":
                    printDaySQL(first, second, printer);
                    return;
                case "HOUR":
                    printHourSQL(first, second, printer);
                    return;
                case "MINUTE":
                    printMinuteSQL(first, second, printer);
                    return;
                case "SECOND":
                    printSecondSQL(first, second, printer);
                    return;
                default:
                    throw new IllegalArgumentException("Unknown EXTRACT function datetime_field: "
                            + ((LiteralExpression) second).getValue().toUpperCase());
            }
        }
        super.printDuo(first, second, printer);
    }

    @Override
    public void printCollection(List items, ExpressionSQLPrinter printer) {
        if (items.size() == 2) {
            final Expression second = items.get(1);
            if (second.isLiteralExpression()) {
                switch (((LiteralExpression) second).getValue().toUpperCase()) {
                    case "YEAR":
                        printYearSQL(items.get(0), second, printer);
                        return;
                    case "QUARTER":
                        printQuarterSQL(items.get(0), second, printer);
                        return;
                    case "MONTH":
                        printMonthSQL(items.get(0), second, printer);
                        return;
                    case "WEEK":
                        printWeekSQL(items.get(0), second, printer);
                        return;
                    case "DAY":
                        printDaySQL(items.get(0), second, printer);
                        return;
                    case "HOUR":
                        printHourSQL(items.get(0), second, printer);
                        return;
                    case "MINUTE":
                        printMinuteSQL(items.get(0), second, printer);
                        return;
                    case "SECOND":
                        printSecondSQL(items.get(0), second, printer);
                        return;
                    default:
                        throw new IllegalArgumentException("Unknown EXTRACT function datetime_field: "
                                + ((LiteralExpression) second).getValue().toUpperCase());
                }
            }
        }
        super.printCollection(items, printer);
    }

    /**
     * Default Java printer for {@code EXTRACT( FROM )}.
     * It expects 2 arguments (first, second), argument indices array of size 2
     * and 3 database Strings (prefix, arguments separator and suffix).
     * Indices swap first and second expression order by default.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    private void printPartJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        final int[] indices = getArgumentIndices(2);
        final String[] dbString = getDatabaseStrings();
        // Print prefix from database Strings
        if (isPrefix()) {
            printer.printString(dbString[0]);
        }
        // Print first or second argument depending on indices
        if (indices[0] == 0) {
            first.printJava(printer);
        }
        if (indices[0] == 1) {
            second.printJava(printer);
        }
        // Print 2nd database String if defined
        if (dbString.length > 1) {
            printer.printString(dbString[1]);
        }
        // Print first or second argument depending on indices
        if (indices[1] == 0) {
            first.printJava(printer);
        }
        if (indices[1] == 1) {
            second.printJava(printer);
        }
        // Print 3rd database String if defined
        if (dbString.length > 2) {
            printer.printString(dbString[2]);
        }
    }

    /**
     * Printer for YEAR ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printYearJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for QUARTER ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printQuarterJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for MONTH ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printMonthJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for WEEK ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printWeekJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for DAY ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printDayJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for HOUR ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printHourJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for MINUTE ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printMinuteJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }

    /**
     * Printer for SECOND ({@code } argument.
     * This method shall be overriden to implement platform specific Java printer.
     *
     * @param first first expression ({@code } argument)
     * @param second second expression ({@code } argument)
     * @param printer target printer
     */
    protected void printSecondJava(final Expression first, Expression second, final ExpressionJavaPrinter printer) {
        printPartJava(first, second, printer);
    }


    @Override
    public void printJavaDuo(Expression first, Expression second, ExpressionJavaPrinter printer) {
        if (second.isLiteralExpression()) {
            switch (((LiteralExpression) second).getValue().toUpperCase()) {
                case "YEAR":
                    printYearJava(first, second, printer);
                    return;
                case "QUARTER":
                    printQuarterJava(first, second, printer);
                    return;
                case "MONTH":
                    printMonthJava(first, second, printer);
                    return;
                case "WEEK":
                    printWeekJava(first, second, printer);
                    return;
                case "DAY":
                    printDayJava(first, second, printer);
                    return;
                case "HOUR":
                    printHourJava(first, second, printer);
                    return;
                case "MINUTE":
                    printMinuteJava(first, second, printer);
                    return;
                case "SECOND":
                    printSecondJava(first, second, printer);
                    return;
                default:
                    throw new IllegalArgumentException("Unknown EXTRACT function datetime_field: "
                            + ((LiteralExpression) second).getValue().toUpperCase());
            }
        }
        super.printJavaDuo(first, second, printer);
    }

    @Override
    public void printJavaCollection(List items, ExpressionJavaPrinter printer) {
        if (items.size() == 2) {
            final Expression second = items.get(1);
            if (second.isLiteralExpression()) {
                switch (((LiteralExpression) second).getValue().toUpperCase()) {
                    case "YEAR":
                        printYearJava(items.get(0), second, printer);
                        return;
                    case "QUARTER":
                        printQuarterJava(items.get(0), second, printer);
                        return;
                    case "MONTH":
                        printMonthJava(items.get(0), second, printer);
                        return;
                    case "WEEK":
                        printWeekJava(items.get(0), second, printer);
                        return;
                    case "DAY":
                        printDayJava(items.get(0), second, printer);
                        return;
                    case "HOUR":
                        printHourJava(items.get(0), second, printer);
                        return;
                    case "MINUTE":
                        printMinuteJava(items.get(0), second, printer);
                        return;
                    case "SECOND":
                        printSecondJava(items.get(0), second, printer);
                        return;
                    default:
                        throw new IllegalArgumentException("Unknown EXTRACT function datetime_field: "
                                + ((LiteralExpression) second).getValue().toUpperCase());
                }
            }
        }
        super.printJavaCollection(items, printer);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy