19
19
import static com .mongodb .hibernate .internal .MongoAssertions .assertNotNull ;
20
20
import static com .mongodb .hibernate .internal .MongoAssertions .assertTrue ;
21
21
import static com .mongodb .hibernate .internal .MongoConstants .ID_FIELD_NAME ;
22
+ import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .COLLECTION_AGGREGATE ;
22
23
import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .COLLECTION_MUTATION ;
24
+ import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .COLLECTION_NAME ;
25
+ import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .FIELD_NAME ;
23
26
import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .FIELD_VALUE ;
27
+ import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .FILTER ;
28
+ import static com .mongodb .hibernate .internal .translate .AstVisitorValueDescriptor .PROJECT_STAGE_SPECIFICATIONS ;
29
+ import static com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .stage .AstProjectStageSpecification .include ;
24
30
import static com .mongodb .hibernate .internal .translate .mongoast .filter .AstComparisonFilterOperator .EQ ;
25
31
import static java .lang .String .format ;
32
+ import static org .hibernate .query .sqm .ComparisonOperator .EQUAL ;
33
+ import static org .hibernate .sql .ast .SqlTreePrinter .logSqlAst ;
26
34
27
35
import com .mongodb .hibernate .internal .FeatureNotSupportedException ;
28
36
import com .mongodb .hibernate .internal .extension .service .StandardServiceRegistryScopedState ;
31
39
import com .mongodb .hibernate .internal .translate .mongoast .AstFieldUpdate ;
32
40
import com .mongodb .hibernate .internal .translate .mongoast .AstNode ;
33
41
import com .mongodb .hibernate .internal .translate .mongoast .AstParameterMarker ;
42
+ import com .mongodb .hibernate .internal .translate .mongoast .command .AstAggregateCommand ;
43
+ import com .mongodb .hibernate .internal .translate .mongoast .command .AstCommand ;
34
44
import com .mongodb .hibernate .internal .translate .mongoast .command .AstDeleteCommand ;
35
45
import com .mongodb .hibernate .internal .translate .mongoast .command .AstInsertCommand ;
36
46
import com .mongodb .hibernate .internal .translate .mongoast .command .AstUpdateCommand ;
47
+ import com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .AstPipeline ;
48
+ import com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .AstStage ;
49
+ import com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .stage .AstMatchStage ;
50
+ import com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .stage .AstProjectStage ;
51
+ import com .mongodb .hibernate .internal .translate .mongoast .command .aggregate .stage .AstProjectStageSpecification ;
37
52
import com .mongodb .hibernate .internal .translate .mongoast .filter .AstComparisonFilterOperation ;
38
53
import com .mongodb .hibernate .internal .translate .mongoast .filter .AstFieldOperationFilter ;
39
54
import com .mongodb .hibernate .internal .translate .mongoast .filter .AstFilter ;
40
55
import com .mongodb .hibernate .internal .translate .mongoast .filter .AstFilterFieldPath ;
56
+ import com .mongodb .hibernate .internal .translate .mongoast .filter .AstMatchesEverythingFilter ;
41
57
import java .io .IOException ;
42
58
import java .io .StringWriter ;
43
59
import java .util .ArrayList ;
60
+ import java .util .HashSet ;
44
61
import java .util .List ;
45
62
import java .util .Set ;
46
63
import org .bson .json .JsonMode ;
47
64
import org .bson .json .JsonWriter ;
48
65
import org .bson .json .JsonWriterSettings ;
49
66
import org .hibernate .engine .spi .SessionFactoryImplementor ;
50
67
import org .hibernate .internal .util .collections .Stack ;
68
+ import org .hibernate .persister .entity .EntityPersister ;
51
69
import org .hibernate .persister .internal .SqlFragmentPredicate ;
52
70
import org .hibernate .query .sqm .tree .expression .Conversion ;
53
71
import org .hibernate .sql .ast .Clause ;
92
110
import org .hibernate .sql .ast .tree .from .FunctionTableReference ;
93
111
import org .hibernate .sql .ast .tree .from .NamedTableReference ;
94
112
import org .hibernate .sql .ast .tree .from .QueryPartTableReference ;
113
+ import org .hibernate .sql .ast .tree .from .StandardTableGroup ;
95
114
import org .hibernate .sql .ast .tree .from .TableGroup ;
96
115
import org .hibernate .sql .ast .tree .from .TableGroupJoin ;
97
116
import org .hibernate .sql .ast .tree .from .TableReferenceJoin ;
@@ -143,6 +162,8 @@ abstract class AbstractMqlTranslator<T extends JdbcOperation> implements SqlAstT
143
162
144
163
private final List <JdbcParameterBinder > parameterBinders = new ArrayList <>();
145
164
165
+ private final Set <String > affectedTableNames = new HashSet <>();
166
+
146
167
AbstractMqlTranslator (SessionFactoryImplementor sessionFactory ) {
147
168
this .sessionFactory = sessionFactory ;
148
169
assertNotNull (sessionFactory
@@ -178,7 +199,7 @@ public Stack<Clause> getCurrentClauseStack() {
178
199
179
200
@ Override
180
201
public Set <String > getAffectedTableNames () {
181
- throw new FeatureNotSupportedException ( "TODO-HIBERNATE-22 https://jira.mongodb.org/browse/HIBERNATE-22" ) ;
202
+ return affectedTableNames ;
182
203
}
183
204
184
205
List <JdbcParameterBinder > getParameterBinders () {
@@ -197,12 +218,12 @@ static String renderMongoAstNode(AstNode rootAstNode) {
197
218
}
198
219
199
220
@ SuppressWarnings ("overloads" )
200
- <R extends AstNode > R acceptAndYield (Statement statement , AstVisitorValueDescriptor <R > resultDescriptor ) {
221
+ <R extends AstCommand > R acceptAndYield (Statement statement , AstVisitorValueDescriptor <R > resultDescriptor ) {
201
222
return astVisitorValueHolder .execute (resultDescriptor , () -> statement .accept (this ));
202
223
}
203
224
204
225
@ SuppressWarnings ("overloads" )
205
- <R extends AstNode > R acceptAndYield (SqlAstNode node , AstVisitorValueDescriptor <R > resultDescriptor ) {
226
+ <R > R acceptAndYield (SqlAstNode node , AstVisitorValueDescriptor <R > resultDescriptor ) {
206
227
return astVisitorValueHolder .execute (resultDescriptor , () -> node .accept (this ));
207
228
}
208
229
@@ -214,20 +235,18 @@ public void visitStandardTableInsert(TableInsertStandard tableInsert) {
214
235
if (tableInsert .getNumberOfReturningColumns () > 0 ) {
215
236
throw new FeatureNotSupportedException ();
216
237
}
217
- var tableName = tableInsert .getTableName ();
218
238
var astElements = new ArrayList <AstElement >(tableInsert .getNumberOfValueBindings ());
219
239
for (var columnValueBinding : tableInsert .getValueBindings ()) {
220
240
var columnExpression = columnValueBinding .getColumnReference ().getColumnExpression ();
221
241
222
242
var valueExpression = columnValueBinding .getValueExpression ();
223
- if (valueExpression == null ) {
224
- throw new FeatureNotSupportedException ();
225
- }
226
243
var astValue = acceptAndYield (valueExpression , FIELD_VALUE );
227
244
228
245
astElements .add (new AstElement (columnExpression , astValue ));
229
246
}
230
- astVisitorValueHolder .yield (COLLECTION_MUTATION , new AstInsertCommand (tableName , new AstDocument (astElements )));
247
+ astVisitorValueHolder .yield (
248
+ COLLECTION_MUTATION ,
249
+ new AstInsertCommand (tableInsert .getMutatingTable ().getTableName (), new AstDocument (astElements )));
231
250
}
232
251
233
252
@ Override
@@ -300,8 +319,91 @@ public void visitParameter(JdbcParameter jdbcParameter) {
300
319
}
301
320
302
321
@ Override
322
+ @ SuppressWarnings ("OperatorPrecedence" )
303
323
public void visitSelectStatement (SelectStatement selectStatement ) {
304
- throw new FeatureNotSupportedException ("TODO-HIBERNATE-22 https://jira.mongodb.org/browse/HIBERNATE-22" );
324
+ logSqlAst (selectStatement );
325
+ if (!selectStatement .getQueryPart ().isRoot ()) {
326
+ throw new FeatureNotSupportedException ("Subquery not supported" );
327
+ }
328
+ if (selectStatement .getCteStatements () != null
329
+ && !selectStatement .getCteStatements ().isEmpty ()
330
+ || selectStatement .getCteObjects () != null
331
+ && !selectStatement .getCteObjects ().isEmpty ()) {
332
+ throw new FeatureNotSupportedException ("CTE feature not supported" );
333
+ }
334
+ selectStatement .getQueryPart ().accept (this );
335
+ }
336
+
337
+ @ Override
338
+ public void visitQuerySpec (QuerySpec querySpec ) {
339
+ var collection = acceptAndYield (assertNotNull (querySpec .getFromClause ()), COLLECTION_NAME );
340
+
341
+ var whereClauseRestrictions = querySpec .getWhereClauseRestrictions ();
342
+ var filter = whereClauseRestrictions == null || whereClauseRestrictions .isEmpty ()
343
+ ? AstMatchesEverythingFilter .INSTANCE
344
+ : acceptAndYield (whereClauseRestrictions , FILTER );
345
+
346
+ var projectStageSpecifications = acceptAndYield (querySpec .getSelectClause (), PROJECT_STAGE_SPECIFICATIONS );
347
+
348
+ var stages = List .<AstStage >of (new AstMatchStage (filter ), new AstProjectStage (projectStageSpecifications ));
349
+ astVisitorValueHolder .yield (COLLECTION_AGGREGATE , new AstAggregateCommand (collection , new AstPipeline (stages )));
350
+ }
351
+
352
+ @ Override
353
+ public void visitFromClause (FromClause fromClause ) {
354
+ if (fromClause .getRoots ().size () == 1
355
+ && fromClause .getRoots ().get (0 ) instanceof StandardTableGroup standardTableGroup
356
+ && standardTableGroup .getModelPart () instanceof EntityPersister entityPersister
357
+ && entityPersister .getQuerySpaces ().length == 1 ) {
358
+ affectedTableNames .add (((String []) entityPersister .getQuerySpaces ())[0 ]);
359
+ standardTableGroup .getPrimaryTableReference ().accept (this );
360
+ }
361
+ throw new FeatureNotSupportedException ();
362
+ }
363
+
364
+ @ Override
365
+ public void visitNamedTableReference (NamedTableReference namedTableReference ) {
366
+ astVisitorValueHolder .yield (COLLECTION_NAME , namedTableReference .getTableExpression ());
367
+ }
368
+
369
+ @ Override
370
+ public void visitRelationalPredicate (ComparisonPredicate comparisonPredicate ) {
371
+ var fieldName = acceptAndYield (comparisonPredicate .getLeftHandExpression (), FIELD_NAME );
372
+ var fieldValue = acceptAndYield (comparisonPredicate .getRightHandExpression (), FIELD_VALUE );
373
+
374
+ if (comparisonPredicate .getOperator () != EQUAL ) {
375
+ throw new FeatureNotSupportedException ();
376
+ }
377
+ var filter = new AstFieldOperationFilter (
378
+ new AstFilterFieldPath (fieldName ), new AstComparisonFilterOperation (EQ , fieldValue ));
379
+ astVisitorValueHolder .yield (FILTER , filter );
380
+ }
381
+
382
+ @ Override
383
+ public void visitSelectClause (SelectClause selectClause ) {
384
+ var projectStageSpecifications = new ArrayList <AstProjectStageSpecification >(
385
+ selectClause .getSqlSelections ().size ());
386
+
387
+ for (SqlSelection sqlSelection : selectClause .getSqlSelections ()) {
388
+ if (sqlSelection .isVirtual ()) {
389
+ continue ;
390
+ }
391
+ if (sqlSelection .getExpression () instanceof ColumnReference columnReference ) {
392
+ var columnName = acceptAndYield (columnReference , FIELD_NAME );
393
+ projectStageSpecifications .add (include (columnName ));
394
+ } else {
395
+ throw new FeatureNotSupportedException ();
396
+ }
397
+ }
398
+ astVisitorValueHolder .yield (PROJECT_STAGE_SPECIFICATIONS , projectStageSpecifications );
399
+ }
400
+
401
+ @ Override
402
+ public void visitColumnReference (ColumnReference columnReference ) {
403
+ if (columnReference .isColumnExpressionFormula ()) {
404
+ throw new FeatureNotSupportedException ();
405
+ }
406
+ astVisitorValueHolder .yield (FIELD_NAME , columnReference .getColumnExpression ());
305
407
}
306
408
307
409
@ Override
@@ -329,11 +431,6 @@ public void visitQueryGroup(QueryGroup queryGroup) {
329
431
throw new FeatureNotSupportedException ();
330
432
}
331
433
332
- @ Override
333
- public void visitQuerySpec (QuerySpec querySpec ) {
334
- throw new FeatureNotSupportedException ();
335
- }
336
-
337
434
@ Override
338
435
public void visitSortSpecification (SortSpecification sortSpecification ) {
339
436
throw new FeatureNotSupportedException ();
@@ -344,21 +441,11 @@ public void visitOffsetFetchClause(QueryPart queryPart) {
344
441
throw new FeatureNotSupportedException ();
345
442
}
346
443
347
- @ Override
348
- public void visitSelectClause (SelectClause selectClause ) {
349
- throw new FeatureNotSupportedException ();
350
- }
351
-
352
444
@ Override
353
445
public void visitSqlSelection (SqlSelection sqlSelection ) {
354
446
throw new FeatureNotSupportedException ();
355
447
}
356
448
357
- @ Override
358
- public void visitFromClause (FromClause fromClause ) {
359
- throw new FeatureNotSupportedException ();
360
- }
361
-
362
449
@ Override
363
450
public void visitTableGroup (TableGroup tableGroup ) {
364
451
throw new FeatureNotSupportedException ();
@@ -369,11 +456,6 @@ public void visitTableGroupJoin(TableGroupJoin tableGroupJoin) {
369
456
throw new FeatureNotSupportedException ();
370
457
}
371
458
372
- @ Override
373
- public void visitNamedTableReference (NamedTableReference namedTableReference ) {
374
- throw new FeatureNotSupportedException ();
375
- }
376
-
377
459
@ Override
378
460
public void visitValuesTableReference (ValuesTableReference valuesTableReference ) {
379
461
throw new FeatureNotSupportedException ();
@@ -394,11 +476,6 @@ public void visitTableReferenceJoin(TableReferenceJoin tableReferenceJoin) {
394
476
throw new FeatureNotSupportedException ();
395
477
}
396
478
397
- @ Override
398
- public void visitColumnReference (ColumnReference columnReference ) {
399
- throw new FeatureNotSupportedException ();
400
- }
401
-
402
479
@ Override
403
480
public void visitNestedColumnReference (NestedColumnReference nestedColumnReference ) {
404
481
throw new FeatureNotSupportedException ();
@@ -609,11 +686,6 @@ public void visitThruthnessPredicate(ThruthnessPredicate thruthnessPredicate) {
609
686
throw new FeatureNotSupportedException ();
610
687
}
611
688
612
- @ Override
613
- public void visitRelationalPredicate (ComparisonPredicate comparisonPredicate ) {
614
- throw new FeatureNotSupportedException ();
615
- }
616
-
617
689
@ Override
618
690
public void visitSelfRenderingPredicate (SelfRenderingPredicate selfRenderingPredicate ) {
619
691
throw new FeatureNotSupportedException ();
0 commit comments