1+ /*****************************************************************
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ *
10+ * https://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing,
13+ * software distributed under the License is distributed on an
14+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+ * KIND, either express or implied. See the License for the
16+ * specific language governing permissions and limitations
17+ * under the License.
18+ ****************************************************************/
19+
20+ package org .apache .cayenne .exp .parser ;
21+
22+ import org .apache .cayenne .ObjectContext ;
23+ import org .apache .cayenne .di .Inject ;
24+ import org .apache .cayenne .exp .Expression ;
25+ import org .apache .cayenne .exp .ExpressionException ;
26+ import org .apache .cayenne .exp .ExpressionFactory ;
27+ import org .apache .cayenne .query .ObjectSelect ;
28+ import org .apache .cayenne .test .jdbc .DBHelper ;
29+ import org .apache .cayenne .test .jdbc .TableHelper ;
30+ import org .apache .cayenne .testdo .testmap .Artist ;
31+ import org .apache .cayenne .testdo .testmap .Gallery ;
32+ import org .apache .cayenne .testdo .testmap .Painting ;
33+ import org .apache .cayenne .unit .di .DataChannelInterceptor ;
34+ import org .apache .cayenne .unit .di .runtime .CayenneProjects ;
35+ import org .apache .cayenne .unit .di .runtime .RuntimeCase ;
36+ import org .apache .cayenne .unit .di .runtime .UseCayenneRuntime ;
37+ import org .junit .Before ;
38+ import org .junit .Test ;
39+
40+ import java .util .List ;
41+
42+ import static org .junit .Assert .*;
43+
44+ @ UseCayenneRuntime (CayenneProjects .TESTMAP_PROJECT )
45+ public class ASTExistsIT extends RuntimeCase {
46+
47+ @ Inject
48+ private ObjectContext context ;
49+
50+ @ Inject
51+ private DBHelper dbHelper ;
52+
53+ @ Inject
54+ private DataChannelInterceptor queryInterceptor ;
55+
56+ @ Before
57+ public void createArtistsDataSet () throws Exception {
58+ TableHelper tArtist = new TableHelper (dbHelper , "ARTIST" );
59+ tArtist .setColumns ("ARTIST_ID" , "ARTIST_NAME" , "DATE_OF_BIRTH" );
60+
61+ long dateBase = System .currentTimeMillis ();
62+ for (int i = 1 ; i <= 20 ; i ++) {
63+ tArtist .insert (i , "artist" + i , new java .sql .Date (dateBase + 10000 * i ));
64+ }
65+
66+ TableHelper tGallery = new TableHelper (dbHelper , "GALLERY" );
67+ tGallery .setColumns ("GALLERY_ID" , "GALLERY_NAME" );
68+ tGallery .insert (1 , "tate modern" );
69+
70+ TableHelper tPaintings = new TableHelper (dbHelper , "PAINTING" );
71+ tPaintings .setColumns ("PAINTING_ID" , "PAINTING_TITLE" , "ARTIST_ID" , "GALLERY_ID" );
72+ for (int i = 1 ; i <= 20 ; i ++) {
73+ tPaintings .insert (i , "painting" + i , i % 5 + 1 , 1 );
74+ }
75+ }
76+
77+ @ Test (expected = ExpressionException .class )
78+ public void testEvaluateInMemoryExistsSubquery () {
79+ ObjectSelect <Painting > subQuery = ObjectSelect .query (Painting .class )
80+ .where (Painting .TO_ARTIST .eq (Artist .ARTIST_ID_PK_PROPERTY .enclosing ()));
81+
82+ doEvaluateWithQuery (ExpressionFactory .notExists (subQuery ));
83+ }
84+
85+ @ Test
86+ public void testEvaluateInMemoryExistsExpression () {
87+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .exists ());
88+
89+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("p%" ).exists ());
90+
91+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("not_exists%" ).exists ());
92+
93+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_PAINTING_INFO ).exists ());
94+
95+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).exists ());
96+
97+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("g%" ).exists ());
98+
99+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("not_exists%" ).exists ());
100+
101+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("g%" )
102+ .andExp (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("p%" ))
103+ .exists ());
104+
105+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("not_exists%" )
106+ .andExp (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("p%" ))
107+ .exists ());
108+
109+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("g%" )
110+ .andExp (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("not_exists%" ))
111+ .exists ());
112+
113+ doEvaluateNoQuery (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).dot (Gallery .GALLERY_NAME ).like ("not_exists%" )
114+ .andExp (Artist .PAINTING_ARRAY .dot (Painting .PAINTING_TITLE ).like ("not_exists%" ))
115+ .exists ());
116+
117+ }
118+
119+ private void doEvaluateNoQuery (Expression exp ) {
120+ List <Artist > artistSelected = ObjectSelect .query (Artist .class , exp ).select (context );
121+
122+ List <Artist > artists = ObjectSelect .query (Artist .class )
123+ .prefetch (Artist .PAINTING_ARRAY .disjoint ())
124+ .prefetch (Artist .PAINTING_ARRAY .dot (Painting .TO_PAINTING_INFO ).disjoint ())
125+ .prefetch (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).disjoint ())
126+ .select (context );
127+
128+ queryInterceptor .runWithQueriesBlocked (() -> {
129+ List <Artist > artistsFiltered = exp .filterObjects (artists );
130+ assertEquals (exp .toString (), artistSelected , artistsFiltered );
131+ });
132+ }
133+
134+ private void doEvaluateWithQuery (Expression exp ) {
135+ List <Artist > artistSelected = ObjectSelect .query (Artist .class , exp ).select (context );
136+
137+ List <Artist > artists = ObjectSelect .query (Artist .class )
138+ .prefetch (Artist .PAINTING_ARRAY .disjoint ())
139+ .prefetch (Artist .PAINTING_ARRAY .dot (Painting .TO_PAINTING_INFO ).disjoint ())
140+ .prefetch (Artist .PAINTING_ARRAY .dot (Painting .TO_GALLERY ).disjoint ())
141+ .select (context );
142+
143+ List <Artist > artistsFiltered = exp .filterObjects (artists );
144+ assertEquals (exp .toString (), artistSelected , artistsFiltered );
145+ }
146+ }
0 commit comments