I'm calling a SQL function which takes a string parameter (varchar2 in SQL) and returns a SYS_REFCURSOR which I'm trying to get in Java using below code.
My function is
CREATE OR REPLACE FUNCTION check_query(p_query_text VARCHAR2) RETURN SYS_REFCURSOR IS
txt VARCHAR2(4000);
from_clause VARCHAR2(4000);
l_qry NVARCHAR2(4000);
ret SYS_REFCURSOR; -- Define the SYS_REFCURSOR type for result set
total_count NUMBER; -- Variable to store the total count
BEGIN
IF p_query_text IS NOT NULL THEN
txt := p_query_text;
from_clause := 'toa_app_data WHERE';
IF txt IS NOT NULL AND LENGTH(txt) > 0 THEN
l_qry := 'SELECT * FROM toa_app_data WHERE app_id IN (SELECT toa_app_data.app_id FROM ' || from_clause ||
' ' || txt || ') FETCH FIRST 5 ROWS ONLY'; -- Fetch top 5 rows
ELSE
l_qry := 'SELECT * FROM toa_app_data WHERE 1 = 0'; -- Return empty result set
END IF;
DBMS_OUTPUT.PUT_LINE('l_qry: ' || l_qry);
OPEN ret FOR l_qry; -- Open the cursor for the top 5 rows or empty result set
-- Get the total count for the query
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM toa_app_data WHERE app_id IN (SELECT toa_app_data.app_id FROM ' || from_clause || ' ' || txt || ')'
INTO total_count;
ELSE
-- Open an empty cursor when p_query_text is NULL
OPEN ret FOR SELECT * FROM toa_app_data WHERE 1 = 0;
-- Set total_count as 0 when there is no input query
total_count := 0;
END IF;
-- Print the total count (optional)
DBMS_OUTPUT.PUT_LINE('Total count: ' || total_count);
RETURN ret; -- Return the SYS_REFCURSOR with the top 5 rows or an empty cursor
END check_query;
In Java I'm trying to get the result of this using below function
public List validateQuery(String queryString) throws SQLException{
logger.debug("In validateQuery: query- ");
//String retValue = null;
Long totalCount = 0L;
List list = new ArrayList();
try{
StoredProcedureQuery query = queryDao.getEntityManager().createStoredProcedureQuery(VALIDATE_QUERY_BEFORE_SAVE);
query.registerStoredProcedureParameter(QUERY_STRING_TEXT, String.class, ParameterMode.IN);
query.setParameter(QUERY_STRING_TEXT, queryString);
query.registerStoredProcedureParameter("ret", Class.forName("java.sql.ResultSet"), ParameterMode.REF_CURSOR);
query.registerStoredProcedureParameter("total_count", Long.class, ParameterMode.OUT);
query.execute();
list = query.getResultList();
//retValue = (String) query.getOutputParameterValue("ret");
totalCount = ((Number) query.getOutputParameterValue("total_count")).longValue();
}catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return list;
}
In the logs I get the error as
Caused by: java.sql.SQLException: ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'CHECK_QUERY' ORA-06550: line 1, column 7: PL/SQL: Statement ignored
Not sure how. Also Class.forName("java.sql.ResultSet") this seems to be correct as I was just testing it and could not find a class myself but this code gives a ResultSet class. the error comes when we do query.execute().
It's a simple SQL validator and we pass the where clause and to confirm if the query is correct or not, if correct then return the total count and top 5 rows from the query if not then return the SQL error