From 490c7086e106c518692ee53b6440d8f3f69fa8c7 Mon Sep 17 00:00:00 2001 From: Yingtao Liu Date: Wed, 28 Feb 2024 16:39:56 -0800 Subject: [PATCH] add test cases --- .../eval/internal/PartiQLEngineDefaultTest.kt | 135 ++++++++++++------ .../planner/internal/typer/PlanTyper.kt | 18 ++- 2 files changed, 105 insertions(+), 48 deletions(-) diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEngineDefaultTest.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEngineDefaultTest.kt index e0032292a4..cff3d81fdf 100644 --- a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEngineDefaultTest.kt +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEngineDefaultTest.kt @@ -1291,54 +1291,107 @@ class PartiQLEngineDefaultTest { ).assert() @Test + // TODO: Add to conformance tests fun wildCard() = SuccessTestCase( input = """ - [ - { - 'id':'5', - 'books':[ - { - 'title':'A', - 'price':5.0 - }, - { - 'title':'B', - 'price':2.0 - } - ] - }, - { - 'id':'6', - 'books':[ - { - 'title':'A', - 'price':5.0 - }, - { - 'title':'E', - 'price':2.0 - } - ] - }, - { - 'id':7, - 'books':[] - } - ][*].books[*].title + [ + { 'id':'5', + 'books':[ + { 'title':'A', + 'price':5.0, + 'authors': [{'name': 'John'}, {'name': 'Doe'}] + }, + { 'title':'B', + 'price':2.0, + 'authors': [{'name': 'Zoe'}, {'name': 'Bill'}] + } + ] + }, + { 'id':'6', + 'books':[ + { 'title':'A', + 'price':5.0, + 'authors': [{'name': 'John'}, {'name': 'Doe'}] + }, + { 'title':'E', + 'price':2.0, + 'authors': [{'name': 'Zoe'}, {'name': 'Bill'}] + } + ] + }, + { 'id':7, + 'books':[] + } + ][*].books[*].authors[*].name """.trimIndent(), - expected = bagValue(listOf(stringValue("A"), stringValue("B"), stringValue("A"), stringValue("E"))) + expected = bagValue( + listOf( + stringValue("John"), stringValue("Doe"), stringValue("Zoe"), stringValue("Bill"), + stringValue("John"), stringValue("Doe"), stringValue("Zoe"), stringValue("Bill") + ) + ) ).assert() @Test - fun wildCard2() { - val query = """ - {'a':1, 'b':2}.* - """.trimIndent() - val expected = bagValue(listOf(int32Value(1), int32Value(2))) + // TODO: add to conformance tests + // Note that the existing pipeline produced identical result when supplying with + // SELECT VALUE v2.name FROM e as v0, v0.books as v1, unpivot v1.authors as v2; + // But it produces different result when supplying with e[*].books[*].authors.* + // << + // <<{ 'name': 'John'},{'name': 'Doe'} >>, + // ... + // >> + fun unpivot() = SuccessTestCase( - query, - expected + input = """ + [ + { 'id':'5', + 'books':[ + { 'title':'A', + 'price':5.0, + 'authors': { + 'first': {'name': 'John'}, + 'second': {'name': 'Doe'} + } + }, + { 'title':'B', + 'price':2.0, + 'authors': { + 'first': {'name': 'Zoe'}, + 'second': {'name': 'Bill'} + } + } + ] + }, + { 'id':'6', + 'books':[ + { 'title':'A', + 'price':5.0, + 'authors': { + 'first': {'name': 'John'}, + 'second': {'name': 'Doe'} + } + }, + { 'title':'E', + 'price':2.0, + 'authors': { + 'first': {'name': 'Zoe'}, + 'second': {'name': 'Bill'} + } + } + ] + }, + { 'id':7, + 'books':[] + } + ][*].books[*].authors.*.name + """.trimIndent(), + expected = bagValue( + listOf( + stringValue("John"), stringValue("Doe"), stringValue("Zoe"), stringValue("Bill"), + stringValue("John"), stringValue("Doe"), stringValue("Zoe"), stringValue("Bill") + ) + ) ).assert() - } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt index a8fc3df8f7..6281efad4d 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt @@ -171,15 +171,19 @@ internal class PlanTyper( val kType = STRING // value type, possibly coerced. - val vType = when (val t = rex.type) { - is StructType -> { - if (t.contentClosed || t.constraints.contains(TupleConstraint.Open(false))) { - unionOf(t.fields.map { it.value }.toSet()).flatten() - } else { - ANY + val vType = rex.type.allTypes.map { type -> + when (type) { + is StructType -> { + if (type.contentClosed || type.constraints.contains(TupleConstraint.Open(false))) { + unionOf(type.fields.map { it.value }.toSet()).flatten() + } else { + ANY + } } + else -> type } - else -> t + }.let { + unionOf(it.toSet()) } // rewrite