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
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ package org .apache .cassandra .cql3 .validation ;
20
+
21
+ import org .junit .Test ;
22
+
23
+ import org .apache .cassandra .cql3 .CQLTester ;
24
+
25
+ /**
26
+ * Test UDT (User Defined Type) field queries in Cassandra.
27
+ *
28
+ * This test demonstrates how to:
29
+ * 1. Create UDTs with multiple fields
30
+ * 2. Select specific UDT fields
31
+ * 3. Query UDT fields in WHERE clauses
32
+ * 4. Use UDT fields with different operators
33
+ */
34
+ public class UDTFieldQueryTest extends CQLTester
35
+ {
36
+ @ Test
37
+ public void testUDTFieldSelection () throws Throwable
38
+ {
39
+ // Create a UDT with multiple fields
40
+ String personType = createType ("CREATE TYPE %s (name text, age int, city text, active boolean)" );
41
+ String personTypeName = KEYSPACE + '.' + personType ;
42
+
43
+ // Create table with UDT column
44
+ createTable ("CREATE TABLE %s (id int PRIMARY KEY, person " + personTypeName + ")" );
45
+
46
+ // Insert data
47
+ execute ("INSERT INTO %s (id, person) VALUES (1, {name: 'John', age: 30, city: 'New York', active: true})" );
48
+ execute ("INSERT INTO %s (id, person) VALUES (2, {name: 'Jane', age: 25, city: 'Boston', active: false})" );
49
+ execute ("INSERT INTO %s (id, person) VALUES (3, {name: 'Bob', age: 35, city: 'Chicago', active: true})" );
50
+
51
+ // Test selecting specific UDT fields
52
+ assertRows (execute ("SELECT person.name FROM %s WHERE id = 1" ), row ("John" ));
53
+ assertRows (execute ("SELECT person.age FROM %s WHERE id = 2" ), row (25 ));
54
+ assertRows (execute ("SELECT person.city FROM %s WHERE id = 3" ), row ("Chicago" ));
55
+ assertRows (execute ("SELECT person.active FROM %s WHERE id = 1" ), row (true ));
56
+
57
+ // Test selecting multiple UDT fields
58
+ assertRows (execute ("SELECT person.name, person.age FROM %s WHERE id = 1" ),
59
+ row ("John" , 30 ));
60
+
61
+ // Test selecting all UDT fields
62
+ assertRows (execute ("SELECT person FROM %s WHERE id = 1" ),
63
+ row (userType ("name" , "John" , "age" , 30 , "city" , "New York" , "active" , true )));
64
+ }
65
+
66
+ @ Test
67
+ public void testUDTFieldQueries () throws Throwable
68
+ {
69
+ // Create a UDT with multiple fields
70
+ String personType = createType ("CREATE TYPE %s (name text, age int, city text, active boolean)" );
71
+ String personTypeName = KEYSPACE + '.' + personType ;
72
+
73
+ // Create table with UDT column
74
+ createTable ("CREATE TABLE %s (id int PRIMARY KEY, person " + personTypeName + ")" );
75
+
76
+ // Insert data
77
+ execute ("INSERT INTO %s (id, person) VALUES (1, {name: 'John', age: 30, city: 'New York', active: true})" );
78
+ execute ("INSERT INTO %s (id, person) VALUES (2, {name: 'Jane', age: 25, city: 'Boston', active: false})" );
79
+ execute ("INSERT INTO %s (id, person) VALUES (3, {name: 'Bob', age: 35, city: 'Chicago', active: true})" );
80
+ execute ("INSERT INTO %s (id, person) VALUES (4, {name: 'Alice', age: 28, city: 'San Francisco', active: true})" );
81
+
82
+ // Test equality queries on UDT fields
83
+ assertRows (execute ("SELECT id FROM %s WHERE person.name = 'John' ALLOW FILTERING" ),
84
+ row (1 ));
85
+ assertRows (execute ("SELECT id FROM %s WHERE person.age = 25 ALLOW FILTERING" ),
86
+ row (2 ));
87
+ assertRows (execute ("SELECT id FROM %s WHERE person.city = 'Chicago' ALLOW FILTERING" ),
88
+ row (3 ));
89
+ assertRows (execute ("SELECT id FROM %s WHERE person.active = true ALLOW FILTERING" ),
90
+ row (1 ), row (3 ), row (4 ));
91
+
92
+ // Test range queries on UDT fields
93
+ assertRows (execute ("SELECT id FROM %s WHERE person.age > 30 ALLOW FILTERING" ),
94
+ row (3 ));
95
+ assertRows (execute ("SELECT id FROM %s WHERE person.age >= 25 ALLOW FILTERING" ),
96
+ row (1 ), row (2 ), row (3 ), row (4 ));
97
+ assertRows (execute ("SELECT id FROM %s WHERE person.age < 30 ALLOW FILTERING" ),
98
+ row (2 ), row (4 ));
99
+
100
+ // Test IN queries on UDT fields
101
+ assertRows (execute ("SELECT id FROM %s WHERE person.age IN (25, 30, 35) ALLOW FILTERING" ),
102
+ row (1 ), row (2 ), row (3 ));
103
+ assertRows (execute ("SELECT id FROM %s WHERE person.city IN ('New York', 'Boston') ALLOW FILTERING" ),
104
+ row (1 ), row (2 ));
105
+
106
+ // Test multiple conditions on UDT fields
107
+ assertRows (execute ("SELECT id FROM %s WHERE person.age > 25 AND person.active = true ALLOW FILTERING" ),
108
+ row (1 ), row (3 ), row (4 ));
109
+ assertRows (execute ("SELECT id FROM %s WHERE person.age >= 30 AND person.city = 'New York' ALLOW FILTERING" ),
110
+ row (1 ));
111
+ }
112
+
113
+ @ Test
114
+ public void testUDTFieldQueriesWithNullValues () throws Throwable
115
+ {
116
+ // Create a UDT with nullable fields
117
+ String personType = createType ("CREATE TYPE %s (name text, age int, city text)" );
118
+ String personTypeName = KEYSPACE + '.' + personType ;
119
+
120
+ // Create table with UDT column
121
+ createTable ("CREATE TABLE %s (id int PRIMARY KEY, person " + personTypeName + ")" );
122
+
123
+ // Insert data with null values
124
+ execute ("INSERT INTO %s (id, person) VALUES (1, {name: 'John', age: 30, city: null})" );
125
+ execute ("INSERT INTO %s (id, person) VALUES (2, {name: null, age: 25, city: 'Boston'})" );
126
+ execute ("INSERT INTO %s (id, person) VALUES (3, {name: 'Bob', age: null, city: 'Chicago'})" );
127
+
128
+ // Test queries with null values
129
+ assertRows (execute ("SELECT id FROM %s WHERE person.name = null ALLOW FILTERING" ),
130
+ row (2 ));
131
+ assertRows (execute ("SELECT id FROM %s WHERE person.city = null ALLOW FILTERING" ),
132
+ row (1 ));
133
+ assertRows (execute ("SELECT id FROM %s WHERE person.age = null ALLOW FILTERING" ),
134
+ row (3 ));
135
+
136
+ // Test queries with non-null values
137
+ assertRows (execute ("SELECT id FROM %s WHERE person.name != null ALLOW FILTERING" ),
138
+ row (1 ), row (3 ));
139
+ assertRows (execute ("SELECT id FROM %s WHERE person.city != null ALLOW FILTERING" ),
140
+ row (2 ), row (3 ));
141
+ }
142
+
143
+ @ Test
144
+ public void testUDTFieldQueriesWithFrozenUDT () throws Throwable
145
+ {
146
+ // Create a UDT
147
+ String personType = createType ("CREATE TYPE %s (name text, age int)" );
148
+ String personTypeName = KEYSPACE + '.' + personType ;
149
+
150
+ // Create table with frozen UDT column
151
+ createTable ("CREATE TABLE %s (id int PRIMARY KEY, person frozen<" + personTypeName + ">)" );
152
+
153
+ // Insert data
154
+ execute ("INSERT INTO %s (id, person) VALUES (1, {name: 'John', age: 30})" );
155
+ execute ("INSERT INTO %s (id, person) VALUES (2, {name: 'Jane', age: 25})" );
156
+
157
+ // Test UDT field selection with frozen UDT
158
+ assertRows (execute ("SELECT person.name FROM %s WHERE id = 1" ), row ("John" ));
159
+ assertRows (execute ("SELECT person.age FROM %s WHERE id = 2" ), row (25 ));
160
+
161
+ // Test UDT field queries with frozen UDT
162
+ assertRows (execute ("SELECT id FROM %s WHERE person.name = 'John' ALLOW FILTERING" ),
163
+ row (1 ));
164
+ assertRows (execute ("SELECT id FROM %s WHERE person.age > 25 ALLOW FILTERING" ),
165
+ row (1 ));
166
+ }
167
+
168
+ @ Test
169
+ public void testUDTFieldQueriesWithComplexUDT () throws Throwable
170
+ {
171
+ // Create nested UDTs
172
+ String addressType = createType ("CREATE TYPE %s (street text, city text, zip text)" );
173
+ String addressTypeName = KEYSPACE + '.' + addressType ;
174
+
175
+ String personType = createType ("CREATE TYPE %s (name text, age int, address " + addressTypeName + ")" );
176
+ String personTypeName = KEYSPACE + '.' + personType ;
177
+
178
+ // Create table with complex UDT
179
+ createTable ("CREATE TABLE %s (id int PRIMARY KEY, person " + personTypeName + ")" );
180
+
181
+ // Insert data with nested UDT
182
+ execute ("INSERT INTO %s (id, person) VALUES (1, {name: 'John', age: 30, address: {street: '123 Main St', city: 'New York', zip: '10001'}})" );
183
+ execute ("INSERT INTO %s (id, person) VALUES (2, {name: 'Jane', age: 25, address: {street: '456 Oak Ave', city: 'Boston', zip: '02101'}})" );
184
+
185
+ // Test nested UDT field selection
186
+ assertRows (execute ("SELECT person.address.city FROM %s WHERE id = 1" ), row ("New York" ));
187
+ assertRows (execute ("SELECT person.address.street FROM %s WHERE id = 2" ), row ("456 Oak Ave" ));
188
+
189
+ // Test nested UDT field queries
190
+ assertRows (execute ("SELECT id FROM %s WHERE person.address.city = 'New York' ALLOW FILTERING" ),
191
+ row (1 ));
192
+ assertRows (execute ("SELECT id FROM %s WHERE person.address.zip = '02101' ALLOW FILTERING" ),
193
+ row (2 ));
194
+
195
+ // Test combining nested UDT field queries with regular UDT field queries
196
+ assertRows (execute ("SELECT id FROM %s WHERE person.age > 25 AND person.address.city = 'New York' ALLOW FILTERING" ),
197
+ row (1 ));
198
+ }
199
+ }
0 commit comments