@@ -104,6 +104,7 @@ public class GraphQLJpaSchemaBuilder implements GraphQLSchemaBuilder {
104104 private Map <Class <?>, GraphQLOutputType > classCache = new HashMap <>();
105105 private Map <EntityType <?>, GraphQLObjectType > entityCache = new HashMap <>();
106106 private Map <ManagedType <?>, GraphQLInputObjectType > inputObjectCache = new HashMap <>();
107+ private Map <ManagedType <?>, GraphQLInputObjectType > subqueryInputObjectCache = new HashMap <>();
107108 private Map <Class <?>, GraphQLObjectType > embeddableOutputCache = new HashMap <>();
108109 private Map <Class <?>, GraphQLInputObjectType > embeddableInputCache = new HashMap <>();
109110
@@ -253,6 +254,18 @@ private GraphQLArgument computeWhereArgument(ManagedType<?> managedType) {
253254 .type (new GraphQLList (new GraphQLTypeReference (type )))
254255 .build ()
255256 )
257+ .field (GraphQLInputObjectField .newInputObjectField ()
258+ .name ("EXISTS" )
259+ .description ("Logical EXISTS subquery expression" )
260+ .type (new GraphQLList (getSubqueryInputType (managedType )))
261+ .build ()
262+ )
263+ .field (GraphQLInputObjectField .newInputObjectField ()
264+ .name ("NOT_EXISTS" )
265+ .description ("Logical NOT EXISTS subquery expression" )
266+ .type (new GraphQLList (getSubqueryInputType (managedType )))
267+ .build ()
268+ )
256269 .fields (managedType .getAttributes ().stream ()
257270 .filter (this ::isValidInput )
258271 .filter (this ::isNotIgnored )
@@ -283,6 +296,58 @@ private String resolveWhereArgumentTypeName(ManagedType<?> managedType) {
283296 return namingStrategy .pluralize (typeName )+"CriteriaExpression" ;
284297 }
285298
299+ private String resolveSubqueryArgumentTypeName (ManagedType <?> managedType ) {
300+ String typeName =resolveTypeName (managedType );
301+
302+ return namingStrategy .pluralize (typeName )+"SubqueryCriteriaExpression" ;
303+ }
304+
305+ private GraphQLInputObjectType getSubqueryInputType (ManagedType <?> managedType ) {
306+ return subqueryInputObjectCache .computeIfAbsent (managedType , this ::computeSubqueryInputType );
307+ }
308+
309+ private GraphQLInputObjectType computeSubqueryInputType (ManagedType <?> managedType ) {
310+ String type =resolveSubqueryArgumentTypeName (managedType );
311+
312+ Builder whereInputObject = GraphQLInputObjectType .newInputObject ()
313+ .name (type )
314+ .description ("Where logical AND specification of the provided list of criteria expressions" )
315+ .field (GraphQLInputObjectField .newInputObjectField ()
316+ .name (OR )
317+ .description ("Logical operation for expressions" )
318+ .type (new GraphQLList (new GraphQLTypeReference (type )))
319+ .build ()
320+ )
321+ .field (GraphQLInputObjectField .newInputObjectField ()
322+ .name (AND )
323+ .description ("Logical operation for expressions" )
324+ .type (new GraphQLList (new GraphQLTypeReference (type )))
325+ .build ()
326+ )
327+ .field (GraphQLInputObjectField .newInputObjectField ()
328+ .name ("EXISTS" )
329+ .description ("Logical EXISTS subquery expression" )
330+ .type (new GraphQLList (new GraphQLTypeReference (type )))
331+ .build ()
332+ )
333+ .field (GraphQLInputObjectField .newInputObjectField ()
334+ .name ("NOT_EXISTS" )
335+ .description ("Logical NOT EXISTS subquery expression" )
336+ .type (new GraphQLList (new GraphQLTypeReference (type )))
337+ .build ()
338+ )
339+ .fields (managedType .getAttributes ().stream ()
340+ .filter (this ::isValidAssociation )
341+ .filter (this ::isNotIgnored )
342+ .filter (this ::isNotIgnoredFilter )
343+ .map (this ::getWhereInputRelationField )
344+ .collect (Collectors .toList ())
345+ );
346+
347+ return whereInputObject .build ();
348+
349+ }
350+
286351 private String resolveTypeName (ManagedType <?> managedType ) {
287352 String typeName ="" ;
288353
@@ -313,31 +378,44 @@ private GraphQLInputObjectType computeWhereInputType(ManagedType<?> managedType)
313378 .name (type )
314379 .description ("Where logical AND specification of the provided list of criteria expressions" )
315380 .field (GraphQLInputObjectField .newInputObjectField ()
316- .name (OR )
317- .description ("Logical operation for expressions" )
318- .type (new GraphQLList (new GraphQLTypeReference (type )))
319- .build ()
381+ .name (OR )
382+ .description ("Logical operation for expressions" )
383+ .type (new GraphQLList (new GraphQLTypeReference (type )))
384+ .build ()
320385 )
321386 .field (GraphQLInputObjectField .newInputObjectField ()
322- .name (AND )
323- .description ("Logical operation for expressions" )
324- .type (new GraphQLList (new GraphQLTypeReference (type )))
325- .build ()
387+ .name (AND )
388+ .description ("Logical operation for expressions" )
389+ .type (new GraphQLList (new GraphQLTypeReference (type )))
390+ .build ()
391+ )
392+ .field (GraphQLInputObjectField .newInputObjectField ()
393+ .name ("EXISTS" )
394+ .description ("Logical EXISTS subquery expression" )
395+ .type (new GraphQLList (getSubqueryInputType (managedType )))
396+ .build ()
397+ )
398+ .field (GraphQLInputObjectField .newInputObjectField ()
399+ .name ("NOT_EXISTS" )
400+ .description ("Logical NOT EXISTS subquery expression" )
401+ .type (new GraphQLList (getSubqueryInputType (managedType )))
402+ .build ()
326403 )
327404 .fields (managedType .getAttributes ().stream ()
328- .filter (this ::isValidInput )
329- .filter (this ::isNotIgnored )
330- .filter (this ::isNotIgnoredFilter )
331- .map (this ::getWhereInputField )
332- .collect (Collectors .toList ())
405+ .filter (this ::isValidInput )
406+ .filter (this ::isNotIgnored )
407+ .filter (this ::isNotIgnoredFilter )
408+ .map (this ::getWhereInputField )
409+ .collect (Collectors .toList ())
333410 )
334411 .fields (managedType .getAttributes ().stream ()
335- .filter (this ::isValidAssociation )
336- .filter (this ::isNotIgnored )
337- .filter (this ::isNotIgnoredFilter )
338- .map (this ::getWhereInputRelationField )
339- .collect (Collectors .toList ())
412+ .filter (this ::isValidAssociation )
413+ .filter (this ::isNotIgnored )
414+ .filter (this ::isNotIgnoredFilter )
415+ .map (this ::getWhereInputRelationField )
416+ .collect (Collectors .toList ())
340417 );
418+
341419
342420 return whereInputObject .build ();
343421
@@ -350,23 +428,22 @@ private GraphQLInputObjectField getWhereInputRelationField(Attribute<?,?> attrib
350428 String description = getSchemaDescription (attribute .getJavaMember ());
351429
352430 return GraphQLInputObjectField .newInputObjectField ()
353- .name (attribute .getName ())
354- .description (description )
355- .type (new GraphQLTypeReference (type ))
356- .build ();
431+ .name (attribute .getName ())
432+ .description (description )
433+ .type (new GraphQLTypeReference (type ))
434+ .build ();
357435 }
358436
359-
360437 private GraphQLInputObjectField getWhereInputField (Attribute <?,?> attribute ) {
361438 GraphQLInputType type = getWhereAttributeType (attribute );
362439 String description = getSchemaDescription (attribute .getJavaMember ());
363440
364441 if (type instanceof GraphQLInputType ) {
365442 return GraphQLInputObjectField .newInputObjectField ()
366- .name (attribute .getName ())
367- .description (description )
368- .type (type )
369- .build ();
443+ .name (attribute .getName ())
444+ .description (description )
445+ .type (type )
446+ .build ();
370447 }
371448
372449 throw new IllegalArgumentException ("Attribute " + attribute .getName () + " cannot be mapped as an Input Argument" );
0 commit comments