{"record":{"id":"74639aad0a448602","repo":"hibernate/hibernate-orm","slug":"gaussdb-only-supports-accessing-ref-cursor-paramet","errorCode":null,"errorMessage":"GaussDB only supports accessing REF_CURSOR parameters by position","messagePattern":"GaussDB only supports accessing REF_CURSOR parameters by position","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/GaussDBDialect.java","lineNumber":908,"sourceCode":"\t\treturn SelectItemReferenceStrategy.POSITION;\n\t}\n\n\t@Override\n\tpublic CallableStatementSupport getCallableStatementSupport() {\n\t\treturn GaussDBCallableStatementSupport.INSTANCE;\n\t}\n\n\t@Override\n\tpublic ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {\n\t\tif ( position != 1 ) {\n\t\t\tthrow new UnsupportedOperationException( \"GaussDB only supports REF_CURSOR parameters as the first parameter\" );\n\t\t}\n\t\treturn (ResultSet) statement.getObject( 1 );\n\t}\n\n\t@Override\n\tpublic ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {\n\t\tthrow new UnsupportedOperationException( \"GaussDB only supports accessing REF_CURSOR parameters by position\" );\n\t}\n\n\t@Override\n\tpublic boolean qualifyIndexName() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IdentityColumnSupport getIdentityColumnSupport() {\n\t\treturn GaussDBIdentityColumnSupport.INSTANCE;\n\t}\n\n\t@Override\n\tpublic boolean supportsExpectedLobUsagePattern() {\n\t\treturn false;\n\t}\n\n\t@Override","sourceCodeStart":890,"sourceCodeEnd":926,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/GaussDBDialect.java#L890-L926","documentation":"Dialect.getResultSet(CallableStatement, name) is the by-name variant for retrieving REF_CURSOR out-parameters. GaussDB (per GaussDBDialect) only supports accessing refcursor parameters by position, so any code path that asks for a cursor by name throws UnsupportedOperationException immediately.","triggerScenarios":"Using named REF_CURSOR parameters with GaussDB: @NamedStoredProcedureQuery with a parameterName of ParameterMode.REF_CURSOR type, or calling StoredProcedureQuery.getResultList after registering the cursor by name - Hibernate resolves names and ends up in the by-name hook.","commonSituations":"Named-parameter stored-procedure code written for Oracle/PostgreSQL being pointed at GaussDB; annotation-based procedure declarations that prefer names for readability; shared persistence units across databases.","solutions":["Register the REF_CURSOR parameter by position (1) instead of by name and access the result positionally","Declare the procedure call with positional parameters throughout on GaussDB - the driver requires it for cursors","Keep named declarations for other databases but branch the GaussDB persistence unit to a positional variant","Verify position 1 usage at the same time - GaussDB only supports the first parameter as a cursor"],"exampleFix":"// before (named refcursor, throws on GaussDB)\n@NamedStoredProcedureQuery(name = \"fetchRows\", procedureName = \"fetch_rows\",\n  parameters = @StoredProcedureParameter(name = \"cur\", mode = ParameterMode.REF_CURSOR))\n\n// after (positional refcursor at position 1)\n@NamedStoredProcedureQuery(name = \"fetchRows\", procedureName = \"fetch_rows\",\n  parameters = @StoredProcedureParameter(position = 1, mode = ParameterMode.REF_CURSOR))","handlingStrategy":"validation","validationCode":"Dialect d = sessionFactory.getJdbcServices().getDialect();\nif (d instanceof GaussDBDialect && hasNamedRefCursorParameter(call)) {\n    call = toPositionalCall(call); // name 'cur' -> position 1, ParameterMode.REF_CURSOR\n}","typeGuard":"static boolean namedRefCursorSafe(Dialect d) {\n    return !(d instanceof GaussDBDialect);\n}","tryCatchPattern":"try {\n    results = namedQuery.getResultList();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"by position\")) {\n        // re-register parameters positionally and retry\n    } else throw e;\n}","preventionTips":["Prefer positional parameter registration for stored procedures in portable code","Review @NamedStoredProcedureQuery annotations for named REF_CURSOR parameters when adding GaussDB","Add GaussDB to the integration-test matrix for procedure-call code"],"tags":["hibernate","gaussdb","stored-procedure","ref-cursor","named-parameters"],"backgroundTag":"stored-procedure-refcursor-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}