1.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIParser.java Tue Dec 24 01:20:57 2013 +0100
1.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIParser.java Tue Dec 24 01:38:55 2013 +0100
1.3 @@ -87,7 +87,7 @@
1.4 arg = args[i];
1.5
1.6 if (arg.startsWith(options.getNamePrefix()) && arg.endsWith(options.getNameSuffix())) { // Named parameters:
1.7 - String paramName = arg.substring(options.getNamePrefix().length());
1.8 + String paramName = arg.substring(options.getNamePrefix().length(), arg.length() - options.getNameSuffix().length());
1.9 String paramValue = fetchNext(args, ++i);
1.10 options.addNamedParameter(new NamedParameter(paramName, paramValue, namedTypes.get(paramName)));
1.11 } else { // Numbered parameters:
2.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/NamedParameter.java Tue Dec 24 01:20:57 2013 +0100
2.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/NamedParameter.java Tue Dec 24 01:38:55 2013 +0100
2.3 @@ -17,11 +17,13 @@
2.4 */
2.5 package info.globalcode.sql.dk;
2.6
2.7 +import info.globalcode.sql.dk.configuration.NameIdentified;
2.8 +
2.9 /**
2.10 *
2.11 * @author Ing. František Kučera (frantovo.cz)
2.12 */
2.13 -public class NamedParameter extends Parameter {
2.14 +public class NamedParameter extends Parameter implements NameIdentified {
2.15
2.16 private String name;
2.17
2.18 @@ -37,4 +39,9 @@
2.19 public void setName(String name) {
2.20 this.name = name;
2.21 }
2.22 +
2.23 + @Override
2.24 + public String toString() {
2.25 + return "NamedParameter {" + name + " = " + getValue() + "; " + getType() + "}";
2.26 + }
2.27 }
3.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java Tue Dec 24 01:20:57 2013 +0100
3.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/SQLCommandNamed.java Tue Dec 24 01:38:55 2013 +0100
3.3 @@ -17,9 +17,16 @@
3.4 */
3.5 package info.globalcode.sql.dk;
3.6
3.7 +import static info.globalcode.sql.dk.Functions.notNull;
3.8 +import static info.globalcode.sql.dk.Functions.escapeRegEx;
3.9 +import static info.globalcode.sql.dk.Functions.findByName;
3.10 +import java.sql.Connection;
3.11 import java.sql.PreparedStatement;
3.12 import java.sql.SQLException;
3.13 +import java.util.ArrayList;
3.14 import java.util.List;
3.15 +import java.util.regex.Matcher;
3.16 +import java.util.regex.Pattern;
3.17
3.18 /**
3.19 *
3.20 @@ -27,16 +34,87 @@
3.21 */
3.22 public class SQLCommandNamed extends SQLCommand {
3.23
3.24 + private static final String PROBLEM_MARK = "<OMG>";
3.25 + private String namePrefix;
3.26 + private String nameSuffix;
3.27 private List<NamedParameter> parameters;
3.28 + private List<NamedParameter> parametersUsed = new ArrayList<>();
3.29 + private StringBuilder updatedQuery;
3.30 + private Pattern pattern;
3.31
3.32 - public SQLCommandNamed(String query, List<NamedParameter> parameters) {
3.33 + public SQLCommandNamed(String query, List<NamedParameter> parameters, String namePrefix, String nameSuffix) {
3.34 super(query);
3.35 + this.updatedQuery = new StringBuilder(query.length());
3.36 this.parameters = parameters;
3.37 + this.namePrefix = namePrefix;
3.38 + this.nameSuffix = nameSuffix;
3.39 + }
3.40 +
3.41 + @Override
3.42 + public PreparedStatement prepareStatement(Connection c) throws SQLException {
3.43 + buildPattern();
3.44 + placeParametersAndUpdateQuery();
3.45 + return c.prepareStatement(updatedQuery.toString());
3.46 }
3.47
3.48 @Override
3.49 public void parametrize(PreparedStatement ps) throws SQLException {
3.50 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
3.51 + int i = 1;
3.52 + for (Parameter p : notNull(parametersUsed)) {
3.53 + ps.setObject(i++, p.getValue(), p.getType());
3.54 + }
3.55 + }
3.56 +
3.57 + /**
3.58 + * Builds a regexp pattern that matches all parameter names (with prefix/suffix) and which has
3.59 + * one group: parameter name (without prefix/suffix)
3.60 + */
3.61 + private void buildPattern() {
3.62 + StringBuilder patternString = new StringBuilder();
3.63 +
3.64 + patternString.append(escapeRegEx(namePrefix));
3.65 + patternString.append("(");
3.66 + for (int i = 0; i < parameters.size(); i++) {
3.67 + patternString.append(escapeRegEx(parameters.get(i).getName()));
3.68 + if (i < parameters.size()) {
3.69 + patternString.append("|");
3.70 + }
3.71 + }
3.72 + patternString.append(")");
3.73 + patternString.append(escapeRegEx(nameSuffix));
3.74 +
3.75 + pattern = Pattern.compile(patternString.toString());
3.76 + }
3.77 +
3.78 + private void placeParametersAndUpdateQuery() throws SQLException {
3.79 + final String originalQuery = getQuery();
3.80 + Matcher m = pattern.matcher(originalQuery);
3.81 +
3.82 + int lastPosition = 0;
3.83 + while (m.find(lastPosition)) {
3.84 + String name = m.group(1);
3.85 +
3.86 + updatedQuery.append(originalQuery.substring(lastPosition, m.start()));
3.87 +
3.88 + if (name.isEmpty()) {
3.89 + updatedQuery.append(PROBLEM_MARK);
3.90 + updatedQuery.append(originalQuery.substring(m.end(), originalQuery.length()));
3.91 + throw new SQLException("Named parameter (near " + PROBLEM_MARK + ") is not defined: " + updatedQuery);
3.92 + }
3.93 +
3.94 + updatedQuery.append("?");
3.95 +
3.96 + parametersUsed.add(findByName(parameters, name));
3.97 +
3.98 + lastPosition = m.end();
3.99 + }
3.100 + updatedQuery.append(originalQuery.substring(lastPosition, originalQuery.length()));
3.101 +
3.102 + for (NamedParameter definedParameter : parameters) {
3.103 + if (findByName(parametersUsed, definedParameter.getName()) == null) {
3.104 + throw new SQLException("Parameter " + definedParameter.getName() + " is defined but not used in the query.");
3.105 + }
3.106 + }
3.107 }
3.108
3.109 @Override