@@ -14,7 +14,9 @@ import org.partiql.value.bagValue
14
14
import org.partiql.value.boolValue
15
15
import org.partiql.value.int32Value
16
16
import org.partiql.value.io.PartiQLValueIonWriterBuilder
17
+ import org.partiql.value.missingValue
17
18
import org.partiql.value.nullValue
19
+ import org.partiql.value.stringValue
18
20
import org.partiql.value.structValue
19
21
import java.io.ByteArrayOutputStream
20
22
import kotlin.test.assertEquals
@@ -112,10 +114,12 @@ class PartiQLEngineDefaultTest {
112
114
fun testJoinOuterFull () {
113
115
val statement =
114
116
parser.parse(" SELECT a, b FROM << { 'a': 1 } >> t FULL OUTER JOIN << { 'b': 2 } >> s ON false;" ).root
117
+
115
118
val session = PartiQLPlanner .Session (" q" , " u" )
116
119
val plan = planner.plan(statement, session)
117
120
118
121
val prepared = engine.prepare(plan.plan)
122
+
119
123
val result = engine.execute(prepared)
120
124
if (result is PartiQLResult .Error ) {
121
125
throw result.cause
@@ -136,15 +140,43 @@ class PartiQLEngineDefaultTest {
136
140
assertEquals(expected, output, comparisonString(expected, output))
137
141
}
138
142
143
+ @OptIn(PartiQLValueExperimental ::class )
144
+ @Test
145
+ fun testTupleUnion () {
146
+ val source = """
147
+ TUPLEUNION(
148
+ { 'a': 1 },
149
+ { 'b': TRUE },
150
+ { 'c': 'hello' }
151
+ );
152
+ """ .trimIndent()
153
+ val statement = parser.parse(source).root
154
+ val session = PartiQLPlanner .Session (" q" , " u" )
155
+ val plan = planner.plan(statement, session)
156
+
157
+ val prepared = engine.prepare(plan.plan)
158
+ val result = engine.execute(prepared) as PartiQLResult .Value
159
+ val output = result.value
160
+
161
+ val expected = structValue(
162
+ " a" to int32Value(1 ),
163
+ " b" to boolValue(true ),
164
+ " c" to stringValue(" hello" )
165
+ )
166
+ assertEquals(expected, output)
167
+ }
168
+
139
169
@OptIn(PartiQLValueExperimental ::class )
140
170
@Test
141
171
fun testJoinOuterFullOnTrue () {
142
172
val statement =
143
173
parser.parse(" SELECT a, b FROM << { 'a': 1 } >> t FULL OUTER JOIN << { 'b': 2 } >> s ON TRUE;" ).root
174
+
144
175
val session = PartiQLPlanner .Session (" q" , " u" )
145
176
val plan = planner.plan(statement, session)
146
177
147
178
val prepared = engine.prepare(plan.plan)
179
+
148
180
val result = engine.execute(prepared)
149
181
if (result is PartiQLResult .Error ) {
150
182
throw result.cause
@@ -161,6 +193,28 @@ class PartiQLEngineDefaultTest {
161
193
assertEquals(expected, output, comparisonString(expected, output))
162
194
}
163
195
196
+ @OptIn(PartiQLValueExperimental ::class )
197
+ @Test
198
+ fun testTupleUnionNullInput () {
199
+ val source = """
200
+ TUPLEUNION(
201
+ { 'a': 1 },
202
+ NULL,
203
+ { 'c': 'hello' }
204
+ );
205
+ """ .trimIndent()
206
+ val statement = parser.parse(source).root
207
+ val session = PartiQLPlanner .Session (" q" , " u" )
208
+ val plan = planner.plan(statement, session)
209
+
210
+ val prepared = engine.prepare(plan.plan)
211
+ val result = engine.execute(prepared) as PartiQLResult .Value
212
+ val output = result.value
213
+
214
+ val expected = structValue<PartiQLValue >(null )
215
+ assertEquals(expected, output)
216
+ }
217
+
164
218
@OptIn(PartiQLValueExperimental ::class )
165
219
private fun comparisonString (expected : PartiQLValue , actual : PartiQLValue ): String {
166
220
val expectedBuffer = ByteArrayOutputStream ()
@@ -173,4 +227,84 @@ class PartiQLEngineDefaultTest {
173
227
appendLine(" Actual : $expectedBuffer " )
174
228
}
175
229
}
230
+
231
+ @OptIn(PartiQLValueExperimental ::class )
232
+ @Test
233
+ fun testTupleUnionBadInput () {
234
+ val source = """
235
+ TUPLEUNION(
236
+ { 'a': 1 },
237
+ 5,
238
+ { 'c': 'hello' }
239
+ );
240
+ """ .trimIndent()
241
+ val statement = parser.parse(source).root
242
+ val session = PartiQLPlanner .Session (" q" , " u" )
243
+ val plan = planner.plan(statement, session)
244
+
245
+ val prepared = engine.prepare(plan.plan)
246
+ val result = engine.execute(prepared) as PartiQLResult .Value
247
+ val output = result.value
248
+
249
+ val expected = missingValue()
250
+ assertEquals(expected, output)
251
+ }
252
+
253
+ @OptIn(PartiQLValueExperimental ::class )
254
+ @Test
255
+ fun testTupleUnionDuplicates () {
256
+ val source = """
257
+ TUPLEUNION(
258
+ { 'a': 1, 'b': FALSE },
259
+ { 'b': TRUE },
260
+ { 'c': 'hello' }
261
+ );
262
+ """ .trimIndent()
263
+ val statement = parser.parse(source).root
264
+ val session = PartiQLPlanner .Session (" q" , " u" )
265
+ val plan = planner.plan(statement, session)
266
+
267
+ val prepared = engine.prepare(plan.plan)
268
+ val result = engine.execute(prepared) as PartiQLResult .Value
269
+ val output = result.value
270
+
271
+ val expected = structValue(
272
+ " a" to int32Value(1 ),
273
+ " b" to boolValue(false ),
274
+ " b" to boolValue(true ),
275
+ " c" to stringValue(" hello" )
276
+ )
277
+ assertEquals(expected, output)
278
+ }
279
+
280
+ @OptIn(PartiQLValueExperimental ::class )
281
+ @Test
282
+ fun testSelectStarTupleUnion () {
283
+ // As SELECT * gets converted to TUPLEUNION, this is a sanity check
284
+ val source = """
285
+ SELECT * FROM
286
+ <<
287
+ { 'a': 1, 'b': FALSE }
288
+ >> AS t,
289
+ <<
290
+ { 'b': TRUE }
291
+ >> AS s
292
+ """ .trimIndent()
293
+ val statement = parser.parse(source).root
294
+ val session = PartiQLPlanner .Session (" q" , " u" )
295
+ val plan = planner.plan(statement, session)
296
+
297
+ val prepared = engine.prepare(plan.plan)
298
+ val result = engine.execute(prepared) as PartiQLResult .Value
299
+ val output = result.value
300
+
301
+ val expected = bagValue(
302
+ structValue(
303
+ " a" to int32Value(1 ),
304
+ " b" to boolValue(false ),
305
+ " b" to boolValue(true )
306
+ )
307
+ )
308
+ assertEquals(expected, output)
309
+ }
176
310
}
0 commit comments