pub struct BindingPowerTable {Show 25 fields
pub or: BindingPower,
pub xor: BindingPower,
pub and: BindingPower,
pub comparison: BindingPower,
pub range_predicate_override: Option<BindingPower>,
pub is_predicate_override: Option<BindingPower>,
pub double_equals: BindingPower,
pub additive: BindingPower,
pub multiplicative: BindingPower,
pub exponent: BindingPower,
pub string_concat: BindingPower,
pub any_operator: BindingPower,
pub json_get: BindingPower,
pub bitwise_or: BindingPower,
pub bitwise_and: BindingPower,
pub bitwise_shift: BindingPower,
pub bitwise_xor: BindingPower,
pub prefix_not: u8,
pub prefix_sign: u8,
pub prefix_bitwise_not: u8,
pub at_time_zone: BindingPower,
pub collate: BindingPower,
pub subscript: BindingPower,
pub typecast: BindingPower,
pub field_selection: BindingPower,
}Expand description
Dialect-owned Pratt and render-time binding powers.
The table is field-based rather than array-indexed so adding a
BinaryOperator or UnaryOperator forces this module to name its binding
power. Dialects can replace the whole table on FeatureSet or build a
small delta with with_binary.
Fields§
§or: BindingPowerBinding power of logical OR.
xor: BindingPowerMySQL XOR logical exclusive-or: binds tighter than OR and looser than
AND (MySQL’s OR < XOR < AND precedence). No standard operator occupies
this rank, so it gets its own field rather than sharing or/and.
and: BindingPowerBinding power of logical AND.
comparison: BindingPowerBinding power of the comparison operators (=/</>/…).
range_predicate_override: Option<BindingPower>The range/pattern/membership predicate tier — [NOT] BETWEEN, [NOT] IN,
[NOT] LIKE/ILIKE/SIMILAR TO. None tracks comparison
(the historical placement every dialect parsed these at, so a dialect that
re-associates its comparisons carries these with it); Some re-ranks them to a
dedicated tier, read through range_predicate.
PostgreSQL/DuckDB place this family one tier ABOVE the comparison operators
(</>/=) and below the %left Op “any other operator” rank — gram.y’s
%nonassoc BETWEEN IN_P LIKE ILIKE SIMILAR row — so a = b BETWEEN c AND d groups
a = (b BETWEEN c AND d) (engine-measured on pg_query 6.1 and DuckDB
json_serialize_sql); the PostgreSQL/Lenient presets set
Some(RANGE_PREDICATE_ABOVE_COMPARISON). MySQL/SQLite rank BETWEEN at or
below comparison (their manuals), so they leave this None and track comparison
automatically, staying byte-identical. The IS [NOT] NULL/IS DISTINCT/truth-value
predicates are a SEPARATE (in PostgreSQL/DuckDB, looser) tier — see
is_predicate_override.
is_predicate_override: Option<BindingPower>The IS-family predicate tier — the postfix IS [NOT] NULL / ISNULL / NOTNULL /
NOT NULL null tests, the IS [NOT] {TRUE|FALSE|UNKNOWN} truth-value tests, IS [NOT] NORMALIZED, and the infix IS [NOT] DISTINCT FROM (keyword form). None tracks
comparison (MySQL/SQLite rank IS at the comparison/equality tier,
so they stay byte-identical); Some re-ranks the whole family to a dedicated tier read
through predicate.
PostgreSQL and DuckDB place this family one tier BELOW the comparison operators
(</>/=) and above NOT — PostgreSQL gram.y’s %nonassoc IS ISNULL NOTNULL row,
which sits under %nonassoc '<' '>' '=' — so a <> b IS NULL groups (a <> b) IS NULL
and a IS DISTINCT FROM b = c groups a IS DISTINCT FROM (b = c) (engine-measured on
PostgreSQL 16 pg_get_viewdef and DuckDB 1.5.4 json_serialize_sql); the
PostgreSQL/DuckDB/Lenient presets set Some(IS_PREDICATE_BELOW_COMPARISON).
Non-associative, matching both engines (a IS DISTINCT FROM b IS DISTINCT FROM c is a
parse error). SQLite’s bare general IS/IS NOT and MySQL’s <=> are comparison-tier
null-safe (in)equality, distinguished by spelling, and are unaffected by this override.
double_equals: BindingPowerThe == spelling of equality (BinaryOperator::Eq with
EqualsSpelling::Double). Carries the
comparison value in every dialect but DuckDB, where ==
is not the %nonassoc '=' comparison but a generic %left Op operator: it
binds tighter than the comparisons and looser than additive, left-associative
(1 == 2 == 3 is ((1 = 2) = 3), 1 < 2 == 3 is (1 < (2 = 3)), 1 + 1 == 2
is ((1 + 1) = 2) — measured on 1.5.4). A distinct field so this DuckDB
re-ranking never disturbs the =/</> comparisons it shares
BinaryOperator::Eq with; with_binary keeps the two in
sync for the comparison-family callers (SQLite/MySQL move both together) and lets
DuckDB move == alone.
additive: BindingPowerBinding power of the additive operators (+/-).
multiplicative: BindingPowerBinding power of the multiplicative operators (*///%).
exponent: BindingPowerPostgreSQL exponentiation (^, BinaryOperator::Exponent). Its OWN precedence
row in gram.y (%left '^'): tighter than multiplicative
* / % and looser than the unary sign, left-associative (2 ^ 3 ^ 2 is
(2 ^ 3) ^ 2, 2 ^ 3 * 2 is (2 ^ 3) * 2 — engine-measured on pg_query). Distinct
from bitwise_xor: MySQL’s ^ (bitwise XOR) binds tighter than
*, PostgreSQL’s ^ (power) binds tighter than * but is a different operator at a
different (higher) rank, so the two never share a field. Only reachable under
CaretOperator::Exponent.
string_concat: BindingPowerBinding power of the || string-concatenation operator.
any_operator: BindingPowerPostgreSQL’s “any other operator” rank — the precedence gram.y gives every
native and user-defined symbolic operator outside the arithmetic/comparison
core (%left Op OPERATOR): looser than additive +/-, tighter than the
comparison/BETWEEN family. The @>/<@ containment and ->> JSON
operators bind here, left-associative. It carries the same value as
string_concat (|| is itself an “any other operator”
in PostgreSQL) but is a distinct field so moving one does not move the other.
json_get: BindingPowerThe -> token’s rank (BinaryOperator::JsonGet, which is also the DuckDB
lambda arrow — one token, one rank). In PostgreSQL/SQLite it carries the
any_operator value (-> is an ordinary Op there),
but DuckDB lexes -> as its own LAMBDA_ARROW grammar token ranked below
every expression operator — x -> x % 2 = 0 and even x -> x OR y put the
whole right side in the lambda body, and NOT x -> y takes NOT x as the
left operand (measured on 1.5.4 via json_serialize_sql) — while its ->>
stays at the Op rank. A distinct field so a dialect can move -> without
moving ->>/@>/<@, the same split rationale as
string_concat vs any_operator.
bitwise_or: BindingPowerBitwise OR (|). In PostgreSQL/SQLite/DuckDB the four binary bitwise operators
share one rank between additive and comparison (engine-measured: 1 | 2 & 2 is
(1 | 2) & 2), so the fields below carry the same standard value but stay distinct
— MySQL ranks | < & < <</>> at three separate levels (its documented
grammar), so a dialect moves each independently, exactly as
string_concat and any_operator
split.
bitwise_and: BindingPowerBitwise AND (&). Standard-equal to bitwise_or; tighter than
it in MySQL.
bitwise_shift: BindingPowerBitwise shift (<< / >>, one shared rank — the two shifts never diverge in any
dialect). Looser than additive everywhere; tighter than & and looser than
additive in MySQL.
bitwise_xor: BindingPowerBitwise exclusive-or (PostgreSQL #, MySQL ^). In the standard table it carries
PostgreSQL’s “any other operator” rank (looser than additive, like #); MySQL
re-ranks it tighter than multiplicative (^ binds above *), so it is its own
field.
prefix_not: u8Binding power of the prefix NOT operator.
prefix_sign: u8Binding power of the prefix +/- sign.
prefix_bitwise_not: u8Prefix bitwise complement (~). Binds like the unary sign in SQLite/MySQL, but in
PostgreSQL/DuckDB it sits between the arithmetic operators and the binary bitwise
family: one above bitwise_or’s left rank, so the bitwise
binaries do not fold into its operand (~ 1 & 3 is (~ 1) & 3) while the tighter
arithmetic does (~ 1 + 1 is ~ (1 + 1)) — both engine-measured — and the render
still parenthesizes ~ (a & b) (the strict-inequality break the equal-rank case
would lose).
at_time_zone: BindingPowerexpr AT TIME ZONE zone (PostgreSQL): binds tighter than the arithmetic
operators and looser than COLLATE and the unary sign.
collate: BindingPowerexpr COLLATE collation (PostgreSQL): just tighter than AT TIME ZONE,
just looser than the unary sign.
subscript: BindingPowerbase[index] / base[lo:hi] array subscript (PostgreSQL): binds tighter
than the unary sign and looser than the :: typecast.
typecast: BindingPowerexpr::type typecast (PostgreSQL): one of the tightest-binding operators,
just looser than composite field selection.
field_selection: BindingPower(expr).field composite field selection (PostgreSQL): the tightest of the
postfix operators.
Implementations§
Source§impl BindingPowerTable
impl BindingPowerTable
Sourcepub const fn binary(&self, op: &BinaryOperator) -> BindingPower
pub const fn binary(&self, op: &BinaryOperator) -> BindingPower
Return the binary binding power for op.
Sourcepub const fn prefix(&self, op: &UnaryOperator) -> u8
pub const fn prefix(&self, op: &UnaryOperator) -> u8
Return the prefix binding power for op.
Sourcepub const fn predicate(&self) -> BindingPower
pub const fn predicate(&self) -> BindingPower
Return the binding power of the IS-family predicates (IS [NOT] NULL, ISNULL,
NOTNULL, NOT NULL, IS [NOT] {TRUE|FALSE|UNKNOWN}, IS [NOT] NORMALIZED, and the
keyword IS [NOT] DISTINCT FROM).
Defaults to comparison — returned when
is_predicate_override is None, so MySQL/SQLite (which
rank IS at the comparison/equality tier) carry these predicates with their comparisons
— while the PostgreSQL/DuckDB/Lenient presets override it to their dedicated tier one
rank below comparison. The parser climbs the family at this rank and forbids chaining
them with comparisons, and render-time parenthesization reads the same level, so the
two can never drift (ADR-0008).
Sourcepub const fn range_predicate(&self) -> BindingPower
pub const fn range_predicate(&self) -> BindingPower
Return the binding power of the range/pattern/membership predicates ([NOT] BETWEEN, [NOT] IN, [NOT] LIKE/ILIKE/SIMILAR TO).
Defaults to comparison — returned when
range_predicate_override is None, so a dialect
that re-associates its comparisons carries these predicates with it — while the
PostgreSQL/Lenient presets override it to their dedicated tighter tier. The parser
climbs these predicates at this rank and the renderer parenthesizes them by it, one
source of truth (ADR-0008).
Sourcepub const fn with_binary(self, op: &BinaryOperator, bp: BindingPower) -> Self
pub const fn with_binary(self, op: &BinaryOperator, bp: BindingPower) -> Self
Return a copy of this table with one binary operator class replaced.
Sourcepub const fn needs_parens(
&self,
parent: &BinaryOperator,
child: &BinaryOperator,
side: Side,
) -> bool
pub const fn needs_parens( &self, parent: &BinaryOperator, child: &BinaryOperator, side: Side, ) -> bool
Return whether a child binary expression needs parentheses under parent.
Trait Implementations§
Source§impl Clone for BindingPowerTable
impl Clone for BindingPowerTable
Source§fn clone(&self) -> BindingPowerTable
fn clone(&self) -> BindingPowerTable
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more