Skip to content

Commit f3f9b49

Browse files
authored
Merge 8a37a9a into f8f6b2a
2 parents f8f6b2a + 8a37a9a commit f3f9b49

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Thank you to all who have contributed!
3636
- **EXPERIMENTAL** Evaluation of `EXCLUDE` in the `EvaluatingCompiler`
3737
- This is currently marked as experimental until the RFC is approved https://github.com/partiql/partiql-lang/issues/27
3838
- This will be added to the `PhysicalPlanCompiler` in an upcoming release
39+
- **EXPERIMENTAL**: Adds support for EXCLUDE in the default SqlDialect.
3940

4041
### Changed
4142
- StaticTypeInferencer and PlanTyper will not raise an error when an expression is inferred to `NULL` or `unionOf(NULL, MISSING)`. In these cases the StaticTypeInferencer and PlanTyper will still raise the Problem Code `ExpressionAlwaysReturnsNullOrMissing` but the severity of the problem has been changed to warning. In the case an expression always returns `MISSING`, problem code `ExpressionAlwaysReturnsMissing` will be raised, which will have problem severity of error.

partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.partiql.ast.sql
22

33
import org.partiql.ast.AstNode
4+
import org.partiql.ast.Exclude
45
import org.partiql.ast.Expr
56
import org.partiql.ast.From
67
import org.partiql.ast.GroupBy
@@ -82,6 +83,38 @@ public abstract class SqlDialect : AstBaseVisitor<SqlBlock, SqlBlock>() {
8283
return head concat r(path)
8384
}
8485

86+
override fun visitExclude(node: Exclude, head: SqlBlock): SqlBlock {
87+
var h = head
88+
h = h concat " EXCLUDE "
89+
h = h concat list(start = null, end = null) { node.exprs }
90+
return h
91+
}
92+
93+
override fun visitExcludeExcludeExpr(node: Exclude.ExcludeExpr, head: SqlBlock): SqlBlock {
94+
var h = head
95+
h = h concat visitIdentifierSymbol(node.root, SqlBlock.Nil)
96+
h = h concat list(delimiter = null, start = null, end = null) { node.steps }
97+
return h
98+
}
99+
100+
override fun visitExcludeStepExcludeCollectionIndex(node: Exclude.Step.ExcludeCollectionIndex, head: SqlBlock): SqlBlock {
101+
return head concat r("[${node.index}]")
102+
}
103+
104+
override fun visitExcludeStepExcludeTupleWildcard(node: Exclude.Step.ExcludeTupleWildcard, head: SqlBlock): SqlBlock {
105+
return head concat r(".*")
106+
}
107+
108+
override fun visitExcludeStepExcludeTupleAttr(node: Exclude.Step.ExcludeTupleAttr, head: SqlBlock): SqlBlock {
109+
var h = head concat r(".")
110+
h = h concat visitIdentifierSymbol(node.symbol, SqlBlock.Nil)
111+
return h
112+
}
113+
114+
override fun visitExcludeStepExcludeCollectionWildcard(node: Exclude.Step.ExcludeCollectionWildcard, head: SqlBlock): SqlBlock {
115+
return head concat r("[*]")
116+
}
117+
85118
// cannot write path step outside the context of a path as we don't want it to reflow
86119
override fun visitPathStep(node: Path.Step, head: SqlBlock) = error("path step cannot be written directly")
87120

@@ -550,6 +583,8 @@ public abstract class SqlDialect : AstBaseVisitor<SqlBlock, SqlBlock>() {
550583
var h = head
551584
// SELECT
552585
h = visit(node.select, h)
586+
// EXCLUDE
587+
h = node.exclude?.let { visit(it, h) } ?: h
553588
// FROM
554589
h = visit(node.from, h concat r(" FROM "))
555590
// LET

partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ class SqlDialectTest {
134134
@Execution(ExecutionMode.CONCURRENT)
135135
fun testSelectClause(case: Case) = case.assert()
136136

137+
@ParameterizedTest(name = "EXCLUDE Clause #{index}")
138+
@MethodSource("excludeClauseCases")
139+
@Execution(ExecutionMode.CONCURRENT)
140+
fun testExcludeClause(case: Case) = case.assert()
141+
137142
@ParameterizedTest(name = "FROM Clause #{index}")
138143
@MethodSource("fromClauseCases")
139144
@Execution(ExecutionMode.CONCURRENT)
@@ -1058,6 +1063,94 @@ class SqlDialectTest {
10581063
},
10591064
)
10601065

1066+
@JvmStatic
1067+
fun excludeClauseCases() = listOf(
1068+
expect("SELECT a EXCLUDE t.a FROM T") {
1069+
exprSFW {
1070+
select = select("a")
1071+
from = fromValue {
1072+
expr = v("T")
1073+
type = From.Value.Type.SCAN
1074+
}
1075+
exclude = exclude {
1076+
exprs += excludeExcludeExpr {
1077+
root = id("t", Identifier.CaseSensitivity.INSENSITIVE)
1078+
steps += excludeStepExcludeTupleAttr {
1079+
symbol = id("a", Identifier.CaseSensitivity.INSENSITIVE)
1080+
}
1081+
}
1082+
}
1083+
}
1084+
},
1085+
expect("SELECT a EXCLUDE a.b, c.d, e.f, g.h FROM T") {
1086+
exprSFW {
1087+
select = select("a")
1088+
from = fromValue {
1089+
expr = v("T")
1090+
type = From.Value.Type.SCAN
1091+
}
1092+
exclude = exclude {
1093+
exprs += excludeExcludeExpr {
1094+
root = id("a", Identifier.CaseSensitivity.INSENSITIVE)
1095+
steps += insensitiveExcludeTupleAttr("b")
1096+
}
1097+
exprs += excludeExcludeExpr {
1098+
root = id("c", Identifier.CaseSensitivity.INSENSITIVE)
1099+
steps += insensitiveExcludeTupleAttr("d")
1100+
}
1101+
exprs += excludeExcludeExpr {
1102+
root = id("e", Identifier.CaseSensitivity.INSENSITIVE)
1103+
steps += insensitiveExcludeTupleAttr("f")
1104+
}
1105+
exprs += excludeExcludeExpr {
1106+
root = id("g", Identifier.CaseSensitivity.INSENSITIVE)
1107+
steps += insensitiveExcludeTupleAttr("h")
1108+
}
1109+
}
1110+
}
1111+
},
1112+
expect("SELECT a EXCLUDE t.a.\"b\".*[*].c, \"s\"[0].d.\"e\"[*].f.* FROM T") {
1113+
exprSFW {
1114+
select = select("a")
1115+
from = fromValue {
1116+
expr = v("T")
1117+
type = From.Value.Type.SCAN
1118+
}
1119+
exclude = exclude {
1120+
exprs += excludeExcludeExpr {
1121+
root = id("t", Identifier.CaseSensitivity.INSENSITIVE)
1122+
steps += mutableListOf(
1123+
insensitiveExcludeTupleAttr("a"),
1124+
sensitiveExcludeTupleAttr("b"),
1125+
excludeStepExcludeTupleWildcard(),
1126+
excludeStepExcludeCollectionWildcard(),
1127+
insensitiveExcludeTupleAttr("c"),
1128+
)
1129+
}
1130+
exprs += excludeExcludeExpr {
1131+
root = id("s", Identifier.CaseSensitivity.SENSITIVE)
1132+
steps += mutableListOf(
1133+
excludeStepExcludeCollectionIndex(0),
1134+
insensitiveExcludeTupleAttr("d"),
1135+
sensitiveExcludeTupleAttr("e"),
1136+
excludeStepExcludeCollectionWildcard(),
1137+
insensitiveExcludeTupleAttr("f"),
1138+
excludeStepExcludeTupleWildcard(),
1139+
)
1140+
}
1141+
}
1142+
}
1143+
},
1144+
)
1145+
1146+
private fun AstBuilder.insensitiveExcludeTupleAttr(str: String) = excludeStepExcludeTupleAttr {
1147+
symbol = id(str, Identifier.CaseSensitivity.INSENSITIVE)
1148+
}
1149+
1150+
private fun AstBuilder.sensitiveExcludeTupleAttr(str: String) = excludeStepExcludeTupleAttr {
1151+
symbol = id(str, Identifier.CaseSensitivity.SENSITIVE)
1152+
}
1153+
10611154
@JvmStatic
10621155
fun fromClauseCases() = listOf(
10631156
expect("SELECT a FROM T") {

0 commit comments

Comments
 (0)