Merge branch '6.1.x'
This commit is contained in:
@@ -22,7 +22,6 @@ import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -305,47 +304,42 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
|
||||
String metaDataSchemaName = metaDataSchemaNameToUse(schemaName);
|
||||
String metaDataProcedureName = procedureNameToUse(procedureName);
|
||||
try {
|
||||
String searchStringEscape = databaseMetaData.getSearchStringEscape();
|
||||
String escapedSchemaName = escapeNamePattern(metaDataSchemaName, searchStringEscape);
|
||||
String escapedProcedureName = escapeNamePattern(metaDataProcedureName, searchStringEscape);
|
||||
if (logger.isDebugEnabled()) {
|
||||
String schemaInfo = (Objects.equals(escapedSchemaName, metaDataSchemaName)
|
||||
? metaDataSchemaName : metaDataCatalogName + "(" + escapedSchemaName + ")");
|
||||
String procedureInfo = (Objects.equals(escapedProcedureName, metaDataProcedureName)
|
||||
? metaDataProcedureName : metaDataProcedureName + "(" + escapedProcedureName + ")");
|
||||
logger.debug("Retrieving meta-data for " + metaDataCatalogName + '/' +
|
||||
schemaInfo + '/' + procedureInfo);
|
||||
}
|
||||
|
||||
List<String> found = new ArrayList<>();
|
||||
boolean function = false;
|
||||
|
||||
try (ResultSet procedures = databaseMetaData.getProcedures(
|
||||
metaDataCatalogName, escapedSchemaName, escapedProcedureName)) {
|
||||
while (procedures.next()) {
|
||||
found.add(procedures.getString("PROCEDURE_CAT") + '.' + procedures.getString("PROCEDURE_SCHEM") +
|
||||
'.' + procedures.getString("PROCEDURE_NAME"));
|
||||
ProcedureMetadata procedureMetadata = getProcedureMetadata(databaseMetaData,
|
||||
metaDataCatalogName, metaDataSchemaName, metaDataProcedureName);
|
||||
if (procedureMetadata.hits() > 1) {
|
||||
// Try again with exact match in case of placeholders
|
||||
String searchStringEscape = databaseMetaData.getSearchStringEscape();
|
||||
if (searchStringEscape != null) {
|
||||
procedureMetadata = getProcedureMetadata(databaseMetaData, metaDataCatalogName,
|
||||
escapeNamePattern(metaDataSchemaName, searchStringEscape),
|
||||
escapeNamePattern(metaDataProcedureName, searchStringEscape));
|
||||
}
|
||||
}
|
||||
|
||||
if (found.isEmpty()) {
|
||||
if (procedureMetadata.hits() == 0) {
|
||||
// Functions not exposed as procedures anymore on PostgreSQL driver 42.2.11
|
||||
try (ResultSet functions = databaseMetaData.getFunctions(
|
||||
metaDataCatalogName, escapedSchemaName, escapedProcedureName)) {
|
||||
while (functions.next()) {
|
||||
found.add(functions.getString("FUNCTION_CAT") + '.' + functions.getString("FUNCTION_SCHEM") +
|
||||
'.' + functions.getString("FUNCTION_NAME"));
|
||||
function = true;
|
||||
procedureMetadata = getProcedureMetadataAsFunction(databaseMetaData,
|
||||
metaDataCatalogName, metaDataSchemaName, metaDataProcedureName);
|
||||
if (procedureMetadata.hits() > 1) {
|
||||
// Try again with exact match in case of placeholders
|
||||
String searchStringEscape = databaseMetaData.getSearchStringEscape();
|
||||
if (searchStringEscape != null) {
|
||||
procedureMetadata = getProcedureMetadataAsFunction(
|
||||
databaseMetaData, metaDataCatalogName,
|
||||
escapeNamePattern(metaDataSchemaName, searchStringEscape),
|
||||
escapeNamePattern(metaDataProcedureName, searchStringEscape));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handling matches
|
||||
|
||||
if (found.size() > 1) {
|
||||
boolean isFunction = procedureMetadata.function();
|
||||
List<String> matches = procedureMetadata.matches;
|
||||
if (matches.size() > 1) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Unable to determine the correct call signature - multiple signatures for '" +
|
||||
metaDataProcedureName + "': found " + found + " " + (function ? "functions" : "procedures"));
|
||||
metaDataProcedureName + "': found " + matches + " " + (isFunction ? "functions" : "procedures"));
|
||||
}
|
||||
else if (found.isEmpty()) {
|
||||
else if (matches.isEmpty()) {
|
||||
if (metaDataProcedureName != null && metaDataProcedureName.contains(".") &&
|
||||
!StringUtils.hasText(metaDataCatalogName)) {
|
||||
String packageName = metaDataProcedureName.substring(0, metaDataProcedureName.indexOf('.'));
|
||||
@@ -368,16 +362,16 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Retrieving column meta-data for " + (function ? "function" : "procedure") + ' ' +
|
||||
metaDataCatalogName + '/' + metaDataSchemaName + '/' + metaDataProcedureName);
|
||||
logger.debug("Retrieving column meta-data for " + (isFunction ? "function" : "procedure") + ' ' +
|
||||
metaDataCatalogName + '/' + procedureMetadata.schemaName + '/' + procedureMetadata.procedureName);
|
||||
}
|
||||
try (ResultSet columns = function ?
|
||||
databaseMetaData.getFunctionColumns(metaDataCatalogName, escapedSchemaName, escapedProcedureName, null) :
|
||||
databaseMetaData.getProcedureColumns(metaDataCatalogName, escapedSchemaName, escapedProcedureName, null)) {
|
||||
try (ResultSet columns = isFunction ?
|
||||
databaseMetaData.getFunctionColumns(metaDataCatalogName, procedureMetadata.schemaName, procedureMetadata.procedureName, null) :
|
||||
databaseMetaData.getProcedureColumns(metaDataCatalogName, procedureMetadata.schemaName, procedureMetadata.procedureName, null)) {
|
||||
while (columns.next()) {
|
||||
String columnName = columns.getString("COLUMN_NAME");
|
||||
int columnType = columns.getInt("COLUMN_TYPE");
|
||||
if (columnName == null && isInOrOutColumn(columnType, function)) {
|
||||
if (columnName == null && isInOrOutColumn(columnType, isFunction)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping meta-data for: " + columnType + " " + columns.getInt("DATA_TYPE") +
|
||||
" " + columns.getString("TYPE_NAME") + " " + columns.getInt("NULLABLE") +
|
||||
@@ -385,8 +379,8 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nullable = (function ? DatabaseMetaData.functionNullable : DatabaseMetaData.procedureNullable);
|
||||
CallParameterMetaData meta = new CallParameterMetaData(function, columnName, columnType,
|
||||
int nullable = (isFunction ? DatabaseMetaData.functionNullable : DatabaseMetaData.procedureNullable);
|
||||
CallParameterMetaData meta = new CallParameterMetaData(isFunction, columnName, columnType,
|
||||
columns.getInt("DATA_TYPE"), columns.getString("TYPE_NAME"),
|
||||
columns.getInt("NULLABLE") == nullable);
|
||||
this.callParameterMetaData.add(meta);
|
||||
@@ -413,6 +407,36 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private ProcedureMetadata getProcedureMetadata(DatabaseMetaData databaseMetaData,
|
||||
@Nullable String catalogName, @Nullable String schemaName, @Nullable String procedureName) throws SQLException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Retrieving meta-data for " + catalogName + '/' + schemaName + '/' + procedureName);
|
||||
}
|
||||
List<String> matches = new ArrayList<>();
|
||||
try (ResultSet procedures = databaseMetaData.getProcedures(catalogName, schemaName, procedureName)) {
|
||||
while (procedures.next()) {
|
||||
matches.add(procedures.getString("PROCEDURE_CAT") + '.' + procedures.getString("PROCEDURE_SCHEM") +
|
||||
'.' + procedures.getString("PROCEDURE_NAME"));
|
||||
}
|
||||
}
|
||||
return new ProcedureMetadata(schemaName, procedureName, matches, false);
|
||||
}
|
||||
|
||||
private ProcedureMetadata getProcedureMetadataAsFunction(DatabaseMetaData databaseMetaData,
|
||||
@Nullable String catalogName, @Nullable String schemaName, @Nullable String procedureName) throws SQLException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Fallback on retrieving function meta-data for " + catalogName + '/' + schemaName + '/' + procedureName);
|
||||
}
|
||||
List<String> matches = new ArrayList<>();
|
||||
try (ResultSet functions = databaseMetaData.getFunctions(catalogName, schemaName, procedureName)) {
|
||||
while (functions.next()) {
|
||||
matches.add(functions.getString("FUNCTION_CAT") + '.' + functions.getString("FUNCTION_SCHEM") +
|
||||
'.' + functions.getString("FUNCTION_NAME"));
|
||||
}
|
||||
}
|
||||
return new ProcedureMetadata(schemaName, procedureName, matches, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String escapeNamePattern(@Nullable String name, @Nullable String escape) {
|
||||
if (name == null || escape == null) {
|
||||
@@ -436,4 +460,12 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private record ProcedureMetadata(@Nullable String schemaName, @Nullable String procedureName,
|
||||
List<String> matches, boolean function) {
|
||||
|
||||
int hits() {
|
||||
return this.matches.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user