Skip to content

Commit 804dcf2

Browse files
committed
#822 Improve schema test coverage (getProcedures/getProcedureColumns)
1 parent 5350741 commit 804dcf2

File tree

3 files changed

+273
-106
lines changed

3 files changed

+273
-106
lines changed

src/test/org/firebirdsql/common/FBTestProperties.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,21 @@ public static <T> T ifSchemaElse(T forSchema, T withoutSchema) {
382382
return getDefaultSupportInfo().ifSchemaElse(forSchema, withoutSchema);
383383
}
384384

385+
/**
386+
* Helper method that replaces {@code "PUBLIC"} with {@code ""} if schemas are not supported.
387+
*
388+
* @param schemaName
389+
* schema name
390+
* @return {@code schemaName}, or &mdash; if {@code schemaName} is {@code "PUBLIC"} and schemas are not supported
391+
* &mdash; {@code ""}
392+
*/
393+
public static String resolveSchema(String schemaName) {
394+
if (!getDefaultSupportInfo().supportsSchemas() && "PUBLIC".equals(schemaName)) {
395+
return "";
396+
}
397+
return schemaName;
398+
}
399+
385400
private FBTestProperties() {
386401
// No instantiation
387402
}

src/test/org/firebirdsql/jdbc/FBDatabaseMetaDataProcedureColumnsTest.java

Lines changed: 121 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import org.firebirdsql.common.extension.UsesDatabaseExtension;
66
import org.firebirdsql.jaybird.props.PropertyNames;
7+
import org.firebirdsql.jaybird.util.ObjectReference;
78
import org.firebirdsql.jdbc.metadata.FbMetadataConstants;
89
import org.firebirdsql.util.FirebirdSupportInfo;
910
import org.junit.jupiter.api.AfterAll;
@@ -12,6 +13,7 @@
1213
import org.junit.jupiter.api.Test;
1314
import org.junit.jupiter.api.extension.RegisterExtension;
1415
import org.junit.jupiter.params.ParameterizedTest;
16+
import org.junit.jupiter.params.provider.CsvSource;
1517
import org.junit.jupiter.params.provider.NullSource;
1618
import org.junit.jupiter.params.provider.ValueSource;
1719

@@ -24,6 +26,8 @@
2426
import static org.firebirdsql.common.FBTestProperties.getDefaultSupportInfo;
2527
import static org.firebirdsql.common.FBTestProperties.getUrl;
2628
import static org.firebirdsql.common.FBTestProperties.ifSchemaElse;
29+
import static org.firebirdsql.common.FBTestProperties.resolveSchema;
30+
import static org.firebirdsql.common.FbAssumptions.assumeFeature;
2731
import static org.firebirdsql.common.JdbcResourceHelper.closeQuietly;
2832
import static org.firebirdsql.jdbc.FBDatabaseMetaDataProceduresTest.isIgnoredProcedure;
2933
import static org.firebirdsql.jdbc.metadata.FbMetadataConstants.*;
@@ -38,8 +42,7 @@
3842
*/
3943
class FBDatabaseMetaDataProcedureColumnsTest {
4044

41-
// TODO Add schema support: tests involving other schema
42-
// TODO This test will need to be expanded with version dependent features
45+
// TODO This test will need to be expanded with version dependent features
4346
// (eg TYPE OF <domain> (2.1), TYPE OF COLUMN <table.column> (2.5), NOT NULL (2.1), DEFAULT <value> (2.0)
4447

4548
private static final String CREATE_NORMAL_PROC_NO_ARG_NO_RETURN = """
@@ -104,6 +107,18 @@ param2 VARCHAR(100) default 'param2 default')
104107
end
105108
end""";
106109

110+
private static final String CREATE_OTHER_SCHEMA = "create schema OTHER_SCHEMA";
111+
112+
private static final String CREATE_OTHER_SCHEMA_PROC_WITH_RETURN = """
113+
create procedure OTHER_SCHEMA.PROC_WITH_RETURN
114+
( PARAM1 varchar(100),
115+
PARAM2 decimal(18,2))
116+
RETURNS (return1 VARCHAR(200))
117+
AS
118+
BEGIN
119+
return1 = param1 || param1;
120+
END""";
121+
107122
private static final MetadataResultSetDefinition getProcedureColumnsDefinition =
108123
new MetadataResultSetDefinition(ProcedureColumnMetaData.class);
109124

@@ -147,6 +162,10 @@ private static List<String> getCreateStatements() {
147162
statements.add(CREATE_PACKAGE_WITH_PROCEDURE);
148163
statements.add(CREATE_PACKAGE_BODY_WITH_PROCEDURE);
149164
}
165+
if (supportInfo.supportsSchemas()) {
166+
statements.add(CREATE_OTHER_SCHEMA);
167+
statements.add(CREATE_OTHER_SCHEMA_PROC_WITH_RETURN);
168+
}
150169
return statements;
151170
}
152171

@@ -174,11 +193,20 @@ void testProcedureColumns_noArg_noReturn() throws Exception {
174193
/**
175194
* Tests getProcedureColumn with normal_proc_no_return using all columnPattern, expecting result set with all defined rows.
176195
*/
177-
@Test
178-
void testProcedureColumns_normalProc_noReturn_allPattern() throws Exception {
196+
@ParameterizedTest
197+
@CsvSource(useHeadersInDisplayName = true, nullValues = "<NIL>", textBlock = """
198+
schemaPattern, columnNamePattern
199+
<NIL>, <NIL>
200+
%, <NIL>
201+
PUBLIC, %
202+
<NIL>, %
203+
""")
204+
void testProcedureColumns_normalProc_noReturn_allPattern(String schemaPattern, String columnNamePattern)
205+
throws Exception {
179206
var expectedColumns = getNormalProcNoReturn_allColumns();
180207

181-
ResultSet procedureColumns = dbmd.getProcedureColumns(null, null, "NORMAL_PROC_NO_RETURN", "%");
208+
ResultSet procedureColumns = dbmd
209+
.getProcedureColumns(null, resolveSchema(schemaPattern), "NORMAL_PROC_NO_RETURN", columnNamePattern);
182210
validate(procedureColumns, expectedColumns);
183211
}
184212

@@ -273,7 +301,11 @@ void testProcedureColumns_useCatalogAsPackage_everything() throws Exception {
273301
try (var connection = DriverManager.getConnection(getUrl(), props)) {
274302
dbmd = connection.getMetaData();
275303

276-
var expectedColumns = new ArrayList<>(getNormalProcNoReturn_allColumns());
304+
var expectedColumns = new ArrayList<Map<ProcedureColumnMetaData, Object>>();
305+
if (supportInfo.supportsSchemas()) {
306+
expectedColumns.addAll(getOtherSchemaProcWithReturn_allColumns());
307+
}
308+
expectedColumns.addAll(getNormalProcNoReturn_allColumns());
277309
expectedColumns.addAll(getNormalProcWithReturn_allColumns());
278310
expectedColumns.addAll(getQuotedProcNoReturn_allColumns());
279311
withCatalog("", expectedColumns);
@@ -330,10 +362,10 @@ void testProcedureColumns_useCatalogAsPackage_specificPackageProcedureColumn(Str
330362
dbmd = connection.getMetaData();
331363

332364
List<Map<ProcedureColumnMetaData, Object>> expectedColumns =
333-
withCatalog("WITH$PROCEDURE",
334-
withSpecificName(ifSchemaElse("\"PUBLIC\".", "") + "\"WITH$PROCEDURE\".\"IN$PACKAGE\"",
335-
List.of(createNumericalType(Types.INTEGER, "IN$PACKAGE", "RETURN1", 1, 10, 0, true,
336-
DatabaseMetaData.procedureColumnOut))));
365+
withCatalog("WITH$PROCEDURE", withSpecificName(
366+
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$PROCEDURE", "IN$PACKAGE").toString(),
367+
List.of(createNumericalType(Types.INTEGER, "IN$PACKAGE", "RETURN1", 1, 10, 0, true,
368+
DatabaseMetaData.procedureColumnOut))));
337369

338370
ResultSet procedureColumns = dbmd.getProcedureColumns(catalog, null, "IN$PACKAGE", "RETURN1");
339371
validate(procedureColumns, expectedColumns);
@@ -349,7 +381,11 @@ void testProcedureColumns_useCatalogAsPackage_nonPackagedOnly() throws Exception
349381
try (var connection = DriverManager.getConnection(getUrl(), props)) {
350382
dbmd = connection.getMetaData();
351383

352-
var expectedColumns = new ArrayList<>(getNormalProcNoReturn_allColumns());
384+
var expectedColumns = new ArrayList<Map<ProcedureColumnMetaData, Object>>();
385+
if (supportInfo.supportsSchemas()) {
386+
expectedColumns.addAll(getOtherSchemaProcWithReturn_allColumns());
387+
}
388+
expectedColumns.addAll(getNormalProcNoReturn_allColumns());
353389
expectedColumns.addAll(getNormalProcWithReturn_allColumns());
354390
expectedColumns.addAll(getQuotedProcNoReturn_allColumns());
355391
withCatalog("", expectedColumns);
@@ -360,15 +396,47 @@ void testProcedureColumns_useCatalogAsPackage_nonPackagedOnly() throws Exception
360396
}
361397

362398
private static List<Map<ProcedureColumnMetaData, Object>> getInPackage_allColumns() {
363-
return withCatalog("WITH$PROCEDURE",
364-
withSpecificName(ifSchemaElse("\"PUBLIC\".", "") + "\"WITH$PROCEDURE\".\"IN$PACKAGE\"",
365-
// TODO Having result columns first might be against JDBC spec
366-
// TODO Describing result columns as procedureColumnOut might be against JDBC spec
367-
List.of(
368-
createNumericalType(Types.INTEGER, "IN$PACKAGE", "RETURN1", 1, 10, 0, true,
369-
DatabaseMetaData.procedureColumnOut),
370-
createNumericalType(Types.INTEGER, "IN$PACKAGE", "PARAM1", 1, 10, 0, true,
371-
DatabaseMetaData.procedureColumnIn))));
399+
return withCatalog("WITH$PROCEDURE", withSpecificName(
400+
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$PROCEDURE", "IN$PACKAGE").toString(),
401+
// TODO Having result columns first might be against JDBC spec
402+
// TODO Describing result columns as procedureColumnOut might be against JDBC spec
403+
List.of(
404+
createNumericalType(Types.INTEGER, "IN$PACKAGE", "RETURN1", 1, 10, 0, true,
405+
DatabaseMetaData.procedureColumnOut),
406+
createNumericalType(Types.INTEGER, "IN$PACKAGE", "PARAM1", 1, 10, 0, true,
407+
DatabaseMetaData.procedureColumnIn))));
408+
}
409+
410+
/**
411+
* Tests getProcedureColumn with OTHER_SCHEMA.PROC_WITH_RETURN, expecting result set with all defined rows.
412+
*/
413+
@ParameterizedTest
414+
@CsvSource(useHeadersInDisplayName = true, nullValues = "<NIL>", textBlock = """
415+
schemaPattern, procedureNamePattern, columnNamePattern
416+
OTHER_SCHEMA, PROC_WITH_RETURN, %
417+
OTHER\\_SCHEMA, PROC\\_WITH\\_RETURN, <NIL>
418+
OTHER%, PROC\\_WITH\\_RETURN, <NIL>
419+
""")
420+
void testProcedureColumns_otherSchemaProcWithReturn_all(String schemaPattern, String procedureNamePattern,
421+
String columnNamePattern) throws Exception {
422+
assumeFeature(FirebirdSupportInfo::supportsSchemas, "Test requires schema support");
423+
var expectedColumns = getOtherSchemaProcWithReturn_allColumns();
424+
425+
ResultSet procedureColumns = dbmd
426+
.getProcedureColumns(null, schemaPattern, procedureNamePattern, columnNamePattern);
427+
validate(procedureColumns, expectedColumns);
428+
}
429+
430+
private static List<Map<ProcedureColumnMetaData, Object>> getOtherSchemaProcWithReturn_allColumns() {
431+
return List.of(
432+
// TODO Having result columns first might be against JDBC spec
433+
// TODO Describing result columns as procedureColumnOut might be against JDBC spec
434+
createStringType(Types.VARCHAR, "OTHER_SCHEMA", "PROC_WITH_RETURN", "RETURN1", 1, 200, true,
435+
DatabaseMetaData.procedureColumnOut),
436+
createStringType(Types.VARCHAR, "OTHER_SCHEMA", "PROC_WITH_RETURN", "PARAM1", 1, 100, true,
437+
DatabaseMetaData.procedureColumnIn),
438+
createNumericalType(Types.DECIMAL, "OTHER_SCHEMA", "PROC_WITH_RETURN", "PARAM2", 2,
439+
NUMERIC_BIGINT_PRECISION, 2, true, DatabaseMetaData.procedureColumnIn));
372440
}
373441

374442
// TODO Add tests for more complex patterns for procedure and column
@@ -392,12 +460,6 @@ private void validate(ResultSet procedureColumns, List<Map<ProcedureColumnMetaDa
392460
}
393461
}
394462

395-
private static Map<ProcedureColumnMetaData, Object> createColumn(String procedureName, String columnName,
396-
int ordinalPosition, boolean nullable, int columnType) {
397-
return createColumn(ifSchemaElse("PUBLIC", null), procedureName, columnName, ordinalPosition, nullable,
398-
columnType);
399-
}
400-
401463
private static Map<ProcedureColumnMetaData, Object> createColumn(String schema, String procedureName,
402464
String columnName, int ordinalPosition, boolean nullable, int columnType) {
403465
Map<ProcedureColumnMetaData, Object> rules = getDefaultValueValidationRules();
@@ -416,19 +478,21 @@ private static Map<ProcedureColumnMetaData, Object> createColumn(String schema,
416478

417479
private static String getProcedureSpecificName(String schema, String procedureName) {
418480
if (schema == null || schema.isEmpty()) return procedureName;
419-
var quote = QuoteStrategy.DIALECT_3;
420-
// 5 = 4 quotes + 1 period
421-
var sb = new StringBuilder(schema.length() + procedureName.length() + 5);
422-
quote.appendQuoted(schema, sb).append('.');
423-
quote.appendQuoted(procedureName, sb);
424-
return sb.toString();
481+
return ObjectReference.of(schema, procedureName).toString();
425482
}
426483

427484
@SuppressWarnings("SameParameterValue")
428485
private static Map<ProcedureColumnMetaData, Object> createStringType(int jdbcType, String procedureName,
429486
String columnName, int ordinalPosition, int length, boolean nullable, int columnType) {
487+
return createStringType(jdbcType, ifSchemaElse("PUBLIC", null), procedureName, columnName, ordinalPosition, length,
488+
nullable, columnType);
489+
}
490+
491+
private static Map<ProcedureColumnMetaData, Object> createStringType(int jdbcType, String schema,
492+
String procedureName, String columnName, int ordinalPosition, int length, boolean nullable,
493+
int columnType) {
430494
Map<ProcedureColumnMetaData, Object> rules =
431-
createColumn(procedureName, columnName, ordinalPosition, nullable, columnType);
495+
createColumn(schema, procedureName, columnName, ordinalPosition, nullable, columnType);
432496
rules.put(ProcedureColumnMetaData.DATA_TYPE, jdbcType);
433497
String typeName = switch (jdbcType) {
434498
case Types.CHAR, Types.BINARY -> "CHAR";
@@ -445,8 +509,15 @@ private static Map<ProcedureColumnMetaData, Object> createStringType(int jdbcTyp
445509
@SuppressWarnings("SameParameterValue")
446510
private static Map<ProcedureColumnMetaData, Object> createNumericalType(int jdbcType, String procedureName,
447511
String columnName, int ordinalPosition, int precision, int scale, boolean nullable, int columnType) {
512+
return createNumericalType(jdbcType, ifSchemaElse("PUBLIC", null), procedureName, columnName, ordinalPosition,
513+
precision, scale, nullable, columnType);
514+
}
515+
516+
private static Map<ProcedureColumnMetaData, Object> createNumericalType(int jdbcType, String schema,
517+
String procedureName, String columnName, int ordinalPosition, int precision, int scale, boolean nullable,
518+
int columnType) {
448519
Map<ProcedureColumnMetaData, Object> rules =
449-
createColumn(procedureName, columnName, ordinalPosition, nullable, columnType);
520+
createColumn(schema, procedureName, columnName, ordinalPosition, nullable, columnType);
450521
rules.put(ProcedureColumnMetaData.DATA_TYPE, jdbcType);
451522
String typeName;
452523
int length;
@@ -483,8 +554,15 @@ private static Map<ProcedureColumnMetaData, Object> createNumericalType(int jdbc
483554
@SuppressWarnings("SameParameterValue")
484555
private static Map<ProcedureColumnMetaData, Object> createDateTime(int jdbcType, String procedureName,
485556
String columnName, int ordinalPosition, boolean nullable, int columnType) {
557+
return createDateTime(jdbcType, ifSchemaElse("PUBLIC", null), procedureName, columnName, ordinalPosition,
558+
nullable, columnType);
559+
}
560+
561+
@SuppressWarnings("SameParameterValue")
562+
private static Map<ProcedureColumnMetaData, Object> createDateTime(int jdbcType, String schema,
563+
String procedureName, String columnName, int ordinalPosition, boolean nullable, int columnType) {
486564
Map<ProcedureColumnMetaData, Object> rules =
487-
createColumn(procedureName, columnName, ordinalPosition, nullable, columnType);
565+
createColumn(schema, procedureName, columnName, ordinalPosition, nullable, columnType);
488566
rules.put(ProcedureColumnMetaData.DATA_TYPE, jdbcType);
489567
String typeName;
490568
int precision;
@@ -526,8 +604,14 @@ private static Map<ProcedureColumnMetaData, Object> createDateTime(int jdbcType,
526604
@SuppressWarnings("SameParameterValue")
527605
private static Map<ProcedureColumnMetaData, Object> createDouble(String procedureName, String columnName,
528606
int ordinalPosition, boolean nullable, int columnType) {
607+
return createDouble(ifSchemaElse("PUBLIC", null), procedureName, columnName, ordinalPosition, nullable,
608+
columnType);
609+
}
610+
611+
private static Map<ProcedureColumnMetaData, Object> createDouble(String schema, String procedureName,
612+
String columnName, int ordinalPosition, boolean nullable, int columnType) {
529613
Map<ProcedureColumnMetaData, Object> rules =
530-
createColumn(procedureName, columnName, ordinalPosition, nullable, columnType);
614+
createColumn(schema, procedureName, columnName, ordinalPosition, nullable, columnType);
531615
rules.put(ProcedureColumnMetaData.DATA_TYPE, Types.DOUBLE);
532616
rules.put(ProcedureColumnMetaData.TYPE_NAME, "DOUBLE PRECISION");
533617
if (getDefaultSupportInfo().supportsFloatBinaryPrecision()) {
@@ -547,6 +631,7 @@ private static Map<ProcedureColumnMetaData, Object> withRemark(Map<ProcedureColu
547631
return column;
548632
}
549633

634+
@SuppressWarnings("SameParameterValue")
550635
private static Map<ProcedureColumnMetaData, Object> withDefault(String defaultDefinition,
551636
Map<ProcedureColumnMetaData, Object> rules) {
552637
rules.put(ProcedureColumnMetaData.COLUMN_DEF, defaultDefinition);

0 commit comments

Comments
 (0)