From a8ba79d19a8791443def79efeb0f38fb5f985f96 Mon Sep 17 00:00:00 2001 From: Ashhar Ahmad Khan <145142826+AshharAhmadKhan@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:15:39 +0530 Subject: [PATCH] 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 --- .../core/service/database/PostgreSQLQueryService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/PostgreSQLQueryService.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/PostgreSQLQueryService.java index 9c1629383..092188c57 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/PostgreSQLQueryService.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/database/PostgreSQLQueryService.java @@ -45,7 +45,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService { public boolean isTablePresent(DataSource dataSource, String tableName) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 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); return Objects.equals(result, 1); } @@ -55,7 +55,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 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" - + " 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 if (columnDefinitions.next()) { return columnDefinitions; @@ -67,7 +67,7 @@ public class PostgreSQLQueryService implements DatabaseQueryService { @Override public List getTableIndexes(DataSource dataSource, String tableName) { 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 if (indexDefinitions.next()) { return DatabaseIndexMapper.getIndexDetails(indexDefinitions);