16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 package info.globalcode.sql.dk; |
18 package info.globalcode.sql.dk; |
19 |
19 |
20 import static info.globalcode.sql.dk.Functions.notNull; |
20 import static info.globalcode.sql.dk.Functions.notNull; |
21 import static info.globalcode.sql.dk.Functions.escapeRegEx; |
|
22 import static info.globalcode.sql.dk.Functions.findByName; |
21 import static info.globalcode.sql.dk.Functions.findByName; |
23 import java.sql.Connection; |
22 import java.sql.Connection; |
24 import java.sql.PreparedStatement; |
23 import java.sql.PreparedStatement; |
25 import java.sql.SQLException; |
24 import java.sql.SQLException; |
26 import java.util.ArrayList; |
25 import java.util.ArrayList; |
27 import java.util.List; |
26 import java.util.List; |
|
27 import java.util.logging.Level; |
|
28 import java.util.logging.Logger; |
28 import java.util.regex.Matcher; |
29 import java.util.regex.Matcher; |
29 import java.util.regex.Pattern; |
30 import java.util.regex.Pattern; |
30 |
31 |
31 /** |
32 /** |
32 * |
33 * |
33 * @author Ing. František Kučera (frantovo.cz) |
34 * @author Ing. František Kučera (frantovo.cz) |
34 */ |
35 */ |
35 public class SQLCommandNamed extends SQLCommand { |
36 public class SQLCommandNamed extends SQLCommand { |
36 |
37 |
37 private static final String PROBLEM_MARK = "<OMG>"; |
38 private static final Logger log = Logger.getLogger(SQLCommandNamed.class.getName()); |
38 private String namePrefix; |
39 private String namePrefix; |
39 private String nameSuffix; |
40 private String nameSuffix; |
40 private List<NamedParameter> parameters; |
41 private List<NamedParameter> parameters; |
41 private List<NamedParameter> parametersUsed = new ArrayList<>(); |
42 private List<NamedParameter> parametersUsed = new ArrayList<>(); |
42 private StringBuilder updatedQuery; |
43 private StringBuilder updatedQuery; |
52 |
53 |
53 @Override |
54 @Override |
54 public PreparedStatement prepareStatement(Connection c) throws SQLException { |
55 public PreparedStatement prepareStatement(Connection c) throws SQLException { |
55 buildPattern(); |
56 buildPattern(); |
56 placeParametersAndUpdateQuery(); |
57 placeParametersAndUpdateQuery(); |
|
58 logPossiblyMissingParameters(); |
57 return c.prepareStatement(updatedQuery.toString()); |
59 return c.prepareStatement(updatedQuery.toString()); |
58 } |
60 } |
59 |
61 |
60 @Override |
62 @Override |
61 public void parametrize(PreparedStatement ps) throws SQLException { |
63 public void parametrize(PreparedStatement ps) throws SQLException { |
70 * one group: parameter name (without prefix/suffix) |
72 * one group: parameter name (without prefix/suffix) |
71 */ |
73 */ |
72 private void buildPattern() { |
74 private void buildPattern() { |
73 StringBuilder patternString = new StringBuilder(); |
75 StringBuilder patternString = new StringBuilder(); |
74 |
76 |
75 patternString.append(escapeRegEx(namePrefix)); |
77 patternString.append(Pattern.quote(namePrefix)); |
76 patternString.append("("); |
78 patternString.append("("); |
77 for (int i = 0; i < parameters.size(); i++) { |
79 for (int i = 0; i < parameters.size(); i++) { |
78 patternString.append(escapeRegEx(parameters.get(i).getName())); |
80 patternString.append(Pattern.quote(parameters.get(i).getName())); |
79 if (i < parameters.size()) { |
81 if (i < parameters.size() - 1) { |
80 patternString.append("|"); |
82 patternString.append("|"); |
81 } |
83 } |
82 } |
84 } |
83 patternString.append(")"); |
85 patternString.append(")"); |
84 patternString.append(escapeRegEx(nameSuffix)); |
86 patternString.append(Pattern.quote(nameSuffix)); |
85 |
87 |
86 pattern = Pattern.compile(patternString.toString()); |
88 pattern = Pattern.compile(patternString.toString()); |
87 } |
89 } |
88 |
90 |
89 private void placeParametersAndUpdateQuery() throws SQLException { |
91 private void placeParametersAndUpdateQuery() throws SQLException { |
93 int lastPosition = 0; |
95 int lastPosition = 0; |
94 while (m.find(lastPosition)) { |
96 while (m.find(lastPosition)) { |
95 String name = m.group(1); |
97 String name = m.group(1); |
96 |
98 |
97 updatedQuery.append(originalQuery.substring(lastPosition, m.start())); |
99 updatedQuery.append(originalQuery.substring(lastPosition, m.start())); |
98 |
|
99 if (name.isEmpty()) { |
|
100 updatedQuery.append(PROBLEM_MARK); |
|
101 updatedQuery.append(originalQuery.substring(m.end(), originalQuery.length())); |
|
102 throw new SQLException("Named parameter (near " + PROBLEM_MARK + ") is not defined: „" + updatedQuery + "“"); |
|
103 } |
|
104 |
|
105 updatedQuery.append("?"); |
100 updatedQuery.append("?"); |
106 |
101 |
107 parametersUsed.add(findByName(parameters, name)); |
102 parametersUsed.add(findByName(parameters, name)); |
108 |
103 |
109 lastPosition = m.end(); |
104 lastPosition = m.end(); |
115 throw new SQLException("Parameter „" + definedParameter.getName() + "“ is defined but not used in the query: „" + originalQuery + "“"); |
110 throw new SQLException("Parameter „" + definedParameter.getName() + "“ is defined but not used in the query: „" + originalQuery + "“"); |
116 } |
111 } |
117 } |
112 } |
118 } |
113 } |
119 |
114 |
|
115 private void logPossiblyMissingParameters() { |
|
116 Pattern p = Pattern.compile(Pattern.quote(namePrefix) + ".*?" + Pattern.quote(nameSuffix)); |
|
117 Matcher m = p.matcher(updatedQuery); |
|
118 int lastPosition = 0; |
|
119 while (m.find(lastPosition)) { |
|
120 |
|
121 log.log(Level.WARNING, "Possibly missing parameter: {0}", m.group()); |
|
122 lastPosition = m.end(); |
|
123 } |
|
124 } |
|
125 |
120 @Override |
126 @Override |
121 public List<NamedParameter> getParameters() { |
127 public List<NamedParameter> getParameters() { |
122 return parameters; |
128 return parameters; |
123 } |
129 } |
124 } |
130 } |