lallemand created CAY-2894:
------------------------------

             Summary: Issue with Oracle NCLOB Search in Version 4.2.2
                 Key: CAY-2894
                 URL: https://issues.apache.org/jira/browse/CAY-2894
             Project: Cayenne
          Issue Type: Bug
          Components: Core Library
    Affects Versions: 4.2.2
            Reporter: lallemand


Dear,

 

In the latest stable version (4.2.2), we are encountering an issue when 
performing a search on Oracle *{{NCLOB}}* fields.

Previously, this functionality worked correctly, and it still behaves as 
expected on SQL Server using *{{{}nvarchar(max){}}}.*
h3. The Issue

The problem arises when executing a query with a {{LIKE}} expression, such as:

 
{code:java}
public static KycRuleCommon getFromNameAndQuery(String pm_name, String 
pm_query) throws BaseException
{
    try {
           if (pm_name == null || pm_name.compareTo("")==0 || pm_query == null 
|| pm_query.compareTo("")==0) return null;

       Map<String, Object> parameters = new HashMap<>();
       parameters.put(NAME.getName(), pm_name);
       parameters.put(QUERY_SQL.getName(), pm_query);

       ObjectSelect<KycRuleCommon> query = 
ObjectSelect.query(KycRuleCommon.class, ExpressionFactory.exp(
             NAME.getName() + " like $" + NAME.getName()
                   + " and " + QUERY_SQL.getName() + " like $" + 
QUERY_SQL.getName()).params(parameters));

       ObjectContext context = BaseContext.getThreadObjectContext();
       return context.selectFirst(query);
    } catch (Exception e) {
       throw new EntityException(new EventSysm1023(e));
    }
} {code}
We understand that using *{{LIKE}}* on *{{NCLOB}}* fields is generally 
discouraged, especially if the value exceeds 4000 characters, as this can lead 
to runtime errors. However, even when the value is well under that limit, it 
now fails on Oracle, while still working on SQL Server.

This suggests that a recent change in parameter binding may be forcing Oracle 
to treat the field as an *NCLOB* explicitly, causing the failure regardless of 
content size.

Normally, in Oracle, such queries should use *{{DBMS_LOB.INSTR()}}* for safe 
processing.

 
h3. Working Queries in Oracle

The following native SQL queries work correctly on our database and bring one 
record:

 
{code:java}
SELECT * FROM TKYCRULECOMMON t WHERE t.name LIKE 'name' AND t.QUERY_SQL LIKE 
'%test%';
SELECT * FROM TKYCRULECOMMON t WHERE t.name LIKE 'name' AND 
DBMS_LOB.INSTR(t.QUERY_SQL, 'test') > 0; {code}
h3. Attempt with {{FunctionExpressionFactory}}

I attempted to adapt the logic using 
{*}{{FunctionExpressionFactory.functionCall()}}{*}, but I cannot get it to 
return any results. The query doesn't crash and seems to be generated 
correctly, but always yields no records.

Here is the updated code and the resulting SQL:

 
{code:java}
public static KycRuleCommon getFromNameAndQuery(String pm_name, String 
pm_query) throws BaseException
{
    try {
           if (pm_name == null || pm_name.compareTo("")==0 || pm_query == null 
|| pm_query.compareTo("")==0) return null;

       Map<String, Object> parameters = new HashMap<>();
       parameters.put(NAME.getName(), pm_name);
       parameters.put(QUERY_SQL.getName(), pm_query);

       Expression dbmsExp = 
FunctionExpressionFactory.functionCall("DBMS_LOB.INSTR",QUERY_SQL.getName(),"$" 
+ QUERY_SQL.getName());
       Expression compareExp = ExpressionFactory.greaterExp(dbmsExp, 0);
       Expression nameExp = ExpressionFactory.exp(NAME.getName() + " like $" + 
NAME.getName());

       ObjectSelect<KycRuleCommon> query = 
ObjectSelect.query(KycRuleCommon.class, 
compareExp.andExp(nameExp).params(parameters));
       query.cacheStrategy(QueryCacheStrategy.NO_CACHE);
       ObjectContext context = BaseContext.getThreadObjectContext();
       return context.selectFirst(query);
    } catch (Exception e) {
       throw new EntityException(new EventSysm1023(e));
    }
} {code}
Generated SQL:

 

 

 
{code:java}
SELECT  t0.created_by c0,  t0.date_created c1,  t0.date_modified c2,  
t0.description c3,  t0.dynfield_identifier c4,  t0.modified_by c5,  t0.name c6, 
 t0.query_sql c7,  RTRIM(t0.standard) c8,  t0.version c9,  t0.id c10 FROM  
tKycRuleCommon t0 WHERE  (DBMS_LOB.INSTR(: 1,: 2) >: 3)  AND t0.name LIKE: 4 
{code}
 

Despite the query looking correct, no results are returned. Using SQL Template 
we do retrieve correctly information.

Could you please clarify:
 * Am I using *{{FunctionExpressionFactory.functionCall()}}* correctly in this 
context?

 * Is this a known limitation or a potential bug introduced in version 4.2.2?

 * Is there an alternative/best-practice approach when working with NCLOBs and 
expressions like this?

Thank you in advance for your help.

Best regards,

Anton



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to