7
7
8
8
import org .hibernate .HibernateException ;
9
9
import org .hibernate .Internal ;
10
+ import org .hibernate .dialect .CockroachDialect ;
10
11
import org .hibernate .dialect .Dialect ;
12
+ import org .hibernate .dialect .MariaDBDialect ;
13
+ import org .hibernate .dialect .MySQLDialect ;
14
+ import org .hibernate .dialect .OracleDialect ;
11
15
import org .hibernate .engine .spi .SharedSessionContractImplementor ;
12
16
import org .hibernate .generator .EventType ;
13
17
import org .hibernate .generator .values .GeneratedValueBasicResultBuilder ;
17
21
import org .hibernate .generator .values .internal .GeneratedValuesImpl ;
18
22
import org .hibernate .generator .values .internal .GeneratedValuesMappingProducer ;
19
23
import org .hibernate .id .IdentifierGeneratorHelper ;
20
- import org .hibernate .id .insert .GetGeneratedKeysDelegate ;
21
- import org .hibernate .id .insert .UniqueKeySelectingDelegate ;
22
24
import org .hibernate .internal .CoreLogging ;
23
25
import org .hibernate .internal .CoreMessageLogger ;
24
26
import org .hibernate .metamodel .mapping .ModelPart ;
27
+ import org .hibernate .metamodel .mapping .SelectableMapping ;
25
28
import org .hibernate .persister .entity .EntityPersister ;
26
29
import org .hibernate .pretty .MessageHelper ;
27
30
import org .hibernate .query .spi .QueryOptions ;
31
+ import org .hibernate .reactive .id .insert .ReactiveGetGeneratedKeysDelegate ;
28
32
import org .hibernate .reactive .id .insert .ReactiveInsertReturningDelegate ;
33
+ import org .hibernate .reactive .id .insert .ReactiveUniqueKeySelectingDelegate ;
29
34
import org .hibernate .reactive .sql .exec .spi .ReactiveRowProcessingState ;
30
35
import org .hibernate .reactive .sql .exec .spi .ReactiveValuesResultSet ;
31
36
import org .hibernate .reactive .sql .results .internal .ReactiveDirectResultSetAccess ;
38
43
import org .hibernate .sql .results .internal .RowTransformerArrayImpl ;
39
44
import org .hibernate .sql .results .jdbc .internal .JdbcValuesSourceProcessingStateStandardImpl ;
40
45
import org .hibernate .sql .results .jdbc .spi .JdbcValuesMappingProducer ;
41
- import org .hibernate .sql .results .jdbc .spi .JdbcValuesSourceProcessingOptions ;
42
46
import org .hibernate .type .descriptor .WrapperOptions ;
43
47
44
48
import java .sql .PreparedStatement ;
51
55
import static org .hibernate .generator .values .internal .GeneratedValuesHelper .noCustomSql ;
52
56
import static org .hibernate .internal .NaturalIdHelper .getNaturalIdPropertyNames ;
53
57
import static org .hibernate .reactive .sql .results .spi .ReactiveListResultsConsumer .UniqueSemantic .NONE ;
58
+ import static org .hibernate .sql .results .jdbc .spi .JdbcValuesSourceProcessingOptions .NO_OPTIONS ;
54
59
55
60
/**
56
61
* @see org.hibernate.generator.values.internal.GeneratedValuesHelper
@@ -64,13 +69,21 @@ public class ReactiveGeneratedValuesHelper {
64
69
* @see GeneratedValuesHelper#getGeneratedValuesDelegate(EntityPersister, EventType)
65
70
*/
66
71
public static GeneratedValuesMutationDelegate getGeneratedValuesDelegate (EntityPersister persister , EventType timing ) {
67
- final boolean hasGeneratedProperties = !persister .getGeneratedProperties ( timing ).isEmpty ();
72
+ final List <? extends ModelPart > generatedProperties = persister .getGeneratedProperties ( timing );
73
+ final boolean hasGeneratedProperties = !generatedProperties .isEmpty ();
68
74
final boolean hasRowId = timing == EventType .INSERT && persister .getRowIdMapping () != null ;
69
75
final Dialect dialect = persister .getFactory ().getJdbcServices ().getDialect ();
70
76
77
+ final boolean hasFormula =
78
+ generatedProperties .stream ()
79
+ .anyMatch ( part -> part instanceof SelectableMapping selectable
80
+ && selectable .isFormula () );
81
+
82
+ // Cockroach supports insert returning it but the CockroachDb#supportsInsertReturningRowId() wrongly returns false ( https://hibernate.atlassian.net/browse/HHH-19717 )
83
+ boolean supportsInsertReturningRowId = dialect .supportsInsertReturningRowId () || dialect instanceof CockroachDialect ;
71
84
if ( hasRowId
72
- && dialect . supportsInsertReturning ()
73
- && dialect . supportsInsertReturningRowId ()
85
+ && supportsInsertReturning ( dialect )
86
+ && supportsInsertReturningRowId
74
87
&& noCustomSql ( persister , timing ) ) {
75
88
// Special case for RowId on INSERT, since GetGeneratedKeysDelegate doesn't support it
76
89
// make InsertReturningDelegate the preferred method if the dialect supports it
@@ -81,26 +94,40 @@ && noCustomSql( persister, timing ) ) {
81
94
return null ;
82
95
}
83
96
84
- if ( dialect .supportsInsertReturningGeneratedKeys ()
85
- && persister .getFactory ().getSessionFactoryOptions ().isGetGeneratedKeysEnabled () ) {
86
- return new GetGeneratedKeysDelegate ( persister , false , timing );
87
- }
88
- else if ( supportsReturning ( dialect , timing ) && noCustomSql ( persister , timing ) ) {
97
+ if ( supportsReturning ( dialect , timing ) && noCustomSql ( persister , timing ) ) {
89
98
return new ReactiveInsertReturningDelegate ( persister , timing );
90
99
}
91
- else if ( timing == EventType .INSERT && persister .getNaturalIdentifierProperties () != null
92
- && !persister .getEntityMetamodel ().isNaturalIdentifierInsertGenerated () ) {
93
- return new UniqueKeySelectingDelegate (
94
- persister ,
95
- getNaturalIdPropertyNames ( persister ),
96
- timing
97
- );
100
+ else if ( !hasFormula && dialect .supportsInsertReturningGeneratedKeys () ) {
101
+ return new ReactiveGetGeneratedKeysDelegate ( persister , false , timing );
102
+ }
103
+ else if ( timing == EventType .INSERT && persister .getNaturalIdentifierProperties () != null && !persister .getEntityMetamodel ()
104
+ .isNaturalIdentifierInsertGenerated () ) {
105
+ return new ReactiveUniqueKeySelectingDelegate ( persister , getNaturalIdPropertyNames ( persister ), timing );
98
106
}
99
107
return null ;
100
108
}
101
109
102
- private static boolean supportsReturning (Dialect dialect , EventType timing ) {
103
- return timing == EventType .INSERT ? dialect .supportsInsertReturning () : dialect .supportsUpdateReturning ();
110
+ public static boolean supportReactiveGetGeneratedKey (Dialect dialect , List <? extends ModelPart > generatedProperties ) {
111
+ return dialect instanceof OracleDialect
112
+ || (dialect instanceof MySQLDialect && generatedProperties .size () == 1 && !(dialect instanceof MariaDBDialect ));
113
+ }
114
+
115
+ public static boolean supportsReturning (Dialect dialect , EventType timing ) {
116
+ if ( dialect instanceof CockroachDialect ) {
117
+ // Cockroach supports insert and update returning but the CockroachDb#supportsInsertReturning() wrongly returns false ( https://hibernate.atlassian.net/browse/HHH-19717 )
118
+ return true ;
119
+ }
120
+ return timing == EventType .INSERT
121
+ ? dialect .supportsInsertReturning ()
122
+ : dialect .supportsUpdateReturning ();
123
+ }
124
+
125
+ public static boolean supportsInsertReturning (Dialect dialect ) {
126
+ if ( dialect instanceof CockroachDialect ) {
127
+ // Cockroach supports insert returning but the CockroachDb#supportsInsertReturning() wrongly returns false ( https://hibernate.atlassian.net/browse/HHH-19717 )
128
+ return true ;
129
+ }
130
+ return dialect .supportsInsertReturning ();
104
131
}
105
132
106
133
/**
@@ -181,31 +208,9 @@ private static CompletionStage<Object[]> readGeneratedValues(
181
208
executionContext
182
209
);
183
210
184
- final JdbcValuesSourceProcessingOptions processingOptions = new JdbcValuesSourceProcessingOptions () {
185
- @ Override
186
- public Object getEffectiveOptionalObject () {
187
- return null ;
188
- }
189
-
190
- @ Override
191
- public String getEffectiveOptionalEntityName () {
192
- return null ;
193
- }
194
-
195
- @ Override
196
- public Object getEffectiveOptionalId () {
197
- return null ;
198
- }
199
-
200
- @ Override
201
- public boolean shouldReturnProxies () {
202
- return true ;
203
- }
204
- };
205
-
206
211
final JdbcValuesSourceProcessingStateStandardImpl valuesProcessingState = new JdbcValuesSourceProcessingStateStandardImpl (
207
212
executionContext ,
208
- processingOptions
213
+ NO_OPTIONS
209
214
);
210
215
211
216
final ReactiveRowReader <Object []> rowReader = ReactiveResultsHelper .createRowReader (
@@ -217,7 +222,7 @@ public boolean shouldReturnProxies() {
217
222
218
223
final ReactiveRowProcessingState rowProcessingState = new ReactiveRowProcessingState ( valuesProcessingState , executionContext , rowReader , jdbcValues );
219
224
return ReactiveListResultsConsumer .<Object []>instance ( NONE )
220
- .consume ( jdbcValues , session , processingOptions , valuesProcessingState , rowProcessingState , rowReader )
225
+ .consume ( jdbcValues , session , NO_OPTIONS , valuesProcessingState , rowProcessingState , rowReader )
221
226
.thenApply ( results -> {
222
227
if ( results .isEmpty () ) {
223
228
throw new HibernateException ( "The database returned no natively generated values : " + persister .getNavigableRole ().getFullPath () );
0 commit comments