Skip to content

Commit

Permalink
Bitwise and plan typer and WIki. (#1232)
Browse files Browse the repository at this point in the history
  • Loading branch information
yliuuuu authored Sep 28, 2023
1 parent 6a18bb7 commit acd74ab
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 5 deletions.
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Thank you to all who have contributed!
## [Unreleased]

### Added
- Support parsing 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).
- 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).

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,29 @@ Example
CAST(5 as decimal(3,2)) % CAST(2 as DECIMAL(3,2)) -- 1
-- IN HONOR PARAMETER MODE
CAST(5 as decimal(3,2)) % CAST(2 as DECIMAL(3,2)) -- 1.00
```

### Bitwise And
Performs a bitwise logical AND operation between two integer values.

Syntax
: `expression & expression`

Example:
```sql
2 & 6 -- 0010 & 0110 = 0010 = 2
```

Return Type:
: If one operand is of `INT` type, returns `INT` type.
: Else if one operand is of INT8 type, returns `INT8` type.
: Else if one operand is of INT4 type, returns `INT4` type.
: Else return `INT2` type.

Note:
: Type precedence of the bitwise operator is lower than the plus/minus operator and higher than the predicates.

```sql
2 & 6 + 1 -- 2 & (6 + 1) = 2 & 7 = 2
(2 & 6) + 1 -- 2 + 1 = 3
```
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ public abstract class SqlDialect : AstBaseVisitor<SqlBlock, SqlBlock>() {
Expr.Binary.Op.GTE -> ">="
Expr.Binary.Op.LT -> "<"
Expr.Binary.Op.LTE -> "<="
Expr.Binary.Op.BITWISE_AND -> "&"
}
var h = head
h = visitExpr(node.lhs, h)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,11 @@ internal object PlanTyper : PlanRewriter<PlanTyper.Context>() {
true -> computeReturnTypeForNAry(args, PlanTyper::inferBinaryArithmeticOp)
false -> StaticType.NUMERIC // continuation type to prevent incompatible types and unknown errors from propagating
}
Rex.Binary.Op.BITWISE_AND -> when (hasValidOperandTypes(args, node.op.name, ctx) { it is IntType }) {
true -> computeReturnTypeForNAry(args, PlanTyper::inferBinaryArithmeticOp)
false -> StaticType.unionOf(StaticType.INT2, StaticType.INT4, StaticType.INT8, StaticType.INT) // continuation type to prevent incompatible types and unknown errors from propagating
}

Rex.Binary.Op.CONCAT -> when (hasValidOperandTypes(args, node.op.name, ctx) { it.isText() }) {
true -> computeReturnTypeForNAry(args, PlanTyper::inferConcatOp)
false -> StaticType.STRING // continuation type to prevent incompatible types and unknown errors from propagating
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@ internal object RexConverter : PartiqlAst.VisitorFold<RexConverter.Ctx>() {
)
}

override fun walkExprBitwiseAnd(node: PartiqlAst.Expr.BitwiseAnd, accumulator: Ctx) = visit(node) {
Plan.rexBinary(
lhs = convert(node.operands[0]),
rhs = convert(node.operands[1]),
op = Rex.Binary.Op.BITWISE_AND,
type = StaticType.unionOf(
StaticType.INT2, StaticType.INT4, StaticType.INT8, StaticType.INT
)
)
}

override fun walkExprConcat(node: PartiqlAst.Expr.Concat, ctx: Ctx) = visit(node) {
Plan.rexBinary(
lhs = convert(node.operands[0]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import org.partiql.types.BagType
import org.partiql.types.ListType
import org.partiql.types.StaticType
import org.partiql.types.StaticType.Companion.INT
import org.partiql.types.StaticType.Companion.MISSING
import org.partiql.types.StaticType.Companion.NULL
import org.partiql.types.StaticType.Companion.STRING
import org.partiql.types.StaticType.Companion.unionOf
import org.partiql.types.StructType
Expand Down Expand Up @@ -1070,6 +1072,95 @@ class PartiQLSchemaInferencerTests {
)
}
),
SuccessTestCase(
name = "BITWISE_AND_1",
query = "1 & 2",
expected = StaticType.INT
),
// casting to a parameterized type produced Missing.
SuccessTestCase(
name = "BITWISE_AND_2",
query = "CAST(1 AS INT2) & CAST(2 AS INT2)",
expected = StaticType.unionOf(StaticType.INT2, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_3",
query = "CAST(1 AS INT4) & CAST(2 AS INT4)",
expected = StaticType.unionOf(StaticType.INT4, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_4",
query = "CAST(1 AS INT8) & CAST(2 AS INT8)",
expected = StaticType.unionOf(StaticType.INT8, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_5",
query = "CAST(1 AS INT2) & CAST(2 AS INT4)",
expected = StaticType.unionOf(StaticType.INT4, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_6",
query = "CAST(1 AS INT2) & CAST(2 AS INT8)",
expected = StaticType.unionOf(StaticType.INT8, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_7",
query = "CAST(1 AS INT2) & 2",
expected = StaticType.unionOf(StaticType.INT, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_8",
query = "CAST(1 AS INT4) & CAST(2 AS INT8)",
expected = StaticType.unionOf(StaticType.INT8, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_9",
query = "CAST(1 AS INT4) & 2",
expected = StaticType.unionOf(StaticType.INT, MISSING)
),
SuccessTestCase(
name = "BITWISE_AND_10",
query = "CAST(1 AS INT8) & 2",
expected = StaticType.unionOf(StaticType.INT, MISSING)
),
ErrorTestCase(
name = "BITWISE_AND_NULL_OPERAND",
query = "1 & NULL",
expected = StaticType.NULL,
problemHandler = assertProblemExists {
Problem(
UNKNOWN_PROBLEM_LOCATION,
SemanticProblemDetails.ExpressionAlwaysReturnsNullOrMissing
)
}
),
ErrorTestCase(
name = "BITWISE_AND_MISSING_OPERAND",
query = "1 & MISSING",
expected = StaticType.MISSING,
problemHandler = assertProblemExists {
Problem(
UNKNOWN_PROBLEM_LOCATION,
SemanticProblemDetails.ExpressionAlwaysReturnsNullOrMissing
)
}
),
ErrorTestCase(
name = "BITWISE_AND_NON_INT_OPERAND",
query = "1 & 'NOT AN INT'",
expected = StaticType.MISSING,
problemHandler = assertProblemExists {
Problem(
UNKNOWN_PROBLEM_LOCATION,
SemanticProblemDetails.IncompatibleDatatypesForOp(
listOf(
INT, STRING
),
Rex.Binary.Op.BITWISE_AND.name
)
)
}
),
)

private fun assertProblemExists(problem: () -> Problem) = ProblemHandler { problems, ignoreSourceLocation ->
Expand Down
2 changes: 1 addition & 1 deletion partiql-parser/src/main/antlr/PartiQL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ joinType
* 2. Unary plus, minus (ex: -a, +a)
* 3. Multiplication, Division, Modulo (ex: a * b)
* 4. Addition, Subtraction (ex: a + b)
* 5. Other operators (ex: a || b)
* 5. Other operators (ex: a || b, a & b)
* 6. Predicates (ex: a LIKE b, a < b, a IN b, a = b)
* 7. IS true/false. Not yet implemented in PartiQL, but defined in SQL-92. (ex: a IS TRUE)
* 8. NOT (ex: NOT a)
Expand Down
2 changes: 1 addition & 1 deletion partiql-plan/src/main/resources/partiql_plan.ion
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ rex::[
lhs: rex,
rhs: rex,
op: [
PLUS, MINUS, TIMES, DIV, MODULO, CONCAT,
PLUS, MINUS, TIMES, DIV, MODULO, CONCAT, BITWISE_AND,
AND, OR,
EQ, NEQ, GTE, GT, LT, LTE,
],
Expand Down

1 comment on commit acd74ab

@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: acd74ab Previous: 4e2a184 Ratio
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncGroupingWithInterruptible 382.12119688891636 us/op 392.9311905387072 us/op 0.97
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncGroupingWithoutInterruptible 392.3519980690888 us/op 383.3409193077414 us/op 1.02
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncWithInterruptible 328.6922523840265 us/op 341.6051232621379 us/op 0.96
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinAggFuncWithoutInterruptible 347.3716346967661 us/op 333.5195286493473 us/op 1.04
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinWithInterruptible 246.0062856125872 us/op 257.3717409712493 us/op 0.96
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.compileCrossJoinWithoutInterruptible 244.2936090192943 us/op 249.15056679648063 us/op 0.98
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinAggWithInterruptible 7834230.1458 us/op 7294615.192749999 us/op 1.07
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinAggWithoutInterruptible 7666112.15245 us/op 7400855.332049998 us/op 1.04
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinWithInterruptible 60.94840838016745 us/op 60.20674856871326 us/op 1.01
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.evalCrossJoinWithoutInterruptible 65.6668636313175 us/op 62.56268767660504 us/op 1.05
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinAggWithInterruptible 7760324.5854 us/op 7264989.224049998 us/op 1.07
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinAggWithoutInterruptible 7519458.6478 us/op 7305786.14275 us/op 1.03
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinWithInterruptible 130421.39095 us/op 132210.3808125 us/op 0.99
org.partiql.jmh.benchmarks.CompilerInterruptionBenchmark.iterCrossJoinWithoutInterruptible 128521.73259375 us/op 131285.17507499998 us/op 0.98
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLCompiler15 124.91578202156272 us/op 125.62511583859369 us/op 0.99
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLCompiler30 228.07585957364932 us/op 238.75192661707214 us/op 0.96
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator15 542491.2025 us/op 512576.01417499996 us/op 1.06
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator30 1089913.46085 us/op 874298.72605 us/op 1.25
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLEvaluator30WithData10 9169107.753099998 us/op 10065962.88535 us/op 0.91
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLParser15 190.33258187881376 us/op 198.5641924624811 us/op 0.96
org.partiql.jmh.benchmarks.MultipleLikeBenchmark.testPartiQLParser30 365.4623738231737 us/op 386.8455468208495 us/op 0.94
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameCaseWhenThen 45.824861000094145 us/op 42.79030936332578 us/op 1.07
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery 62.80762067278236 us/op 57.41752138048305 us/op 1.09
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery01 327.7666918481925 us/op 288.97727490081076 us/op 1.13
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameComplexQuery02 561.3503832803597 us/op 483.7342774136142 us/op 1.16
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameExceptUnionIntersectSixty 215.60355466502293 us/op 225.33550041280373 us/op 0.96
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameExec20Expressions 72.51323189344842 us/op 65.55524848674034 us/op 1.11
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameFromLet 50.205637093161414 us/op 47.63343270477948 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGraphPattern 49.434683038334065 us/op 45.40381599991029 us/op 1.09
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGraphPreFilters 74.22924336968615 us/op 70.76290021664943 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameGroupLimit 49.974450989712764 us/op 47.723688149324104 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameLongFromSourceOrderBy 73.34680320930049 us/op 71.41104989372248 us/op 1.03
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameManyJoins 68.54935958963918 us/op 64.07999483717366 us/op 1.07
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameNestedAggregates 117.28064110349021 us/op 108.7635831552193 us/op 1.08
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameNestedParen 21.984086452333578 us/op 19.37066201655882 us/op 1.13
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNamePivot 73.48607578687063 us/op 70.72190740148912 us/op 1.04
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuery15OrsAndLikes 218.06703177038875 us/op 220.00006506285268 us/op 0.99
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuery30Plus 121.91695842557938 us/op 116.41685587758737 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryFunc 57.63010292638152 us/op 53.19472796426629 us/op 1.08
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryFuncInProjection 128.70945766697292 us/op 107.95434577689261 us/op 1.19
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryList 86.47052726207801 us/op 82.73714242388021 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQueryNestedSelect 751.9737956411111 us/op 710.1401479727981 us/op 1.06
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameQuerySimple 19.749776553747587 us/op 17.01492471995136 us/op 1.16
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralJoins 26.13114413952731 us/op 23.59482887341644 us/op 1.11
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralProjections 79.86678467755118 us/op 78.5765651604181 us/op 1.02
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSeveralSelect 221.70820521870968 us/op 209.77996234927778 us/op 1.06
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSimpleInsert 34.09524926234913 us/op 32.64166080166967 us/op 1.04
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeJoins 26.891999381917554 us/op 23.501093799053415 us/op 1.14
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeProjections 34.593058571164164 us/op 31.949168155641445 us/op 1.08
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameSomeSelect 57.65228441963616 us/op 53.80969164766439 us/op 1.07
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameTimeZone 29.446681074542568 us/op 25.819644474478633 us/op 1.14
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameVeryLongQuery 366.2323250459336 us/op 335.6307367495184 us/op 1.09
org.partiql.jmh.benchmarks.ParserBenchmark.parseFailNameVeryLongQuery01 1077.9499207976182 us/op 1032.9343659467677 us/op 1.04
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameCaseWhenThen 28.945182353099757 us/op 29.041608725525215 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameComplexQuery 246.91641904054023 us/op 248.20074388071316 us/op 0.99
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameComplexQuery01 119.48064224116331 us/op 122.93995527546909 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameExceptUnionIntersectSixty 237.70121984862334 us/op 247.1102403149502 us/op 0.96
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameExec20Expressions 73.1065639126262 us/op 69.82804283167198 us/op 1.05
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameFromLet 39.77050591559147 us/op 42.97023292712176 us/op 0.93
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGraphPattern 44.13007585810279 us/op 44.11962432949669 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGraphPreFilters 74.82783971317892 us/op 77.05972877291292 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameGroupLimit 37.234583792411414 us/op 37.300935901029625 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameLongFromSourceOrderBy 136.10327803191598 us/op 146.21823369917905 us/op 0.93
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameManyJoins 48.333784258899904 us/op 52.7255661958756 us/op 0.92
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameNestedAggregates 104.10043120129164 us/op 102.79248663335679 us/op 1.01
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameNestedParen 89.2636396193917 us/op 89.95902428311226 us/op 0.99
org.partiql.jmh.benchmarks.ParserBenchmark.parseNamePivot 72.61135841803286 us/op 69.88658510432082 us/op 1.04
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuery15OrsAndLikes 191.3193758210371 us/op 197.27253421608705 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuery30Plus 65.31487891095622 us/op 67.06082642712934 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryFunc 138.41076543391932 us/op 134.37016000549278 us/op 1.03
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryFuncInProjection 98.4274676948555 us/op 102.27169831342248 us/op 0.96
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryList 87.96158411694728 us/op 88.2837287207332 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQueryNestedSelect 142.553229374776 us/op 138.82326419413693 us/op 1.03
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameQuerySimple 14.673911069296915 us/op 14.150853682725437 us/op 1.04
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralJoins 79.09011347471001 us/op 84.44026457986301 us/op 0.94
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralProjections 61.66279381350877 us/op 63.378688366044784 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSeveralSelect 122.2080953103592 us/op 121.77476505294067 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSimpleInsert 24.191576436454472 us/op 24.59892474293587 us/op 0.98
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeJoins 22.752370910434514 us/op 23.90367001221754 us/op 0.95
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeProjections 21.62078719752899 us/op 20.3137076145755 us/op 1.06
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameSomeSelect 37.83900464050047 us/op 37.901521865720945 us/op 1.00
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameTimeZone 10.385651792848705 us/op 9.65595300908863 us/op 1.08
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameVeryLongQuery 450.30120823372454 us/op 464.2188546758218 us/op 0.97
org.partiql.jmh.benchmarks.ParserBenchmark.parseNameVeryLongQuery01 1263.1944751581673 us/op 1276.5508712106814 us/op 0.99
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLCompiler 9.887778282688156 us/op 11.921134870589208 us/op 0.83
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLEvaluator 2.7081749580536103 us/op 2.9216396940391944 us/op 0.93
org.partiql.jmh.benchmarks.PartiQLBenchmark.testPartiQLParser 13.306115091699724 us/op 12.490459462579778 us/op 1.07

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

Please sign in to comment.