Mercurial > hg > monetdb-java
comparison src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @ 172:60063c67f9e7 embedded
Merged with default
author | Pedro Ferreira <pedro.ferreira@monetdbsolutions.com> |
---|---|
date | Tue, 19 Sep 2017 13:49:34 +0200 (2017-09-19) |
parents | 890dce2d5305 5c575fb21be0 |
children | 89c285fc0a49 |
comparison
equal
deleted
inserted
replaced
171:0f95fee3cf29 | 172:60063c67f9e7 |
---|---|
44 * [ "int", 9, 0 ] | 44 * [ "int", 9, 0 ] |
45 * [ "int", 9, 0 ] | 45 * [ "int", 9, 0 ] |
46 * </pre> | 46 * </pre> |
47 * | 47 * |
48 * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira | 48 * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira |
49 * @version 0.4 | 49 * @version 0.5v |
50 */ | 50 */ |
51 public class MonetPreparedStatement extends MonetStatement implements PreparedStatement { | 51 public class MonetPreparedStatement extends MonetStatement implements PreparedStatement, AutoCloseable { |
52 | 52 |
53 private final MonetConnection connection; | 53 private final MonetConnection connection; |
54 private final String[] monetdbType; | 54 private final String[] monetdbType; |
55 private final int[] javaType; | 55 private final int[] javaType; |
56 private final int[] digits; | 56 private final int[] digits; |
104 | 104 |
105 this.connection = connection; | 105 this.connection = connection; |
106 | 106 |
107 // fill the arrays | 107 // fill the arrays |
108 ResultSet rs = super.getResultSet(); | 108 ResultSet rs = super.getResultSet(); |
109 for (int i = 0; rs.next(); i++) { | 109 if (rs != null) { |
110 monetdbType[i] = rs.getString("type"); | 110 // System.out.println("After super.getResultSet();"); |
111 javaType[i] = MonetDriver.getJavaType(monetdbType[i]); | 111 int type_colnr = rs.findColumn("type"); |
112 digits[i] = rs.getInt("digits"); | 112 int digits_colnr = rs.findColumn("digits"); |
113 scale[i] = rs.getInt("scale"); | 113 int scale_colnr = rs.findColumn("scale"); |
114 if (rscolcnt == 3) | 114 int schema_colnr = rs.findColumn("schema"); |
115 continue; | 115 int table_colnr = rs.findColumn("table"); |
116 schema[i] = rs.getString("schema"); | 116 int column_colnr = rs.findColumn("column"); |
117 table[i] = rs.getString("table"); | 117 for (int i = 0; rs.next(); i++) { |
118 column[i] = rs.getString("column"); | 118 monetdbType[i] = rs.getString(type_colnr); |
119 } | 119 javaType[i] = MonetDriver.getJavaType(monetdbType[i]); |
120 rs.close(); | 120 digits[i] = rs.getInt(digits_colnr); |
121 scale[i] = rs.getInt(scale_colnr); | |
122 if (rscolcnt == 3) | |
123 continue; | |
124 schema[i] = rs.getString(schema_colnr); | |
125 table[i] = rs.getString(table_colnr); | |
126 column[i] = rs.getString(column_colnr); | |
127 /* when column[i] != null it is a result column of the prepared query, see getColumnIdx(int), | |
128 when column[i] == null it is a parameter for the prepared statement, see getParamIdx(int). */ | |
129 // System.out.println("column " + i + " has value: " + column[i]); | |
130 } | |
131 rs.close(); | |
132 } | |
121 | 133 |
122 // PreparedStatements are by default poolable | 134 // PreparedStatements are by default poolable |
123 poolable = true; | 135 poolable = true; |
124 | 136 |
125 mTimestampZ = connection.getProtocol().getMonetTimestampTz(); | 137 mTimestampZ = connection.getProtocol().getMonetTimestampTz(); |
236 * when not found | 248 * when not found |
237 */ | 249 */ |
238 private int getColumnIdx(int colnr) throws SQLException { | 250 private int getColumnIdx(int colnr) throws SQLException { |
239 int curcol = 0; | 251 int curcol = 0; |
240 for (int i = 0; i < size; i++) { | 252 for (int i = 0; i < size; i++) { |
253 /* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */ | |
241 if (column[i] == null) | 254 if (column[i] == null) |
242 continue; | 255 continue; |
243 curcol++; | 256 curcol++; |
244 if (curcol == colnr) | 257 if (curcol == colnr) |
245 return i; | 258 return i; |
252 * parameter number or an SQLException when not found | 265 * parameter number or an SQLException when not found |
253 */ | 266 */ |
254 private int getParamIdx(int paramnr) throws SQLException { | 267 private int getParamIdx(int paramnr) throws SQLException { |
255 int curparam = 0; | 268 int curparam = 0; |
256 for (int i = 0; i < size; i++) { | 269 for (int i = 0; i < size; i++) { |
270 /* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */ | |
257 if (column[i] != null) | 271 if (column[i] != null) |
258 continue; | 272 continue; |
259 curparam++; | 273 curparam++; |
260 if (curparam == paramnr) | 274 if (curparam == paramnr) |
261 return i; | 275 return i; |
798 | 812 |
799 /** | 813 /** |
800 * Sets the designated parameter to the given Array object. The | 814 * Sets the designated parameter to the given Array object. The |
801 * driver converts this to an SQL ARRAY value when it sends it to | 815 * driver converts this to an SQL ARRAY value when it sends it to |
802 * the database. | 816 * the database. |
803 * | 817 * |
804 * @param i the first parameter is 1, the second is 2, ... | 818 * @param parameterIndex the first parameter is 1, the second is 2, ... |
805 * @param x an Array object that maps an SQL ARRAY value | 819 * @param x an Array object that maps an SQL ARRAY value |
806 * @throws SQLException if a database access error occurs | 820 * @throws SQLException if a database access error occurs |
807 */ | 821 */ |
808 @Override | 822 @Override |
809 public void setArray(int i, Array x) throws SQLException { | 823 public void setArray(int parameterIndex, Array x) throws SQLException { |
810 throw newSQLFeatureNotSupportedException("setArray"); | 824 throw newSQLFeatureNotSupportedException("setArray"); |
811 } | 825 } |
812 | 826 |
813 /** | 827 /** |
814 * Sets the designated parameter to the given input stream, which will have | 828 * Sets the designated parameter to the given input stream, which will have |
880 /** | 894 /** |
881 * Sets the designated parameter to the given java.math.BigDecimal value. | 895 * Sets the designated parameter to the given java.math.BigDecimal value. |
882 * The driver converts this to an SQL NUMERIC value when it sends it to the | 896 * The driver converts this to an SQL NUMERIC value when it sends it to the |
883 * database. | 897 * database. |
884 * | 898 * |
885 * @param idx the first parameter is 1, the second is 2, ... | 899 * @param parameterIndex the first parameter is 1, the second is 2, ... |
886 * @param x the parameter value | 900 * @param x the parameter value |
887 * @throws SQLException if a database access error occurs | 901 * @throws SQLException if a database access error occurs |
888 */ | 902 */ |
889 @Override | 903 @Override |
890 public void setBigDecimal(int idx, BigDecimal x) throws SQLException { | 904 public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { |
891 // get array position | 905 // get array position |
892 int i = getParamIdx(idx); | 906 int i = getParamIdx(parameterIndex); |
893 | 907 |
894 // round to the scale of the DB: | 908 // round to the scale of the DB: |
895 x = x.setScale(scale[i], RoundingMode.HALF_UP); | 909 x = x.setScale(scale[i], RoundingMode.HALF_UP); |
896 | 910 |
897 // if precision is now greater than that of the db, throw an error: | 911 // if precision is now greater than that of the db, throw an error: |
908 int dot = xStr.indexOf('.'); | 922 int dot = xStr.indexOf('.'); |
909 if (dot >= 0) | 923 if (dot >= 0) |
910 xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i])); | 924 xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i])); |
911 while (xStr.startsWith("0") && xStr.length() > 1) | 925 while (xStr.startsWith("0") && xStr.length() > 1) |
912 xStr = xStr.substring(1); | 926 xStr = xStr.substring(1); |
913 setValue(idx, xStr); | 927 setValue(parameterIndex, xStr); |
914 } | 928 } |
915 | 929 |
916 /** | 930 /** |
917 * Sets the designated parameter to the given input stream, which will have | 931 * Sets the designated parameter to the given input stream, which will have |
918 * the specified number of bytes. When a very large binary value is input | 932 * the specified number of bytes. When a very large binary value is input |
981 /** | 995 /** |
982 * Sets the designated parameter to the given Blob object. The driver | 996 * Sets the designated parameter to the given Blob object. The driver |
983 * converts this to an SQL BLOB value when it sends it to the database. | 997 * converts this to an SQL BLOB value when it sends it to the database. |
984 * | 998 * |
985 * @param parameterIndex the first parameter is 1, the second is 2, ... | 999 * @param parameterIndex the first parameter is 1, the second is 2, ... |
986 * @param stream an object that contains the data to set the parameter value to | 1000 * @param x a Blob object that maps an SQL BLOB value |
987 * @throws SQLException if a database access error occurs | 1001 * @throws SQLException if a database access error occurs |
988 */ | 1002 */ |
989 @Override | 1003 @Override |
990 public void setBlob(int parameterIndex, InputStream stream) throws SQLException { | 1004 public void setBlob(int parameterIndex, InputStream x) throws SQLException { |
991 if (stream == null) { | 1005 if (x == null) { |
992 setNull(parameterIndex, -1); | 1006 setNull(parameterIndex, -1); |
993 return; | 1007 return; |
994 } | 1008 } |
995 // Some buffer. Size of 8192 is default for BufferedReader, so... | 1009 // Some buffer. Size of 8192 is default for BufferedReader, so... |
996 byte[] arr = new byte[8192]; | 1010 byte[] arr = new byte[8192]; |
997 ByteArrayOutputStream buf = new ByteArrayOutputStream(); | 1011 ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
998 int numChars; | 1012 int numChars; |
999 try { | 1013 try { |
1000 while ((numChars = stream.read(arr, 0, arr.length)) > 0) { | 1014 while ((numChars = x.read(arr, 0, arr.length)) > 0) { |
1001 buf.write(arr, 0, numChars); | 1015 buf.write(arr, 0, numChars); |
1002 } | 1016 } |
1003 setBytes(parameterIndex, buf.toByteArray()); | 1017 setBytes(parameterIndex, buf.toByteArray()); |
1004 } catch (IOException e) { | 1018 } catch (IOException e) { |
1005 throw new SQLException(e); | 1019 throw new SQLException(e); |
1033 * as a BLOB. When the setBinaryStream method is used, the driver | 1047 * as a BLOB. When the setBinaryStream method is used, the driver |
1034 * may have to do extra work to determine whether the parameter data | 1048 * may have to do extra work to determine whether the parameter data |
1035 * should be sent to the server as a LONGVARBINARY or a BLOB. | 1049 * should be sent to the server as a LONGVARBINARY or a BLOB. |
1036 * | 1050 * |
1037 * @param parameterIndex the first parameter is 1, the second is 2, ... | 1051 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1038 * @param stream an object that contains the data to set the parameter value to | 1052 * @param is an object that contains the data to set the parameter value to |
1039 * @param length the number of bytes in the parameter data | 1053 * @param length the number of bytes in the parameter data |
1040 * @throws SQLException if a database access error occurs | 1054 * @throws SQLException if a database access error occurs |
1041 */ | 1055 */ |
1042 @Override | 1056 @Override |
1043 public void setBlob(int parameterIndex, InputStream stream, long length) throws SQLException { | 1057 public void setBlob(int parameterIndex, InputStream is, long length) throws SQLException { |
1044 if (stream == null) { | 1058 if (is == null) { |
1045 setNull(parameterIndex, -1); | 1059 setNull(parameterIndex, -1); |
1046 return; | 1060 return; |
1047 } | 1061 } |
1048 try { | 1062 try { |
1049 byte[] arr = new byte[(int) length]; | 1063 byte[] arr = new byte[(int) length]; |
1050 ByteArrayOutputStream buf = new ByteArrayOutputStream((int) length); | 1064 ByteArrayOutputStream buf = new ByteArrayOutputStream((int) length); |
1051 | 1065 |
1052 int numChars = stream.read(arr, 0, (int) length); | 1066 int numChars = is.read(arr, 0, (int) length); |
1053 buf.write(arr, 0, numChars); | 1067 buf.write(arr, 0, numChars); |
1054 setBytes(parameterIndex, buf.toByteArray()); | 1068 setBytes(parameterIndex, buf.toByteArray()); |
1055 } catch (IOException e) { | 1069 } catch (IOException e) { |
1056 throw new SQLException(e); | 1070 throw new SQLException(e); |
1057 } | 1071 } |
1185 | 1199 |
1186 /** | 1200 /** |
1187 * Sets the designated parameter to the given Clob object. The driver | 1201 * Sets the designated parameter to the given Clob object. The driver |
1188 * converts this to an SQL CLOB value when it sends it to the database. | 1202 * converts this to an SQL CLOB value when it sends it to the database. |
1189 * | 1203 * |
1190 * @param i the first parameter is 1, the second is 2, ... | 1204 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1191 * @param x a Clob object that maps an SQL CLOB value | 1205 * @param x a Clob object that maps an SQL CLOB value |
1192 * @throws SQLException if a database access error occurs | 1206 * @throws SQLException if a database access error occurs |
1193 */ | 1207 */ |
1194 @Override | 1208 @Override |
1195 public void setClob(int i, Clob x) throws SQLException { | 1209 public void setClob(int parameterIndex, Clob x) throws SQLException { |
1196 if (x == null) { | 1210 if (x == null) { |
1197 setNull(i, -1); | 1211 setNull(parameterIndex, -1); |
1198 return; | 1212 return; |
1199 } | 1213 } |
1200 | 1214 |
1201 // simply serialise the CLOB into a variable for now... far from | 1215 // simply serialise the CLOB into a variable for now... far from |
1202 // efficient, but might work for a few cases... | 1216 // efficient, but might work for a few cases... |
1203 // be on your marks: we have to cast the length down! | 1217 // be on your marks: we have to cast the length down! |
1204 setString(i, x.getSubString(1L, (int)(x.length()))); | 1218 setString(parameterIndex, x.getSubString(1L, (int)(x.length()))); |
1205 } | 1219 } |
1206 | 1220 |
1207 /** | 1221 /** |
1208 * Sets the designated parameter to the given Clob object. The driver | 1222 * Sets the designated parameter to the given Clob object. The driver |
1209 * converts this to an SQL CLOB value when it sends it to the database. | 1223 * converts this to an SQL CLOB value when it sends it to the database. |
1210 * | 1224 * |
1211 * @param i the first parameter is 1, the second is 2, ... | 1225 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1212 * @param reader an object that contains the data to set the parameter | 1226 * @param reader an object that contains the data to set the parameter |
1213 * value to | 1227 * value to |
1214 * @throws SQLException if a database access error occurs | 1228 * @throws SQLException if a database access error occurs |
1215 */ | 1229 */ |
1216 @Override | 1230 @Override |
1217 public void setClob(int i, Reader reader) throws SQLException { | 1231 public void setClob(int parameterIndex, Reader reader) throws SQLException { |
1218 if (reader == null) { | 1232 if (reader == null) { |
1219 setNull(i, -1); | 1233 setNull(parameterIndex, -1); |
1220 return; | 1234 return; |
1221 } | 1235 } |
1222 // Some buffer. Size of 8192 is default for BufferedReader, so... | 1236 // Some buffer. Size of 8192 is default for BufferedReader, so... |
1223 char[] arr = new char[8192]; | 1237 char[] arr = new char[8192]; |
1224 StringBuilder buf = new StringBuilder(8192 * 8); | 1238 StringBuilder buf = new StringBuilder(8192 * 8); |
1225 int numChars; | 1239 int numChars; |
1226 try { | 1240 try { |
1227 while ((numChars = reader.read(arr, 0, arr.length)) > 0) { | 1241 while ((numChars = reader.read(arr, 0, arr.length)) > 0) { |
1228 buf.append(arr, 0, numChars); | 1242 buf.append(arr, 0, numChars); |
1229 } | 1243 } |
1230 setString(i, buf.toString()); | 1244 setString(parameterIndex, buf.toString()); |
1231 } catch (IOException e) { | 1245 } catch (IOException e) { |
1232 throw new SQLException(e); | 1246 throw new SQLException(e); |
1233 } | 1247 } |
1234 } | 1248 } |
1235 | 1249 |
1242 * parameter value should be sent to the server as a CLOB. When the | 1256 * parameter value should be sent to the server as a CLOB. When the |
1243 * setCharacterStream method is used, the driver may have to do | 1257 * setCharacterStream method is used, the driver may have to do |
1244 * extra work to determine whether the parameter data should be sent | 1258 * extra work to determine whether the parameter data should be sent |
1245 * to the server as a LONGVARCHAR or a CLOB. | 1259 * to the server as a LONGVARCHAR or a CLOB. |
1246 * | 1260 * |
1247 * @param i the first parameter is 1, the second is 2, ... | 1261 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1248 * @param reader An object that contains the data to set the | 1262 * @param reader An object that contains the data to set the |
1249 * parameter value to. | 1263 * parameter value to. |
1250 * @param length the number of characters in the parameter data. | 1264 * @param length the number of characters in the parameter data. |
1251 * @throws SQLException if a database access error occurs | 1265 * @throws SQLException if a database access error occurs |
1252 */ | 1266 */ |
1253 @Override | 1267 @Override |
1254 public void setClob(int i, Reader reader, long length) throws SQLException { | 1268 public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { |
1255 if (reader == null || length < 0) { | 1269 if (reader == null || length < 0) { |
1256 setNull(i, -1); | 1270 setNull(parameterIndex, -1); |
1257 return; | 1271 return; |
1258 } | 1272 } |
1259 // simply serialise the CLOB into a variable for now... far from | 1273 // simply serialise the CLOB into a variable for now... far from |
1260 // efficient, but might work for a few cases... | 1274 // efficient, but might work for a few cases... |
1261 CharBuffer buf = CharBuffer.allocate((int) length); // have to down cast :( | 1275 CharBuffer buf = CharBuffer.allocate((int) length); // have to down cast :( |
1265 throw new SQLException("failed to read from stream: " + | 1279 throw new SQLException("failed to read from stream: " + |
1266 e.getMessage(), "M1M25"); | 1280 e.getMessage(), "M1M25"); |
1267 } | 1281 } |
1268 // We have to rewind the buffer, because otherwise toString() returns "". | 1282 // We have to rewind the buffer, because otherwise toString() returns "". |
1269 buf.rewind(); | 1283 buf.rewind(); |
1270 setString(i, buf.toString()); | 1284 setString(parameterIndex, buf.toString()); |
1271 } | 1285 } |
1272 | 1286 |
1273 /** | 1287 /** |
1274 * Sets the designated parameter to the given java.sql.Date value. The | 1288 * Sets the designated parameter to the given java.sql.Date value. The |
1275 * driver converts this to an SQL DATE value when it sends it to the | 1289 * driver converts this to an SQL DATE value when it sends it to the |
1369 * Sets the designated parameter to a Reader object. The Reader | 1383 * Sets the designated parameter to a Reader object. The Reader |
1370 * reads the data till end-of-file is reached. The driver does the | 1384 * reads the data till end-of-file is reached. The driver does the |
1371 * necessary conversion from Java character format to the national | 1385 * necessary conversion from Java character format to the national |
1372 * character set in the database. | 1386 * character set in the database. |
1373 * | 1387 * |
1374 * @param i the first parameter is 1, the second is 2, ... | 1388 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1375 * @param value the parameter value | 1389 * @param value the parameter value |
1376 * @throws SQLException if a database access error occurs | 1390 * @throws SQLException if a database access error occurs |
1377 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1391 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1378 * not support this method | 1392 * not support this method |
1379 */ | 1393 */ |
1380 @Override | 1394 @Override |
1381 public void setNCharacterStream(int i, Reader value) throws SQLException { | 1395 public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { |
1382 throw newSQLFeatureNotSupportedException("setNCharacterStream"); | 1396 setCharacterStream(parameterIndex, value, 0); |
1383 } | 1397 } |
1384 | 1398 |
1385 /** | 1399 /** |
1386 * Sets the designated parameter to a Reader object. The Reader | 1400 * Sets the designated parameter to a Reader object. The Reader |
1387 * reads the data till end-of-file is reached. The driver does the | 1401 * reads the data till end-of-file is reached. The driver does the |
1388 * necessary conversion from Java character format to the national | 1402 * necessary conversion from Java character format to the national |
1389 * character set in the database. | 1403 * character set in the database. |
1390 * | 1404 * |
1391 * @param i the first parameter is 1, the second is 2, ... | 1405 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1392 * @param value the parameter value | 1406 * @param value the parameter value |
1393 * @param length the number of characters in the parameter data. | 1407 * @param length the number of characters in the parameter data. |
1394 * @throws SQLException if a database access error occurs | 1408 * @throws SQLException if a database access error occurs |
1395 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1409 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1396 * not support this method | 1410 * not support this method |
1397 */ | 1411 */ |
1398 @Override | 1412 @Override |
1399 public void setNCharacterStream(int i, Reader value, long length) throws SQLException { | 1413 public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { |
1400 throw newSQLFeatureNotSupportedException("setNCharacterStream"); | 1414 setCharacterStream(parameterIndex, value, length); |
1401 } | 1415 } |
1402 | 1416 |
1403 /** | 1417 /** |
1404 * Sets the designated parameter to a java.sql.NClob object. The | 1418 * Sets the designated parameter to a java.sql.NClob object. The |
1405 * driver converts this to a SQL NCLOB value when it sends it to the | 1419 * driver converts this to a SQL NCLOB value when it sends it to the |
1406 * database. | 1420 * database. |
1407 * | 1421 * |
1408 * @param i the first parameter is 1, the second is 2, ... | 1422 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1409 * @param value the parameter value | 1423 * @param value the parameter value |
1410 * @throws SQLException if a database access error occurs | 1424 * @throws SQLException if a database access error occurs |
1411 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1425 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1412 * not support this method | 1426 * not support this method |
1413 */ | 1427 */ |
1414 @Override | 1428 @Override |
1415 public void setNClob(int i, Reader value) throws SQLException { | 1429 public void setNClob(int parameterIndex, Reader value) throws SQLException { |
1416 throw newSQLFeatureNotSupportedException("setNClob"); | 1430 throw newSQLFeatureNotSupportedException("setNClob"); |
1417 } | 1431 } |
1418 | 1432 |
1419 /** | 1433 /** |
1420 * Sets the designated parameter to a java.sql.NClob object. The | 1434 * Sets the designated parameter to a java.sql.NClob object. The |
1421 * driver converts this to a SQL NCLOB value when it sends it to the | 1435 * driver converts this to a SQL NCLOB value when it sends it to the |
1422 * database. | 1436 * database. |
1423 * | 1437 * |
1424 * @param i the first parameter is 1, the second is 2, ... | 1438 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1425 * @param value the parameter value | 1439 * @param value the parameter value |
1426 * @throws SQLException if a database access error occurs | 1440 * @throws SQLException if a database access error occurs |
1427 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1441 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1428 * not support this method | 1442 * not support this method |
1429 */ | 1443 */ |
1430 @Override | 1444 @Override |
1431 public void setNClob(int i, NClob value) throws SQLException { | 1445 public void setNClob(int parameterIndex, NClob value) throws SQLException { |
1432 throw newSQLFeatureNotSupportedException("setNClob"); | 1446 throw newSQLFeatureNotSupportedException("setNClob"); |
1433 } | 1447 } |
1434 | 1448 |
1435 /** | 1449 /** |
1436 * Sets the designated parameter to a Reader object. The reader must | 1450 * Sets the designated parameter to a Reader object. The reader must |
1441 * parameter value should be sent to the server as a NCLOB. When the | 1455 * parameter value should be sent to the server as a NCLOB. When the |
1442 * setCharacterStream method is used, the driver may have to do | 1456 * setCharacterStream method is used, the driver may have to do |
1443 * extra work to determine whether the parameter data should be sent | 1457 * extra work to determine whether the parameter data should be sent |
1444 * to the server as a LONGNVARCHAR or a NCLOB. | 1458 * to the server as a LONGNVARCHAR or a NCLOB. |
1445 * | 1459 * |
1446 * @param i the first parameter is 1, the second is 2, ... | 1460 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1447 * @param r An object that contains the data to set the parameter | 1461 * @param r An object that contains the data to set the parameter |
1448 * value to | 1462 * value to |
1449 * @param length the number of characters in the parameter data | 1463 * @param length the number of characters in the parameter data |
1450 * @throws SQLException if a database access error occurs | 1464 * @throws SQLException if a database access error occurs |
1451 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1465 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1452 * not support this method | 1466 * not support this method |
1453 */ | 1467 */ |
1454 @Override | 1468 @Override |
1455 public void setNClob(int i, Reader r, long length) throws SQLException { | 1469 public void setNClob(int parameterIndex, Reader r, long length) throws SQLException { |
1456 throw newSQLFeatureNotSupportedException("setNClob"); | 1470 throw newSQLFeatureNotSupportedException("setNClob"); |
1457 } | 1471 } |
1458 | 1472 |
1459 /** | 1473 /** |
1460 * Sets the designated paramter to the given String object. The | 1474 * Sets the designated paramter to the given String object. The |
1461 * driver converts this to a SQL NCHAR or NVARCHAR or LONGNVARCHAR | 1475 * driver converts this to a SQL NCHAR or NVARCHAR or LONGNVARCHAR |
1462 * value (depending on the argument's size relative to the driver's | 1476 * value (depending on the argument's size relative to the driver's |
1463 * limits on NVARCHAR values) when it sends it to the database. | 1477 * limits on NVARCHAR values) when it sends it to the database. |
1464 * | 1478 * |
1465 * @param i the first parameter is 1, the second is 2, ... | 1479 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1466 * @param value the parameter value | 1480 * @param value the parameter value |
1467 * @throws SQLException if a database access error occurs | 1481 * @throws SQLException if a database access error occurs |
1468 * @throws SQLFeatureNotSupportedException the JDBC driver does | 1482 * @throws SQLFeatureNotSupportedException the JDBC driver does |
1469 * not support this method | 1483 * not support this method |
1470 */ | 1484 */ |
1471 @Override | 1485 @Override |
1472 public void setNString(int i, String value) throws SQLException { | 1486 public void setNString(int parameterIndex, String value) throws SQLException { |
1473 throw newSQLFeatureNotSupportedException("setNString"); | 1487 setString(parameterIndex, value); |
1474 } | 1488 } |
1475 | 1489 |
1476 /** | 1490 /** |
1477 * Sets the designated parameter to SQL NULL. | 1491 * Sets the designated parameter to SQL NULL. |
1478 * | 1492 * |
1503 * type name information, it may ignore it. Although it is intended for | 1517 * type name information, it may ignore it. Although it is intended for |
1504 * user-defined and Ref parameters, this method may be used to set a null | 1518 * user-defined and Ref parameters, this method may be used to set a null |
1505 * parameter of any JDBC type. If the parameter does not have a | 1519 * parameter of any JDBC type. If the parameter does not have a |
1506 * user-defined or REF type, the given typeName is ignored. | 1520 * user-defined or REF type, the given typeName is ignored. |
1507 * | 1521 * |
1508 * @param paramIndex the first parameter is 1, the second is 2, ... | 1522 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1509 * @param sqlType a value from java.sql.Types | 1523 * @param sqlType a value from java.sql.Types |
1510 * @param typeName the fully-qualified name of an SQL user-defined type; | 1524 * @param typeName the fully-qualified name of an SQL user-defined type; |
1511 * ignored if the parameter is not a user-defined type or | 1525 * ignored if the parameter is not a user-defined type or |
1512 * REF | 1526 * REF |
1513 * @throws SQLException if a database access error occurs | 1527 * @throws SQLException if a database access error occurs |
1514 */ | 1528 */ |
1515 @Override | 1529 @Override |
1516 public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException { | 1530 public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { |
1517 // MonetDB/SQL's NULL needs no type | 1531 // MonetDB/SQL's NULL needs no type |
1518 setNull(paramIndex, sqlType); | 1532 setNull(parameterIndex, sqlType); |
1519 } | 1533 } |
1520 | 1534 |
1521 /** | 1535 /** |
1522 * Sets the value of the designated parameter using the given | 1536 * Sets the value of the designated parameter using the given |
1523 * object. The second parameter must be of type Object; therefore, | 1537 * object. The second parameter must be of type Object; therefore, |
1538 * | 1552 * |
1539 * This method throws an exception if there is an ambiguity, for | 1553 * This method throws an exception if there is an ambiguity, for |
1540 * example, if the object is of a class implementing more than one | 1554 * example, if the object is of a class implementing more than one |
1541 * of the interfaces named above. | 1555 * of the interfaces named above. |
1542 * | 1556 * |
1543 * @param index the first parameter is 1, the second is 2, ... | 1557 * @param parameterIndex the first parameter is 1, the second is 2, ... |
1544 * @param x the object containing the input parameter value | 1558 * @param x the object containing the input parameter value |
1545 * @throws SQLException if a database access error occurs or the type of | 1559 * @throws SQLException if a database access error occurs or the type of |
1546 * the given object is ambiguous | 1560 * the given object is ambiguous |
1547 */ | 1561 */ |
1548 @Override | 1562 @Override |
1549 public void setObject(int index, Object x) throws SQLException { | 1563 public void setObject(int parameterIndex, Object x) throws SQLException { |
1550 setObject(index, x, javaType[getParamIdx(index)]); | 1564 setObject(parameterIndex, x, javaType[getParamIdx(parameterIndex)], 0); |
1551 } | 1565 } |
1552 | 1566 |
1553 /** | 1567 /** |
1554 * Sets the value of the designated parameter with the given object. This | 1568 * Sets the value of the designated parameter with the given object. This |
1555 * method is like the method setObject below, except that it assumes a scale | 1569 * method is like the method setObject below, except that it assumes a scale |
1598 * ignored. | 1612 * ignored. |
1599 * @throws SQLException if a database access error occurs | 1613 * @throws SQLException if a database access error occurs |
1600 * @see Types | 1614 * @see Types |
1601 */ | 1615 */ |
1602 @Override | 1616 @Override |
1603 public void setObject( | 1617 public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException { |
1604 int parameterIndex, | 1618 if (x == null) { |
1605 Object x, | 1619 setNull(parameterIndex, -1); |
1606 int targetSqlType, | 1620 return; |
1607 int scale) | 1621 } |
1608 throws SQLException | |
1609 { | |
1610 // this is according to table B-5 | 1622 // this is according to table B-5 |
1611 if (x instanceof String) { | 1623 if (x instanceof String) { |
1612 switch (targetSqlType) { | 1624 setString(parameterIndex, (String)x); |
1613 case Types.CHAR: | |
1614 case Types.VARCHAR: | |
1615 case Types.LONGVARCHAR: | |
1616 case Types.CLOB: | |
1617 setString(parameterIndex, (String)x); | |
1618 break; | |
1619 case Types.TINYINT: | |
1620 case Types.SMALLINT: | |
1621 case Types.INTEGER: | |
1622 { | |
1623 int val; | |
1624 try { | |
1625 val = Integer.parseInt((String)x); | |
1626 } catch (NumberFormatException e) { | |
1627 val = 0; | |
1628 } | |
1629 setInt(parameterIndex, val); | |
1630 } break; | |
1631 case Types.BIGINT: | |
1632 { | |
1633 long val; | |
1634 try { | |
1635 val = Long.parseLong((String)x); | |
1636 } catch (NumberFormatException e) { | |
1637 val = 0; | |
1638 } | |
1639 setLong(parameterIndex, val); | |
1640 } break; | |
1641 case Types.REAL: | |
1642 { | |
1643 float val; | |
1644 try { | |
1645 val = Float.parseFloat((String)x); | |
1646 } catch (NumberFormatException e) { | |
1647 val = 0; | |
1648 } | |
1649 setFloat(parameterIndex, val); | |
1650 } break; | |
1651 case Types.FLOAT: | |
1652 case Types.DOUBLE: | |
1653 { | |
1654 double val; | |
1655 try { | |
1656 val = Double.parseDouble((String)x); | |
1657 } catch (NumberFormatException e) { | |
1658 val = 0; | |
1659 } | |
1660 setDouble(parameterIndex, val); | |
1661 } break; | |
1662 case Types.DECIMAL: | |
1663 case Types.NUMERIC: | |
1664 { | |
1665 BigDecimal val; | |
1666 try { | |
1667 val = new BigDecimal((String)x); | |
1668 } catch (NumberFormatException e) { | |
1669 try { | |
1670 val = new BigDecimal(0.0); | |
1671 } catch (NumberFormatException ex) { | |
1672 throw new SQLException("Internal error: unable to create template BigDecimal: " + ex.getMessage(), "M0M03"); | |
1673 } | |
1674 } | |
1675 val = val.setScale(scale, BigDecimal.ROUND_HALF_UP); | |
1676 setBigDecimal(parameterIndex, val); | |
1677 } break; | |
1678 case Types.BIT: | |
1679 case Types.BOOLEAN: | |
1680 setBoolean(parameterIndex, (Boolean.valueOf((String)x)).booleanValue()); | |
1681 break; | |
1682 case Types.BINARY: | |
1683 case Types.VARBINARY: | |
1684 case Types.LONGVARBINARY: | |
1685 setBytes(parameterIndex, ((String)x).getBytes()); | |
1686 break; | |
1687 case Types.DATE: | |
1688 { | |
1689 java.sql.Date val; | |
1690 try { | |
1691 val = java.sql.Date.valueOf((String)x); | |
1692 } catch (IllegalArgumentException e) { | |
1693 val = new java.sql.Date(0L); | |
1694 } | |
1695 setDate(parameterIndex, val); | |
1696 } break; | |
1697 case Types.TIME: | |
1698 { | |
1699 Time val; | |
1700 try { | |
1701 val = Time.valueOf((String)x); | |
1702 } catch (IllegalArgumentException e) { | |
1703 val = new Time(0L); | |
1704 } | |
1705 setTime(parameterIndex, val); | |
1706 } break; | |
1707 case Types.TIMESTAMP: | |
1708 { | |
1709 Timestamp val; | |
1710 try { | |
1711 val = Timestamp.valueOf((String)x); | |
1712 } catch (IllegalArgumentException e) { | |
1713 val = new Timestamp(0L); | |
1714 } | |
1715 setTimestamp(parameterIndex, val); | |
1716 } break; | |
1717 case Types.NCHAR: | |
1718 case Types.NVARCHAR: | |
1719 case Types.LONGNVARCHAR: | |
1720 throw newSQLFeatureNotSupportedException("setObject() with targetType N[VAR]CHAR"); | |
1721 default: | |
1722 throw new SQLException("Conversion not allowed", "M1M05"); | |
1723 } | |
1724 } else if (x instanceof BigDecimal || | 1625 } else if (x instanceof BigDecimal || |
1725 x instanceof Byte || | 1626 x instanceof Byte || |
1726 x instanceof Short || | 1627 x instanceof Short || |
1727 x instanceof Integer || | 1628 x instanceof Integer || |
1728 x instanceof Long || | 1629 x instanceof Long || |
1877 setDate(parameterIndex, new java.sql.Date(((Timestamp)x).getTime())); | 1778 setDate(parameterIndex, new java.sql.Date(((Timestamp)x).getTime())); |
1878 } else if (x instanceof java.util.Date) { | 1779 } else if (x instanceof java.util.Date) { |
1879 setDate(parameterIndex, new java.sql.Date( | 1780 setDate(parameterIndex, new java.sql.Date( |
1880 ((java.util.Date)x).getTime())); | 1781 ((java.util.Date)x).getTime())); |
1881 } else if (x instanceof Calendar) { | 1782 } else if (x instanceof Calendar) { |
1882 setDate(parameterIndex, new java.sql.Date( | 1783 setDate(parameterIndex, new java.sql.Date(((Calendar)x).getTimeInMillis())); |
1883 ((Calendar)x).getTimeInMillis())); | |
1884 } else { | 1784 } else { |
1885 throw new SQLException("Conversion not allowed", "M1M05"); | 1785 throw new SQLException("Conversion not allowed", "M1M05"); |
1886 } | 1786 } |
1887 break; | 1787 break; |
1888 case Types.TIME: | 1788 case Types.TIME: |
1789 case 2013: //Types.TIME_WITH_TIMEZONE: | |
1889 if (x instanceof Time) { | 1790 if (x instanceof Time) { |
1890 setTime(parameterIndex, (Time)x); | 1791 setTime(parameterIndex, (Time)x); |
1891 } else if (x instanceof Timestamp) { | 1792 } else if (x instanceof Timestamp) { |
1892 setTime(parameterIndex, new Time(((Timestamp)x).getTime())); | 1793 setTime(parameterIndex, new Time(((Timestamp)x).getTime())); |
1893 } else if (x instanceof java.util.Date) { | 1794 } else if (x instanceof java.util.Date) { |
1894 setTime(parameterIndex, new java.sql.Time( | 1795 setTime(parameterIndex, new java.sql.Time( |
1895 ((java.util.Date)x).getTime())); | 1796 ((java.util.Date)x).getTime())); |
1896 } else if (x instanceof Calendar) { | 1797 } else if (x instanceof Calendar) { |
1897 setTime(parameterIndex, new java.sql.Time( | 1798 setTime(parameterIndex, new java.sql.Time(((Calendar)x).getTimeInMillis())); |
1898 ((Calendar)x).getTimeInMillis())); | |
1899 } else { | 1799 } else { |
1900 throw new SQLException("Conversion not allowed", "M1M05"); | 1800 throw new SQLException("Conversion not allowed", "M1M05"); |
1901 } | 1801 } |
1902 break; | 1802 break; |
1903 case Types.TIMESTAMP: | 1803 case Types.TIMESTAMP: |
1804 case 2014: //Types.TIMESTAMP_WITH_TIMEZONE: | |
1904 if (x instanceof Timestamp) { | 1805 if (x instanceof Timestamp) { |
1905 setTimestamp(parameterIndex, (Timestamp)x); | 1806 setTimestamp(parameterIndex, (Timestamp)x); |
1906 } else if (x instanceof java.sql.Date) { | 1807 } else if (x instanceof java.sql.Date) { |
1907 setTimestamp(parameterIndex, new Timestamp(((java.sql.Date)x).getTime())); | 1808 setTimestamp(parameterIndex, new Timestamp(((java.sql.Date)x).getTime())); |
1908 } else if (x instanceof java.util.Date) { | 1809 } else if (x instanceof java.util.Date) { |
1909 setTimestamp(parameterIndex, new java.sql.Timestamp( | 1810 setTimestamp(parameterIndex, new java.sql.Timestamp( |
1910 ((java.util.Date)x).getTime())); | 1811 ((java.util.Date)x).getTime())); |
1911 } else if (x instanceof Calendar) { | 1812 } else if (x instanceof Calendar) { |
1912 setTimestamp(parameterIndex, new java.sql.Timestamp( | 1813 setTimestamp(parameterIndex, new java.sql.Timestamp(((Calendar)x).getTimeInMillis())); |
1913 ((Calendar)x).getTimeInMillis())); | |
1914 } else { | 1814 } else { |
1915 throw new SQLException("Conversion not allowed", "M1M05"); | 1815 throw new SQLException("Conversion not allowed", "M1M05"); |
1916 } | 1816 } |
1917 break; | 1817 break; |
1918 case Types.CHAR: | 1818 case Types.CHAR: |
1924 default: | 1824 default: |
1925 throw new SQLException("Conversion not allowed", "M1M05"); | 1825 throw new SQLException("Conversion not allowed", "M1M05"); |
1926 } | 1826 } |
1927 } else if (x instanceof Array) { | 1827 } else if (x instanceof Array) { |
1928 setArray(parameterIndex, (Array)x); | 1828 setArray(parameterIndex, (Array)x); |
1929 } else if (x instanceof Blob) { | 1829 } else if (x instanceof Blob || x instanceof MonetBlob) { |
1930 setBlob(parameterIndex, (Blob)x); | 1830 setBlob(parameterIndex, (Blob)x); |
1931 } else if (x instanceof Clob) { | 1831 } else if (x instanceof Clob || x instanceof MonetClob) { |
1932 setClob(parameterIndex, (Clob)x); | 1832 setClob(parameterIndex, (Clob)x); |
1933 } else if (x instanceof Struct) { | 1833 } else if (x instanceof Struct) { |
1934 // I have no idea how to do this... | 1834 // I have no idea how to do this... |
1935 throw newSQLFeatureNotSupportedException("setObject() with object of type Struct"); | 1835 throw newSQLFeatureNotSupportedException("setObject() with object of type Struct"); |
1936 } else if (x instanceof Ref) { | 1836 } else if (x instanceof Ref) { |
1937 setRef(parameterIndex, (Ref)x); | 1837 setRef(parameterIndex, (Ref)x); |
1938 } else if (x instanceof java.net.URL) { | 1838 } else if (x instanceof java.net.URL) { |
1939 setURL(parameterIndex, (java.net.URL)x); | 1839 setURL(parameterIndex, (java.net.URL)x); |
1840 } else if (x instanceof java.util.UUID) { | |
1841 setString(parameterIndex, x.toString()); | |
1940 } else if (x instanceof RowId) { | 1842 } else if (x instanceof RowId) { |
1941 setRowId(parameterIndex, (RowId)x); | 1843 setRowId(parameterIndex, (RowId)x); |
1942 } else if (x instanceof NClob) { | 1844 } else if (x instanceof NClob) { |
1943 throw newSQLFeatureNotSupportedException("setObject() with object of type NClob"); | 1845 setNClob(parameterIndex, (NClob)x); |
1944 } else if (x instanceof SQLXML) { | 1846 } else if (x instanceof SQLXML) { |
1945 throw newSQLFeatureNotSupportedException("setObject() with object of type SQLXML"); | 1847 setSQLXML(parameterIndex, (SQLXML)x); |
1946 } else if (x instanceof SQLData) { // not in JDBC4.1??? | 1848 } else if (x instanceof SQLData) { // not in JDBC4.1??? |
1947 SQLData sx = (SQLData)x; | 1849 SQLData sx = (SQLData)x; |
1948 final int paramnr = parameterIndex; | 1850 final int paramnr = parameterIndex; |
1949 final String sqltype = sx.getSQLTypeName(); | 1851 final String sqltype = sx.getSQLTypeName(); |
1950 SQLOutput out = new SQLOutput() { | 1852 SQLOutput out = new SQLOutput() { |
2020 setTimestamp(paramnr, x); | 1922 setTimestamp(paramnr, x); |
2021 } | 1923 } |
2022 | 1924 |
2023 @Override | 1925 @Override |
2024 public void writeCharacterStream(Reader x) throws SQLException { | 1926 public void writeCharacterStream(Reader x) throws SQLException { |
2025 setCharacterStream(paramnr, x); | 1927 setCharacterStream(paramnr, x, 0); |
2026 } | 1928 } |
2027 | 1929 |
2028 @Override | 1930 @Override |
2029 public void writeAsciiStream(InputStream x) throws SQLException { | 1931 public void writeAsciiStream(InputStream x) throws SQLException { |
2030 setAsciiStream(paramnr, x); | 1932 setAsciiStream(paramnr, x); |
2090 setSQLXML(paramnr, x); | 1992 setSQLXML(paramnr, x); |
2091 } | 1993 } |
2092 }; | 1994 }; |
2093 sx.writeSQL(out); | 1995 sx.writeSQL(out); |
2094 } else { // java Class | 1996 } else { // java Class |
2095 throw newSQLFeatureNotSupportedException("setObject() with object of type Class"); | 1997 throw newSQLFeatureNotSupportedException("setObject() with object of type Class " + x.getClass().getName()); |
2096 } | 1998 } |
2097 } | 1999 } |
2098 | 2000 |
2099 /** | 2001 /** |
2100 * Sets the designated parameter to the given REF(<structured-type>) value. | 2002 * Sets the designated parameter to the given REF(<structured-type>) value. |
2101 * The driver converts this to an SQL REF value when it sends it to the | 2003 * The driver converts this to an SQL REF value when it sends it to the |
2102 * database. | 2004 * database. |
2103 * | 2005 * |
2104 * @param i the first parameter is 1, the second is 2, ... | 2006 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2105 * @param x an SQL REF value | 2007 * @param x an SQL REF value |
2106 * @throws SQLException if a database access error occurs | 2008 * @throws SQLException if a database access error occurs |
2107 * @throws SQLFeatureNotSupportedException the JDBC driver does | 2009 * @throws SQLFeatureNotSupportedException the JDBC driver does |
2108 * not support this method | 2010 * not support this method |
2109 */ | 2011 */ |
2110 @Override | 2012 @Override |
2111 public void setRef(int i, Ref x) throws SQLException { | 2013 public void setRef(int parameterIndex, Ref x) throws SQLException { |
2112 throw newSQLFeatureNotSupportedException("setRef"); | 2014 throw newSQLFeatureNotSupportedException("setRef"); |
2113 } | 2015 } |
2114 | 2016 |
2115 /** | 2017 /** |
2116 * Sets the designated parameter to the given java.sql.RowId object. | 2018 * Sets the designated parameter to the given java.sql.RowId object. |
2117 * The driver converts this to a SQL ROWID value when it sends it to | 2019 * The driver converts this to a SQL ROWID value when it sends it to |
2118 * the database. | 2020 * the database. |
2119 * | 2021 * |
2120 * @param i the first parameter is 1, the second is 2, ... | 2022 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2121 * @param x the parameter value | 2023 * @param x the parameter value |
2122 * @throws SQLException if a database access error occurs | 2024 * @throws SQLException if a database access error occurs |
2123 * @throws SQLFeatureNotSupportedException the JDBC driver does | 2025 * @throws SQLFeatureNotSupportedException the JDBC driver does |
2124 * not support this method | 2026 * not support this method |
2125 */ | 2027 */ |
2126 @Override | 2028 @Override |
2127 public void setRowId(int i, RowId x) throws SQLException { | 2029 public void setRowId(int parameterIndex, RowId x) throws SQLException { |
2128 throw newSQLFeatureNotSupportedException("setRowId"); | 2030 throw newSQLFeatureNotSupportedException("setRowId"); |
2129 } | 2031 } |
2130 | 2032 |
2131 /** | 2033 /** |
2132 * Sets the designated parameter to the given Java short value. The driver | 2034 * Sets the designated parameter to the given Java short value. The driver |
2155 public void setString(int parameterIndex, String x) throws SQLException { | 2057 public void setString(int parameterIndex, String x) throws SQLException { |
2156 if (x == null) { | 2058 if (x == null) { |
2157 setNull(parameterIndex, -1); | 2059 setNull(parameterIndex, -1); |
2158 return; | 2060 return; |
2159 } | 2061 } |
2160 setValue(parameterIndex, "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'"); | 2062 int paramIdx = getParamIdx(parameterIndex); // this will throw a SQLException if parameter can not be found |
2063 | |
2064 /* depending on the parameter data type (as expected by MonetDB) we | |
2065 may need to add the data type as cast prefix to the parameter value */ | |
2066 int paramJdbcType = javaType[paramIdx]; | |
2067 String paramMonetdbType = monetdbType[paramIdx]; | |
2068 | |
2069 switch (paramJdbcType) { | |
2070 case Types.CHAR: | |
2071 case Types.VARCHAR: | |
2072 case Types.LONGVARCHAR: | |
2073 case Types.CLOB: | |
2074 case Types.NCHAR: | |
2075 case Types.NVARCHAR: | |
2076 case Types.LONGNVARCHAR: | |
2077 { | |
2078 String castprefix = ""; | |
2079 switch (paramMonetdbType) { | |
2080 // some MonetDB specific data types require a cast prefix | |
2081 case "inet": | |
2082 try { | |
2083 // check if x represents a valid inet string to prevent | |
2084 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2085 nl.cwi.monetdb.jdbc.MonetINET inet_obj = new nl.cwi.monetdb.jdbc.MonetINET(x); | |
2086 } catch (Exception se) { | |
2087 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + se.getMessage(), "22M29"); | |
2088 } | |
2089 castprefix = "inet "; | |
2090 break; | |
2091 case "json": | |
2092 // There is no support for JSON in standard java class libraries. | |
2093 // Possibly we could use org.json.simple.JSONObject or other/faster libs | |
2094 // javax.json.Json is not released yet (see https://json-processing-spec.java.net/) | |
2095 // see also https://github.com/fabienrenaud/java-json-benchmark | |
2096 // Note that it would make our JDBC driver dependent of an external jar | |
2097 // and we don't want that. | |
2098 | |
2099 // do simplistic check if x represents a valid json string to prevent | |
2100 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2101 if (x.isEmpty() || | |
2102 (x.startsWith("{") && !x.endsWith("}")) || | |
2103 (x.startsWith("[") && !x.endsWith("]")) | |
2104 // TODO check completely if x represents a valid json string | |
2105 ) | |
2106 throw new SQLDataException("Invalid json string. It does not start with { or [ and end with } or ]", "22M32"); | |
2107 | |
2108 // TODO check completely if x represents a valid json string | |
2109 | |
2110 castprefix = "json "; | |
2111 break; | |
2112 case "url": | |
2113 try { | |
2114 // also check if x represents a valid url string to prevent | |
2115 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2116 java.net.URL url_obj = new java.net.URL(x); | |
2117 } catch (java.net.MalformedURLException mue) { | |
2118 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + mue.getMessage(), "22M30"); | |
2119 } | |
2120 castprefix = "url "; | |
2121 break; | |
2122 case "uuid": | |
2123 try { | |
2124 // also check if x represents a valid uuid string to prevent | |
2125 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2126 java.util.UUID uuid_obj = java.util.UUID.fromString(x); | |
2127 } catch (IllegalArgumentException iae) { | |
2128 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + iae.getMessage(), "22M31"); | |
2129 } | |
2130 castprefix = "uuid "; | |
2131 break; | |
2132 } | |
2133 /* in specific cases prefix the string with: inet or json or url or uuid */ | |
2134 setValue(parameterIndex, | |
2135 castprefix + "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'"); | |
2136 break; | |
2137 } | |
2138 case Types.TINYINT: | |
2139 case Types.SMALLINT: | |
2140 case Types.INTEGER: | |
2141 case Types.BIGINT: | |
2142 case Types.REAL: | |
2143 case Types.FLOAT: | |
2144 case Types.DOUBLE: | |
2145 case Types.DECIMAL: | |
2146 case Types.NUMERIC: | |
2147 try { | |
2148 // check (by calling parse) if the string represents a valid number to prevent | |
2149 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2150 if (paramJdbcType == Types.TINYINT) { | |
2151 int number = Byte.parseByte(x); | |
2152 } else if (paramJdbcType == Types.SMALLINT ) { | |
2153 int number = Short.parseShort(x); | |
2154 } else if (paramJdbcType == Types.INTEGER) { | |
2155 int number = Integer.parseInt(x); | |
2156 } else if (paramJdbcType == Types.BIGINT) { | |
2157 long number = Long.parseLong(x); | |
2158 } else if (paramJdbcType == Types.REAL || paramJdbcType == Types.DOUBLE || paramJdbcType == Types.FLOAT) { | |
2159 double number = Double.parseDouble(x); | |
2160 } else { | |
2161 BigDecimal number = new BigDecimal(x); | |
2162 } | |
2163 } catch (NumberFormatException nfe) { | |
2164 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + nfe.getMessage(), "22003"); | |
2165 } | |
2166 setValue(parameterIndex, x); | |
2167 break; | |
2168 case Types.BIT: | |
2169 case Types.BOOLEAN: | |
2170 if (x.equalsIgnoreCase("false") || x.equalsIgnoreCase("true") || x.equals("0") || x.equals("1")) { | |
2171 setValue(parameterIndex, x); | |
2172 } else { | |
2173 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed", "22000"); | |
2174 } | |
2175 break; | |
2176 case Types.DATE: | |
2177 case Types.TIME: | |
2178 case 2013: //Types.TIME_WITH_TIMEZONE: | |
2179 case Types.TIMESTAMP: | |
2180 case 2014: //Types.TIMESTAMP_WITH_TIMEZONE: | |
2181 try { | |
2182 // check if the string represents a valid calendar date or time or timestamp to prevent | |
2183 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2184 if (paramJdbcType == Types.DATE) { | |
2185 java.sql.Date datum = java.sql.Date.valueOf(x); | |
2186 } else if (paramJdbcType == Types.TIME || paramJdbcType == 2013) { | |
2187 Time tijdstip = Time.valueOf(x); | |
2188 } else { | |
2189 Timestamp tijdstip = Timestamp.valueOf(x); | |
2190 } | |
2191 } catch (IllegalArgumentException iae) { | |
2192 throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + iae.getMessage(), "22007"); | |
2193 } | |
2194 /* prefix the string with: date or time or timetz or timestamp or timestamptz */ | |
2195 setValue(parameterIndex, paramMonetdbType + " '" + x + "'"); | |
2196 break; | |
2197 case Types.BINARY: | |
2198 case Types.VARBINARY: | |
2199 case Types.LONGVARBINARY: | |
2200 case Types.BLOB: | |
2201 // check if the string x contains pairs of hex chars to prevent | |
2202 // failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351 | |
2203 int xlen = x.length(); | |
2204 for (int i = 0; i < xlen; i++) { | |
2205 char c = x.charAt(i); | |
2206 if (c < '0' || c > '9') { | |
2207 if (c < 'A' || c > 'F') { | |
2208 if (c < 'a' || c > 'f') { | |
2209 throw new SQLDataException("Invalid string for parameter data type " + paramMonetdbType + ". The string may contain only hex chars", "22M28"); | |
2210 } | |
2211 } | |
2212 } | |
2213 } | |
2214 /* prefix the string with: blob */ | |
2215 setValue(parameterIndex, "blob '" + x + "'"); | |
2216 break; | |
2217 default: | |
2218 throw new SQLException("Conversion of string to parameter data type " + paramMonetdbType + " is not (yet) supported", "M1M05"); | |
2219 } | |
2161 } | 2220 } |
2162 | 2221 |
2163 /** | 2222 /** |
2164 * Sets the designated parameter to the given java.sql.SQLXML | 2223 * Sets the designated parameter to the given java.sql.SQLXML |
2165 * object. The driver converts this to an SQL XML value when it | 2224 * object. The driver converts this to an SQL XML value when it |
2179 /** | 2238 /** |
2180 * Sets the designated parameter to the given java.sql.Time value. | 2239 * Sets the designated parameter to the given java.sql.Time value. |
2181 * The driver converts this to an SQL TIME value when it sends it to | 2240 * The driver converts this to an SQL TIME value when it sends it to |
2182 * the database. | 2241 * the database. |
2183 * | 2242 * |
2184 * @param index the first parameter is 1, the second is 2, ... | 2243 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2185 * @param x the parameter value | 2244 * @param x the parameter value |
2186 * @throws SQLException if a database access error occurs | 2245 * @throws SQLException if a database access error occurs |
2187 */ | 2246 */ |
2188 @Override | 2247 @Override |
2189 public void setTime(int index, Time x) throws SQLException { | 2248 public void setTime(int parameterIndex, Time x) throws SQLException { |
2190 setTime(index, x, null); | 2249 setTime(parameterIndex, x, null); |
2191 } | 2250 } |
2192 | 2251 |
2193 /** | 2252 /** |
2194 * Sets the designated parameter to the given java.sql.Time value, | 2253 * Sets the designated parameter to the given java.sql.Time value, |
2195 * using the given Calendar object. The driver uses the Calendar | 2254 * using the given Calendar object. The driver uses the Calendar |
2198 * calculate the time taking into account a custom timezone. If no | 2257 * calculate the time taking into account a custom timezone. If no |
2199 * Calendar object is specified, the driver uses the default | 2258 * Calendar object is specified, the driver uses the default |
2200 * timezone, which is that of the virtual machine running the | 2259 * timezone, which is that of the virtual machine running the |
2201 * application. | 2260 * application. |
2202 * | 2261 * |
2203 * @param index the first parameter is 1, the second is 2, ... | 2262 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2204 * @param x the parameter value | 2263 * @param x the parameter value |
2205 * @param cal the Calendar object the driver will use to construct the time | 2264 * @param cal the Calendar object the driver will use to construct the time |
2206 * @throws SQLException if a database access error occurs | 2265 * @throws SQLException if a database access error occurs |
2207 */ | 2266 */ |
2208 @Override | 2267 @Override |
2209 public void setTime(int index, Time x, Calendar cal) throws SQLException { | 2268 public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { |
2210 if (x == null) { | 2269 if (x == null) { |
2211 setNull(index, -1); | 2270 setNull(parameterIndex, -1); |
2212 return; | 2271 return; |
2213 } | 2272 } |
2214 | 2273 |
2215 boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz"); | 2274 String MonetDBType = monetdbType[getParamIdx(parameterIndex)]; |
2275 boolean hasTimeZone = ("timetz".equals(MonetDBType) || "timestamptz".equals(MonetDBType)); | |
2216 if (hasTimeZone) { | 2276 if (hasTimeZone) { |
2217 // timezone shouldn't matter, since the server is timezone | 2277 // timezone shouldn't matter, since the server is timezone |
2218 // aware in this case | 2278 // aware in this case |
2219 String RFC822 = mTimeZ.format(x); | 2279 String RFC822 = mTimeZ.format(x); |
2220 setValue(index, "timetz '" + RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'"); | 2280 setValue(parameterIndex, "timetz '" + RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'"); |
2221 } else { | 2281 } else { |
2222 // server is not timezone aware for this field, and no | 2282 // server is not timezone aware for this field, and no |
2223 // calendar given, since we told the server our timezone at | 2283 // calendar given, since we told the server our timezone at |
2224 // connection creation, we can just write a plain timestamp | 2284 // connection creation, we can just write a plain timestamp |
2225 // here | 2285 // here |
2226 if (cal == null) { | 2286 if (cal == null) { |
2227 setValue(index, "time '" + x.toString() + "'"); | 2287 setValue(parameterIndex, "time '" + x.toString() + "'"); |
2228 } else { | 2288 } else { |
2229 mTime.setTimeZone(cal.getTimeZone()); | 2289 mTime.setTimeZone(cal.getTimeZone()); |
2230 setValue(index, "time '" + mTime.format(x) + "'"); | 2290 setValue(parameterIndex, "time '" + mTime.format(x) + "'"); |
2231 } | 2291 } |
2232 } | 2292 } |
2233 } | 2293 } |
2234 | 2294 |
2235 /** | 2295 /** |
2236 * Sets the designated parameter to the given java.sql.Timestamp | 2296 * Sets the designated parameter to the given java.sql.Timestamp |
2237 * value. The driver converts this to an SQL TIMESTAMP value when | 2297 * value. The driver converts this to an SQL TIMESTAMP value when |
2238 * it sends it to the database. | 2298 * it sends it to the database. |
2239 * | 2299 * |
2240 * @param index the first parameter is 1, the second is 2, ... | 2300 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2241 * @param x the parameter value | 2301 * @param x the parameter value |
2242 * @throws SQLException if a database access error occurs | 2302 * @throws SQLException if a database access error occurs |
2243 */ | 2303 */ |
2244 @Override | 2304 @Override |
2245 public void setTimestamp(int index, Timestamp x) throws SQLException { | 2305 public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { |
2246 setTimestamp(index, x, null); | 2306 setTimestamp(parameterIndex, x, null); |
2247 } | 2307 } |
2248 | 2308 |
2249 /** | 2309 /** |
2250 * Sets the designated parameter to the given java.sql.Timestamp | 2310 * Sets the designated parameter to the given java.sql.Timestamp |
2251 * value, using the given Calendar object. The driver uses the | 2311 * value, using the given Calendar object. The driver uses the |
2254 * driver can calculate the timestamp taking into account a custom | 2314 * driver can calculate the timestamp taking into account a custom |
2255 * timezone. If no Calendar object is specified, the driver uses the | 2315 * timezone. If no Calendar object is specified, the driver uses the |
2256 * default timezone, which is that of the virtual machine running | 2316 * default timezone, which is that of the virtual machine running |
2257 * the application. | 2317 * the application. |
2258 * | 2318 * |
2259 * @param index the first parameter is 1, the second is 2, ... | 2319 * @param parameterIndex the first parameter is 1, the second is 2, ... |
2260 * @param x the parameter value | 2320 * @param x the parameter value |
2261 * @param cal the Calendar object the driver will use to construct the | 2321 * @param cal the Calendar object the driver will use to construct the |
2262 * timestamp | 2322 * timestamp |
2263 * @throws SQLException if a database access error occurs | 2323 * @throws SQLException if a database access error occurs |
2264 */ | 2324 */ |
2265 @Override | 2325 @Override |
2266 public void setTimestamp(int index, Timestamp x, Calendar cal) throws SQLException { | 2326 public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { |
2267 if (x == null) { | 2327 if (x == null) { |
2268 setNull(index, -1); | 2328 setNull(parameterIndex, -1); |
2269 return; | 2329 return; |
2270 } | 2330 } |
2271 | 2331 |
2272 boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz"); | 2332 String MonetDBType = monetdbType[getParamIdx(parameterIndex)]; |
2333 boolean hasTimeZone = ("timestamptz".equals(MonetDBType) || "timetz".equals(MonetDBType)); | |
2273 if (hasTimeZone) { | 2334 if (hasTimeZone) { |
2274 // timezone shouldn't matter, since the server is timezone | 2335 // timezone shouldn't matter, since the server is timezone |
2275 // aware in this case | 2336 // aware in this case |
2276 String RFC822 = mTimestampZ.format(x); | 2337 String RFC822 = mTimestampZ.format(x); |
2277 setValue(index, "timestamptz '" + RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'"); | 2338 setValue(parameterIndex, "timestamptz '" + RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'"); |
2278 } else { | 2339 } else { |
2279 // server is not timezone aware for this field, and no | 2340 // server is not timezone aware for this field, and no |
2280 // calendar given, since we told the server our timezone at | 2341 // calendar given, since we told the server our timezone at |
2281 // connection creation, we can just write a plain timestamp | 2342 // connection creation, we can just write a plain timestamp here |
2282 // here | |
2283 if (cal == null) { | 2343 if (cal == null) { |
2284 setValue(index, "timestamp '" + x.toString() + "'"); | 2344 setValue(parameterIndex, "timestamp '" + x.toString() + "'"); |
2285 } else { | 2345 } else { |
2286 mTimestamp.setTimeZone(cal.getTimeZone()); | 2346 mTimestamp.setTimeZone(cal.getTimeZone()); |
2287 setValue(index, "timestamp '" + mTimestamp.format(x) + "'"); | 2347 setValue(parameterIndex, "timestamp '" + mTimestamp.format(x) + "'"); |
2288 } | 2348 } |
2289 } | 2349 } |
2290 } | 2350 } |
2291 | 2351 |
2292 /** | 2352 /** |
2324 * @param x the java.net.URL object to be set | 2384 * @param x the java.net.URL object to be set |
2325 * @throws SQLException if a database access error occurs | 2385 * @throws SQLException if a database access error occurs |
2326 */ | 2386 */ |
2327 @Override | 2387 @Override |
2328 public void setURL(int parameterIndex, URL x) throws SQLException { | 2388 public void setURL(int parameterIndex, URL x) throws SQLException { |
2329 setString(parameterIndex, x.toString()); | 2389 if (x == null) { |
2330 values[getParamIdx(parameterIndex)] = "url " + values[getParamIdx(parameterIndex)]; | 2390 setNull(parameterIndex, -1); |
2391 return; | |
2392 } | |
2393 | |
2394 String val = x.toString(); | |
2395 setValue(parameterIndex, "url '" + val.replaceAll("\\\\", "\\\\\\\\") | |
2396 .replaceAll("'", "\\\\'") + "'"); | |
2331 } | 2397 } |
2332 | 2398 |
2333 /** | 2399 /** |
2334 * Releases this PreparedStatement object's database and JDBC | 2400 * Releases this PreparedStatement object's database and JDBC |
2335 * resources immediately instead of waiting for this to happen when | 2401 * resources immediately instead of waiting for this to happen when |
2367 | 2433 |
2368 /** | 2434 /** |
2369 * Sets the given index with the supplied value. If the given index is out of bounds, and SQLException is thrown. | 2435 * Sets the given index with the supplied value. If the given index is out of bounds, and SQLException is thrown. |
2370 * The given value should never be null. | 2436 * The given value should never be null. |
2371 * | 2437 * |
2372 * @param index the parameter index | 2438 * @param parameterIndex the parameter index |
2373 * @param val the exact String representation to set | 2439 * @param val the exact String representation to set |
2374 * @throws SQLException if the given index is out of bounds | 2440 * @throws SQLException if the given index is out of bounds |
2375 */ | 2441 */ |
2376 private void setValue(int index, String val) throws SQLException { | 2442 private void setValue(int parameterIndex, String val) throws SQLException { |
2377 values[getParamIdx(index)] = val; | 2443 values[getParamIdx(parameterIndex)] = (val == null ? "NULL" : val); |
2378 } | 2444 } |
2379 | 2445 |
2380 /** | 2446 /** |
2381 * Transforms the prepare query into a simple SQL query by replacing | 2447 * Transforms the prepare query into a simple SQL query by replacing |
2382 * the ?'s with the given column contents. | 2448 * the ?'s with the given column contents. |
2386 * @return the simple SQL string for the prepare query | 2452 * @return the simple SQL string for the prepare query |
2387 * @throws SQLException if not all columns are set | 2453 * @throws SQLException if not all columns are set |
2388 */ | 2454 */ |
2389 private String transform() throws SQLException { | 2455 private String transform() throws SQLException { |
2390 StringBuilder buf = new StringBuilder(8 + 12 * size); | 2456 StringBuilder buf = new StringBuilder(8 + 12 * size); |
2391 buf.append("exec "); | 2457 buf.append("exec ").append(id).append('('); |
2392 buf.append(id); | |
2393 buf.append('('); | |
2394 // check if all columns are set and do a replace | 2458 // check if all columns are set and do a replace |
2395 int col = 0; | 2459 int col = 0; |
2396 for (int i = 0; i < size; i++) { | 2460 for (int i = 0; i < size; i++) { |
2397 if (column[i] != null) | 2461 if (column[i] != null) |
2398 continue; | 2462 continue; |
2399 col++; | 2463 col++; |
2400 if (col > 1) | 2464 if (col > 1) |
2401 buf.append(','); | 2465 buf.append(','); |
2402 if (values[i] == null) throw | 2466 if (values[i] == null) |
2403 new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05"); | 2467 throw new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05"); |
2404 | 2468 |
2405 buf.append(values[i]); | 2469 buf.append(values[i]); |
2406 } | 2470 } |
2407 buf.append(')'); | 2471 buf.append(')'); |
2408 | 2472 |
2409 return buf.toString(); | 2473 return buf.toString(); |
2410 } | 2474 } |
2411 | 2475 |
2412 /** | 2476 /** |
2413 * Small helper method that formats the "Invalid Parameter Index number ..." message | 2477 * Small helper method that formats the "Invalid Parameter Index number ..." message |
2414 * and creates a new SQLException object whose SQLState is set to "M1M05". | 2478 * and creates a new SQLDataException object whose SQLState is set |
2479 * to "22010": invalid indicator parameter value. | |
2415 * | 2480 * |
2416 * @param paramIdx the parameter index number | 2481 * @param paramIdx the parameter index number |
2417 * @return a new created SQLException object with SQLState M1M05 | 2482 * @return a new created SQLDataException object with SQLState 22010 |
2418 */ | 2483 */ |
2419 private static SQLException newSQLInvalidParameterIndexException(int paramIdx) { | 2484 private static SQLDataException newSQLInvalidParameterIndexException(int paramIdx) { |
2420 return new SQLException("Invalid Parameter Index number: " + paramIdx, "M1M05"); | 2485 return new SQLDataException("Invalid Parameter Index number: " + paramIdx, "22010"); |
2421 } | 2486 } |
2422 | 2487 |
2423 /** | 2488 /** |
2424 * Small helper method that formats the "Method ... not implemented" message | 2489 * Small helper method that formats the "Method ... not implemented" message |
2425 * and creates a new SQLFeatureNotSupportedException object | 2490 * and creates a new SQLFeatureNotSupportedException object |
2426 * whose SQLState is set to "0A000". | 2491 * whose SQLState is set to "0A000": feature not supported. |
2427 * | 2492 * |
2428 * @param name the method name | 2493 * @param name the method name |
2429 * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 | 2494 * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 |
2430 */ | 2495 */ |
2431 private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { | 2496 private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { |