changeset 725:224d73363dc9

Fixed issue when you create a new Statement, call getGeneratedKeys().getMetaData(). It throwed: Exception in thread "main" java.lang.IllegalArgumentException: Header may not be null! at org.monetdb.jdbc.MonetResultSetMetaData.<init>(MonetResultSetMetaData.java:88) at org.monetdb.jdbc.MonetResultSet.getMetaData(MonetResultSet.java:1255) Added test to JDBC_API_Tester.java
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 26 Jan 2023 17:46:22 +0100 (2023-01-26)
parents 2b763b189452
children 89bbd04036cd
files src/main/java/org/monetdb/jdbc/MonetResultSet.java src/main/java/org/monetdb/jdbc/MonetResultSetMetaData.java tests/JDBC_API_Tester.java
diffstat 3 files changed, 69 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/monetdb/jdbc/MonetResultSet.java
+++ b/src/main/java/org/monetdb/jdbc/MonetResultSet.java
@@ -1247,12 +1247,38 @@ public class MonetResultSet
 	 * columns.
 	 *
 	 * @return the description of this ResultSet object's columns
+	 * @throws SQLException if a database access error occurs or this method is called on a closed result set
 	 */
 	@Override
 	public ResultSetMetaData getMetaData() throws SQLException {
 		if (rsmd == null) {
 			// first use, construct it once and reuse it for all next calls
-			rsmd = new MonetResultSetMetaData((MonetConnection) getStatement().getConnection(), header);
+			if (header != null) {
+				rsmd = new MonetResultSetMetaData((MonetConnection) getStatement().getConnection(), header);
+			} else {
+				// this will be a MonetVirtualResultSet object, see MonetStatement.getGeneratedKeys()
+				// create arrays for storing the result columns meta data to pass to the constructor
+				final int array_size = 1;
+				final String[] schemas = new String[array_size];
+				final String[] tables = new String[array_size];
+				final String[] columns = new String[array_size];
+				final String[] types = new String[array_size];
+				final int[] jdbcTypes = new int[array_size];
+				final int[] lengths = new int[array_size];
+				final int[] precisions = new int[array_size];
+				final int[] scales = new int[array_size];
+				// fill the arrays with the getGeneratedKeys() resultset columns metadata. It only has 1 column.
+				schemas[0] = null;
+				tables[0] = null;
+				columns[0] = "GENERATED_KEY";
+				types[0] = "bigint";
+				jdbcTypes[0] = Types.BIGINT;
+				lengths[0] = 20;
+				precisions[0] = 19;
+				scales[0] = 0;
+				rsmd = new MonetResultSetMetaData((MonetConnection) getStatement().getConnection(), 1,
+					schemas, tables, columns, types, jdbcTypes, lengths, precisions, scales);
+			}
 		}
 		return rsmd;
 	}
--- a/src/main/java/org/monetdb/jdbc/MonetResultSetMetaData.java
+++ b/src/main/java/org/monetdb/jdbc/MonetResultSetMetaData.java
@@ -520,7 +520,7 @@ final class MonetResultSetMetaData
 		checkColumnIndexValidity(column);
 		try {
 			final String monettype = types[column - 1];
-			if (monettype.endsWith("_interval")) {
+			if (monettype != null && monettype.endsWith("_interval")) {
 				/* convert the interval type names to valid SQL data type names,
 				 * such that generic applications can use them in create table statements
 				 */
--- a/tests/JDBC_API_Tester.java
+++ b/tests/JDBC_API_Tester.java
@@ -91,6 +91,7 @@ final public class JDBC_API_Tester {
 		jt.Test_Rtimedate();
 		jt.Test_RSgetMetaData();
 		jt.Test_Sbatching();
+		jt.Test_SgeneratedKeys();
 		jt.Test_Smoreresults();
 		jt.Test_Wrapper();
 		jt.bogus_auto_generated_keys();
@@ -4318,6 +4319,46 @@ final public class JDBC_API_Tester {
 			"0. true	true\n");
 	}
 
+	private void Test_SgeneratedKeys() {
+		sb.setLength(0);	// clear the output log buffer
+
+		Statement stmt = null;
+		ResultSet rsk = null;
+		try {
+			stmt = con.createStatement();
+			// test getGeneratedKeys
+			rsk = stmt.getGeneratedKeys();
+			// test meta data retrieval of this MonetVirtualResultSet.
+			// It used to fail with: Exception in thread "main" java.lang.IllegalArgumentException: Header may not be null!
+			final ResultSetMetaData rsmd = rsk.getMetaData();
+			sb.append("rsmd has ").append(rsmd.getColumnCount()).append(" columns\n");
+			for (int col = 1; col <= rsmd.getColumnCount(); col++) {
+				sb.append("ColumnName: ").append(rsmd.getColumnName(col))
+				.append(" ColumnTypeName: ").append(rsmd.getColumnTypeName(col))
+				.append(" Precision: ").append(rsmd.getPrecision(col))
+				.append(" Scale: ").append(rsmd.getScale(col))
+				.append(" ColumnDisplaySize: ").append(rsmd.getColumnDisplaySize(col))
+				.append(" ColumnType: ").append(rsmd.getColumnType(col))
+				.append(" ColumnClassName: ").append(rsmd.getColumnClassName(col))
+				.append(" isNullable: ").append(rsmd.isNullable(col))
+				.append(" isAutoIncrement: ").append(rsmd.isAutoIncrement(col))
+				.append("\n");
+			}
+			rsk.close();
+			rsk = null;
+			stmt.close();
+			stmt = null;
+		} catch (SQLException e) {
+			sb.append("FAILED: ").append(e.getMessage()).append("\n");
+		}
+
+		closeStmtResSet(stmt, rsk);
+
+		compareExpectedOutput("Test_SgeneratedKeys",
+				"rsmd has 1 columns\n" +
+				"ColumnName: GENERATED_KEY ColumnTypeName: bigint Precision: 19 Scale: 0 ColumnDisplaySize: 20 ColumnType: -5 ColumnClassName: java.lang.Long isNullable: 2 isAutoIncrement: false\n");
+	}
+
 	private void Test_Smoreresults() {
 		sb.setLength(0);	// clear the output log buffer