From: Date: August 23 2005 6:10pm Subject: Connector/J commit: r4124 - in branches/branch_3_1/connector-j/src: com/mysql/jdbc testsuite/regression testsuite/simple List-Archive: http://lists.mysql.com/internals/28696 Message-Id: <200508231610.j7NGAMxh028117@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java branches/branch_3_1/connector-j/src/testsuite/regression/MetaDataRegressionTest.java branches/branch_3_1/connector-j/src/testsuite/simple/MetadataTest.java Log: Fixed BUG#11781, foreign key information that is quoted is parsed incorrectly when DatabaseMetaData methods use that information. Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java =================================================================== --- branches/branch_3_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2005-08-23 13:12:18 UTC (rev 4123) +++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2005-08-23 16:10:21 UTC (rev 4124) @@ -24,6 +24,9 @@ */ package com.mysql.jdbc; +import java.io.IOException; +import java.io.StreamTokenizer; +import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.sql.ResultSet; @@ -685,50 +688,62 @@ } } + if (line.startsWith("FOREIGN KEY")) { if (line.endsWith(",")) { line = line.substring(0, line.length() - 1); } - // Remove all back-ticks - int lineLength = line.length(); - StringBuffer lineBuf = new StringBuffer(lineLength); + char quote = this.quotedId.charAt(0); + + int indexOfFK = line.indexOf("FOREIGN KEY"); + + String localColumnName = null; + String referencedCatalogName = this.quotedId + catalog + this.quotedId; + String referencedTableName = null; + String referencedColumnName = null; + + + if (indexOfFK != -1) { + int afterFk = indexOfFK + "FOREIGN KEY".length(); + + int indexOfRef = StringUtils.indexOfIgnoreCaseRespectQuotes(afterFk, line, "REFERENCES", quote, true); + + if (indexOfRef != -1) { + + int indexOfParenOpen = line.indexOf('(', afterFk); + int indexOfParenClose = StringUtils.indexOfIgnoreCaseRespectQuotes(indexOfParenOpen, line, ")", quote, true); + + if (indexOfParenOpen == -1 || indexOfParenClose == -1) { + // throw new SQLException(); + } + + localColumnName = line.substring(indexOfParenOpen + 1, indexOfParenClose); + + int afterRef = indexOfRef + "REFERENCES".length(); + + int referencedColumnBegin = StringUtils.indexOfIgnoreCaseRespectQuotes(afterRef, line, "(", quote, true); + + if (referencedColumnBegin != -1) { + referencedTableName = line.substring(afterRef, referencedColumnBegin); - for (int i = 0; i < lineLength; i++) { - char c = line.charAt(i); - - if (c != quoteChar.charAt(0)) { - lineBuf.append(c); + int referencedColumnEnd = StringUtils.indexOfIgnoreCaseRespectQuotes(referencedColumnBegin + 1, line, ")", quote, true); + + if (referencedColumnEnd != -1) { + referencedColumnName = line.substring(referencedColumnBegin + 1, referencedColumnEnd); + } + + int indexOfCatalogSep = StringUtils.indexOfIgnoreCaseRespectQuotes(0, referencedTableName, ".", quote, true); + + if (indexOfCatalogSep != -1) { + referencedCatalogName = referencedTableName.substring(0, indexOfCatalogSep); + referencedTableName = referencedTableName.substring(indexOfCatalogSep + 1); + } + } } } - - line = lineBuf.toString(); - - StringTokenizer keyTokens = new StringTokenizer(line, "()", - false); - keyTokens.nextToken(); // eat 'FOREIGN KEY' - - String localColumnNamesString = keyTokens.nextToken(); - String referCatalogTableString = keyTokens.nextToken(); - StringTokenizer referSchemaTable = new StringTokenizer( - referCatalogTableString.trim(), " ."); - String referColumnNamesString = keyTokens.nextToken(); - referSchemaTable.nextToken(); // discard the REFERENCES token - - int numTokensLeft = referSchemaTable.countTokens(); - - String referCatalog = null; - String referTable = null; - - if (numTokensLeft == 2) { - // some versions of MySQL don't report the database name - referCatalog = referSchemaTable.nextToken(); - referTable = referSchemaTable.nextToken(); - } else { - referTable = referSchemaTable.nextToken(); - referCatalog = catalog; - } - + + if (!firstTime) { commentBuf.append("; "); } else { @@ -742,13 +757,13 @@ } commentBuf.append("("); - commentBuf.append(localColumnNamesString); + commentBuf.append(localColumnName); commentBuf.append(") REFER "); - commentBuf.append(referCatalog); + commentBuf.append(referencedCatalogName); commentBuf.append("/"); - commentBuf.append(referTable); + commentBuf.append(referencedTableName); commentBuf.append("("); - commentBuf.append(referColumnNamesString); + commentBuf.append(referencedColumnName); commentBuf.append(")"); int lastParenIndex = line.lastIndexOf(")"); @@ -2188,7 +2203,7 @@ fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); fields[13] = new Field("", "DEFERRABILITY", Types.INTEGER, 2); - final ArrayList rows = new ArrayList(); + final ArrayList tuples = new ArrayList(); if (this.conn.versionMeetsMinimum(3, 23, 0)) { @@ -2226,7 +2241,7 @@ /* * Parse imported foreign key information */ - ArrayList tuples = new ArrayList(); + String dummy; while (fkresults.next()) { @@ -2252,45 +2267,17 @@ while (commentTokens.hasMoreTokens()) { String keys = commentTokens .nextToken(); - - // simple-columned keys: (m) REFER - // airline/tt(a) - // multi-columned keys : (m n) REFER - // airline/vv(a b) - int firstLeftParenIndex = keys - .indexOf('('); - int firstRightParenIndex = keys - .indexOf(')'); - String referencingColumns = keys - .substring( - firstLeftParenIndex + 1, - firstRightParenIndex); - StringTokenizer referencingColumnsTokenizer = new StringTokenizer( - referencingColumns, ", "); - int secondLeftParenIndex = keys - .indexOf( - '(', - firstRightParenIndex + 1); - int secondRightParenIndex = keys - .indexOf( - ')', - firstRightParenIndex + 1); - String referencedColumns = keys - .substring( - secondLeftParenIndex + 1, - secondRightParenIndex); - StringTokenizer referencedColumnsTokenizer = new StringTokenizer( - referencedColumns, ", "); - int slashIndex = keys.indexOf('/'); - String referencedTable = keys - .substring(slashIndex + 1, - secondLeftParenIndex); + LocalAndReferencedColumns parsedInfo = + parseTableStatusIntoLocalAndReferencedColumns(keys); + + int keySeq = 0; - while (referencingColumnsTokenizer - .hasMoreTokens()) { - String referencingColumn = referencingColumnsTokenizer - .nextToken(); + Iterator referencingColumns = parsedInfo.localColumnsList.iterator(); + Iterator referencedColumns = parsedInfo.referencedColumnsList.iterator(); + + while (referencingColumns.hasNext()) { + String referencingColumn = removeQuotedId(referencingColumns.next().toString()); // one tuple for each table // between @@ -2319,14 +2306,13 @@ // Skip foreign key if it // doesn't refer to // the right table - if (referencedTable + if (parsedInfo.referencedTable .compareTo(primaryTableWithCase) != 0) { continue; } - tuple[2] = s2b(referencedTable); // PKTABLE_NAME - tuple[3] = s2b(referencedColumnsTokenizer - .nextToken()); // PKCOLUMN_NAME + tuple[2] = s2b(parsedInfo.referencedTable); // PKTABLE_NAME + tuple[3] = s2b(removeQuotedId(referencedColumns.next().toString())); // PKCOLUMN_NAME tuple[8] = Integer.toString( keySeq).getBytes(); // KEY_SEQ @@ -2371,7 +2357,7 @@ } } - java.sql.ResultSet results = buildResultSet(fields, rows); + java.sql.ResultSet results = buildResultSet(fields, tuples); return results; } @@ -3856,74 +3842,182 @@ private void getResultsImpl(String catalog, String table, String keysComment, List tuples, String fkTableName, boolean isExport) throws SQLException { - // keys will equal something like this: - // (parent_service_id child_service_id) REFER - // ds/subservices(parent_service_id child_service_id) - // parse of the string into three phases: - // 1: parse the opening parentheses to determine how many results there - // will be - // 2: read in the schema name/table name - // 3: parse the closing parentheses - int firstLeftParenIndex = keysComment.indexOf('('); - String constraintName = keysComment.substring(0, firstLeftParenIndex) - .trim(); - keysComment = keysComment.substring(firstLeftParenIndex, keysComment - .length()); - StringTokenizer keyTokens = new StringTokenizer(keysComment.trim(), - "()", false); - String localColumnNamesString = keyTokens.nextToken(); - StringTokenizer localColumnNames = new StringTokenizer( - localColumnNamesString, " ,"); - String referCatalogTableString = keyTokens.nextToken(); - StringTokenizer referSchemaTable = new StringTokenizer( - referCatalogTableString, " /"); - String referColumnNamesString = keyTokens.nextToken(); - StringTokenizer referColumnNames = new StringTokenizer( - referColumnNamesString, " ,"); - referSchemaTable.nextToken(); // discard the REFER token + LocalAndReferencedColumns parsedInfo = parseTableStatusIntoLocalAndReferencedColumns(keysComment); + - String referCatalog = referSchemaTable.nextToken(); - String referTable = referSchemaTable.nextToken(); - - if (isExport && !referTable.equals(table)) { + if (isExport && !parsedInfo.referencedTable.equals(table)) { return; } - if (localColumnNames.countTokens() != referColumnNames.countTokens()) { - throw new SQLException("Error parsing foriegn keys definition", + if (parsedInfo.localColumnsList.size() != parsedInfo.referencedColumnsList.size()) { + throw new SQLException( + "Error parsing foreign keys definition," + + "number of local and referenced columns is not the same.", SQLError.SQL_STATE_GENERAL_ERROR); } + Iterator localColumnNames = parsedInfo.localColumnsList.iterator(); + Iterator referColumnNames = parsedInfo.referencedColumnsList.iterator(); + int keySeqIndex = 1; - while (localColumnNames.hasMoreTokens()) { + while (localColumnNames.hasNext()) { byte[][] tuple = new byte[14][]; - String localColumnName = localColumnNames.nextToken(); - String referColumnName = referColumnNames.nextToken(); + String lColumnName = removeQuotedId(localColumnNames.next() + .toString()); + String rColumnName = removeQuotedId(referColumnNames.next() + .toString()); tuple[FKTABLE_CAT] = ((catalog == null) ? new byte[0] : s2b(catalog)); tuple[FKTABLE_SCHEM] = null; tuple[FKTABLE_NAME] = s2b((isExport) ? fkTableName : table); - tuple[FKCOLUMN_NAME] = s2b(localColumnName); - tuple[PKTABLE_CAT] = s2b(referCatalog); + tuple[FKCOLUMN_NAME] = s2b(lColumnName); + tuple[PKTABLE_CAT] = s2b(parsedInfo.referencedCatalog); tuple[PKTABLE_SCHEM] = null; - tuple[PKTABLE_NAME] = s2b((isExport) ? table : referTable); - tuple[PKCOLUMN_NAME] = s2b(referColumnName); + tuple[PKTABLE_NAME] = s2b((isExport) ? table : parsedInfo.referencedTable); + tuple[PKCOLUMN_NAME] = s2b(rColumnName); tuple[KEY_SEQ] = s2b(Integer.toString(keySeqIndex++)); int[] actions = getForeignKeyActions(keysComment); tuple[UPDATE_RULE] = s2b(Integer.toString(actions[1])); tuple[DELETE_RULE] = s2b(Integer.toString(actions[0])); - tuple[FK_NAME] = s2b(constraintName); + tuple[FK_NAME] = s2b(parsedInfo.constraintName); tuple[PK_NAME] = null; // not available from show table status tuple[DEFERRABILITY] = s2b(Integer .toString(java.sql.DatabaseMetaData.importedKeyNotDeferrable)); tuples.add(tuple); } } + + class LocalAndReferencedColumns { + List localColumnsList; + List referencedColumnsList; + String constraintName; + String referencedTable; + String referencedCatalog; + + LocalAndReferencedColumns(List localColumns, List refColumns, + String constName, String refCatalog, String refTable) { + this.localColumnsList = localColumns; + this.referencedColumnsList = refColumns; + this.constraintName = constName; + this.referencedTable = refTable; + this.referencedCatalog = refCatalog; + } + } + + private LocalAndReferencedColumns parseTableStatusIntoLocalAndReferencedColumns(String keysComment) throws SQLException { + // keys will equal something like this: + // (parent_service_id child_service_id) REFER + // ds/subservices(parent_service_id child_service_id) + // + // simple-columned keys: (m) REFER + // airline/tt(a) + // + // multi-columned keys : (m n) REFER + // airline/vv(a b) + // + // parse of the string into three phases: + // 1: parse the opening parentheses to determine how many results there + // will be + // 2: read in the schema name/table name + // 3: parse the closing parentheses + String columnsDelimitter = ","; // what version did this change in? + + char quoteChar = this.quotedId.length() == 0 ? 0 : this.quotedId + .charAt(0); + + int indexOfOpenParenLocalColumns = StringUtils + .indexOfIgnoreCaseRespectQuotes(0, keysComment, "(", quoteChar, + true); + + if (indexOfOpenParenLocalColumns == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find start of local columns list.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + String constraintName = removeQuotedId(keysComment.substring(0, + indexOfOpenParenLocalColumns).trim()); + keysComment = keysComment.substring(indexOfOpenParenLocalColumns, + keysComment.length()); + + String keysCommentTrimmed = keysComment.trim(); + + int indexOfCloseParenLocalColumns = StringUtils + .indexOfIgnoreCaseRespectQuotes(0, keysCommentTrimmed, ")", + quoteChar, true); + + if (indexOfCloseParenLocalColumns == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find end of local columns list.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + String localColumnNamesString = keysCommentTrimmed.substring(1, + indexOfCloseParenLocalColumns); + + int indexOfRefer = StringUtils.indexOfIgnoreCaseRespectQuotes(0, + keysCommentTrimmed, "REFER ", this.quotedId.charAt(0), true); + + if (indexOfRefer == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find start of referenced tables list.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + int indexOfOpenParenReferCol = StringUtils + .indexOfIgnoreCaseRespectQuotes(indexOfRefer, + keysCommentTrimmed, "(", quoteChar, false); + + if (indexOfOpenParenReferCol == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find start of referenced columns list.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + String referCatalogTableString = keysCommentTrimmed.substring( + indexOfRefer + "REFER ".length(), indexOfOpenParenReferCol); + + int indexOfSlash = StringUtils.indexOfIgnoreCaseRespectQuotes(0, + referCatalogTableString, "/", this.quotedId.charAt(0), false); + + if (indexOfSlash == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find name of referenced catalog.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + String referCatalog = removeQuotedId(referCatalogTableString.substring( + 0, indexOfSlash)); + String referTable = removeQuotedId(referCatalogTableString.substring( + indexOfSlash + 1).trim()); + + int indexOfCloseParenRefer = StringUtils + .indexOfIgnoreCaseRespectQuotes(indexOfOpenParenReferCol, + keysCommentTrimmed, ")", quoteChar, true); + + if (indexOfCloseParenRefer == -1) { + throw new SQLException("Error parsing foreign keys definition," + + " couldn't find end of referenced columns list.", + SQLError.SQL_STATE_GENERAL_ERROR); + } + + String referColumnNamesString = keysCommentTrimmed.substring( + indexOfOpenParenReferCol + 1, indexOfCloseParenRefer); + + List referColumnsList = StringUtils.split(referColumnNamesString, columnsDelimitter, + this.quotedId, this.quotedId, false); + List localColumnsList = StringUtils.split(localColumnNamesString, columnsDelimitter, + this.quotedId, this.quotedId, false); + + return new LocalAndReferencedColumns(localColumnsList, referColumnsList, + constraintName, referCatalog, referTable); + } + /** * Get the schema names available in this database. The results are ordered * by schema name. @@ -7216,4 +7310,30 @@ public boolean usesLocalFiles() throws SQLException { return false; } + + private String removeQuotedId(String s) { + if (s == null) { + return null; + } + + if (this.quotedId.equals("")) { + return s; + } + + s = s.trim(); + + int frontOffset = 0; + int backOffset = s.length(); + int quoteLength = this.quotedId.length(); + + if (s.startsWith(this.quotedId)) { + frontOffset = quoteLength; + } + + if (s.endsWith(this.quotedId)) { + backOffset -= quoteLength; + } + + return s.substring(frontOffset, backOffset); + } } Modified: branches/branch_3_1/connector-j/src/testsuite/regression/MetaDataRegressionTest.java =================================================================== --- branches/branch_3_1/connector-j/src/testsuite/regression/MetaDataRegressionTest.java 2005-08-23 13:12:18 UTC (rev 4123) +++ branches/branch_3_1/connector-j/src/testsuite/regression/MetaDataRegressionTest.java 2005-08-23 16:10:21 UTC (rev 4124) @@ -1175,6 +1175,43 @@ } } + /** + * Tests fix for BUG#11781, foreign key information + * that is quoted is parsed incorrectly. + */ + public void testBug11781() throws Exception { + + createTable("`app tab`", "( C1 int(11) NULL, INDEX NEWINX (C1), INDEX NEWINX2 (C1)) ENGINE = InnoDB CHECKSUM = 0 COMMENT = 'InnoDB free: 3072 kB; (`C1`) REFER`test/app tab`(`C1`)' PACK_KEYS = 0"); + + this.stmt.executeUpdate("ALTER TABLE `app tab` ADD CONSTRAINT APPFK FOREIGN KEY (C1) REFERENCES `app tab` (C1)"); + + /* + this.rs = this.conn.getMetaData().getCrossReference( + this.conn.getCatalog(), + null, + "app tab", + this.conn.getCatalog(), + null, + "app tab"); + */ + rs = ((com.mysql.jdbc.DatabaseMetaData)this.conn.getMetaData()).extractForeignKeyFromCreateTable(this.conn.getCatalog(),"app tab"); + assertTrue("must return a row",rs.next()) ; + System.out.println(rs.getString(1)); + System.out.println(rs.getString(2)); + System.out.println(rs.getString(3)); + assertEquals("comment; APPFK(`C1`) REFER `test`/ `app tab` (`C1`)", rs.getString(3)); + + rs.close(); + + rs = this.conn.getMetaData().getImportedKeys(this.conn.getCatalog(), null, "app tab"); + + assertTrue(this.rs.next()); + + rs = this.conn.getMetaData().getExportedKeys(this.conn.getCatalog(), null, "app tab"); + + assertTrue(this.rs.next()); + } + public void testSupportsCorrelatedSubqueries() throws Exception { DatabaseMetaData dbmd = this.conn.getMetaData(); Modified: branches/branch_3_1/connector-j/src/testsuite/simple/MetadataTest.java =================================================================== --- branches/branch_3_1/connector-j/src/testsuite/simple/MetadataTest.java 2005-08-23 13:12:18 UTC (rev 4123) +++ branches/branch_3_1/connector-j/src/testsuite/simple/MetadataTest.java 2005-08-23 16:10:21 UTC (rev 4124) @@ -85,46 +85,48 @@ * DOCUMENT ME! */ public void testForeignKeys() throws SQLException { - DatabaseMetaData dbmd = this.conn.getMetaData(); - this.rs = dbmd.getImportedKeys(null, null, "child"); + try { + DatabaseMetaData dbmd = this.conn.getMetaData(); + this.rs = dbmd.getImportedKeys(null, null, "child"); - while (this.rs.next()) { - String pkColumnName = this.rs.getString("PKCOLUMN_NAME"); - String fkColumnName = this.rs.getString("FKCOLUMN_NAME"); - assertTrue("Primary Key not returned correctly ('" + pkColumnName - + "' != 'parent_id')", pkColumnName - .equalsIgnoreCase("parent_id")); - assertTrue("Foreign Key not returned correctly ('" + fkColumnName - + "' != 'parent_id_fk')", fkColumnName - .equalsIgnoreCase("parent_id_fk")); - } + while (this.rs.next()) { + String pkColumnName = this.rs.getString("PKCOLUMN_NAME"); + String fkColumnName = this.rs.getString("FKCOLUMN_NAME"); + assertTrue("Primary Key not returned correctly ('" + + pkColumnName + "' != 'parent_id')", pkColumnName + .equalsIgnoreCase("parent_id")); + assertTrue("Foreign Key not returned correctly ('" + + fkColumnName + "' != 'parent_id_fk')", fkColumnName + .equalsIgnoreCase("parent_id_fk")); + } - this.rs.close(); - this.rs = dbmd.getExportedKeys(null, null, "parent"); + this.rs.close(); + this.rs = dbmd.getExportedKeys(null, null, "parent"); - while (this.rs.next()) { - String pkColumnName = this.rs.getString("PKCOLUMN_NAME"); - String fkColumnName = this.rs.getString("FKCOLUMN_NAME"); - String fkTableName = this.rs.getString("FKTABLE_NAME"); - assertTrue("Primary Key not returned correctly ('" + pkColumnName - + "' != 'parent_id')", pkColumnName - .equalsIgnoreCase("parent_id")); - assertTrue( - "Foreign Key table not returned correctly for getExportedKeys ('" - + fkTableName + "' != 'child')", fkTableName - .equalsIgnoreCase("child")); - assertTrue( - "Foreign Key not returned correctly for getExportedKeys ('" - + fkColumnName + "' != 'parent_id_fk')", - fkColumnName.equalsIgnoreCase("parent_id_fk")); - } + while (this.rs.next()) { + String pkColumnName = this.rs.getString("PKCOLUMN_NAME"); + String fkColumnName = this.rs.getString("FKCOLUMN_NAME"); + String fkTableName = this.rs.getString("FKTABLE_NAME"); + assertTrue("Primary Key not returned correctly ('" + + pkColumnName + "' != 'parent_id')", pkColumnName + .equalsIgnoreCase("parent_id")); + assertTrue( + "Foreign Key table not returned correctly for getExportedKeys ('" + + fkTableName + "' != 'child')", fkTableName + .equalsIgnoreCase("child")); + assertTrue( + "Foreign Key not returned correctly for getExportedKeys ('" + + fkColumnName + "' != 'parent_id_fk')", + fkColumnName.equalsIgnoreCase("parent_id_fk")); + } - this.rs.close(); + this.rs.close(); - this.rs = dbmd.getCrossReference(null, null, "cpd_foreign_3", null, - null, "cpd_foreign_4"); + this.rs = dbmd.getCrossReference(null, null, "cpd_foreign_3", null, + null, "cpd_foreign_4"); - while (this.rs.next()) { + assertTrue(this.rs.next()); + String pkColumnName = this.rs.getString("PKCOLUMN_NAME"); String pkTableName = this.rs.getString("PKTABLE_NAME"); String fkColumnName = this.rs.getString("FKCOLUMN_NAME"); @@ -134,16 +136,22 @@ String updateAction = cascadeOptionToString(this.rs .getInt("UPDATE_RULE")); - System.out.println("[D] " + deleteAction); - System.out.println("[U] " + updateAction); + assertEquals(pkColumnName, "cpd_foreign_1_id"); + assertEquals(pkTableName, "cpd_foreign_3"); + assertEquals(fkColumnName, "cpd_foreign_1_id"); + assertEquals(fkTableName, "cpd_foreign_4"); + assertEquals(deleteAction, "NO ACTION"); + assertEquals(updateAction, "CASCADE"); - System.out.println(pkTableName + "(" + pkColumnName + ") -> " - + fkTableName + "(" + fkColumnName + ")"); + this.rs.close(); + this.rs = null; + } finally { + if (this.rs != null) { + this.rs.close(); + this.rs = null; + } } - this.rs.close(); - - this.rs = dbmd.getImportedKeys(null, null, "fktable2"); } /**