FINERACT-2468: Fix datatable operations in PostgreSQL non-public schemas

Use current_schema instead of hardcoded 'public' in getTableIndexes()
and isTablePresent() methods to support multi-tenant PostgreSQL
deployments where datatables reside in tenant-specific schemas.

This fixes:
- GET /datatables returning 404 for new datatables
- Datatable save operations failing with 'Datatable not found'

Root cause: Index metadata queries were looking in 'public' schema
while table columns query correctly used current_schema, causing
inconsistent behavior in GenericDataServiceImpl.

Changes:
- PostgreSQLQueryService.getTableIndexes(): Use current_schema
- PostgreSQLQueryService.isTablePresent(): Use current_schema

Testing:
- All unit tests pass (93/93 in fineract-core)
- Manual PostgreSQL verification confirms fix works correctly
This commit is contained in:
Ashhar Ahmad Khan
2026-02-18 15:38:50 +00:00
committed by Adam Saghy
parent 5cd6b718ed
commit a8ba79d19a
@@ -45,7 +45,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService {
public boolean isTablePresent(DataSource dataSource, String tableName) { public boolean isTablePresent(DataSource dataSource, String tableName) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Integer result = jdbcTemplate.queryForObject( Integer result = jdbcTemplate.queryForObject(
"SELECT COUNT(table_name) FROM information_schema.tables " + "WHERE table_schema = 'public' AND table_name = ?", "SELECT COUNT(table_name) FROM information_schema.tables " + "WHERE table_schema = current_schema() AND table_name = ?",
Integer.class, tableName); Integer.class, tableName);
return Objects.equals(result, 1); return Objects.equals(result, 1);
} }
@@ -55,7 +55,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = "SELECT column_name, is_nullable, data_type," String sql = "SELECT column_name, is_nullable, data_type,"
+ " coalesce(character_maximum_length, numeric_precision, datetime_precision) AS max_length, ordinal_position = 1 AS column_key" + " coalesce(character_maximum_length, numeric_precision, datetime_precision) AS max_length, ordinal_position = 1 AS column_key"
+ " FROM information_schema.columns WHERE table_catalog = current_catalog AND table_schema = current_schema AND table_name = ? ORDER BY ordinal_position"; + " FROM information_schema.columns WHERE table_catalog = current_catalog AND table_schema = current_schema() AND table_name = ? ORDER BY ordinal_position";
final SqlRowSet columnDefinitions = jdbcTemplate.queryForRowSet(sql, tableName); // NOSONAR final SqlRowSet columnDefinitions = jdbcTemplate.queryForRowSet(sql, tableName); // NOSONAR
if (columnDefinitions.next()) { if (columnDefinitions.next()) {
return columnDefinitions; return columnDefinitions;
@@ -67,7 +67,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService {
@Override @Override
public List<IndexDetail> getTableIndexes(DataSource dataSource, String tableName) { public List<IndexDetail> getTableIndexes(DataSource dataSource, String tableName) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = "SELECT indexname FROM pg_indexes WHERE schemaname = 'public' AND tablename = ?"; String sql = "SELECT indexname FROM pg_indexes WHERE schemaname = current_schema() AND tablename = ?";
final SqlRowSet indexDefinitions = jdbcTemplate.queryForRowSet(sql, tableName); // NOSONAR final SqlRowSet indexDefinitions = jdbcTemplate.queryForRowSet(sql, tableName); // NOSONAR
if (indexDefinitions.next()) { if (indexDefinitions.next()) {
return DatabaseIndexMapper.getIndexDetails(indexDefinitions); return DatabaseIndexMapper.getIndexDetails(indexDefinitions);