Skip to content

Commit

Permalink
Add EXCLUDE to the parser, ast, plan, and plan schema inferencer (#…
Browse files Browse the repository at this point in the history
…1226)

Co-authored-by: John Ed Quinn <[email protected]>
  • Loading branch information
alancai98 and johnedquinn authored Sep 29, 2023
1 parent 316fe36 commit c7432aa
Show file tree
Hide file tree
Showing 18 changed files with 2,151 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Thank you to all who have contributed!
- Support parsing, planning, and evaluation of Bitwise AND operator (&).
- The Bitwise And Operator only works for integer operands.
- The operator precedence may change based on the pending operator precedence [RFC](https://github.com/partiql/partiql-docs/issues/50).
- **EXPERIMENTAL** Adds `EXCLUDE` to parser, ast, plan, and plan schema inferencer
- This feature is marked as experimental until an RFC is added https://github.com/partiql/partiql-spec/issues/39
- NOTE: this feature is not currently implemented in the evaluator

### Changed

Expand All @@ -42,6 +45,7 @@ Thank you to all who have contributed!
### Fixed
- Fixes typing of scalar subqueries in the PartiQLSchemaInferencer. Note that usage of `SELECT *` in subqueries
is not fully supported. Please make sure to handle InferenceExceptions.
- Fixes schema inferencer behavior for ORDER BY

### Removed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.amazon.ionelement.api.ionSymbol
import com.amazon.ionelement.api.metaContainerOf
import org.partiql.ast.AstNode
import org.partiql.ast.DatetimeField
import org.partiql.ast.Exclude
import org.partiql.ast.Expr
import org.partiql.ast.From
import org.partiql.ast.GraphMatch
Expand Down Expand Up @@ -665,14 +666,15 @@ private class AstTranslator(val metas: Map<String, MetaContainer>) : AstBaseVisi
}
val project = visitSelect(node.select, ctx)
val from = visitFrom(node.from, ctx)
val exclude = node.exclude?.let { visitExclude(it, ctx) }
val fromLet = node.let?.let { visitLet(it, ctx) }
val where = node.where?.let { visitExpr(it, ctx) }
val groupBy = node.groupBy?.let { visitGroupBy(it, ctx) }
val having = node.having?.let { visitExpr(it, ctx) }
val orderBy = node.orderBy?.let { visitOrderBy(it, ctx) }
val limit = node.limit?.let { visitExpr(it, ctx) }
val offset = node.offset?.let { visitExpr(it, ctx) }
select(setq, project, from, fromLet, where, groupBy, having, orderBy, limit, offset, metas)
select(setq, project, exclude, from, fromLet, where, groupBy, having, orderBy, limit, offset, metas)
}

/**
Expand Down Expand Up @@ -750,6 +752,48 @@ private class AstTranslator(val metas: Map<String, MetaContainer>) : AstBaseVisi
join(type, lhs, rhs, condition, metas)
}

override fun visitExclude(node: Exclude, ctx: Ctx): PartiqlAst.ExcludeOp = translate(node) { metas ->
val excludeExprs = node.exprs.translate<PartiqlAst.ExcludeExpr>(ctx)
excludeOp(excludeExprs, metas)
}

override fun visitExcludeExcludeExpr(node: Exclude.ExcludeExpr, ctx: Ctx) = translate(node) { metas ->
val root = visitIdentifierSymbol(node.root, ctx)
val steps = node.steps.translate<PartiqlAst.ExcludeStep>(ctx)
excludeExpr(root = root, steps = steps, metas)
}

override fun visitExcludeStep(node: Exclude.Step, ctx: Ctx) =
super.visitExcludeStep(node, ctx) as PartiqlAst.ExcludeStep

override fun visitExcludeStepExcludeTupleAttr(node: Exclude.Step.ExcludeTupleAttr, ctx: Ctx) = translate(node) { metas ->
val attr = node.symbol.symbol
val case = node.symbol.caseSensitivity.toLegacyCaseSensitivity()
excludeTupleAttr(identifier(attr, case), metas)
}

override fun visitExcludeStepExcludeCollectionIndex(
node: Exclude.Step.ExcludeCollectionIndex,
ctx: Ctx
) = translate(node) { metas ->
val index = node.index.toLong()
excludeCollectionIndex(index, metas)
}

override fun visitExcludeStepExcludeTupleWildcard(
node: Exclude.Step.ExcludeTupleWildcard,
ctx: Ctx
) = translate(node) { metas ->
excludeTupleWildcard(metas)
}

override fun visitExcludeStepExcludeCollectionWildcard(
node: Exclude.Step.ExcludeCollectionWildcard,
ctx: Ctx
) = translate(node) { metas ->
excludeCollectionWildcard(metas)
}

override fun visitLet(node: Let, ctx: Ctx) = translate(node) { metas ->
val bindings = node.bindings.translate<PartiqlAst.LetBinding>(ctx)
let(bindings, metas)
Expand Down
19 changes: 18 additions & 1 deletion partiql-ast/src/main/pig/partiql.ion
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ may then be further optimized by selecting better implementations of each operat
(select
(setq (? set_quantifier))
(project projection)
(exclude_clause (? exclude_op))
(from from_source)
(from_let (? let))
(where (? expr))
Expand Down Expand Up @@ -197,7 +198,7 @@ may then be further optimized by selecting better implementations of each operat
(sum path_step
// `someRoot[<expr>]`, or `someRoot.someField` which is equivalent to `someRoot['someField']`.
(path_expr index::expr case::case_sensitivity)
// `someRoot[*]`]
// `someRoot[*]`
(path_wildcard)
// `someRoot.*`
(path_unpivot))
Expand All @@ -220,6 +221,22 @@ may then be further optimized by selecting better implementations of each operat
// For `<expr> [AS <id>]`
(project_expr expr::expr as_alias::(? symbol)))

// EXCLUDE clause
(product exclude_op exprs::(* exclude_expr 1))

(product exclude_expr root::identifier steps::(* exclude_step 1))

(sum exclude_step
// `someRoot.someField` case sensitivity depends on if `someField` is quoted
// `someRoot[<string literal>] is equivalent to `someRoot."<string literal>"` (case-sensitive)
(exclude_tuple_attr attr::identifier)
// `someRoot[<int literal>]`
(exclude_collection_index index::int)
// `someRoot[*]`]
(exclude_tuple_wildcard)
// `someRoot.*`
(exclude_collection_wildcard))

// A list of LET bindings
(product let let_bindings::(* let_binding 1))

Expand Down
17 changes: 17 additions & 0 deletions partiql-ast/src/main/resources/partiql_ast.ion
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ expr::[
// The PartiQL `<sfw>` query expression, think SQL `<query specification>`
s_f_w::{
select: select, // oneof SELECT / SELECT VALUE / PIVOT
exclude: optional::exclude,
from: from,
let: optional::let,
where: optional::expr,
Expand Down Expand Up @@ -561,6 +562,22 @@ select::[
},
]

exclude::{
exprs: list::[exclude_expr],
_: [
exclude_expr::{
root: '.identifier.symbol',
steps: list::[step],
},
step::[
exclude_tuple_attr::{ symbol: '.identifier.symbol' },
exclude_collection_index::{ index: int },
exclude_tuple_wildcard::{},
exclude_collection_wildcard::{},
]
]
}

// PartiQL FROM Clause Variants — https://partiql.org/dql/from.html
from::[

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class GroupByPathExpressionVisitorTransform(
val projection = currentAndUnshadowedTransformer.transformExprSelect_project(node)

// The scope of the expressions in the FROM clause is the same as that of the parent scope.
val exclude = unshadowedTransformer.transformExprSelect_excludeClause(node)
val from = this.transformExprSelect_from(node)
val fromLet = unshadowedTransformer.transformExprSelect_fromLet(node)
val where = unshadowedTransformer.transformExprSelect_where(node)
Expand All @@ -116,6 +117,7 @@ class GroupByPathExpressionVisitorTransform(
PartiqlAst.Expr.Select(
setq = node.setq,
project = projection,
excludeClause = exclude,
from = from,
fromLet = fromLet,
where = where,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ abstract class VisitorTransformBase : PartiqlAst.VisitorTransform() {
* infinite recursion.
*/
fun transformExprSelectEvaluationOrder(node: PartiqlAst.Expr.Select): PartiqlAst.Expr {
val exclude = transformExprSelect_excludeClause(node)
val from = transformExprSelect_from(node)
val fromLet = transformExprSelect_fromLet(node)
val where = transformExprSelect_where(node)
Expand All @@ -51,6 +52,7 @@ abstract class VisitorTransformBase : PartiqlAst.VisitorTransform() {
PartiqlAst.Expr.Select(
setq = setq,
project = project,
excludeClause = exclude,
from = from,
fromLet = fromLet,
where = where,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ sealed class PlanningProblemDetails(
"Please use the `INSERT INTO <table> << <expr>, ... >>` form instead."
}
)

data class UnresolvedExcludeExprRoot(val root: String) :
PlanningProblemDetails(
ProblemSeverity.ERROR,
{ "Exclude expression given an unresolvable root '$root'" }
)
}

private fun quotationHint(caseSensitive: Boolean) =
Expand Down
Loading

1 comment on commit c7432aa

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JMH Benchmark

Benchmark suite Current: c7432aa Previous: 316fe36 Ratio
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncGroupingWithInterruptible 523.3873867179028 us/op 577.8098733361851 us/op 0.91
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncGroupingWithoutInterruptible 502.1819389484217 us/op 543.9402479334356 us/op 0.92
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncWithInterruptible 412.4644918410806 us/op 477.1744785423983 us/op 0.86
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncWithoutInterruptible 449.293046594432 us/op 481.1758287603178 us/op 0.93
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinWithInterruptible 291.2035204606167 us/op 345.62261454909765 us/op 0.84
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinWithoutInterruptible 311.33273212034385 us/op 359.3555819460761 us/op 0.87
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinAggWithInterruptible 9259050.80235 us/op 10723998.077650001 us/op 0.86
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinAggWithoutInterruptible 9298115.404599998 us/op 10910423.615199998 us/op 0.85
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinWithInterruptible 76.17111592285036 us/op 83.60116283343227 us/op 0.91
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinWithoutInterruptible 80.22238235149733 us/op 87.83260645439518 us/op 0.91
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinAggWithInterruptible 9009875.521150002 us/op 10639614.73645 us/op 0.85
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinAggWithoutInterruptible 9299050.84795 us/op 11088775.37455 us/op 0.84
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinWithInterruptible 182010.9237314286 us/op 176351.632075 us/op 1.03
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinWithoutInterruptible 161538.74630714284 us/op 176065.158025 us/op 0.92
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLCompiler15 147.05137835368376 us/op 183.11916407445054 us/op 0.80
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLCompiler30 279.67076789906247 us/op 335.96778405276507 us/op 0.83
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator15 670726.0924249999 us/op 638908.581725 us/op 1.05
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator30 1331213.3068 us/op 1265467.5007000002 us/op 1.05
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator30WithData10 11602960.34505 us/op 12420455.441700004 us/op 0.93
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLParser15 222.7442061885143 us/op 258.8210157759367 us/op 0.86
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLParser30 427.2011127502971 us/op 490.07588901081044 us/op 0.87
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameCaseWhenThen 55.28444063546874 us/op 80.84287537516794 us/op 0.68
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery 73.98318220472575 us/op 99.08779753654291 us/op 0.75
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery01 398.52499176321055 us/op 473.767773901882 us/op 0.84
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery02 665.8824184425324 us/op 784.8107922015397 us/op 0.85
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameExceptUnionIntersectSixty 258.36962649554613 us/op 301.10656497809924 us/op 0.86
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameExec20Expressions 84.78016150240039 us/op 101.22330340140684 us/op 0.84
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameFromLet 55.99648959082138 us/op 83.53803715192508 us/op 0.67
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGraphPattern 54.591862675273 us/op 81.23458065444396 us/op 0.67
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGraphPreFilters 87.9469350005991 us/op 133.46058288255784 us/op 0.66
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGroupLimit 61.413438009013326 us/op 91.45902538578218 us/op 0.67
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameLongFromSourceOrderBy 88.56429768131329 us/op 107.54581771276739 us/op 0.82
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameManyJoins 82.8470421379365 us/op 130.50156009429026 us/op 0.63
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameNestedAggregates 138.036998377704 us/op 182.29853538448668 us/op 0.76
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameNestedParen 26.36443289349312 us/op 34.651161687570045 us/op 0.76
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNamePivot 88.03785130717435 us/op 119.06723278150926 us/op 0.74
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuery15OrsAndLikes 266.7860238957238 us/op 373.15459020811556 us/op 0.71
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuery30Plus 144.20494857387135 us/op 177.1935787874308 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryFunc 67.41655305226979 us/op 89.66431493784911 us/op 0.75
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryFuncInProjection 71.692282198392 us/op 188.91081456116606 us/op 0.38
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryList 104.15227404294201 us/op 128.8454499454017 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryNestedSelect 964.942154773694 us/op 1049.460745543333 us/op 0.92
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuerySimple 22.821639732379303 us/op 31.19171628059892 us/op 0.73
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralJoins 30.629380716182965 us/op 46.5313631013197 us/op 0.66
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralProjections 97.62756631611543 us/op 116.80876643050719 us/op 0.84
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralSelect 261.00395538348283 us/op 333.97180605983533 us/op 0.78
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSimpleInsert 40.126016589699546 us/op 60.71267748514911 us/op 0.66
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeJoins 31.527843320410785 us/op 45.32743841168469 us/op 0.70
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeProjections 41.64903216123505 us/op 56.50946249142504 us/op 0.74
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeSelect 67.66300516814991 us/op 97.03213109117296 us/op 0.70
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameTimeZone 34.124793043948706 us/op 49.168605313177316 us/op 0.69
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameVeryLongQuery 350.3859348187405 us/op 526.5703987619071 us/op 0.67
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameVeryLongQuery01 1326.4220856701618 us/op 1615.1108952504035 us/op 0.82
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameCaseWhenThen 34.44085197754919 us/op 43.80110126136175 us/op 0.79
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameComplexQuery 301.63168433840946 us/op 372.84956541876244 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameComplexQuery01 139.0460081856347 us/op 173.454141933256 us/op 0.80
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameExceptUnionIntersectSixty 296.645738153823 us/op 311.8027694371126 us/op 0.95
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameExec20Expressions 87.50661531685785 us/op 96.60564772441711 us/op 0.91
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameFromLet 46.34771123394444 us/op 65.51464388819369 us/op 0.71
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGraphPattern 54.472730222083484 us/op 71.41232973520994 us/op 0.76
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGraphPreFilters 91.95757580038534 us/op 114.0810637652673 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGroupLimit 45.623152780369786 us/op 60.09772954255584 us/op 0.76
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameLongFromSourceOrderBy 165.4206761537284 us/op 196.56055945037352 us/op 0.84
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameManyJoins 57.72895588259435 us/op 74.1910159899002 us/op 0.78
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameNestedAggregates 119.76771696819404 us/op 147.8226684367247 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameNestedParen 97.26704215837285 us/op 118.01102223583159 us/op 0.82
org.partiql.jmh.benchmarks.ParserBenchmark.parseNamePivot 80.94259498007395 us/op 107.60208988654321 us/op 0.75
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuery15OrsAndLikes 230.27578009190697 us/op 257.081190297246 us/op 0.90
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuery30Plus 80.77257738392676 us/op 87.70375349556187 us/op 0.92
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryFunc 177.9053630728917 us/op 213.13875722460858 us/op 0.83
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryFuncInProjection 122.28117121800032 us/op 138.6140429081383 us/op 0.88
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryList 103.06266417481808 us/op 116.26574555540003 us/op 0.89
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryNestedSelect 170.79517858484812 us/op 214.23994611462135 us/op 0.80
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuerySimple 16.511679094613193 us/op 22.677051417877216 us/op 0.73
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralJoins 96.79822897193947 us/op 107.39643483343211 us/op 0.90
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralProjections 75.64439723514946 us/op 86.54423035057705 us/op 0.87
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralSelect 141.43692686254892 us/op 160.5876843267661 us/op 0.88
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSimpleInsert 29.18823534485594 us/op 37.040401538109975 us/op 0.79
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeJoins 27.9967115743137 us/op 34.65208472800599 us/op 0.81
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeProjections 25.373653628968444 us/op 30.953102872965776 us/op 0.82
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeSelect 44.09586871755434 us/op 55.08231643432758 us/op 0.80
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameTimeZone 12.024551378627294 us/op 18.71411785372883 us/op 0.64
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameVeryLongQuery 538.7854930192854 us/op 586.3720588341728 us/op 0.92
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameVeryLongQuery01 1561.283164017132 us/op 1617.1239902005698 us/op 0.97
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLCompiler 13.296576256106192 us/op 14.48512554399151 us/op 0.92
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLEvaluator 3.2361264835011125 us/op 3.2674335479331917 us/op 0.99
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLParser 15.211054839824723 us/op 21.110938921694828 us/op 0.72

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.