Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,38 @@ private void checkClosed() throws SQLServerException {
"AND ic.key_ordinal = 0 " +
"ORDER BY t.name, i.name, ic.key_ordinal";

private static final String GET_FUNCTIONS_QUERY_BASE = "SELECT " +
"DB_NAME() AS FUNCTION_CAT, " +
"SCHEMA_NAME(o.schema_id) AS FUNCTION_SCHEM, " +
"o.name AS FUNCTION_NAME, " +
"-1 AS NUM_INPUT_PARAMS, " +
"-1 AS NUM_OUTPUT_PARAMS, " +
"-1 AS NUM_RESULT_SETS, " +
"CAST(NULL AS VARCHAR(254)) AS REMARKS, " +
"CASE o.type " +
"WHEN 'FN' THEN " + java.sql.DatabaseMetaData.functionReturnsTable + " " +
"WHEN 'IF' THEN " + java.sql.DatabaseMetaData.functionReturnsTable + " " +
"WHEN 'TF' THEN " + java.sql.DatabaseMetaData.functionReturnsTable + " " +
"ELSE " + java.sql.DatabaseMetaData.functionNoNulls + " " +
"END AS FUNCTION_TYPE " +
"FROM sys.all_objects o " +
"WHERE o.type IN (";

private static final String GET_PROCEDURES_QUERY_BASE = "SELECT " +
"DB_NAME() AS PROCEDURE_CAT, " +
"SCHEMA_NAME(o.schema_id) AS PROCEDURE_SCHEM, " +
"o.name AS PROCEDURE_NAME, " +
"-1 AS NUM_INPUT_PARAMS, " +
"-1 AS NUM_OUTPUT_PARAMS, " +
"-1 AS NUM_RESULT_SETS, " +
"CAST(NULL AS VARCHAR(254)) AS REMARKS, " +
"1 AS PROCEDURE_TYPE " +
"FROM sys.all_objects o " +
"WHERE o.type IN (";

private static final String FUNCTIONS_ORDER_BY = " ORDER BY FUNCTION_CAT, FUNCTION_SCHEM, FUNCTION_NAME";
private static final String PROCEDURES_ORDER_BY = " ORDER BY PROCEDURE_CAT, PROCEDURE_SCHEM, PROCEDURE_NAME";

// Use LinkedHashMap to force retrieve elements in order they were inserted
/** getColumns columns */
private LinkedHashMap<Integer, String> getColumnsDWColumns = null;
Expand Down Expand Up @@ -432,6 +464,81 @@ private SQLServerResultSet getResultSetWithProvidedColumnNames(String catalog, C
return rs;
}

/*
* Builds a filter string for object types based on the provided object types array.
*
* @param objectTypes
* Array of object types to be included in the filter.
*
* @return A string representing the filter for the object types.
*/
private String buildObjectTypesFilter(String[] objectTypes) {
return "'" + String.join("', '", objectTypes) + "')";
}

/*
* Helper method to append catalog, schema, and object name filters to the query
*/
private void appendFiltersAndOrderBy(StringBuilder queryBuilder, String catalog, String schemaPattern,
String objectNamePattern, String orderByClause) {

// Add catalog filter
if (catalog != null) {
queryBuilder.append(" AND DB_NAME() = ?");
}

// Add schema filter
if (schemaPattern != null && !schemaPattern.equals("%")) {
queryBuilder.append(" AND SCHEMA_NAME(o.schema_id) LIKE ?");
}

// Add object name filter
if (objectNamePattern != null && !objectNamePattern.equals("%")) {
queryBuilder.append(" AND o.name LIKE ?");
}

queryBuilder.append(orderByClause);
}

/*
* Executes a query against sys.objects to retrieve metadata about database objects.
* This method is used for both functions and procedures.
*/
private SQLServerResultSet executeSysObjectsQuery(String catalog, String schemaPattern,
String objectNamePattern, String query, String[] columnNames) throws SQLException {

String orgCat = switchCatalogs(catalog);

try {
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.closeOnCompletion();
int paramIndex = 1;

if (catalog != null) {
pstmt.setString(paramIndex++, escapeIDName(catalog));
}
if (schemaPattern != null && !schemaPattern.equals("%")) {
pstmt.setString(paramIndex++, escapeIDName(schemaPattern));
}
if (objectNamePattern != null && !objectNamePattern.equals("%")) {
pstmt.setString(paramIndex++, escapeIDName(objectNamePattern));
}

SQLServerResultSet rs = (SQLServerResultSet) pstmt.executeQuery();

// Set the column names to match the expected format
for (int i = 0; i < columnNames.length; i++) {
rs.setColumnName(i + 1, columnNames[i]);
}
return rs;

} finally {
if (null != orgCat) {
connection.setCatalog(orgCat);
}
}
}

/**
* Switches the database catalogs.
*
Expand Down Expand Up @@ -947,23 +1054,34 @@ public java.sql.ResultSet getFunctions(String catalog, String schemaPattern,
String functionNamePattern) throws SQLException {
checkClosed();

/*
* sp_stored_procedures [ [ @sp_name = ] 'name' ] [ , [ @sp_owner = ] 'schema'] [ , [ @sp_qualifier = ]
* 'qualifier' ] [ , [@fUsePattern = ] 'fUsePattern' ]
*/ // use default ie use pattern matching.
// catalog cannot be empty in sql server
if (null != catalog && catalog.length() == 0) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidArgument"));
Object[] msgArgs = {"catalog"};
Object[] msgArgs = { "catalog" };
SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false);
}

String[] arguments = new String[3];
arguments[0] = escapeIDName(functionNamePattern);
arguments[1] = escapeIDName(schemaPattern);
arguments[2] = catalog;
return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_STORED_PROCEDURES, arguments,
getFunctionsColumnNames);
return getFunctionsFromSysObjects(catalog, schemaPattern, functionNamePattern, getFunctionsColumnNames);
}

/*
* Returns a ResultSet containing metadata about functions in the database.
* This method queries the sys.all_objects system view to retrieve
* information about functions, including their names, schemas, and types.
*/
private SQLServerResultSet getFunctionsFromSysObjects(String catalog, String schemaPattern,
String functionNamePattern, String[] columnNames) throws SQLException {

String[] functionTypes = { "FN", "IF", "TF" };

// Build the query
StringBuilder queryBuilder = new StringBuilder(GET_FUNCTIONS_QUERY_BASE);
queryBuilder.append(buildObjectTypesFilter(functionTypes));

appendFiltersAndOrderBy(queryBuilder, catalog, schemaPattern, functionNamePattern, FUNCTIONS_ORDER_BY);

return executeSysObjectsQuery(catalog, schemaPattern, functionNamePattern, queryBuilder.toString(),
columnNames);
}

private static final String[] getFunctionsColumnsColumnNames = { /* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM,
Expand Down Expand Up @@ -1540,22 +1658,34 @@ public java.sql.ResultSet getProcedureColumns(String catalog, String schema, Str

@Override
public java.sql.ResultSet getProcedures(String catalog, String schema,
String proc) throws SQLServerException, SQLTimeoutException {
String proc) throws SQLServerException, SQLTimeoutException, SQLException {
if (loggerExternal.isLoggable(Level.FINER) && Util.isActivityTraceOn()) {
loggerExternal.finer(toString() + ACTIVITY_ID + ActivityCorrelator.getCurrent().toString());
}

checkClosed();
/*
* sp_stored_procedures [ [ @sp_name = ] 'name' ] [ , [ @sp_owner = ] 'schema'] [ , [ @sp_qualifier = ]
* 'qualifier' ] [ , [@fUsePattern = ] 'fUsePattern' ]
*/
String[] arguments = new String[3];
arguments[0] = escapeIDName(proc);
arguments[1] = escapeIDName(schema);
arguments[2] = catalog;
return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_STORED_PROCEDURES, arguments,
getProceduresColumnNames);

return getProceduresFromSysObjects(catalog, schema, proc, getProceduresColumnNames);
}

/*
* Returns a ResultSet containing metadata about stored procedures in the database.
* This method queries the sys.all_objects system view to retrieve information about
* procedures, including their names, schemas, and types.
*/
private SQLServerResultSet getProceduresFromSysObjects(String catalog, String schemaPattern,
String procedureNamePattern, String[] columnNames) throws SQLException {

String[] procedureTypes = { "P", "PC" };

// Build the query
StringBuilder queryBuilder = new StringBuilder(GET_PROCEDURES_QUERY_BASE);
queryBuilder.append(buildObjectTypesFilter(procedureTypes));

appendFiltersAndOrderBy(queryBuilder, catalog, schemaPattern, procedureNamePattern, PROCEDURES_ORDER_BY);

return executeSysObjectsQuery(catalog, schemaPattern, procedureNamePattern, queryBuilder.toString(),
columnNames);
}

@Override
Expand Down
Loading
Loading