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

com.microsoft.sqlserver.jdbc.SQLServerFMTQuery Maven / Gradle / Ivy

There is a newer version: 12.8.1.jre11
Show newest version
/*
 * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
 * available under the terms of the MIT License. See the LICENSE file in the project root for more information.
 */

package com.microsoft.sqlserver.jdbc;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.Token;


class SQLServerFMTQuery {

    private static final String FMT_ON = "SET FMTONLY ON;";
    private static final String SELECT = "SELECT ";
    private static final String FROM = " FROM ";
    private static final String FMT_OFF = ";SET FMTONLY OFF;";

    private String prefix = "";
    private ArrayList tokenList = null;
    private List userColumns = new ArrayList<>();
    private List tableTarget = new ArrayList<>();
    private List possibleAliases = new ArrayList<>();
    private List> valuesList = new ArrayList<>();

    List getColumns() {
        return userColumns;
    }

    List getTableTarget() {
        return tableTarget;
    }

    List> getValuesList() {
        return valuesList;
    }

    List getAliases() {
        return possibleAliases;
    }

    /**
     * Takes the list of user parameters ('?') and appends their respective parsed column names together. In the case of
     * an INSERT INTO table VALUES(?,?,?...), we need to wait for the server to reply to know the column names. The
     * parser uses an '*' followed by placeholder '?'s to indicate these unknown columns, and we can't include the '?'s
     * in column targets. This method is used to generate the column targets in the FMT Select query: SELECT
     * {constructColumnTargets} FROM ... .
     */
    String constructColumnTargets() {
        if (userColumns.contains("?")) {
            return userColumns.stream().filter(s -> !s.equals("?")).map(s -> s.equals("") ? "NULL" : s)
                    .collect(Collectors.joining(","));
        } else {
            return userColumns.isEmpty() ? "*" : userColumns.stream().map(s -> s.equals("") ? "NULL" : s)
                    .collect(Collectors.joining(","));
        }
    }

    String constructTableTargets() {
        return tableTarget.stream().distinct().filter(s -> !possibleAliases.contains(s))
                .collect(Collectors.joining(","));
    }

    String getFMTQuery() {
        StringBuilder sb = new StringBuilder(FMT_ON);
        if (prefix != "") {
            sb.append(prefix);
        }
        sb.append(SELECT);
        sb.append(constructColumnTargets());
        if (!tableTarget.isEmpty()) {
            sb.append(FROM);
            sb.append(constructTableTargets());
        }
        sb.append(FMT_OFF);
        return sb.toString();
    }

    // Do not allow default instantiation, class must be used with sql query
    @SuppressWarnings("unused")
    private SQLServerFMTQuery() {};

    SQLServerFMTQuery(String userSql) throws SQLServerException {
        if (null == userSql || userSql.length() == 0) {
            SQLServerException.makeFromDriverError(null, this,
                    SQLServerResource.getResource("R_noTokensFoundInUserQuery"), "", false);
        }
        InputStream stream = new ByteArrayInputStream(userSql.getBytes(StandardCharsets.UTF_8));
        SQLServerLexer lexer = null;
        try {
            lexer = new SQLServerLexer(CharStreams.fromStream(stream));
        } catch (IOException e) {
            SQLServerException.makeFromDriverError(null, userSql, e.getLocalizedMessage(), "", false);
        }

        this.tokenList = (ArrayList) lexer.getAllTokens();
        if (tokenList.size() <= 0) {
            SQLServerException.makeFromDriverError(null, this,
                    SQLServerResource.getResource("R_noTokensFoundInUserQuery"), "", false);
        }
        SQLServerTokenIterator iter = new SQLServerTokenIterator(tokenList);
        this.prefix = SQLServerParser.getCTE(iter);
        SQLServerParser.parseQuery(iter, this);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy