Farooq Ayoade created FINERACT-2713:
---------------------------------------
Summary: Cascaded report-parameter lookups fail on PostgreSQL with
"operator does not exist: bigint = character varying" since FINERACT-2624
Key: FINERACT-2713
URL: https://issues.apache.org/jira/browse/FINERACT-2713
Project: Apache Fineract
Issue Type: Bug
Components: Reports
Reporter: Farooq Ayoade
---Since FINERACT-2624 replaced string interpolation of report parameters with
JDBC bind variables, a parameter that appears in a report's SQL but is not one
of that report's own declared parameters — i.e. a {}cascaded{} lookup parameter
— is
bound as a {{String}}. On PostgreSQL, comparing a {{bigint}} column to a
bound {{character varying}} throws {{operator does not exist: bigint =
character varying}}, so the lookup fails.
The stock {{loanOfficerIdSelectAll}} option lookup is the clearest case: its
SQL filters {{... and o.id = ${officeId}}}, where {{officeId}} is supplied by
the parent parameter, not by {{loanOfficerIdSelectAll}} itself. The Loan
Officer dropdown of
every report that cascades off office is therefore empty on PostgreSQL.
h3. Steps to reproduce
Run Fineract on PostgreSQL (MySQL/MariaDB masks the bug — it coerces the
types).
Ensure at least one staff member with {{is_loan_officer = true}} exists under
the head office.
Call the cascaded option lookup exactly as the UI does when populating the
Loan Officer dropdown:
{noformat}
GET
/fineract-provider/api/v1/runreports/loanOfficerIdSelectAll?parameterType=true&genericResultSet=true&R_officeId=1
{noformat}
h3. Actual
HTTP 403; server log:
{noformat}
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback;
bad SQL grammar
[select x.* from ((select lo.id, lo.display_name AS name ... where
lo.is_loan_officer = true and o.id = ?) ...) x]
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist:
bigint = character varying
{noformat}
Every report using this lookup shows an empty Loan Officer dropdown.
h3. Expected
The lookup returns the loan officers under office 1 (as it does on
MySQL/MariaDB, and as it did before FINERACT-2624).
h3. Root cause
{{ReadReportingServiceImpl.buildPreparedQuery}} binds each {{${param}}} via
{{castParamValue(value, paramFormatTypes.get(param))}}. {{paramFormatTypes}} is
loaded for the report being run ({{loanOfficerIdSelectAll}}), whose own
parameters do not
include {{officeId}}; the cascaded {{officeId}} placeholder therefore
resolves to a {{null}} format type and {{castParamValue}} returns the raw
{{String}}. {{o.id = ?}} then compares {{bigint}} to a {{varchar}} bind —
accepted by MySQL, rejected
by PostgreSQL.
h3. Suggested fix
When the format type is unknown, infer a numeric bind for a plain integer
value so strict engines compare correctly; leave currency codes, identifiers
with leading zeros and free text as strings:
{code:java}
if ((formatType == null || formatType.isBlank()) &&
UNTYPED_INTEGER.matcher(value).matches()) {
return Long.parseLong(value); // UNTYPED_INTEGER = -?(0|[1-9]\d*)
}
return value;
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)