|
11 | 11 | import java.math.BigDecimal;
|
12 | 12 | import java.nio.charset.StandardCharsets;
|
13 | 13 | import java.sql.Blob;
|
| 14 | +import java.sql.CallableStatement; |
14 | 15 | import java.sql.Clob;
|
15 | 16 | import java.sql.Connection;
|
16 | 17 | import java.sql.ParameterMetaData;
|
@@ -267,6 +268,7 @@ public Map<String, Object> connectAndCollectMetadata() throws Exception {
|
267 | 268 | public static class PreparedStmt {
|
268 | 269 | public String query;
|
269 | 270 | public Object[] arguments;
|
| 271 | + public Map<String, Object> callargs = new LinkedHashMap<>(); |
270 | 272 |
|
271 | 273 | /**
|
272 | 274 | * handle common casting issues when JSON parameters are fed into SQL
|
@@ -311,6 +313,7 @@ static PreparedStmt prepareStatement(String query, Map<String, Object> arguments
|
311 | 313 |
|
312 | 314 | String x = m.group().substring(2, m.group().length() - 1);
|
313 | 315 | args.add(arguments == null ? null : arguments.get(x));
|
| 316 | + ps.callargs.put(x, arguments == null ? null : arguments.get(x)); |
314 | 317 | ps.query = m.replaceFirst("?");
|
315 | 318 | }
|
316 | 319 | ps.arguments = args.toArray();
|
@@ -717,6 +720,55 @@ protected List<Map<String, Object>> query(QueryMeta info, Map<String, Object> ar
|
717 | 720 | List<Map<String, Object>> data = new ArrayList<>();
|
718 | 721 | List<Map<String, Object>> multidata = null;
|
719 | 722 | try (Connection con = getConnection(info)) {
|
| 723 | + |
| 724 | + // if one of the parameters has output=true, use CallableStatement API |
| 725 | + if (info.arguments != null) |
| 726 | + for (Object i : info.arguments.values()) |
| 727 | + if (i instanceof Map) { |
| 728 | + @SuppressWarnings({"unchecked"}) |
| 729 | + Map<String, Object> m = (Map<String, Object>) i; |
| 730 | + if (Boolean.TRUE.equals(m.get("output"))) { |
| 731 | + try (CallableStatement pstmt = con.prepareCall(ps.query)) { |
| 732 | + if (limit != null) |
| 733 | + pstmt.setMaxRows(limit); |
| 734 | + int idx = 1; |
| 735 | + for (Entry<String, Object> x : ps.callargs.entrySet()) |
| 736 | + if (x.getValue() == null) { |
| 737 | + @SuppressWarnings("unchecked") |
| 738 | + Map<String, Object> o = (Map<String, Object>) info.arguments.get(x.getKey()); |
| 739 | + String type = (String) o.get("type"); |
| 740 | + switch (type) { |
| 741 | + case "integer": |
| 742 | + pstmt.registerOutParameter(idx++, Types.INTEGER); |
| 743 | + break; |
| 744 | + case "number": |
| 745 | + pstmt.registerOutParameter(idx++, Types.DOUBLE); |
| 746 | + break; |
| 747 | + case "boolean": |
| 748 | + pstmt.registerOutParameter(idx++, Types.BOOLEAN); |
| 749 | + break; |
| 750 | + case "date": |
| 751 | + pstmt.registerOutParameter(idx++, Types.DATE); |
| 752 | + break; |
| 753 | + default: |
| 754 | + pstmt.registerOutParameter(idx++, Types.VARCHAR); |
| 755 | + } |
| 756 | + } else |
| 757 | + pstmt.setObject(idx++, x.getValue()); |
| 758 | + idx = 1; |
| 759 | + pstmt.execute(); |
| 760 | + Map<String, Object> row = new HashMap<>(); |
| 761 | + data.add(row); |
| 762 | + for (Entry<String, Object> x : ps.callargs.entrySet()) { |
| 763 | + if (x.getValue() == null) |
| 764 | + row.put(x.getKey(), pstmt.getObject(idx)); |
| 765 | + idx++; |
| 766 | + } |
| 767 | + } |
| 768 | + return data; |
| 769 | + } |
| 770 | + } |
| 771 | + |
720 | 772 | try (PreparedStatement pstmt = con.prepareStatement(ps.query)) {
|
721 | 773 | ps.cast(pstmt.getParameterMetaData());
|
722 | 774 | if (limit != null)
|
|
0 commit comments