Skip to content

Commit c520670

Browse files
SweetWuXiaoMeibeikov
authored andcommitted
hhh-19598 - support gaussdb callable
1 parent 567d999 commit c520670

File tree

1 file changed

+10
-153
lines changed

1 file changed

+10
-153
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/GaussDBCallableStatementSupport.java

Lines changed: 10 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,9 @@
44
*/
55
package org.hibernate.community.dialect;
66

7-
import java.util.List;
8-
9-
import org.hibernate.HibernateException;
10-
import org.hibernate.dialect.type.AbstractPostgreSQLStructJdbcType;
11-
import org.hibernate.procedure.internal.AbstractStandardCallableStatementSupport;
12-
import org.hibernate.procedure.spi.FunctionReturnImplementor;
13-
import org.hibernate.procedure.spi.ProcedureCallImplementor;
7+
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
148
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
15-
import org.hibernate.type.OutputableType;
16-
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
17-
import org.hibernate.sql.exec.internal.JdbcCallImpl;
189
import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration;
19-
import org.hibernate.sql.exec.spi.JdbcOperationQueryCall;
20-
import org.hibernate.type.SqlTypes;
21-
22-
import jakarta.persistence.ParameterMode;
2310

2411
/**
2512
* GaussDB implementation of CallableStatementSupport.
@@ -28,150 +15,20 @@
2815
*
2916
* Notes: Original code of this class is based on PostgreSQLCallableStatementSupport.
3017
*/
31-
public class GaussDBCallableStatementSupport extends AbstractStandardCallableStatementSupport {
32-
/**
33-
* Singleton access
34-
*/
35-
public static final GaussDBCallableStatementSupport INSTANCE = new GaussDBCallableStatementSupport( true );
18+
public class GaussDBCallableStatementSupport extends StandardCallableStatementSupport {
3619

37-
private final boolean supportsProcedures;
20+
public static final StandardCallableStatementSupport INSTANCE = new GaussDBCallableStatementSupport(
21+
true );
3822

3923
private GaussDBCallableStatementSupport(boolean supportsProcedures) {
40-
this.supportsProcedures = supportsProcedures;
24+
super( supportsProcedures );
4125
}
4226

4327
@Override
44-
public JdbcOperationQueryCall interpretCall(ProcedureCallImplementor<?> procedureCall) {
45-
final String procedureName = procedureCall.getProcedureName();
46-
final FunctionReturnImplementor<?> functionReturn = procedureCall.getFunctionReturn();
47-
final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata();
48-
final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0
49-
&& isFirstParameterModeRefCursor( parameterMetadata );
50-
51-
final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
52-
final int paramStringSizeEstimate;
53-
if ( functionReturn == null && parameterMetadata.hasNamedParameters() ) {
54-
// That's just a rough estimate. I guess most params will have fewer than 8 chars on average
55-
paramStringSizeEstimate = registrations.size() * 10;
56-
}
57-
else {
58-
// For every param rendered as '?' we have a comma, hence the estimate
59-
paramStringSizeEstimate = registrations.size() * 2;
60-
}
61-
final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder();
62-
63-
final int jdbcParameterOffset;
64-
final int startIndex;
65-
final CallMode callMode;
66-
if ( functionReturn != null ) {
67-
if ( functionReturn.getJdbcTypeCode() == SqlTypes.REF_CURSOR ) {
68-
if ( firstParamIsRefCursor ) {
69-
// validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
70-
if ( parameterMetadata.hasNamedParameters() ) {
71-
throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on GaussDB" );
72-
}
73-
callMode = CallMode.CALL_RETURN;
74-
startIndex = 1;
75-
jdbcParameterOffset = 1;
76-
builder.addParameterRegistration( registrations.get( 0 ).toJdbcParameterRegistration( 1, procedureCall ) );
77-
}
78-
else {
79-
callMode = CallMode.TABLE_FUNCTION;
80-
startIndex = 0;
81-
jdbcParameterOffset = 1;
82-
}
83-
}
84-
else {
85-
callMode = CallMode.FUNCTION;
86-
startIndex = 0;
87-
jdbcParameterOffset = 1;
88-
}
89-
}
90-
else if ( supportsProcedures ) {
91-
jdbcParameterOffset = 1;
92-
startIndex = 0;
93-
callMode = CallMode.NATIVE_CALL;
94-
}
95-
else if ( firstParamIsRefCursor ) {
96-
// validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
97-
if ( parameterMetadata.hasNamedParameters() ) {
98-
throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on GaussDB" );
99-
}
100-
jdbcParameterOffset = 1;
101-
startIndex = 1;
102-
callMode = CallMode.CALL_RETURN;
103-
builder.addParameterRegistration( registrations.get( 0 ).toJdbcParameterRegistration( 1, procedureCall ) );
104-
}
105-
else {
106-
jdbcParameterOffset = 1;
107-
startIndex = 0;
108-
callMode = CallMode.CALL;
109-
}
110-
111-
final StringBuilder buffer = new StringBuilder( callMode.start.length() + callMode.end.length() + procedureName.length() + paramStringSizeEstimate )
112-
.append( callMode.start );
113-
buffer.append( procedureName );
114-
115-
if ( startIndex == registrations.size() ) {
116-
buffer.append( '(' );
117-
}
118-
else {
119-
char sep = '(';
120-
for ( int i = startIndex; i < registrations.size(); i++ ) {
121-
final ProcedureParameterImplementor<?> parameter = registrations.get( i );
122-
if ( !supportsProcedures && parameter.getMode() == ParameterMode.REF_CURSOR ) {
123-
throw new HibernateException(
124-
"GaussDB supports only one REF_CURSOR parameter, but multiple were registered" );
125-
}
126-
buffer.append( sep );
127-
final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration(
128-
i + jdbcParameterOffset,
129-
procedureCall
130-
);
131-
final OutputableType<?> type = registration.getParameterType();
132-
final String castType;
133-
if ( parameter.getName() != null ) {
134-
buffer.append( parameter.getName() ).append( " => " );
135-
}
136-
if ( type != null && type.getJdbcType() instanceof AbstractPostgreSQLStructJdbcType ) {
137-
// We have to cast struct type parameters so that GaussDB understands nulls
138-
castType = ( (AbstractPostgreSQLStructJdbcType) type.getJdbcType() ).getStructTypeName();
139-
buffer.append( "cast(" );
140-
}
141-
else {
142-
castType = null;
143-
}
144-
buffer.append( "?" );
145-
if ( castType != null ) {
146-
buffer.append( " as " ).append( castType ).append( ')' );
147-
}
148-
sep = ',';
149-
builder.addParameterRegistration( registration );
150-
}
151-
}
152-
153-
buffer.append( callMode.end );
154-
builder.setCallableName( buffer.toString() );
155-
return builder.buildJdbcCall();
156-
}
157-
158-
private static boolean isFirstParameterModeRefCursor(ProcedureParameterMetadataImplementor parameterMetadata) {
159-
return parameterMetadata.getRegistrationsAsList().get( 0 ).getMode() == ParameterMode.REF_CURSOR;
160-
}
161-
162-
enum CallMode {
163-
TABLE_FUNCTION("select * from ", ")"),
164-
FUNCTION("select ", ")"),
165-
NATIVE_CALL("call ", ")"),
166-
CALL_RETURN("{?=call ", ")}"),
167-
CALL("{call ", ")}");
168-
169-
private final String start;
170-
private final String end;
171-
172-
CallMode(String start, String end) {
173-
this.start = start;
174-
this.end = end;
175-
}
28+
protected void appendNameParameter(
29+
StringBuilder buffer,
30+
ProcedureParameterImplementor parameter,
31+
JdbcCallParameterRegistration registration) {
32+
buffer.append( parameter.getName() ).append( " => ?" );
17633
}
17734
}

0 commit comments

Comments
 (0)