diff -r 7e08730da258 -r 4a1864c3e867 java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java Mon Mar 04 17:06:42 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/** - * SQL-DK - * Copyright © 2013 František Kučera (frantovo.cz) - * - * 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 info.globalcode.sql.dk; - -import static info.globalcode.sql.dk.Functions.findByName; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * Has named parameters. - * - * @author Ing. František Kučera (frantovo.cz) - */ -public class SQLCommandNamed extends SQLCommand { - - private static final Logger log = Logger.getLogger(SQLCommandNamed.class.getName()); - private String namePrefix; - private String nameSuffix; - private List parameters; - private List parametersUsed = new ArrayList<>(); - private StringBuilder updatedQuery; - private Pattern pattern; - private SQLCommandNumbered numbered; - - public SQLCommandNamed(String query, List parameters, String namePrefix, String nameSuffix) { - super(query); - this.updatedQuery = new StringBuilder(query.length()); - this.parameters = parameters; - this.namePrefix = namePrefix; - this.nameSuffix = nameSuffix; - } - - @Override - public PreparedStatement prepareStatement(Connection c) throws SQLException { - return getSQLCommandNumbered().prepareStatement(c); - } - - @Override - public void parametrize(PreparedStatement ps) throws SQLException { - getSQLCommandNumbered().parametrize(ps); - } - - private void prepare() throws SQLException { - try { - buildPattern(); - placeParametersAndUpdateQuery(); - logPossiblyMissingParameters(); - } catch (PatternSyntaxException e) { - throw new SQLException("Name prefix „" + namePrefix + "“ or suffix „" + nameSuffix + "“ contain a wrong regular expression. " + e.getLocalizedMessage(), e); - } - } - - /** - * @return SQL command with named parameters converted to SQL command with numbered parameters - */ - public SQLCommandNumbered getSQLCommandNumbered() throws SQLException { - if (numbered == null) { - prepare(); - numbered = new SQLCommandNumbered(updatedQuery.toString(), parametersUsed); - } - - return numbered; - } - - /** - * Builds a regexp pattern that matches all parameter names (with prefix/suffix) and which has - * one group: parameter name (without prefix/suffix) - */ - private void buildPattern() throws PatternSyntaxException { - StringBuilder patternString = new StringBuilder(); - - patternString.append(namePrefix); - patternString.append("(?"); - for (int i = 0; i < parameters.size(); i++) { - patternString.append(Pattern.quote(parameters.get(i).getName())); - if (i < parameters.size() - 1) { - patternString.append("|"); - } - } - patternString.append(")"); - patternString.append(nameSuffix); - - pattern = Pattern.compile(patternString.toString()); - } - - private void placeParametersAndUpdateQuery() { - final String originalQuery = getQuery(); - Matcher m = pattern.matcher(originalQuery); - - int lastPosition = 0; - while (m.find(lastPosition)) { - String name = m.group("paramName"); - - updatedQuery.append(originalQuery.substring(lastPosition, m.start())); - updatedQuery.append("?"); - - parametersUsed.add(findByName(parameters, name)); - - lastPosition = m.end(); - } - updatedQuery.append(originalQuery.substring(lastPosition, originalQuery.length())); - - for (NamedParameter definedParameter : parameters) { - if (findByName(parametersUsed, definedParameter.getName()) == null) { - /** - * User can have predefined set of parameters and use them with different SQL - * queries that use only subset of these parameters → just warning, not exception. - */ - log.log(Level.WARNING, "Parameter „{0}“ is defined but not used in the query: „{1}“", new Object[]{definedParameter.getName(), originalQuery}); - } - } - } - - private void logPossiblyMissingParameters() { - Pattern p = Pattern.compile(namePrefix + "(?.+?)" + nameSuffix); - Matcher m = p.matcher(updatedQuery); - int lastPosition = 0; - while (m.find(lastPosition)) { - /** - * We have not parsed and understood the SQL query; the parameter-like looking string - * could be inside a literal part of the query → just warning, not exception. - */ - log.log(Level.WARNING, "Possibly missing parameter „{0}“ in the query: „{1}“", new Object[]{m.group("paramName"), getQuery()}); - lastPosition = m.end(); - } - } - - @Override - public List getParameters() { - return parameters; - } -}