88import java .lang .invoke .MethodHandles ;
99import java .util .concurrent .CompletionStage ;
1010
11+ import org .hibernate .dialect .CockroachDialect ;
1112import org .hibernate .dialect .Dialect ;
1213import org .hibernate .dialect .PostgreSQLDialect ;
1314import org .hibernate .dialect .SQLServerDialect ;
2324import org .hibernate .reactive .logging .impl .LoggerFactory ;
2425import org .hibernate .reactive .pool .ReactiveConnection ;
2526import org .hibernate .reactive .session .ReactiveConnectionSupplier ;
27+ import org .hibernate .type .Type ;
2628
27- import static java . util . function . Function . identity ;
28- import static org .hibernate .dialect .DialectDelegateWrapper . extractRealDialect ;
29+
30+ import static org .hibernate .reactive . dialect .ReactiveDialectWrapper . instanceOf ;
2931
3032public interface ReactiveAbstractReturningDelegate extends ReactiveInsertGeneratedIdentifierDelegate {
3133
@@ -48,16 +50,36 @@ default CompletionStage<Object> reactivePerformInsert(PreparedStatementDetails i
4850 ReactiveConnection reactiveConnection = ( (ReactiveConnectionSupplier ) session ).getReactiveConnection ();
4951 return reactiveConnection
5052 .insertAndSelectIdentifier ( insertSql , params , idType , identifierColumnName )
51- .thenApply ( identity () );
53+ .thenApply ( this ::validateGeneratedIdentityId );
54+ }
55+
56+ private Object validateGeneratedIdentityId (Object generatedId ) {
57+ if ( generatedId == null ) {
58+ throw LOG .noNativelyGeneratedValueReturned ();
59+ }
60+
61+ // CockroachDB might generate an identifier that fits an integer (and maybe a short) from time to time.
62+ // Users should not rely on it, or they might have random, hard to debug failures.
63+ Type identifierType = getPersister ().getIdentifierType ();
64+ if ( ( identifierType .getReturnedClass ().equals ( Short .class ) || identifierType .getReturnedClass ().equals ( Integer .class ) )
65+ && instanceOf ( getPersister ().getFactory ().getJdbcServices ().getDialect (), CockroachDialect .class ) ) {
66+ throw LOG .invalidIdentifierTypeForCockroachDB ( identifierType .getReturnedClass (), getPersister ().getEntityName () );
67+ }
68+ return generatedId ;
5269 }
5370
5471 private static String createInsert (PreparedStatementDetails insertStatementDetails , String identifierColumnName , Dialect dialect ) {
72+ final String sqlEnd = " returning " + identifierColumnName ;
5573 if ( instanceOf ( dialect , PostgreSQLDialect .class ) ) {
56- return insertStatementDetails .getSqlString () + " returning " + identifierColumnName ;
74+ return insertStatementDetails .getSqlString () + sqlEnd ;
75+ }
76+ if ( instanceOf ( dialect , CockroachDialect .class )
77+ && !insertStatementDetails .getSqlString ().endsWith ( sqlEnd ) ) {
78+ return insertStatementDetails .getSqlString () + sqlEnd ;
5779 }
5880 if ( instanceOf ( dialect , SQLServerDialect .class ) ) {
5981 String sql = insertStatementDetails .getSqlString ();
60- int index = sql .lastIndexOf ( " returning " + identifierColumnName );
82+ int index = sql .lastIndexOf ( sqlEnd );
6183 // FIXME: this is a hack for HHH-16365
6284 if ( index > -1 ) {
6385 sql = sql .substring ( 0 , index );
@@ -75,10 +97,6 @@ private static String createInsert(PreparedStatementDetails insertStatementDetai
7597 return insertStatementDetails .getSqlString ();
7698 }
7799
78- private static boolean instanceOf (Dialect dialect , Class <?> dialectClass ) {
79- return dialectClass .isInstance ( extractRealDialect ( dialect ) );
80- }
81-
82100 @ Override
83101 default CompletionStage <Object > reactivePerformInsert (String insertSQL , SharedSessionContractImplementor session , Binder binder ) {
84102 throw LOG .notYetImplemented ();
0 commit comments