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

javax0.jamal.sql.Select Maven / Gradle / Ivy

The newest version!
package javax0.jamal.sql;

import javax0.jamal.api.*;
import javax0.jamal.tools.IdentifiedObjectHolder;
import javax0.jamal.tools.Scanner;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Select implements Macro, Scanner, OptionsControlled {
    @Override
    public String evaluate(Input in, Processor processor) throws BadSyntax {
        final var scanner = newScanner(in, processor);
        final var resultName = SqlTools.getResultSetName(scanner);
        final var statementName = SqlTools.getStatementName(scanner);
        scanner.done();
        final var statementMacro = processor.getRegister().getUserDefined(statementName.get());
        BadSyntax.when(statementMacro.isEmpty(), "Statement is not prepared to execute select");
        BadSyntax.when(!(statementMacro.get() instanceof ObjectHolder), "Statement macro '%s' is not a statement,it does not hold object.", statementName.get());
        final var statement = ((ObjectHolder) statementMacro.get()).getObject();
        BadSyntax.when(!(statement instanceof Statement), "Statement macro '%s' is not a statement. It is an '%s'.", statementName.get(), statement.getClass().getName());
        final var sql = in.toString().trim();
        SqlTools.assertSqlSelectSafe(sql);
        try {
            final var resultSet = ((Statement) statement).executeQuery("SELECT " + sql);
            final var resultSetHolder = new ResultSetHolder(resultSet, resultName.get(), processor);
            processor.define(resultSetHolder);
        } catch (SQLException e) {
            throw new BadSyntax("Cannot execute 'select " + sql + "'", e);
        }
        return "";
    }

    @Override
    public String getId() {
        return "sql:select";
    }

    static class ResultSetHolder extends IdentifiedObjectHolder implements UserDefinedMacro, AutoCloseable {

        ResultSetHolder(final java.sql.ResultSet resultSet, final String name, final Processor processor) {
            super(resultSet, name);
            processor.deferredClose(this);
        }

        @Override
        public void close() throws Exception {
            getObject().close();
        }

        @Override
        public String evaluate(String... parameters) throws BadSyntax {
            BadSyntax.when(parameters.length < 1, "The column name or number is missing");
            var params = parameters[0].trim().split("\\s");
            var columnName = params[0];
            final String type = (parameters.length > 2 && "as".equals(parameters[1]))
                    ? parameters[2]
                    : (parameters.length > 1 ? parameters[1] : "string");

            final var resultSet = getObject();
            try {
                if (columnName.equals("next")) {
                    BadSyntax.when( params.length > 1, "Result set 'next' must ot have any parameter");
                    resultSet.next();
                    return "";
                }
                if (columnName.equals("close")) {
                    BadSyntax.when( params.length > 1, "Result set 'close' must ot have any parameter");
                    resultSet.close();
                    return "";
                }
                int columnNumber = 0;
                if (columnName.startsWith("\"") && columnName.endsWith("\"")) {
                    columnName = columnName.substring(1, columnName.length() - 1);
                } else if (columnName.matches("\\d+")) {
                    columnNumber = Integer.parseInt(columnName);
                    columnName = "";
                }
                switch (type) {
                    case "string":
                        return columnName.isEmpty() ? resultSet.getString(columnNumber) : resultSet.getString(columnName);
                    case "int":
                        return columnName.isEmpty() ? Integer.toString(resultSet.getInt(columnNumber)) : Integer.toString(resultSet.getInt(columnName));
                    case "long":
                        return columnName.isEmpty() ? Long.toString(resultSet.getLong(columnNumber)) : Long.toString(resultSet.getLong(columnName));
                    case "double":
                        return columnName.isEmpty() ? Double.toString(resultSet.getDouble(columnNumber)) : Double.toString(resultSet.getDouble(columnName));
                    case "float":
                        return columnName.isEmpty() ? Float.toString(resultSet.getFloat(columnNumber)) : Float.toString(resultSet.getFloat(columnName));
                    case "boolean":
                        return columnName.isEmpty() ? Boolean.toString(resultSet.getBoolean(columnNumber)) : Boolean.toString(resultSet.getBoolean(columnName));
                    case "date":
                        return columnName.isEmpty() ? resultSet.getDate(columnNumber).toString() : resultSet.getDate(columnName).toString();
                    case "time":
                        return columnName.isEmpty() ? resultSet.getTime(columnNumber).toString() : resultSet.getTime(columnName).toString();
                    case "timestamp":
                        return columnName.isEmpty() ? resultSet.getTimestamp(columnNumber).toString() : resultSet.getTimestamp(columnName).toString();
                    default:
                        throw BadSyntax.format( "Unknown type '%s'", type);
                }
            } catch (Exception e) {
                throw BadSyntax.format( "Cannot read column '%s' as '%s'", columnName, type);
            }
        }

        @Override
        public boolean isVerbatim() {
            return true;
        }

        @Override
        public int expectedNumberOfArguments() {
            return 1;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy