4
4
5
5
import org .firebirdsql .common .extension .UsesDatabaseExtension ;
6
6
import org .firebirdsql .jaybird .props .PropertyNames ;
7
+ import org .firebirdsql .jaybird .util .ObjectReference ;
7
8
import org .firebirdsql .jdbc .metadata .FbMetadataConstants ;
8
9
import org .firebirdsql .util .FirebirdSupportInfo ;
9
10
import org .junit .jupiter .api .AfterAll ;
12
13
import org .junit .jupiter .api .Test ;
13
14
import org .junit .jupiter .api .extension .RegisterExtension ;
14
15
import org .junit .jupiter .params .ParameterizedTest ;
16
+ import org .junit .jupiter .params .provider .CsvSource ;
15
17
import org .junit .jupiter .params .provider .NullSource ;
16
18
import org .junit .jupiter .params .provider .ValueSource ;
17
19
24
26
import static org .firebirdsql .common .FBTestProperties .getDefaultSupportInfo ;
25
27
import static org .firebirdsql .common .FBTestProperties .getUrl ;
26
28
import static org .firebirdsql .common .FBTestProperties .ifSchemaElse ;
29
+ import static org .firebirdsql .common .FBTestProperties .resolveSchema ;
30
+ import static org .firebirdsql .common .FbAssumptions .assumeFeature ;
27
31
import static org .firebirdsql .common .JdbcResourceHelper .closeQuietly ;
28
32
import static org .firebirdsql .jdbc .FBDatabaseMetaDataProceduresTest .isIgnoredProcedure ;
29
33
import static org .firebirdsql .jdbc .metadata .FbMetadataConstants .*;
38
42
*/
39
43
class FBDatabaseMetaDataProcedureColumnsTest {
40
44
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
43
46
// (eg TYPE OF <domain> (2.1), TYPE OF COLUMN <table.column> (2.5), NOT NULL (2.1), DEFAULT <value> (2.0)
44
47
45
48
private static final String CREATE_NORMAL_PROC_NO_ARG_NO_RETURN = """
@@ -104,6 +107,18 @@ param2 VARCHAR(100) default 'param2 default')
104
107
end
105
108
end""" ;
106
109
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
+
107
122
private static final MetadataResultSetDefinition getProcedureColumnsDefinition =
108
123
new MetadataResultSetDefinition (ProcedureColumnMetaData .class );
109
124
@@ -147,6 +162,10 @@ private static List<String> getCreateStatements() {
147
162
statements .add (CREATE_PACKAGE_WITH_PROCEDURE );
148
163
statements .add (CREATE_PACKAGE_BODY_WITH_PROCEDURE );
149
164
}
165
+ if (supportInfo .supportsSchemas ()) {
166
+ statements .add (CREATE_OTHER_SCHEMA );
167
+ statements .add (CREATE_OTHER_SCHEMA_PROC_WITH_RETURN );
168
+ }
150
169
return statements ;
151
170
}
152
171
@@ -174,11 +193,20 @@ void testProcedureColumns_noArg_noReturn() throws Exception {
174
193
/**
175
194
* Tests getProcedureColumn with normal_proc_no_return using all columnPattern, expecting result set with all defined rows.
176
195
*/
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 {
179
206
var expectedColumns = getNormalProcNoReturn_allColumns ();
180
207
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 );
182
210
validate (procedureColumns , expectedColumns );
183
211
}
184
212
@@ -273,7 +301,11 @@ void testProcedureColumns_useCatalogAsPackage_everything() throws Exception {
273
301
try (var connection = DriverManager .getConnection (getUrl (), props )) {
274
302
dbmd = connection .getMetaData ();
275
303
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 ());
277
309
expectedColumns .addAll (getNormalProcWithReturn_allColumns ());
278
310
expectedColumns .addAll (getQuotedProcNoReturn_allColumns ());
279
311
withCatalog ("" , expectedColumns );
@@ -330,10 +362,10 @@ void testProcedureColumns_useCatalogAsPackage_specificPackageProcedureColumn(Str
330
362
dbmd = connection .getMetaData ();
331
363
332
364
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 ))));
337
369
338
370
ResultSet procedureColumns = dbmd .getProcedureColumns (catalog , null , "IN$PACKAGE" , "RETURN1" );
339
371
validate (procedureColumns , expectedColumns );
@@ -349,7 +381,11 @@ void testProcedureColumns_useCatalogAsPackage_nonPackagedOnly() throws Exception
349
381
try (var connection = DriverManager .getConnection (getUrl (), props )) {
350
382
dbmd = connection .getMetaData ();
351
383
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 ());
353
389
expectedColumns .addAll (getNormalProcWithReturn_allColumns ());
354
390
expectedColumns .addAll (getQuotedProcNoReturn_allColumns ());
355
391
withCatalog ("" , expectedColumns );
@@ -360,15 +396,47 @@ void testProcedureColumns_useCatalogAsPackage_nonPackagedOnly() throws Exception
360
396
}
361
397
362
398
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 ));
372
440
}
373
441
374
442
// TODO Add tests for more complex patterns for procedure and column
@@ -392,12 +460,6 @@ private void validate(ResultSet procedureColumns, List<Map<ProcedureColumnMetaDa
392
460
}
393
461
}
394
462
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
-
401
463
private static Map <ProcedureColumnMetaData , Object > createColumn (String schema , String procedureName ,
402
464
String columnName , int ordinalPosition , boolean nullable , int columnType ) {
403
465
Map <ProcedureColumnMetaData , Object > rules = getDefaultValueValidationRules ();
@@ -416,19 +478,21 @@ private static Map<ProcedureColumnMetaData, Object> createColumn(String schema,
416
478
417
479
private static String getProcedureSpecificName (String schema , String procedureName ) {
418
480
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 ();
425
482
}
426
483
427
484
@ SuppressWarnings ("SameParameterValue" )
428
485
private static Map <ProcedureColumnMetaData , Object > createStringType (int jdbcType , String procedureName ,
429
486
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 ) {
430
494
Map <ProcedureColumnMetaData , Object > rules =
431
- createColumn (procedureName , columnName , ordinalPosition , nullable , columnType );
495
+ createColumn (schema , procedureName , columnName , ordinalPosition , nullable , columnType );
432
496
rules .put (ProcedureColumnMetaData .DATA_TYPE , jdbcType );
433
497
String typeName = switch (jdbcType ) {
434
498
case Types .CHAR , Types .BINARY -> "CHAR" ;
@@ -445,8 +509,15 @@ private static Map<ProcedureColumnMetaData, Object> createStringType(int jdbcTyp
445
509
@ SuppressWarnings ("SameParameterValue" )
446
510
private static Map <ProcedureColumnMetaData , Object > createNumericalType (int jdbcType , String procedureName ,
447
511
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 ) {
448
519
Map <ProcedureColumnMetaData , Object > rules =
449
- createColumn (procedureName , columnName , ordinalPosition , nullable , columnType );
520
+ createColumn (schema , procedureName , columnName , ordinalPosition , nullable , columnType );
450
521
rules .put (ProcedureColumnMetaData .DATA_TYPE , jdbcType );
451
522
String typeName ;
452
523
int length ;
@@ -483,8 +554,15 @@ private static Map<ProcedureColumnMetaData, Object> createNumericalType(int jdbc
483
554
@ SuppressWarnings ("SameParameterValue" )
484
555
private static Map <ProcedureColumnMetaData , Object > createDateTime (int jdbcType , String procedureName ,
485
556
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 ) {
486
564
Map <ProcedureColumnMetaData , Object > rules =
487
- createColumn (procedureName , columnName , ordinalPosition , nullable , columnType );
565
+ createColumn (schema , procedureName , columnName , ordinalPosition , nullable , columnType );
488
566
rules .put (ProcedureColumnMetaData .DATA_TYPE , jdbcType );
489
567
String typeName ;
490
568
int precision ;
@@ -526,8 +604,14 @@ private static Map<ProcedureColumnMetaData, Object> createDateTime(int jdbcType,
526
604
@ SuppressWarnings ("SameParameterValue" )
527
605
private static Map <ProcedureColumnMetaData , Object > createDouble (String procedureName , String columnName ,
528
606
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 ) {
529
613
Map <ProcedureColumnMetaData , Object > rules =
530
- createColumn (procedureName , columnName , ordinalPosition , nullable , columnType );
614
+ createColumn (schema , procedureName , columnName , ordinalPosition , nullable , columnType );
531
615
rules .put (ProcedureColumnMetaData .DATA_TYPE , Types .DOUBLE );
532
616
rules .put (ProcedureColumnMetaData .TYPE_NAME , "DOUBLE PRECISION" );
533
617
if (getDefaultSupportInfo ().supportsFloatBinaryPrecision ()) {
@@ -547,6 +631,7 @@ private static Map<ProcedureColumnMetaData, Object> withRemark(Map<ProcedureColu
547
631
return column ;
548
632
}
549
633
634
+ @ SuppressWarnings ("SameParameterValue" )
550
635
private static Map <ProcedureColumnMetaData , Object > withDefault (String defaultDefinition ,
551
636
Map <ProcedureColumnMetaData , Object > rules ) {
552
637
rules .put (ProcedureColumnMetaData .COLUMN_DEF , defaultDefinition );
0 commit comments