Skip to content

Commit ec1056e

Browse files
committed
SPECIFIC_NAME should not include the schema
1 parent 4a83dec commit ec1056e

11 files changed

Lines changed: 44 additions & 80 deletions

src/main/org/firebirdsql/jdbc/FBDatabaseMetaData.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,9 +1211,8 @@ public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
12111211
* <li>Column {@code PROCEDURE_CAT} for normal procedures is empty string ({@code ""}) instead of {@code null},
12121212
* for packaged procedures it is the package name</li>
12131213
* <li>Column {@code SPECIFIC_NAME} for packaged procedures will report
1214-
* {@code [<quoted-schema-name>.]<quoted-package-name>.<quoted-procedure-name>} (on Firebird 5.0 and older, normal
1215-
* procedures will report the same as column {@code PROCEDURE_NAME}, the unquoted name, on Firebird 6.0 and higher,
1216-
* {@code <quoted-schema-name>.<quoted-procedure-name>})</li>
1214+
* {@code <quoted-package-name>.<quoted-procedure-name>} (normal procedures will report the same as column
1215+
* {@code PROCEDURE_NAME}, the unquoted name)</li>
12171216
* </ul>
12181217
*/
12191218
@Override

src/main/org/firebirdsql/jdbc/metadata/GetFunctionColumns.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ final RowValue createMetadataRow(ResultSet rs, RowValueBuilder valueBuilder) thr
114114
.at(13).setInt(typeMetadata.getCharOctetLength())
115115
.at(14).setInt(ordinalPosition)
116116
.at(15).setString(nullable ? "YES" : "NO")
117-
.at(16).setString(toSpecificName(catalog, schema, functionName))
117+
.at(16).setString(toSpecificName(catalog, functionName))
118118
.toRowValue(false);
119119
}
120120

src/main/org/firebirdsql/jdbc/metadata/GetFunctions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ final RowValue createMetadataRow(ResultSet rs, RowValueBuilder valueBuilder) thr
8181
.at(2).setString(functionName)
8282
.at(3).setString(rs.getString("REMARKS"))
8383
.at(4).setShort(functionNoTable)
84-
.at(5).setString(toSpecificName(catalog, schema, functionName))
84+
.at(5).setString(toSpecificName(catalog, functionName))
8585
.at(6).setString(rs.getString("JB_FUNCTION_SOURCE"))
8686
.at(7).setString(rs.getString("JB_FUNCTION_KIND"))
8787
.at(8).setString(rs.getString("JB_MODULE_NAME"))

src/main/org/firebirdsql/jdbc/metadata/GetProcedureColumns.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ final RowValue createMetadataRow(ResultSet rs, RowValueBuilder valueBuilder) thr
127127
.at(17).setInt(rs.getInt("PARAMETER_NUMBER"))
128128
// TODO: Find out if there is a conceptual difference with NULLABLE (idx 11)
129129
.at(18).setString(nullFlag == 1 ? "NO" : "YES")
130-
.at(19).setString(toSpecificName(catalog, schema, procedureName))
130+
.at(19).setString(toSpecificName(catalog, procedureName))
131131
.toRowValue(false);
132132
}
133133

src/main/org/firebirdsql/jdbc/metadata/GetProcedures.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ final RowValue createMetadataRow(ResultSet rs, RowValueBuilder valueBuilder) thr
8181
.at(2).setString(procedureName)
8282
.at(6).setString(rs.getString("REMARKS"))
8383
.at(7).setShort(rs.getShort("PROCEDURE_TYPE") == 0 ? procedureNoResult : procedureReturnsResult)
84-
.at(8).setString(toSpecificName(catalog, schema, procedureName))
84+
.at(8).setString(toSpecificName(catalog, procedureName))
8585
.at(9).setShort(rs.getShort("JB_PROCEDURE_TYPE"))
8686
.at(10).setString(rs.getString("JB_PROCEDURE_SOURCE"))
8787
.toRowValue(true);

src/main/org/firebirdsql/jdbc/metadata/NameHelper.java

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,48 +25,31 @@ private NameHelper() {
2525
* Generates a name for the {@code SPECIFIC_NAME} column of {@code getFunctions}, {@code getFunctionColumns},
2626
* {@code getProcedures} and {@code getProcedureColumns}.
2727
* <p>
28+
* According to the JDBC API documentation, the specific name <i>uniquely identifies this [routine]
29+
* within its schema</i>. In other words, the schema itself is not part of the specific name. Its intention is to
30+
* disambiguate overloads (which Firebird doesn't have). ISO 9075-11 (Schemata) only says it is the qualified
31+
* identifier of the routine. Be aware that the name we generate for a packaged routine does not comply with these
32+
* definitions.
33+
* </p>
34+
* <p>
2835
* The specific name is generated as follows:
2936
* </p>
3037
* <ul>
31-
* <li>
32-
* <p>For Firebird versions <em>without</em> schema support</p>
33-
* <ul>
34-
* <li>for non-packaged routines, the {@code routineName}</li>
35-
* <li>for packaged routines, both {@code catalog} (package name) and {@code routineName} are transformed to
36-
* quoted identifiers and separated by {@code .} (period)</li>
37-
* </ul>
38-
* </li>
39-
* <li>
40-
* <p>For Firebird versions <em>with</em> schema support</p>
41-
* <ul>
42-
* <li>for non-packaged routines, both {@code schema} and {@code routineName} are transformed to
43-
* quoted identifiers and separated by {@code .} (period)</li>
44-
* <li>for packaged routines, {@code catalog} (package name), {@code schema} and {@code routineName} are
45-
* transformed to quoted identifiers and separated by {@code .} (period)</li>
46-
* </ul>
47-
* </li>
38+
* <li>for non-packaged routines, {@code routineName} is returned as-is</li>
39+
* <li>for packaged routines, {@code catalog} (package name) and {@code routineName} are transformed to quoted
40+
* identifiers and separated by {@code .} (period)</li>
4841
* </ul>
4942
*
5043
* @param catalog
5144
* generally {@code null}, or &mdash; when {@code useCatalogAsPackage = true} &mdash; an empty string (no
5245
* package) or a package name
53-
* @param schema
54-
* schema name, or {@code null} for Firebird versions without schema support, empty string is handled same
55-
* as {@code null}
5646
* @param routineName
5747
* name of the routine (procedure or function)
5848
* @return specific name
5949
* @since 7
6050
*/
61-
static String toSpecificName(@Nullable String catalog, @Nullable String schema, String routineName) {
62-
if (isNullOrEmpty(catalog) && isNullOrEmpty(schema)) {
63-
// TODO Add schema support: consider quoting always for consistency
64-
return routineName;
65-
} else if (isNullOrEmpty(catalog)) {
66-
return ObjectReference.of(schema, routineName).toString();
67-
}
68-
// this order assumes the catalog actually represents the package name
69-
return ObjectReference.of(schema, catalog, routineName).toString();
51+
static String toSpecificName(@Nullable String catalog, String routineName) {
52+
return isNullOrEmpty(catalog) ? routineName : ObjectReference.of(catalog, routineName).toString();
7053
}
7154

7255
}

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void testFunctionColumnMetaData_useCatalogAsPackage_specificPackageProcedureColu
374374
try (var connection = DriverManager.getConnection(getUrl(), props)) {
375375
dbmd = connection.getMetaData();
376376
List<Map<FunctionColumnMetaData, Object>> expectedColumns = withCatalog("WITH$FUNCTION", withSpecificName(
377-
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$FUNCTION", "IN$PACKAGE").toString(),
377+
ObjectReference.of("WITH$FUNCTION", "IN$PACKAGE").toString(),
378378
List.of(createNumericalType(Types.INTEGER, "IN$PACKAGE", "PARAM1", 1, 10, 0, true))));
379379
validateExpectedFunctionColumns(catalog, "IN$PACKAGE", "PARAM1", expectedColumns);
380380
}
@@ -536,7 +536,7 @@ private static List<Map<FunctionColumnMetaData, Object>> getUdfExample2Columns()
536536

537537
private static List<Map<FunctionColumnMetaData, Object>> getWithFunctionInPackageColumns() {
538538
return withCatalog("WITH$FUNCTION",
539-
withSpecificName(ifSchemaElse("\"PUBLIC\".", "") + "\"WITH$FUNCTION\".\"IN$PACKAGE\"",
539+
withSpecificName("\"WITH$FUNCTION\".\"IN$PACKAGE\"",
540540
List.of(
541541
withColumnTypeFunctionReturn(
542542
createNumericalType(Types.INTEGER, "IN$PACKAGE", "PARAM_0", 0, 10, 0, true)),
@@ -569,8 +569,7 @@ private static List<Map<FunctionColumnMetaData, Object>> withSpecificName(String
569569
private static List<Map<FunctionColumnMetaData, Object>> withSchema(String schema,
570570
List<Map<FunctionColumnMetaData, Object>> rules) {
571571
for (Map<FunctionColumnMetaData, Object> rowRule : rules) {
572-
String functionName = (String) rowRule.get(FunctionColumnMetaData.FUNCTION_NAME);
573-
rowRule.put(FunctionColumnMetaData.SPECIFIC_NAME, ObjectReference.of(schema, functionName).toString());
572+
rowRule.put(FunctionColumnMetaData.SPECIFIC_NAME, rowRule.get(FunctionColumnMetaData.FUNCTION_NAME));
574573
rowRule.put(FunctionColumnMetaData.FUNCTION_SCHEM, schema);
575574
}
576575
return rules;
@@ -580,8 +579,7 @@ private static Map<FunctionColumnMetaData, Object> createColumn(String functionN
580579
int ordinalPosition, boolean nullable) {
581580
Map<FunctionColumnMetaData, Object> rules = getDefaultValidationRules();
582581
rules.put(FunctionColumnMetaData.FUNCTION_NAME, functionName);
583-
rules.put(FunctionColumnMetaData.SPECIFIC_NAME, ifSchemaElse(
584-
ObjectReference.of("PUBLIC", functionName).toString(), functionName));
582+
rules.put(FunctionColumnMetaData.SPECIFIC_NAME, functionName);
585583
rules.put(FunctionColumnMetaData.COLUMN_NAME, columnName);
586584
rules.put(FunctionColumnMetaData.ORDINAL_POSITION, ordinalPosition);
587585
if (nullable) {

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,7 @@ private static Map<FunctionMetaData, Object> getPsqlExample(boolean useCatalogAs
340340
rules.put(FunctionMetaData.FUNCTION_CAT, "");
341341
}
342342
rules.put(FunctionMetaData.FUNCTION_NAME, "PSQL$EXAMPLE");
343-
rules.put(FunctionMetaData.SPECIFIC_NAME, ifSchemaElse(
344-
ObjectReference.of("PUBLIC", "PSQL$EXAMPLE").toString(), "PSQL$EXAMPLE"));
343+
rules.put(FunctionMetaData.SPECIFIC_NAME, "PSQL$EXAMPLE");
345344
if (supportsComments) {
346345
rules.put(FunctionMetaData.REMARKS, "Comment on PSQL$EXAMPLE");
347346
}
@@ -364,7 +363,7 @@ private static Map<FunctionMetaData, Object> getOtherSchemaPsqlExample(boolean u
364363
}
365364
rules.put(FunctionMetaData.FUNCTION_SCHEM, "OTHER_SCHEMA");
366365
rules.put(FunctionMetaData.FUNCTION_NAME, "PSQL$EXAMPLE");
367-
rules.put(FunctionMetaData.SPECIFIC_NAME, ObjectReference.of("OTHER_SCHEMA", "PSQL$EXAMPLE").toString());
366+
rules.put(FunctionMetaData.SPECIFIC_NAME, "PSQL$EXAMPLE");
368367
rules.put(FunctionMetaData.JB_FUNCTION_SOURCE, """
369368
begin
370369
return cast(x as varchar(50));
@@ -384,7 +383,7 @@ private static Map<FunctionMetaData, Object> getOtherSchemaPsqlExample2(boolean
384383
}
385384
rules.put(FunctionMetaData.FUNCTION_SCHEM, "OTHER_SCHEMA");
386385
rules.put(FunctionMetaData.FUNCTION_NAME, "PSQL$EXAMPLE2");
387-
rules.put(FunctionMetaData.SPECIFIC_NAME, ObjectReference.of("OTHER_SCHEMA", "PSQL$EXAMPLE2").toString());
386+
rules.put(FunctionMetaData.SPECIFIC_NAME, "PSQL$EXAMPLE2");
388387
rules.put(FunctionMetaData.JB_FUNCTION_SOURCE, """
389388
begin
390389
return X+1;
@@ -404,8 +403,7 @@ private static Map<FunctionMetaData, Object> getUdfExample(boolean useCatalogAsP
404403
rules.put(FunctionMetaData.FUNCTION_CAT, "");
405404
}
406405
rules.put(FunctionMetaData.FUNCTION_NAME, "UDF$EXAMPLE");
407-
rules.put(FunctionMetaData.SPECIFIC_NAME, ifSchemaElse(
408-
ObjectReference.of("PUBLIC", "UDF$EXAMPLE").toString(), "UDF$EXAMPLE"));
406+
rules.put(FunctionMetaData.SPECIFIC_NAME, "UDF$EXAMPLE");
409407
if (supportsComments) {
410408
rules.put(FunctionMetaData.REMARKS, "Comment on UDF$EXAMPLE");
411409
}
@@ -419,8 +417,7 @@ private static Map<FunctionMetaData, Object> getPackageFunctionExample() {
419417
Map<FunctionMetaData, Object> rules = getDefaultValidationRules();
420418
rules.put(FunctionMetaData.FUNCTION_CAT, "WITH$FUNCTION");
421419
rules.put(FunctionMetaData.FUNCTION_NAME, "IN$PACKAGE");
422-
rules.put(FunctionMetaData.SPECIFIC_NAME,
423-
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$FUNCTION", "IN$PACKAGE").toString());
420+
rules.put(FunctionMetaData.SPECIFIC_NAME, ObjectReference.of("WITH$FUNCTION", "IN$PACKAGE").toString());
424421
// Stored with package
425422
rules.put(FunctionMetaData.JB_FUNCTION_SOURCE, null);
426423
rules.put(FunctionMetaData.JB_FUNCTION_KIND, "PSQL");

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ void testProcedureColumns_useCatalogAsPackage_specificPackageProcedureColumn(Str
363363

364364
List<Map<ProcedureColumnMetaData, Object>> expectedColumns =
365365
withCatalog("WITH$PROCEDURE", withSpecificName(
366-
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$PROCEDURE", "IN$PACKAGE").toString(),
366+
ObjectReference.of("WITH$PROCEDURE", "IN$PACKAGE").toString(),
367367
List.of(createNumericalType(Types.INTEGER, "IN$PACKAGE", "RETURN1", 1, 10, 0, true,
368368
DatabaseMetaData.procedureColumnOut))));
369369

@@ -397,7 +397,7 @@ void testProcedureColumns_useCatalogAsPackage_nonPackagedOnly() throws Exception
397397

398398
private static List<Map<ProcedureColumnMetaData, Object>> getInPackage_allColumns() {
399399
return withCatalog("WITH$PROCEDURE", withSpecificName(
400-
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$PROCEDURE", "IN$PACKAGE").toString(),
400+
ObjectReference.of("WITH$PROCEDURE", "IN$PACKAGE").toString(),
401401
// TODO Having result columns first might be against JDBC spec
402402
// TODO Describing result columns as procedureColumnOut might be against JDBC spec
403403
List.of(
@@ -465,7 +465,7 @@ private static Map<ProcedureColumnMetaData, Object> createColumn(String schema,
465465
Map<ProcedureColumnMetaData, Object> rules = getDefaultValueValidationRules();
466466
rules.put(ProcedureColumnMetaData.PROCEDURE_SCHEM, schema);
467467
rules.put(ProcedureColumnMetaData.PROCEDURE_NAME, procedureName);
468-
rules.put(ProcedureColumnMetaData.SPECIFIC_NAME, getProcedureSpecificName(schema, procedureName));
468+
rules.put(ProcedureColumnMetaData.SPECIFIC_NAME, procedureName);
469469
rules.put(ProcedureColumnMetaData.COLUMN_NAME, columnName);
470470
rules.put(ProcedureColumnMetaData.ORDINAL_POSITION, ordinalPosition);
471471
rules.put(ProcedureColumnMetaData.COLUMN_TYPE, columnType);
@@ -476,11 +476,6 @@ private static Map<ProcedureColumnMetaData, Object> createColumn(String schema,
476476
return rules;
477477
}
478478

479-
private static String getProcedureSpecificName(String schema, String procedureName) {
480-
if (schema == null || schema.isEmpty()) return procedureName;
481-
return ObjectReference.of(schema, procedureName).toString();
482-
}
483-
484479
@SuppressWarnings("SameParameterValue")
485480
private static Map<ProcedureColumnMetaData, Object> createStringType(int jdbcType, String procedureName,
486481
String columnName, int ordinalPosition, int length, boolean nullable, int columnType) {

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,7 @@ static boolean isIgnoredProcedure(String specificName) {
345345
final class Ignored {
346346
// Skipping procedures from system packages (when testing with useCatalogAsPackage=true)
347347
private static final List<String> PREFIXES_TO_IGNORE =
348-
List.of("\"SYSTEM\".\"RDB$", "\"RDB$BLOB_UTIL\".", "\"RDB$PROFILER\".", "\"RDB$TIME_ZONE_UTIL\".",
349-
"\"RDB$SQL\".");
348+
List.of("\"RDB$BLOB_UTIL\".", "\"RDB$PROFILER\".", "\"RDB$TIME_ZONE_UTIL\".", "\"RDB$SQL\".");
350349
}
351350
return Ignored.PREFIXES_TO_IGNORE.stream().anyMatch(specificName::startsWith);
352351
}
@@ -439,8 +438,7 @@ Map<ProcedureMetaData, Object> getSpecificValidationRules(Map<ProcedureMetaData,
439438
rules.put(ProcedureMetaData.PROCEDURE_NAME, "NORMAL_PROC_NO_RETURN");
440439
rules.put(ProcedureMetaData.PROCEDURE_TYPE, DatabaseMetaData.procedureNoResult);
441440
rules.put(ProcedureMetaData.JB_PROCEDURE_TYPE, FirebirdDatabaseMetaData.jbProcedureTypeExecutable);
442-
rules.put(ProcedureMetaData.SPECIFIC_NAME, ifSchemaElse(
443-
ObjectReference.of("PUBLIC", "NORMAL_PROC_NO_RETURN").toString(), "NORMAL_PROC_NO_RETURN"));
441+
rules.put(ProcedureMetaData.SPECIFIC_NAME, "NORMAL_PROC_NO_RETURN");
444442
rules.put(ProcedureMetaData.JB_PROCEDURE_SOURCE, extractBody(CREATE_NORMAL_PROC_NO_RETURN));
445443
return rules;
446444
}
@@ -453,8 +451,7 @@ Map<ProcedureMetaData, Object> getSpecificValidationRules(Map<ProcedureMetaData,
453451
rules.put(ProcedureMetaData.PROCEDURE_TYPE, DatabaseMetaData.procedureReturnsResult);
454452
rules.put(ProcedureMetaData.JB_PROCEDURE_TYPE, FirebirdDatabaseMetaData.jbProcedureTypeExecutable);
455453
rules.put(ProcedureMetaData.REMARKS, "Some comment");
456-
rules.put(ProcedureMetaData.SPECIFIC_NAME, ifSchemaElse(
457-
ObjectReference.of("PUBLIC", "NORMAL_PROC_WITH_RETURN").toString(), "NORMAL_PROC_WITH_RETURN"));
454+
rules.put(ProcedureMetaData.SPECIFIC_NAME, "NORMAL_PROC_WITH_RETURN");
458455
rules.put(ProcedureMetaData.JB_PROCEDURE_SOURCE, extractBody(CREATE_NORMAL_PROC_WITH_RETURN));
459456
return rules;
460457
}
@@ -466,8 +463,7 @@ Map<ProcedureMetaData, Object> getSpecificValidationRules(Map<ProcedureMetaData,
466463
rules.put(ProcedureMetaData.PROCEDURE_NAME, "quoted_proc_no_return");
467464
rules.put(ProcedureMetaData.PROCEDURE_TYPE, DatabaseMetaData.procedureNoResult);
468465
rules.put(ProcedureMetaData.JB_PROCEDURE_TYPE, FirebirdDatabaseMetaData.jbProcedureTypeExecutable);
469-
rules.put(ProcedureMetaData.SPECIFIC_NAME, ifSchemaElse(
470-
ObjectReference.of("PUBLIC", "quoted_proc_no_return").toString(), "quoted_proc_no_return"));
466+
rules.put(ProcedureMetaData.SPECIFIC_NAME, "quoted_proc_no_return");
471467
rules.put(ProcedureMetaData.JB_PROCEDURE_SOURCE, extractBody(CREATE_QUOTED_PROC_NO_RETURN));
472468
return rules;
473469
}
@@ -481,7 +477,7 @@ Map<ProcedureMetaData, Object> getSpecificValidationRules(Map<ProcedureMetaData,
481477
rules.put(ProcedureMetaData.PROCEDURE_TYPE, DatabaseMetaData.procedureReturnsResult);
482478
rules.put(ProcedureMetaData.JB_PROCEDURE_TYPE, FirebirdDatabaseMetaData.jbProcedureTypeExecutable);
483479
rules.put(ProcedureMetaData.SPECIFIC_NAME,
484-
ObjectReference.of(ifSchemaElse("PUBLIC", ""), "WITH$PROCEDURE", "IN$PACKAGE").toString());
480+
ObjectReference.of("WITH$PROCEDURE", "IN$PACKAGE").toString());
485481
// No procedure body for packaged procedures
486482
rules.put(ProcedureMetaData.JB_PROCEDURE_SOURCE, null);
487483
return rules;
@@ -504,8 +500,7 @@ Map<ProcedureMetaData, Object> getSpecificValidationRules(Map<ProcedureMetaData,
504500
rules.put(ProcedureMetaData.PROCEDURE_NAME, "PROC_NO_RETURN");
505501
rules.put(ProcedureMetaData.PROCEDURE_TYPE, DatabaseMetaData.procedureNoResult);
506502
rules.put(ProcedureMetaData.JB_PROCEDURE_TYPE, FirebirdDatabaseMetaData.jbProcedureTypeExecutable);
507-
rules.put(ProcedureMetaData.SPECIFIC_NAME,
508-
ObjectReference.of("OTHER_SCHEMA", "PROC_NO_RETURN").toString());
503+
rules.put(ProcedureMetaData.SPECIFIC_NAME, "PROC_NO_RETURN");
509504
rules.put(ProcedureMetaData.JB_PROCEDURE_SOURCE, extractBody(CREATE_OTHER_SCHEMA_PROC_NO_RETURN));
510505
return rules;
511506
}

0 commit comments

Comments
 (0)