pub enum Expr {
Show 17 variants
Column(Name),
Literal(Cell),
And(Vec<Expr>),
Or(Vec<Expr>),
Not(Box<Expr>),
Cmp(Box<Expr>, CmpOp, Box<Expr>),
Is {
value: Box<Expr>,
to: Option<bool>,
negated: bool,
},
In {
value: Box<Expr>,
list: Vec<Expr>,
negated: bool,
},
Match {
value: Box<Expr>,
pattern: Box<Expr>,
negated: bool,
insensitive: bool,
},
Case {
operand: Option<Box<Expr>>,
arms: Vec<(Expr, Expr)>,
otherwise: Option<Box<Expr>>,
},
Call {
name: String,
args: Vec<Expr>,
},
Cast {
value: Box<Expr>,
ty: String,
},
Concat(Box<Expr>, Box<Expr>),
Subquery {
id: usize,
select: Box<Select>,
},
Array {
id: usize,
select: Box<Select>,
},
Any(Box<Expr>),
Subscript(Box<Expr>, Box<Expr>),
}Expand description
A scalar expression, evaluated over one row.
Every variant here is something a catalogue query writes. What is not here is arithmetic, because nothing asks for it: a read model computes its numbers in the program.
Variants§
Column(Name)
Literal(Cell)
And(Vec<Expr>)
Or(Vec<Expr>)
Not(Box<Expr>)
Cmp(Box<Expr>, CmpOp, Box<Expr>)
a = b, and the other five comparisons. Three-valued: a comparison against NULL is
unknown, and unknown is not true.
Is
a is null / a is not null, and a is true / a is not false.
In
c in ('r', 'v') — the form psql narrows relkind with.
Match
~, !~, ~*, !~* — a POSIX regular expression match, run by a simulation over a set
of states rather than by backtracking, because the pattern arrives from a client.
Case
case … when … then … else … end, in both SQL’s forms.
Lazy, as SQL specifies: the arms after the one that matched are not evaluated. That is
load-bearing here rather than an optimisation — psql writes case when c.reloftype = 0 then '' else c.reloftype::regtype::text end, and the branch this catalogue cannot compute
is the branch no row reaches.
Call
A function call. crate::pg::call is what answers one, and a name it does not know is
refused by name rather than answered NULL.
Cast
x::text. A cast to a type this has is the value; to anything else it is refused by name,
which is why the case above has to be lazy.
Concat(Box<Expr>, Box<Expr>)
a || b, string concatenation.
Subquery
A scalar subquery — (select … from …).
The id distinguishes two subqueries in one statement, so the answer to each can be
computed once rather than once per row: see Eval::subquery for why it is the same for
every row.
Array
array(select …) and any(x): parsed, and refused by name if a row ever asks. Both appear
in psql’s catalogue queries inside branches that no row reaches, and a query refused at
parse time for a branch it never takes is a \d that does not work.
Any(Box<Expr>)
Subscript(Box<Expr>, Box<Expr>)
x[i], an array subscript. Parsed for Expr::Array’s reason and refused for the same
one.
Implementations§
Source§impl Expr
impl Expr
Sourcepub fn names(&self, out: &mut Vec<Name>)
pub fn names(&self, out: &mut Vec<Name>)
Every column this expression names, including those in a subquery it carries.
crate::query uses it to decide which table a where term narrows, so a term that names
a column inside a subquery counts as naming it: pushing such a term into one table’s scan
would evaluate the subquery against the wrong rows.