Skip to main content

rupg_analyze/
node.rs

1//! The stored form of an expression, which the catalog keeps for a column default, a check constraint and an index expression.
2//!
3//! PostgreSQL stores these as `pg_node_tree` text that `nodeToString` writes. rupg stores its own text, which document 05 section 5.2 permits, because clients do not read it. The form looks like the form of PostgreSQL: `{NAME :field value ...}`. A constant keeps its value in a form that does not change with the settings of the session, so the expression reads back to the same tree.
4
5use rupg_common::{Error, Result};
6use rupg_types::{Array, ArrayDim, Inet, Interval, NetFamily, Range, Record, Recv, Value};
7
8use crate::expr::{
9    BoolOp, BoolTest, Case, CastForm, Expr, ExprKind, FieldStore, Func, FuncForm, IsJson, JoinRow,
10    JsonBehavior, JsonBehaviorKind, JsonCtor, JsonCtorKind, JsonEncoding, JsonExpr, JsonExprOp,
11    JsonFormat, JsonFormatKind, JsonItemType, JsonReturning, JsonValue, JsonWrapper, NamedArg,
12    RowCompare, RowCompareKind, SqlValue, Subscript, Var, XmlExpr, XmlOp,
13};
14
15/// The stored form of an expression.
16///
17/// # Errors
18///
19/// An internal error for an aggregate call, a subquery or a parameter, which a stored expression cannot have.
20pub fn write(expr: &Expr) -> Result<String> {
21    let mut out = String::new();
22    write_expr(expr, &mut out)?;
23    Ok(out)
24}
25
26/// The expression of a stored form that [`write()`] made.
27///
28/// # Errors
29///
30/// An internal error when the text is not a stored form.
31pub fn read(text: &str) -> Result<Expr> {
32    let mut tokens = Tokens { text, at: 0 };
33    let item = tokens.item()?;
34    if tokens.next()?.is_some() {
35        return Err(bad("text after the end"));
36    }
37    expr_of(&item)
38}
39
40/// The stored form of a list of expressions, such as the expressions of an index: `(e1 e2 ...)`.
41///
42/// # Errors
43///
44/// As [`write()`].
45pub fn write_list(exprs: &[Expr]) -> Result<String> {
46    let mut out = String::from("(");
47    for (i, expr) in exprs.iter().enumerate() {
48        if i > 0 {
49            out.push(' ');
50        }
51        write_expr(expr, &mut out)?;
52    }
53    out.push(')');
54    Ok(out)
55}
56
57/// The expressions of a stored form that [`write_list`] made.
58///
59/// # Errors
60///
61/// An internal error when the text is not a stored list.
62pub fn read_list(text: &str) -> Result<Vec<Expr>> {
63    let mut tokens = Tokens { text, at: 0 };
64    let item = tokens.item()?;
65    if tokens.next()?.is_some() {
66        return Err(bad("text after the end"));
67    }
68    list(&item)?.iter().map(expr_of).collect()
69}
70
71/// A datum of the stored bound of a range partition.
72#[derive(Debug)]
73pub enum StoredDatum {
74    /// `MINVALUE`.
75    MinValue,
76    /// `MAXVALUE`.
77    MaxValue,
78    /// A constant.
79    Value(Expr),
80}
81
82/// The stored bound of a partition, as `relpartbound` keeps a `PartitionBoundSpec`.
83#[derive(Debug)]
84pub enum StoredBound {
85    /// `DEFAULT`.
86    Default,
87    /// `FOR VALUES WITH (MODULUS m, REMAINDER r)`.
88    Hash {
89        /// The modulus.
90        modulus: i32,
91        /// The remainder.
92        remainder: i32,
93    },
94    /// `FOR VALUES IN (...)`: each constant, or `None` for `NULL`.
95    List(Vec<Option<Expr>>),
96    /// `FOR VALUES FROM (...) TO (...)`.
97    Range {
98        /// The lower bound.
99        lower: Vec<StoredDatum>,
100        /// The upper bound.
101        upper: Vec<StoredDatum>,
102    },
103}
104
105/// The name of the node of a stored bound.
106const BOUND: &str = "PARTITIONBOUNDSPEC";
107
108/// True for the stored form of the bound of a partition, which [`write_bound`] made.
109pub fn is_bound(text: &str) -> bool {
110    text.trim_start().strip_prefix('{').is_some_and(|rest| rest.starts_with(BOUND))
111}
112
113/// The stored form of the bound of a partition, `relpartbound`. Each constant of the bound is already in the stored form of [`write()`].
114pub fn write_bound(bound: &rupg_catalog::PartitionBound) -> String {
115    use rupg_catalog::{PartitionBound, RangeDatum};
116    let datums = |list: &[RangeDatum]| {
117        let items: Vec<String> = list
118            .iter()
119            .map(|d| match d {
120                RangeDatum::MinValue => "{PARTITIONRANGEDATUM :kind -1 :value <>}".to_string(),
121                RangeDatum::MaxValue => "{PARTITIONRANGEDATUM :kind 1 :value <>}".to_string(),
122                RangeDatum::Value(text) => format!("{{PARTITIONRANGEDATUM :kind 0 :value {text}}}"),
123            })
124            .collect();
125        format!("({})", items.join(" "))
126    };
127    match bound {
128        PartitionBound::Default => format!("{{{BOUND} :strategy <> :is_default true}}"),
129        PartitionBound::Hash { modulus, remainder } => format!(
130            "{{{BOUND} :strategy h :is_default false :modulus {modulus} :remainder {remainder}}}"
131        ),
132        PartitionBound::List(values) => {
133            let items: Vec<&str> = values.iter().map(|v| v.as_deref().unwrap_or("<>")).collect();
134            format!("{{{BOUND} :strategy l :is_default false :listdatums ({})}}", items.join(" "))
135        }
136        PartitionBound::Range { lower, upper } => format!(
137            "{{{BOUND} :strategy r :is_default false :lowerdatums {} :upperdatums {}}}",
138            datums(lower),
139            datums(upper)
140        ),
141    }
142}
143
144/// The bound of a stored form that [`write_bound`] made.
145///
146/// # Errors
147///
148/// An internal error when the text is not a stored bound.
149pub fn read_bound(text: &str) -> Result<StoredBound> {
150    let mut tokens = Tokens { text, at: 0 };
151    let item = tokens.item()?;
152    if tokens.next()?.is_some() {
153        return Err(bad("text after the end"));
154    }
155    let Item::Node(name, fields) = &item else { return Err(bad("no node")) };
156    if name != BOUND {
157        return Err(bad("no partition bound"));
158    }
159    let f = Fields { fields };
160    if f.flag("is_default")? {
161        return Ok(StoredBound::Default);
162    }
163    let datums = |name: &str| -> Result<Vec<StoredDatum>> {
164        list(f.get(name)?)?
165            .iter()
166            .map(|item| {
167                let Item::Node(_, fields) = item else { return Err(bad("no range datum")) };
168                let d = Fields { fields };
169                Ok(match d.number::<i32>("kind")? {
170                    -1 => StoredDatum::MinValue,
171                    1 => StoredDatum::MaxValue,
172                    _ => StoredDatum::Value(expr_of(d.get("value")?)?),
173                })
174            })
175            .collect()
176    };
177    match f.atom("strategy")? {
178        "h" => Ok(StoredBound::Hash {
179            modulus: f.number("modulus")?,
180            remainder: f.number("remainder")?,
181        }),
182        "l" => {
183            let values = list(f.get("listdatums")?)?
184                .iter()
185                .map(|item| match item {
186                    Item::Atom(empty) if empty == "<>" => Ok(None),
187                    item => expr_of(item).map(Some),
188                })
189                .collect::<Result<Vec<_>>>()?;
190            Ok(StoredBound::List(values))
191        }
192        "r" => {
193            Ok(StoredBound::Range { lower: datums("lowerdatums")?, upper: datums("upperdatums")? })
194        }
195        other => Err(bad(&format!("partition strategy {other}"))),
196    }
197}
198
199/// The error of a bad stored form.
200fn bad(what: &str) -> Error {
201    Error::internal(format!("bad stored expression: {what}"))
202}
203
204fn write_expr(expr: &Expr, out: &mut String) -> Result<()> {
205    let name = match &expr.kind {
206        ExprKind::Const(_) => "CONST",
207        ExprKind::Func(_) => "FUNC",
208        ExprKind::Relabel(..) => "RELABEL",
209        ExprKind::CoerceViaIo(..) => "COERCEVIAIO",
210        ExprKind::ArrayCoerce { .. } => "ARRAYCOERCE",
211        ExprKind::CoerceToDomain(..) => "COERCETODOMAIN",
212        ExprKind::DomainValue => "COERCETODOMAINVALUE",
213        ExprKind::Subscript(_) => "SUBSCRIPT",
214        ExprKind::Bool(..) => "BOOL",
215        ExprKind::NullTest(..) => "NULLTEST",
216        ExprKind::BooleanTest(..) => "BOOLEANTEST",
217        ExprKind::Case(_) => "CASE",
218        ExprKind::CaseTest => "CASETEST",
219        ExprKind::Coalesce(_) => "COALESCE",
220        ExprKind::MinMax { .. } => "MINMAX",
221        ExprKind::NullIf { .. } => "NULLIF",
222        ExprKind::Distinct { .. } => "DISTINCT",
223        ExprKind::ScalarArrayOp { .. } => "SCALARARRAYOP",
224        ExprKind::Array { .. } => "ARRAY",
225        ExprKind::Row(..) => "ROW",
226        ExprKind::JoinRow(_) => "JOINROW",
227        ExprKind::RowCompare(_) => "ROWCOMPARE",
228        ExprKind::SqlValue(_) => "SQLVALUE",
229        ExprKind::Var(_) => "VAR",
230        ExprKind::FieldSelect(..) => "FIELDSELECT",
231        ExprKind::FieldStore(_) => "FIELDSTORE",
232        ExprKind::NamedArg(_) => "NAMEDARG",
233        ExprKind::JsonValue(_) => "JSONVALUEEXPR",
234        ExprKind::JsonCtor(_) => "JSONCONSTRUCTOREXPR",
235        ExprKind::IsJson(_) => "JSONISPREDICATE",
236        ExprKind::JsonExpr(_) => "JSONEXPR",
237        ExprKind::Xml(_) => "XMLEXPR",
238        ExprKind::Param(_)
239        | ExprKind::Agg(_)
240        | ExprKind::Grouping(_)
241        | ExprKind::PlaceHolder(_)
242        | ExprKind::Window(_)
243        | ExprKind::SubLink(_)
244        | ExprKind::SubColumn(_)
245        | ExprKind::CurrentOf(_)
246        | ExprKind::JsonTable(_) => {
247            return Err(Error::internal("a stored expression cannot have this node"));
248        }
249    };
250    let location = expr.location.map_or(-1, |l| i64::try_from(l).unwrap_or(-1));
251    out.push('{');
252    out.push_str(name);
253    out.push_str(&format!(" :type {} :typmod {} :location {location}", expr.ty, expr.typmod));
254    match &expr.kind {
255        ExprKind::Const(value) => {
256            out.push_str(" :value ");
257            write_value(value, out);
258        }
259        ExprKind::Func(f) => {
260            out.push_str(&format!(" :oid {}", f.oid));
261            match f.form {
262                FuncForm::Call => out.push_str(" :form call"),
263                FuncForm::Operator(op) => out.push_str(&format!(" :form (operator {op})")),
264                FuncForm::ExplicitCast => out.push_str(" :form explicit"),
265                FuncForm::ImplicitCast => out.push_str(" :form implicit"),
266                FuncForm::SqlSyntax => out.push_str(" :form sql"),
267            }
268            out.push_str(&format!(" :variadic {}", f.variadic));
269            write_args(&f.args, out)?;
270        }
271        ExprKind::Relabel(arg, form)
272        | ExprKind::CoerceViaIo(arg, form)
273        | ExprKind::CoerceToDomain(arg, form) => {
274            out.push_str(match form {
275                CastForm::Explicit => " :form explicit",
276                CastForm::Implicit => " :form implicit",
277            });
278            write_field("arg", arg, out)?;
279        }
280        ExprKind::ArrayCoerce { arg, element, form } => {
281            out.push_str(match form {
282                CastForm::Explicit => " :form explicit",
283                CastForm::Implicit => " :form implicit",
284            });
285            write_field("arg", arg, out)?;
286            write_field("element", element, out)?;
287        }
288        ExprKind::Subscript(sub) => {
289            write_field("container", &sub.container, out)?;
290            out.push_str(" :upper ");
291            write_bounds(&sub.upper, out)?;
292            out.push_str(" :lower ");
293            match &sub.lower {
294                Some(lower) => write_bounds(lower, out)?,
295                None => out.push_str("<>"),
296            }
297            // A fetch has no field `assign`, as before assignments had the field.
298            if let Some(assign) = &sub.assign {
299                write_field("assign", assign, out)?;
300            }
301        }
302        ExprKind::Bool(op, args) => {
303            let op = match op {
304                BoolOp::And => "and",
305                BoolOp::Or => "or",
306                BoolOp::Not => "not",
307            };
308            out.push_str(&format!(" :op {op}"));
309            write_args(args, out)?;
310        }
311        ExprKind::NullTest(arg, is_null) => {
312            write_field("arg", arg, out)?;
313            out.push_str(&format!(" :isnull {is_null}"));
314        }
315        ExprKind::BooleanTest(arg, test) => {
316            write_field("arg", arg, out)?;
317            out.push_str(" :test ");
318            out.push_str(test_name(*test));
319        }
320        ExprKind::Case(case) => {
321            out.push_str(" :arg ");
322            match &case.arg {
323                Some(arg) => write_expr(arg, out)?,
324                None => out.push_str("<>"),
325            }
326            out.push_str(" :whens (");
327            for (i, (when, then)) in case.whens.iter().enumerate() {
328                if i > 0 {
329                    out.push(' ');
330                }
331                out.push('(');
332                write_expr(when, out)?;
333                out.push(' ');
334                write_expr(then, out)?;
335                out.push(')');
336            }
337            out.push(')');
338            write_field("default", &case.default, out)?;
339        }
340        ExprKind::CaseTest | ExprKind::DomainValue => {}
341        ExprKind::Coalesce(args) => write_args(args, out)?,
342        ExprKind::Row(args, form) => {
343            out.push_str(match form {
344                CastForm::Explicit => " :form explicit",
345                CastForm::Implicit => " :form implicit",
346            });
347            write_args(args, out)?;
348        }
349        ExprKind::JoinRow(row) => {
350            out.push_str(" :alias ");
351            match &row.alias {
352                Some(alias) => hex(alias.as_bytes(), out),
353                None => out.push_str("<>"),
354            }
355            out.push_str(" :names (");
356            for (i, name) in row.names.iter().enumerate() {
357                if i > 0 {
358                    out.push(' ');
359                }
360                hex(name.as_bytes(), out);
361            }
362            out.push(')');
363            write_args(&row.fields, out)?;
364        }
365        ExprKind::MinMax { greatest, less, args } => {
366            out.push_str(&format!(" :greatest {greatest} :less {less}"));
367            write_args(args, out)?;
368        }
369        ExprKind::NullIf { equal, args } => {
370            out.push_str(&format!(" :equal {equal}"));
371            write_args(args, out)?;
372        }
373        ExprKind::Distinct { equal, not, args } => {
374            out.push_str(&format!(" :equal {equal} :not {not}"));
375            write_args(args, out)?;
376        }
377        ExprKind::RowCompare(rc) => {
378            let compares: Vec<String> = rc.compares.iter().map(u32::to_string).collect();
379            out.push_str(&format!(" :kind {} :compares ({})", rc.kind.name(), compares.join(" ")));
380            write_args(&rc.ops, out)?;
381        }
382        ExprKind::ScalarArrayOp { func, any, args } => {
383            out.push_str(&format!(" :func {func} :any {any}"));
384            write_args(args, out)?;
385        }
386        ExprKind::Array { element, multidims, elements } => {
387            out.push_str(&format!(" :element {element} :multidims {multidims}"));
388            write_args(elements, out)?;
389        }
390        ExprKind::SqlValue(value) => {
391            let (name, precision) = sql_value_name(*value);
392            out.push_str(&format!(" :function {name} :precision "));
393            match precision {
394                Some(p) => out.push_str(&p.to_string()),
395                None => out.push_str("<>"),
396            }
397        }
398        ExprKind::Var(var) => {
399            out.push_str(&format!(
400                " :relation {} :attnum {} :levelsup {}",
401                var.relation, var.attnum, var.levels_up
402            ));
403        }
404        ExprKind::FieldSelect(arg, field) => {
405            out.push_str(&format!(" :field {field}"));
406            write_field("arg", arg, out)?;
407        }
408        ExprKind::FieldStore(store) => {
409            let numbers = |n: &mut dyn Iterator<Item = String>| n.collect::<Vec<_>>().join(" ");
410            let fields = numbers(&mut store.fields.iter().map(|(i, _)| i.to_string()));
411            let types = numbers(&mut store.types.iter().map(u32::to_string));
412            out.push_str(&format!(" :fieldnums ({fields}) :types ({types})"));
413            write_field("arg", &store.arg, out)?;
414            let values: Vec<Expr> = store.fields.iter().map(|(_, v)| v.clone()).collect();
415            write_args(&values, out)?;
416        }
417        ExprKind::NamedArg(na) => {
418            out.push_str(" :name ");
419            hex(na.name.as_bytes(), out);
420            out.push_str(&format!(" :number {}", na.number));
421            write_field("arg", &na.arg, out)?;
422        }
423        ExprKind::JsonValue(v) => {
424            write_format(v.format, out);
425            write_field("raw", &v.raw, out)?;
426            write_field("formatted", &v.formatted, out)?;
427        }
428        ExprKind::JsonCtor(c) => {
429            let kind = CTOR_KINDS.iter().find(|(k, _)| *k == c.kind).map_or("object", |(_, n)| n);
430            out.push_str(&format!(
431                " :kind {kind} :unique {} :absent {} :rtype {} :rtypmod {}",
432                c.unique, c.absent_on_null, c.returning.ty, c.returning.typmod
433            ));
434            write_format(c.returning.format, out);
435            write_args(&c.args, out)?;
436            if c.func.is_some() {
437                return Err(Error::internal("a stored expression cannot have this node"));
438            }
439            out.push_str(" :coercion ");
440            match &c.coercion {
441                Some(coercion) => write_expr(coercion, out)?,
442                None => out.push_str("<>"),
443            }
444        }
445        ExprKind::IsJson(p) => {
446            let item = ITEM_TYPES.iter().find(|(i, _)| *i == p.item).map_or("any", |(_, n)| n);
447            out.push_str(&format!(" :item {item} :unique {} :basetype {}", p.unique, p.base_type));
448            write_field("arg", &p.expr, out)?;
449        }
450        ExprKind::JsonExpr(j) => {
451            let op = JSON_OPS.iter().find(|(o, _)| *o == j.op).map_or("exists", |(_, n)| n);
452            let wrapper =
453                WRAPPERS.iter().find(|(w, _)| *w == j.wrapper).map_or("unspec", |(_, n)| n);
454            out.push_str(&format!(
455                " :op {op} :wrapper {wrapper} :omitquotes {} :jsoncoercion {} :iocoercion {} :rtype {} :rtypmod {}",
456                j.omit_quotes, j.json_coercion, j.io_coercion, j.returning.ty, j.returning.typmod
457            ));
458            write_format(j.returning.format, out);
459            write_field("formatted", &j.formatted, out)?;
460            write_field("path", &j.path, out)?;
461            out.push_str(" :names (");
462            for (i, (name, _)) in j.passing.iter().enumerate() {
463                if i > 0 {
464                    out.push(' ');
465                }
466                hex(name.as_bytes(), out);
467            }
468            out.push(')');
469            let values: Vec<Expr> = j.passing.iter().map(|(_, e)| e.clone()).collect();
470            write_args(&values, out)?;
471            out.push_str(" :onempty ");
472            match &j.on_empty {
473                Some(behavior) => write_behavior(behavior, out)?,
474                None => out.push_str("<>"),
475            }
476            out.push_str(" :onerror ");
477            write_behavior(&j.on_error, out)?;
478        }
479        ExprKind::Xml(x) => {
480            let op = XML_OPS.iter().find(|(o, _)| *o == x.op).map_or("concat", |(_, n)| n);
481            out.push_str(&format!(" :op {op} :name "));
482            match &x.name {
483                Some(name) => hex(name.as_bytes(), out),
484                None => out.push_str("<>"),
485            }
486            out.push_str(" :names (");
487            for (i, (name, _)) in x.named.iter().enumerate() {
488                if i > 0 {
489                    out.push(' ');
490                }
491                hex(name.as_bytes(), out);
492            }
493            out.push(')');
494            let values: Vec<Expr> = x.named.iter().map(|(_, e)| e.clone()).collect();
495            out.push_str(" :named ");
496            out.push_str(&write_list(&values)?);
497            write_args(&x.args, out)?;
498            out.push_str(&format!(
499                " :document {} :indent {} :ttype {} :ttypmod {}",
500                x.document, x.indent, x.target.0, x.target.1
501            ));
502        }
503        ExprKind::Param(_)
504        | ExprKind::Agg(_)
505        | ExprKind::Grouping(_)
506        | ExprKind::PlaceHolder(_)
507        | ExprKind::Window(_)
508        | ExprKind::SubLink(_)
509        | ExprKind::SubColumn(_)
510        | ExprKind::CurrentOf(_)
511        | ExprKind::JsonTable(_) => {}
512    }
513    out.push('}');
514    Ok(())
515}
516
517/// The names of the formats of a `FORMAT` clause.
518const FORMAT_KINDS: [(JsonFormatKind, &str); 3] = [
519    (JsonFormatKind::Default, "default"),
520    (JsonFormatKind::Json, "json"),
521    (JsonFormatKind::Jsonb, "jsonb"),
522];
523
524/// The names of the encodings of a `FORMAT` clause.
525const ENCODINGS: [(JsonEncoding, &str); 4] = [
526    (JsonEncoding::Default, "default"),
527    (JsonEncoding::Utf8, "utf8"),
528    (JsonEncoding::Utf16, "utf16"),
529    (JsonEncoding::Utf32, "utf32"),
530];
531
532/// The names of the SQL/JSON constructors.
533const CTOR_KINDS: [(JsonCtorKind, &str); 8] = [
534    (JsonCtorKind::Object, "object"),
535    (JsonCtorKind::Array, "array"),
536    (JsonCtorKind::Parse, "parse"),
537    (JsonCtorKind::Scalar, "scalar"),
538    (JsonCtorKind::Serialize, "serialize"),
539    (JsonCtorKind::ObjectAgg, "objectagg"),
540    (JsonCtorKind::ArrayAgg, "arrayagg"),
541    (JsonCtorKind::ArrayQuery, "arrayquery"),
542];
543
544/// The names of the kinds of `IS JSON`.
545const ITEM_TYPES: [(JsonItemType, &str); 4] = [
546    (JsonItemType::Any, "any"),
547    (JsonItemType::Object, "object"),
548    (JsonItemType::Array, "array"),
549    (JsonItemType::Scalar, "scalar"),
550];
551
552/// The names of the SQL/JSON query functions.
553const JSON_OPS: [(JsonExprOp, &str); 3] =
554    [(JsonExprOp::Exists, "exists"), (JsonExprOp::Query, "query"), (JsonExprOp::Value, "value")];
555
556/// The names of the SQL/XML functions.
557const XML_OPS: [(XmlOp, &str); 8] = [
558    (XmlOp::Concat, "concat"),
559    (XmlOp::Element, "element"),
560    (XmlOp::Forest, "forest"),
561    (XmlOp::Parse, "parse"),
562    (XmlOp::Pi, "pi"),
563    (XmlOp::Root, "root"),
564    (XmlOp::Serialize, "serialize"),
565    (XmlOp::Document, "document"),
566];
567
568/// The names of the `WRAPPER` clauses.
569const WRAPPERS: [(JsonWrapper, &str); 4] = [
570    (JsonWrapper::Unspec, "unspec"),
571    (JsonWrapper::None, "none"),
572    (JsonWrapper::Conditional, "conditional"),
573    (JsonWrapper::Unconditional, "unconditional"),
574];
575
576/// The names of the behaviors of `ON EMPTY` and `ON ERROR`.
577const BEHAVIORS: [(JsonBehaviorKind, &str); 9] = [
578    (JsonBehaviorKind::Null, "null"),
579    (JsonBehaviorKind::Error, "error"),
580    (JsonBehaviorKind::Empty, "empty"),
581    (JsonBehaviorKind::True, "true"),
582    (JsonBehaviorKind::False, "false"),
583    (JsonBehaviorKind::Unknown, "unknown"),
584    (JsonBehaviorKind::EmptyArray, "emptyarray"),
585    (JsonBehaviorKind::EmptyObject, "emptyobject"),
586    (JsonBehaviorKind::Default, "default"),
587];
588
589/// A behavior as the list of its kind, its flag of the cast at run time and its value, with `<>` for no value.
590fn write_behavior(behavior: &JsonBehavior, out: &mut String) -> Result<()> {
591    let kind = BEHAVIORS.iter().find(|(k, _)| *k == behavior.kind).map_or("null", |(_, n)| n);
592    out.push_str(&format!("({kind} {} ", behavior.coerce));
593    match &behavior.expr {
594        Some(expr) => write_expr(expr, out)?,
595        None => out.push_str("<>"),
596    }
597    out.push(')');
598    Ok(())
599}
600
601/// The behavior that [`write_behavior`] wrote.
602fn behavior_of(item: &Item) -> Result<JsonBehavior> {
603    let [kind, coerce, expr] = list(item)? else { return Err(bad("a SQL/JSON behavior")) };
604    let kind = atom(kind)?;
605    let kind =
606        BEHAVIORS.iter().find(|(_, n)| *n == kind).ok_or_else(|| bad("a SQL/JSON behavior"))?.0;
607    let coerce = atom(coerce)? == "true";
608    let expr = match expr {
609        Item::Atom(empty) if empty == "<>" => None,
610        item => Some(expr_of(item)?),
611    };
612    Ok(JsonBehavior { kind, expr, coerce })
613}
614
615/// The fields of a `FORMAT` clause.
616fn write_format(format: JsonFormat, out: &mut String) {
617    let kind = FORMAT_KINDS.iter().find(|(k, _)| *k == format.kind).map_or("default", |(_, n)| n);
618    let encoding =
619        ENCODINGS.iter().find(|(e, _)| *e == format.encoding).map_or("default", |(_, n)| n);
620    out.push_str(&format!(" :format {kind} :encoding {encoding}"));
621}
622
623/// The `FORMAT` clause of the fields that [`write_format`] wrote.
624fn format_of(f: &Fields<'_>) -> Result<JsonFormat> {
625    let kind = f.atom("format")?;
626    let encoding = f.atom("encoding")?;
627    let kind = FORMAT_KINDS.iter().find(|(_, n)| *n == kind).ok_or_else(|| bad("a JSON format"))?;
628    let encoding =
629        ENCODINGS.iter().find(|(_, n)| *n == encoding).ok_or_else(|| bad("a JSON encoding"))?;
630    Ok(JsonFormat { kind: kind.0, encoding: encoding.0 })
631}
632
633fn write_field(name: &str, expr: &Expr, out: &mut String) -> Result<()> {
634    out.push_str(&format!(" :{name} "));
635    write_expr(expr, out)
636}
637
638fn write_args(args: &[Expr], out: &mut String) -> Result<()> {
639    out.push_str(" :args (");
640    for (i, arg) in args.iter().enumerate() {
641        if i > 0 {
642            out.push(' ');
643        }
644        write_expr(arg, out)?;
645    }
646    out.push(')');
647    Ok(())
648}
649
650/// The subscripts of one bound of a `SUBSCRIPT`, with `<>` for a bound that the query does not give.
651fn write_bounds(bounds: &[Option<Expr>], out: &mut String) -> Result<()> {
652    out.push('(');
653    for (i, bound) in bounds.iter().enumerate() {
654        if i > 0 {
655            out.push(' ');
656        }
657        match bound {
658            Some(bound) => write_expr(bound, out)?,
659            None => out.push_str("<>"),
660        }
661    }
662    out.push(')');
663    Ok(())
664}
665
666/// The subscripts of one bound of a `SUBSCRIPT`.
667fn bounds_of(item: &Item) -> Result<Vec<Option<Expr>>> {
668    list(item)?
669        .iter()
670        .map(|item| match item {
671            Item::Atom(empty) if empty == "<>" => Ok(None),
672            item => expr_of(item).map(Some),
673        })
674        .collect()
675}
676
677const TESTS: [(BoolTest, &str); 6] = [
678    (BoolTest::IsTrue, "is_true"),
679    (BoolTest::IsNotTrue, "is_not_true"),
680    (BoolTest::IsFalse, "is_false"),
681    (BoolTest::IsNotFalse, "is_not_false"),
682    (BoolTest::IsUnknown, "is_unknown"),
683    (BoolTest::IsNotUnknown, "is_not_unknown"),
684];
685
686fn test_name(test: BoolTest) -> &'static str {
687    TESTS.iter().find(|(t, _)| *t == test).map_or("is_true", |(_, name)| name)
688}
689
690fn sql_value_name(value: SqlValue) -> (&'static str, Option<i32>) {
691    match value {
692        SqlValue::CurrentDate => ("current_date", None),
693        SqlValue::CurrentTime(p) => ("current_time", p),
694        SqlValue::CurrentTimestamp(p) => ("current_timestamp", p),
695        SqlValue::LocalTime(p) => ("localtime", p),
696        SqlValue::LocalTimestamp(p) => ("localtimestamp", p),
697        SqlValue::CurrentRole => ("current_role", None),
698        SqlValue::CurrentUser => ("current_user", None),
699        SqlValue::User => ("user", None),
700        SqlValue::SessionUser => ("session_user", None),
701        SqlValue::CurrentCatalog => ("current_catalog", None),
702        SqlValue::CurrentSchema => ("current_schema", None),
703    }
704}
705
706fn sql_value_of(name: &str, precision: Option<i32>) -> Option<SqlValue> {
707    Some(match name {
708        "current_date" => SqlValue::CurrentDate,
709        "current_time" => SqlValue::CurrentTime(precision),
710        "current_timestamp" => SqlValue::CurrentTimestamp(precision),
711        "localtime" => SqlValue::LocalTime(precision),
712        "localtimestamp" => SqlValue::LocalTimestamp(precision),
713        "current_role" => SqlValue::CurrentRole,
714        "current_user" => SqlValue::CurrentUser,
715        "user" => SqlValue::User,
716        "session_user" => SqlValue::SessionUser,
717        "current_catalog" => SqlValue::CurrentCatalog,
718        "current_schema" => SqlValue::CurrentSchema,
719        _ => return None,
720    })
721}
722
723/// Writes the bytes as `x` and two hex digits for each byte.
724fn hex(bytes: &[u8], out: &mut String) {
725    out.push('x');
726    for b in bytes {
727        out.push_str(&format!("{b:02x}"));
728    }
729}
730
731/// A value as a list of its kind and its parts, or `null`. A float keeps its bits, and a `numeric` and a `tsvector` keep the bytes of their binary form.
732fn write_value(value: &Value, out: &mut String) {
733    match value {
734        Value::Null => out.push_str("null"),
735        Value::Bool(v) => out.push_str(&format!("(bool {v})")),
736        Value::Int2(v) => out.push_str(&format!("(int2 {v})")),
737        Value::Int4(v) => out.push_str(&format!("(int4 {v})")),
738        Value::Int8(v) => out.push_str(&format!("(int8 {v})")),
739        Value::Float4(v) => out.push_str(&format!("(float4 {})", v.to_bits())),
740        Value::Float8(v) => out.push_str(&format!("(float8 {})", v.to_bits())),
741        Value::Numeric(v) => {
742            let mut bytes = Vec::new();
743            rupg_types::numeric_send(v, &mut bytes);
744            out.push_str("(numeric ");
745            hex(&bytes, out);
746            out.push(')');
747        }
748        Value::Oid(v) => out.push_str(&format!("(oid {v})")),
749        Value::Char(v) => out.push_str(&format!("(char {v})")),
750        Value::Text(v) => {
751            out.push_str("(text \"");
752            for c in v.chars() {
753                if c == '"' || c == '\\' {
754                    out.push('\\');
755                }
756                out.push(c);
757            }
758            out.push_str("\")");
759        }
760        Value::Bytea(v) => {
761            out.push_str("(bytea ");
762            hex(v, out);
763            out.push(')');
764        }
765        Value::Uuid(v) => {
766            out.push_str("(uuid ");
767            hex(v, out);
768            out.push(')');
769        }
770        Value::Date(v) => out.push_str(&format!("(date {v})")),
771        Value::Time(v) => out.push_str(&format!("(time {v})")),
772        Value::TimeTz(time, zone) => out.push_str(&format!("(timetz {time} {zone})")),
773        Value::Timestamp(v) => out.push_str(&format!("(timestamp {v})")),
774        Value::TimestampTz(v) => out.push_str(&format!("(timestamptz {v})")),
775        Value::Interval(v) => {
776            out.push_str(&format!("(interval {} {} {})", v.time, v.day, v.month));
777        }
778        Value::Inet(v) => {
779            let family = if v.family == NetFamily::V4 { 4 } else { 6 };
780            out.push_str(&format!("(inet {family} {} ", v.bits));
781            hex(v.bytes(), out);
782            out.push(')');
783        }
784        Value::Array(array) => {
785            out.push_str("(array (");
786            for (i, dim) in array.dims.iter().enumerate() {
787                if i > 0 {
788                    out.push(' ');
789                }
790                out.push_str(&format!("({} {})", dim.len, dim.lower));
791            }
792            out.push_str(") (");
793            for (i, element) in array.values.iter().enumerate() {
794                if i > 0 {
795                    out.push(' ');
796                }
797                match element {
798                    Some(element) => write_value(element, out),
799                    None => out.push_str("null"),
800                }
801            }
802            out.push_str("))");
803        }
804        Value::Record(record) => {
805            out.push_str("(record (");
806            for (i, ty) in record.types.iter().enumerate() {
807                if i > 0 {
808                    out.push(' ');
809                }
810                out.push_str(&ty.to_string());
811            }
812            out.push_str(") (");
813            for (i, field) in record.values.iter().enumerate() {
814                if i > 0 {
815                    out.push(' ');
816                }
817                write_value(field, out);
818            }
819            out.push_str("))");
820        }
821        Value::TsVector(lexemes) => {
822            let mut bytes = Vec::new();
823            rupg_types::tsvector_send(lexemes, &mut bytes);
824            out.push_str("(tsvector ");
825            hex(&bytes, out);
826            out.push(')');
827        }
828        Value::TsQuery(items) => {
829            let mut bytes = Vec::new();
830            rupg_types::tsquery_send(items, &mut bytes);
831            out.push_str("(tsquery ");
832            hex(&bytes, out);
833            out.push(')');
834        }
835        Value::JsonPath(path) => {
836            let mut bytes = Vec::new();
837            rupg_types::jsonpath_send(path, &mut bytes);
838            out.push_str("(jsonpath ");
839            hex(&bytes, out);
840            out.push(')');
841        }
842        Value::Range(range) => write_range(range, out),
843        Value::Multirange(ranges) => {
844            out.push_str("(multirange");
845            for range in ranges {
846                out.push(' ');
847                write_range(range, out);
848            }
849            out.push(')');
850        }
851    }
852}
853
854/// The stored form of a range: `(range FLAGS LOWER UPPER)`.
855fn write_range(range: &Range, out: &mut String) {
856    out.push_str(&format!("(range {} ", range.flags));
857    write_value(&range.lower, out);
858    out.push(' ');
859    write_value(&range.upper, out);
860    out.push(')');
861}
862
863/// A part of a stored form.
864#[derive(Debug)]
865enum Item {
866    /// A word or a number. `<>` is the empty value.
867    Atom(String),
868    /// A quoted string.
869    Str(String),
870    List(Vec<Item>),
871    /// `{NAME :field value ...}`.
872    Node(String, Vec<(String, Item)>),
873}
874
875/// The tokens of a stored form.
876struct Tokens<'a> {
877    text: &'a str,
878    at: usize,
879}
880
881/// One token.
882enum Token {
883    Open(char),
884    Close(char),
885    Str(String),
886    Atom(String),
887}
888
889impl Tokens<'_> {
890    fn next(&mut self) -> Result<Option<Token>> {
891        let rest = &self.text[self.at..];
892        let trimmed = rest.trim_start();
893        self.at += rest.len() - trimmed.len();
894        let Some(c) = trimmed.chars().next() else { return Ok(None) };
895        match c {
896            '{' | '(' => {
897                self.at += 1;
898                Ok(Some(Token::Open(c)))
899            }
900            '}' | ')' => {
901                self.at += 1;
902                Ok(Some(Token::Close(c)))
903            }
904            '"' => {
905                let mut value = String::new();
906                let mut chars = trimmed[1..].char_indices();
907                loop {
908                    let Some((i, c)) = chars.next() else { return Err(bad("an open string")) };
909                    match c {
910                        '"' => {
911                            self.at += i + 2;
912                            return Ok(Some(Token::Str(value)));
913                        }
914                        '\\' => match chars.next() {
915                            Some((_, c)) => value.push(c),
916                            None => return Err(bad("an open string")),
917                        },
918                        _ => value.push(c),
919                    }
920                }
921            }
922            _ => {
923                let end = trimmed
924                    .find(|c: char| c.is_whitespace() || "{}()\"".contains(c))
925                    .unwrap_or(trimmed.len());
926                self.at += end;
927                Ok(Some(Token::Atom(trimmed[..end].to_string())))
928            }
929        }
930    }
931
932    fn item(&mut self) -> Result<Item> {
933        match self.next()? {
934            Some(token) => self.item_from(token),
935            None => Err(bad("an early end")),
936        }
937    }
938
939    fn item_from(&mut self, token: Token) -> Result<Item> {
940        match token {
941            Token::Atom(atom) => Ok(Item::Atom(atom)),
942            Token::Str(text) => Ok(Item::Str(text)),
943            Token::Close(_) => Err(bad("a close bracket with no open bracket")),
944            Token::Open('(') => {
945                let mut items = Vec::new();
946                loop {
947                    match self.next()? {
948                        Some(Token::Close(')')) => return Ok(Item::List(items)),
949                        Some(token) => items.push(self.item_from(token)?),
950                        None => return Err(bad("an open list")),
951                    }
952                }
953            }
954            Token::Open(_) => {
955                let Some(Token::Atom(name)) = self.next()? else {
956                    return Err(bad("a node with no name"));
957                };
958                let mut fields = Vec::new();
959                loop {
960                    match self.next()? {
961                        Some(Token::Close('}')) => return Ok(Item::Node(name, fields)),
962                        Some(Token::Atom(field)) if field.starts_with(':') => {
963                            fields.push((field[1..].to_string(), self.item()?));
964                        }
965                        _ => return Err(bad("a node field")),
966                    }
967                }
968            }
969        }
970    }
971}
972
973/// The fields of one node.
974struct Fields<'a> {
975    fields: &'a [(String, Item)],
976}
977
978impl<'a> Fields<'a> {
979    fn get(&self, name: &str) -> Result<&'a Item> {
980        self.fields
981            .iter()
982            .find(|(field, _)| field == name)
983            .map(|(_, item)| item)
984            .ok_or_else(|| bad(&format!("no field {name}")))
985    }
986
987    fn atom(&self, name: &str) -> Result<&'a str> {
988        atom(self.get(name)?)
989    }
990
991    fn number<T: std::str::FromStr>(&self, name: &str) -> Result<T> {
992        number(self.atom(name)?)
993    }
994
995    fn flag(&self, name: &str) -> Result<bool> {
996        match self.atom(name)? {
997            "true" => Ok(true),
998            "false" => Ok(false),
999            _ => Err(bad(&format!("field {name} is not true or false"))),
1000        }
1001    }
1002
1003    fn expr(&self, name: &str) -> Result<Box<Expr>> {
1004        Ok(Box::new(expr_of(self.get(name)?)?))
1005    }
1006
1007    fn exprs(&self, name: &str) -> Result<Vec<Expr>> {
1008        list(self.get(name)?)?.iter().map(expr_of).collect()
1009    }
1010}
1011
1012fn atom(item: &Item) -> Result<&str> {
1013    match item {
1014        Item::Atom(atom) => Ok(atom),
1015        _ => Err(bad("a list where a word must be")),
1016    }
1017}
1018
1019fn number<T: std::str::FromStr>(text: &str) -> Result<T> {
1020    text.parse().map_err(|_| bad(&format!("{text} is not a number")))
1021}
1022
1023fn list(item: &Item) -> Result<&[Item]> {
1024    match item {
1025        Item::List(items) => Ok(items),
1026        _ => Err(bad("a word where a list must be")),
1027    }
1028}
1029
1030fn expr_of(item: &Item) -> Result<Expr> {
1031    let Item::Node(name, fields) = item else { return Err(bad("no node")) };
1032    let f = Fields { fields };
1033    let ty = f.number("type")?;
1034    let typmod = f.number("typmod")?;
1035    let location: i64 = f.number("location")?;
1036    let location = usize::try_from(location).ok();
1037    let kind = match name.as_str() {
1038        "CONST" => ExprKind::Const(value_of(f.get("value")?)?),
1039        "FUNC" => {
1040            let form = match f.get("form")? {
1041                Item::Atom(form) if form == "call" => FuncForm::Call,
1042                Item::Atom(form) if form == "explicit" => FuncForm::ExplicitCast,
1043                Item::Atom(form) if form == "implicit" => FuncForm::ImplicitCast,
1044                Item::Atom(form) if form == "sql" => FuncForm::SqlSyntax,
1045                Item::List(parts) if parts.len() == 2 && atom(&parts[0])? == "operator" => {
1046                    FuncForm::Operator(number(atom(&parts[1])?)?)
1047                }
1048                _ => return Err(bad("a function form")),
1049            };
1050            ExprKind::Func(Func {
1051                oid: f.number("oid")?,
1052                args: f.exprs("args")?,
1053                form,
1054                variadic: f.flag("variadic")?,
1055                // A stored expression has no call of a function that gives a set.
1056                retset: false,
1057            })
1058        }
1059        "RELABEL" => ExprKind::Relabel(f.expr("arg")?, cast_form(&f)?),
1060        "COERCEVIAIO" => ExprKind::CoerceViaIo(f.expr("arg")?, cast_form(&f)?),
1061        "COERCETODOMAIN" => ExprKind::CoerceToDomain(f.expr("arg")?, cast_form(&f)?),
1062        "COERCETODOMAINVALUE" => ExprKind::DomainValue,
1063        "ARRAYCOERCE" => ExprKind::ArrayCoerce {
1064            arg: f.expr("arg")?,
1065            element: f.expr("element")?,
1066            form: cast_form(&f)?,
1067        },
1068        "SUBSCRIPT" => ExprKind::Subscript(Box::new(Subscript {
1069            container: *f.expr("container")?,
1070            upper: bounds_of(f.get("upper")?)?,
1071            lower: match f.get("lower")? {
1072                Item::Atom(empty) if empty == "<>" => None,
1073                item => Some(bounds_of(item)?),
1074            },
1075            assign: f.get("assign").ok().map(expr_of).transpose()?,
1076        })),
1077        "BOOL" => {
1078            let op = match f.atom("op")? {
1079                "and" => BoolOp::And,
1080                "or" => BoolOp::Or,
1081                "not" => BoolOp::Not,
1082                _ => return Err(bad("a boolean operator")),
1083            };
1084            ExprKind::Bool(op, f.exprs("args")?)
1085        }
1086        "NULLTEST" => ExprKind::NullTest(f.expr("arg")?, f.flag("isnull")?),
1087        "BOOLEANTEST" => {
1088            let test = f.atom("test")?;
1089            let Some((test, _)) = TESTS.iter().find(|(_, name)| *name == test) else {
1090                return Err(bad("a boolean test"));
1091            };
1092            ExprKind::BooleanTest(f.expr("arg")?, *test)
1093        }
1094        "CASE" => {
1095            let arg = match f.get("arg")? {
1096                Item::Atom(empty) if empty == "<>" => None,
1097                item => Some(Box::new(expr_of(item)?)),
1098            };
1099            let mut whens = Vec::new();
1100            for when in list(f.get("whens")?)? {
1101                let [when, then] = list(when)? else { return Err(bad("a WHEN of a CASE")) };
1102                whens.push((expr_of(when)?, expr_of(then)?));
1103            }
1104            ExprKind::Case(Case { arg, whens, default: f.expr("default")? })
1105        }
1106        "CASETEST" => ExprKind::CaseTest,
1107        "COALESCE" => ExprKind::Coalesce(f.exprs("args")?),
1108        // A row of an older node text has no form, and is implicit.
1109        "ROW" => ExprKind::Row(f.exprs("args")?, cast_form(&f).unwrap_or(CastForm::Implicit)),
1110        "JOINROW" => {
1111            let text = |b: &str| {
1112                String::from_utf8(bytes_of(b)?).map_err(|_| bad("a name that is not UTF-8"))
1113            };
1114            let alias = match f.atom("alias")? {
1115                "<>" => None,
1116                alias => Some(text(alias)?),
1117            };
1118            let names =
1119                list(f.get("names")?)?.iter().map(|n| text(atom(n)?)).collect::<Result<_>>()?;
1120            ExprKind::JoinRow(Box::new(JoinRow { alias, names, fields: f.exprs("args")? }))
1121        }
1122        "FIELDSTORE" => {
1123            let numbers = |name: &str| -> Result<Vec<String>> {
1124                list(f.get(name)?)?.iter().map(|n| atom(n).map(str::to_owned)).collect()
1125            };
1126            let fields =
1127                numbers("fieldnums")?.iter().map(|n| number(n)).collect::<Result<Vec<usize>>>()?;
1128            let types = numbers("types")?.iter().map(|n| number(n)).collect::<Result<_>>()?;
1129            let values = f.exprs("args")?;
1130            if values.len() != fields.len() {
1131                return Err(bad("a FIELDSTORE with more fields than values"));
1132            }
1133            ExprKind::FieldStore(Box::new(FieldStore {
1134                arg: *f.expr("arg")?,
1135                fields: fields.into_iter().zip(values).collect(),
1136                types,
1137            }))
1138        }
1139        "ROWCOMPARE" => {
1140            let kind = RowCompareKind::of_name(f.atom("kind")?)
1141                .ok_or_else(|| bad("a kind of row comparison"))?;
1142            let compares = list(f.get("compares")?)?
1143                .iter()
1144                .map(|c| number(atom(c)?))
1145                .collect::<Result<_>>()?;
1146            ExprKind::RowCompare(Box::new(RowCompare { kind, ops: f.exprs("args")?, compares }))
1147        }
1148        "MINMAX" => ExprKind::MinMax {
1149            greatest: f.flag("greatest")?,
1150            less: f.number("less")?,
1151            args: f.exprs("args")?,
1152        },
1153        "NULLIF" => ExprKind::NullIf { equal: f.number("equal")?, args: f.exprs("args")? },
1154        "DISTINCT" => ExprKind::Distinct {
1155            equal: f.number("equal")?,
1156            not: f.flag("not")?,
1157            args: f.exprs("args")?,
1158        },
1159        "SCALARARRAYOP" => ExprKind::ScalarArrayOp {
1160            func: f.number("func")?,
1161            any: f.flag("any")?,
1162            args: f.exprs("args")?,
1163        },
1164        "ARRAY" => ExprKind::Array {
1165            element: f.number("element")?,
1166            multidims: f.flag("multidims")?,
1167            elements: f.exprs("args")?,
1168        },
1169        "SQLVALUE" => {
1170            let precision = match f.atom("precision")? {
1171                "<>" => None,
1172                p => Some(number(p)?),
1173            };
1174            let value = sql_value_of(f.atom("function")?, precision)
1175                .ok_or_else(|| bad("a SQL value function"))?;
1176            ExprKind::SqlValue(value)
1177        }
1178        "VAR" => ExprKind::Var(Var {
1179            relation: f.number("relation")?,
1180            attnum: f.number("attnum")?,
1181            levels_up: f.number("levelsup")?,
1182        }),
1183        "FIELDSELECT" => ExprKind::FieldSelect(f.expr("arg")?, f.number("field")?),
1184        "NAMEDARG" => {
1185            let name = String::from_utf8(bytes_of(f.atom("name")?)?)
1186                .map_err(|_| bad("a name that is not UTF-8"))?;
1187            let number = f.number("number")?;
1188            ExprKind::NamedArg(Box::new(NamedArg { arg: *f.expr("arg")?, name, number }))
1189        }
1190        "JSONVALUEEXPR" => ExprKind::JsonValue(Box::new(JsonValue {
1191            raw: *f.expr("raw")?,
1192            formatted: *f.expr("formatted")?,
1193            format: format_of(&f)?,
1194        })),
1195        "JSONCONSTRUCTOREXPR" => {
1196            let kind = f.atom("kind")?;
1197            let kind = CTOR_KINDS
1198                .iter()
1199                .find(|(_, n)| *n == kind)
1200                .ok_or_else(|| bad("a SQL/JSON constructor"))?;
1201            let returning = JsonReturning {
1202                format: format_of(&f)?,
1203                ty: f.number("rtype")?,
1204                typmod: f.number("rtypmod")?,
1205            };
1206            let coercion = match f.get("coercion")? {
1207                Item::Atom(empty) if empty == "<>" => None,
1208                item => Some(expr_of(item)?),
1209            };
1210            ExprKind::JsonCtor(Box::new(JsonCtor {
1211                kind: kind.0,
1212                args: f.exprs("args")?,
1213                func: None,
1214                format: JsonFormat::default(),
1215                returning,
1216                unique: f.flag("unique")?,
1217                absent_on_null: f.flag("absent")?,
1218                coercion,
1219            }))
1220        }
1221        "JSONISPREDICATE" => {
1222            let item = f.atom("item")?;
1223            let item = ITEM_TYPES
1224                .iter()
1225                .find(|(_, n)| *n == item)
1226                .ok_or_else(|| bad("an IS JSON kind"))?;
1227            ExprKind::IsJson(Box::new(IsJson {
1228                expr: *f.expr("arg")?,
1229                item: item.0,
1230                unique: f.flag("unique")?,
1231                base_type: f.number("basetype")?,
1232            }))
1233        }
1234        "JSONEXPR" => {
1235            let op = f.atom("op")?;
1236            let op = JSON_OPS
1237                .iter()
1238                .find(|(_, n)| *n == op)
1239                .ok_or_else(|| bad("a SQL/JSON function"))?;
1240            let wrapper = f.atom("wrapper")?;
1241            let wrapper = WRAPPERS
1242                .iter()
1243                .find(|(_, n)| *n == wrapper)
1244                .ok_or_else(|| bad("a SQL/JSON wrapper"))?;
1245            let returning = JsonReturning {
1246                format: format_of(&f)?,
1247                ty: f.number("rtype")?,
1248                typmod: f.number("rtypmod")?,
1249            };
1250            let text = |b: &str| {
1251                String::from_utf8(bytes_of(b)?).map_err(|_| bad("a name that is not UTF-8"))
1252            };
1253            let names: Vec<String> =
1254                list(f.get("names")?)?.iter().map(|n| text(atom(n)?)).collect::<Result<_>>()?;
1255            let values = f.exprs("args")?;
1256            if names.len() != values.len() {
1257                return Err(bad("a PASSING clause"));
1258            }
1259            let on_empty = match f.get("onempty")? {
1260                Item::Atom(empty) if empty == "<>" => None,
1261                item => Some(behavior_of(item)?),
1262            };
1263            ExprKind::JsonExpr(Box::new(JsonExpr {
1264                op: op.0,
1265                formatted: *f.expr("formatted")?,
1266                path: *f.expr("path")?,
1267                passing: names.into_iter().zip(values).collect(),
1268                returning,
1269                on_empty,
1270                on_error: behavior_of(f.get("onerror")?)?,
1271                wrapper: wrapper.0,
1272                omit_quotes: f.flag("omitquotes")?,
1273                json_coercion: f.flag("jsoncoercion")?,
1274                io_coercion: f.flag("iocoercion")?,
1275                column: None,
1276            }))
1277        }
1278        "XMLEXPR" => {
1279            let op = f.atom("op")?;
1280            let op =
1281                XML_OPS.iter().find(|(_, n)| *n == op).ok_or_else(|| bad("a SQL/XML function"))?;
1282            let text = |b: &str| {
1283                String::from_utf8(bytes_of(b)?).map_err(|_| bad("a name that is not UTF-8"))
1284            };
1285            let name = match f.atom("name")? {
1286                "<>" => None,
1287                name => Some(text(name)?),
1288            };
1289            let names: Vec<String> =
1290                list(f.get("names")?)?.iter().map(|n| text(atom(n)?)).collect::<Result<_>>()?;
1291            let values = f.exprs("named")?;
1292            if names.len() != values.len() {
1293                return Err(bad("the named arguments of a SQL/XML function"));
1294            }
1295            ExprKind::Xml(Box::new(XmlExpr {
1296                op: op.0,
1297                name,
1298                named: names.into_iter().zip(values).collect(),
1299                args: f.exprs("args")?,
1300                document: f.flag("document")?,
1301                indent: f.flag("indent")?,
1302                target: (f.number("ttype")?, f.number("ttypmod")?),
1303            }))
1304        }
1305        _ => return Err(bad(&format!("the node {name}"))),
1306    };
1307    Ok(Expr { kind, ty, typmod, location })
1308}
1309
1310/// The form of a relabel or of an I/O cast.
1311fn cast_form(f: &Fields<'_>) -> Result<CastForm> {
1312    match f.atom("form")? {
1313        "explicit" => Ok(CastForm::Explicit),
1314        "implicit" => Ok(CastForm::Implicit),
1315        _ => Err(bad("a cast form")),
1316    }
1317}
1318
1319/// The bytes of `x` and hex digits.
1320fn bytes_of(text: &str) -> Result<Vec<u8>> {
1321    let digits = text.strip_prefix('x').ok_or_else(|| bad("bytes with no x"))?;
1322    if digits.len() % 2 != 0 {
1323        return Err(bad("an odd number of hex digits"));
1324    }
1325    (0..digits.len())
1326        .step_by(2)
1327        .map(|i| u8::from_str_radix(&digits[i..i + 2], 16).map_err(|_| bad("a hex digit")))
1328        .collect()
1329}
1330
1331fn value_of(item: &Item) -> Result<Value> {
1332    let parts = match item {
1333        Item::Atom(null) if null == "null" => return Ok(Value::Null),
1334        item => list(item)?,
1335    };
1336    let Some((kind, parts)) = parts.split_first() else { return Err(bad("an empty value")) };
1337    let part = |i: usize| -> Result<&str> {
1338        parts.get(i).ok_or_else(|| bad("a value with too few parts")).and_then(atom)
1339    };
1340    let value = match atom(kind)? {
1341        "bool" => Value::Bool(part(0)? == "true"),
1342        "int2" => Value::Int2(number(part(0)?)?),
1343        "int4" => Value::Int4(number(part(0)?)?),
1344        "int8" => Value::Int8(number(part(0)?)?),
1345        "float4" => Value::Float4(f32::from_bits(number(part(0)?)?)),
1346        "float8" => Value::Float8(f64::from_bits(number(part(0)?)?)),
1347        "numeric" => {
1348            let bytes = bytes_of(part(0)?)?;
1349            let mut recv = Recv::new(&bytes);
1350            let value = rupg_types::numeric_recv(&mut recv, -1)
1351                .map_err(|_| bad("the bytes of a numeric"))?;
1352            Value::Numeric(value)
1353        }
1354        "tsvector" => {
1355            let bytes = bytes_of(part(0)?)?;
1356            let value = rupg_types::tsvector_recv(&mut Recv::new(&bytes))
1357                .map_err(|_| bad("the bytes of a tsvector"))?;
1358            Value::TsVector(value)
1359        }
1360        "tsquery" => {
1361            let bytes = bytes_of(part(0)?)?;
1362            // The binary input takes no empty query, so the count 0 is the empty query here.
1363            if bytes == [0; 4] {
1364                Value::TsQuery(Vec::new())
1365            } else {
1366                let value = rupg_types::tsquery_recv(&mut Recv::new(&bytes))
1367                    .map_err(|_| bad("the bytes of a tsquery"))?;
1368                Value::TsQuery(value)
1369            }
1370        }
1371        "jsonpath" => {
1372            let bytes = bytes_of(part(0)?)?;
1373            // The input checked the patterns of `like_regex` when it made the value.
1374            let value = rupg_types::jsonpath_recv(&mut Recv::new(&bytes), &|_, _| Ok(()))
1375                .map_err(|_| bad("the bytes of a jsonpath"))?;
1376            Value::JsonPath(Box::new(value))
1377        }
1378        "oid" => Value::Oid(number(part(0)?)?),
1379        "char" => Value::Char(number(part(0)?)?),
1380        "text" => match parts.first() {
1381            Some(Item::Str(text)) => Value::Text(text.clone()),
1382            _ => return Err(bad("a text value with no string")),
1383        },
1384        "bytea" => Value::Bytea(bytes_of(part(0)?)?),
1385        "uuid" => {
1386            let bytes: [u8; 16] =
1387                bytes_of(part(0)?)?.try_into().map_err(|_| bad("a uuid that is not 16 bytes"))?;
1388            Value::Uuid(bytes)
1389        }
1390        "date" => Value::Date(number(part(0)?)?),
1391        "time" => Value::Time(number(part(0)?)?),
1392        "timetz" => Value::TimeTz(number(part(0)?)?, number(part(1)?)?),
1393        "timestamp" => Value::Timestamp(number(part(0)?)?),
1394        "timestamptz" => Value::TimestampTz(number(part(0)?)?),
1395        "inet" => {
1396            let family = match part(0)? {
1397                "4" => NetFamily::V4,
1398                "6" => NetFamily::V6,
1399                _ => return Err(bad("an inet family that is not 4 or 6")),
1400            };
1401            let bytes = bytes_of(part(2)?)?;
1402            if bytes.len() != family.size() {
1403                return Err(bad("an inet address of the wrong size"));
1404            }
1405            let mut addr = [0u8; 16];
1406            addr[..bytes.len()].copy_from_slice(&bytes);
1407            Value::Inet(Inet { family, bits: number(part(1)?)?, addr })
1408        }
1409        "interval" => Value::Interval(Interval {
1410            time: number(part(0)?)?,
1411            day: number(part(1)?)?,
1412            month: number(part(2)?)?,
1413        }),
1414        "array" => {
1415            let [dims, values] = parts else { return Err(bad("an array value")) };
1416            let mut array = Array::empty();
1417            for dim in list(dims)? {
1418                let [len, lower] = list(dim)? else { return Err(bad("an array dimension")) };
1419                array
1420                    .dims
1421                    .push(ArrayDim { len: number(atom(len)?)?, lower: number(atom(lower)?)? });
1422            }
1423            for value in list(values)? {
1424                array.values.push(match value_of(value)? {
1425                    Value::Null => None,
1426                    value => Some(value),
1427                });
1428            }
1429            Value::Array(Box::new(array))
1430        }
1431        "record" => {
1432            let [types, values] = parts else { return Err(bad("a record value")) };
1433            let types = list(types)?.iter().map(|t| number(atom(t)?)).collect::<Result<_>>()?;
1434            let values = list(values)?.iter().map(value_of).collect::<Result<_>>()?;
1435            Value::Record(Box::new(Record::new(types, values)))
1436        }
1437        "range" => {
1438            let [flags, lower, upper] = parts else { return Err(bad("a range value")) };
1439            Value::Range(Box::new(Range {
1440                flags: number(atom(flags)?)?,
1441                lower: value_of(lower)?,
1442                upper: value_of(upper)?,
1443            }))
1444        }
1445        "multirange" => Value::Multirange(
1446            parts
1447                .iter()
1448                .map(|part| match value_of(part)? {
1449                    Value::Range(range) => Ok(*range),
1450                    _ => Err(bad("a multirange value")),
1451                })
1452                .collect::<Result<_>>()?,
1453        ),
1454        kind => return Err(bad(&format!("the value kind {kind}"))),
1455    };
1456    Ok(value)
1457}
1458
1459#[cfg(test)]
1460mod tests {
1461    use rupg_types::oid;
1462
1463    use super::*;
1464
1465    fn round_trip(expr: &Expr) -> String {
1466        let text = write(expr).expect("write");
1467        assert_eq!(&read(&text).expect("read"), expr, "{text}");
1468        text
1469    }
1470
1471    fn constant(value: Value, ty: u32) -> Expr {
1472        Expr::constant(value, ty, -1, Some(3))
1473    }
1474
1475    #[test]
1476    fn values() {
1477        let numeric = rupg_types::numeric_in("-12.3400", -1).expect("numeric");
1478        let values = [
1479            (Value::Null, oid::INT4),
1480            (Value::Bool(true), oid::BOOL),
1481            (Value::Int2(-7), oid::INT2),
1482            (Value::Int4(i32::MIN), oid::INT4),
1483            (Value::Int8(i64::MAX), oid::INT8),
1484            (Value::Float4(-0.0), oid::FLOAT4),
1485            (Value::Float8(0.1), oid::FLOAT8),
1486            (Value::Float8(f64::INFINITY), oid::FLOAT8),
1487            (Value::Numeric(numeric), oid::NUMERIC),
1488            (Value::Oid(u32::MAX), oid::OID),
1489            (Value::Char(0), oid::CHAR),
1490            (Value::text("a \"b\" \\c\n{d} (e) é"), oid::TEXT),
1491            (Value::text(""), oid::TEXT),
1492            (Value::Bytea(vec![]), oid::BYTEA),
1493            (Value::Bytea(vec![0, 255, 16]), oid::BYTEA),
1494            (Value::Uuid([7; 16]), oid::UUID),
1495            (Value::Date(-1), oid::DATE),
1496            (Value::Time(86_400_000_000), oid::TIME),
1497            (Value::TimeTz(1, -3600), oid::TIMETZ),
1498            (Value::Timestamp(i64::MIN), oid::TIMESTAMP),
1499            (Value::TimestampTz(5), oid::TIMESTAMPTZ),
1500            (Value::Interval(Interval { time: -1, day: 2, month: -3 }), oid::INTERVAL),
1501            (Value::Inet(rupg_types::inet_in("10.1.2.3/8", false).expect("inet")), oid::INET),
1502            (Value::Inet(rupg_types::inet_in("2001:db8::/32", true).expect("cidr")), oid::CIDR),
1503            (
1504                Value::Range(Box::new(Range {
1505                    flags: rupg_types::RANGE_LB_INC,
1506                    lower: Value::Int4(1),
1507                    upper: Value::Int4(10),
1508                })),
1509                oid::INT4RANGE,
1510            ),
1511            (Value::Range(Box::new(Range::empty())), oid::DATERANGE),
1512            (Value::Multirange(Vec::new()), oid::INT4MULTIRANGE),
1513            (Value::TsVector(Vec::new()), oid::TSVECTOR),
1514            (
1515                Value::TsVector(
1516                    rupg_types::tsvector_parse("'it''s':3A a b:1,2C").expect("tsvector"),
1517                ),
1518                oid::TSVECTOR,
1519            ),
1520            (Value::TsQuery(Vec::new()), oid::TSQUERY),
1521            (
1522                Value::TsQuery(
1523                    rupg_types::tsquery_parse("'it''s':A* & !(b | c <2> d)").expect("tsquery"),
1524                ),
1525                oid::TSQUERY,
1526            ),
1527            (
1528                Value::JsonPath(Box::new(
1529                    rupg_types::jsonpath_parse(
1530                        "strict $.a[1 to last] ? (@ like_regex \"^b\" flag \"i\").**{2}",
1531                        false,
1532                        &|_, _| Ok(()),
1533                    )
1534                    .expect("jsonpath"),
1535                )),
1536                oid::JSONPATH,
1537            ),
1538            (
1539                Value::Multirange(vec![
1540                    Range {
1541                        flags: rupg_types::RANGE_LB_INF,
1542                        lower: Value::Null,
1543                        upper: Value::Int8(-4),
1544                    },
1545                    Range {
1546                        flags: rupg_types::RANGE_LB_INC,
1547                        lower: Value::Int8(7),
1548                        upper: Value::Int8(9),
1549                    },
1550                ]),
1551                oid::INT8MULTIRANGE,
1552            ),
1553        ];
1554        for (value, ty) in values {
1555            round_trip(&constant(value, ty));
1556        }
1557        let mut array = Array::one(vec![Some(Value::Int4(1)), None, Some(Value::Int4(3))]);
1558        array.dims[0].lower = -2;
1559        round_trip(&constant(Value::Array(Box::new(array)), oid::INT4_ARRAY));
1560        round_trip(&constant(Value::Array(Box::new(Array::empty())), oid::TEXT_ARRAY));
1561    }
1562
1563    #[test]
1564    fn nodes() {
1565        let var =
1566            |attnum| Expr::new(ExprKind::Var(Var { relation: 0, attnum, levels_up: 0 }), oid::INT4);
1567        let call = Expr {
1568            kind: ExprKind::Func(Func {
1569                oid: 177,
1570                args: vec![var(1), constant(Value::Int4(1), oid::INT4)],
1571                form: FuncForm::Operator(551),
1572                variadic: false,
1573                retset: false,
1574            }),
1575            ty: oid::INT4,
1576            typmod: -1,
1577            location: Some(12),
1578        };
1579        let text = round_trip(&call);
1580        assert_eq!(
1581            text,
1582            "{FUNC :type 23 :typmod -1 :location 12 :oid 177 :form (operator 551) :variadic false :args ({VAR :type 23 :typmod -1 :location -1 :relation 0 :attnum 1 :levelsup 0} {CONST :type 23 :typmod -1 :location 3 :value (int4 1)})}"
1583        );
1584        let test = Expr::new(ExprKind::NullTest(Box::new(var(2)), false), oid::BOOL);
1585        let case = Expr::new(
1586            ExprKind::Case(Case {
1587                arg: Some(Box::new(var(1))),
1588                whens: vec![(Expr::new(ExprKind::CaseTest, oid::INT4), var(2))],
1589                default: Box::new(constant(Value::Null, oid::INT4)),
1590            }),
1591            oid::INT4,
1592        );
1593        let nodes = [
1594            Expr::new(ExprKind::Bool(BoolOp::Not, vec![test.clone()]), oid::BOOL),
1595            Expr::new(ExprKind::BooleanTest(Box::new(test), BoolTest::IsNotUnknown), oid::BOOL),
1596            case,
1597            Expr::new(
1598                ExprKind::Case(Case { arg: None, whens: vec![], default: Box::new(var(1)) }),
1599                oid::INT4,
1600            ),
1601            Expr::new(ExprKind::Coalesce(vec![var(1), var(2)]), oid::INT4),
1602            Expr::new(
1603                ExprKind::NamedArg(Box::new(NamedArg {
1604                    arg: var(1),
1605                    name: "a b".to_owned(),
1606                    number: 2,
1607                })),
1608                oid::INT4,
1609            ),
1610            Expr::new(
1611                ExprKind::JoinRow(Box::new(JoinRow {
1612                    alias: Some("j k".to_owned()),
1613                    names: vec!["a".to_owned(), String::new()],
1614                    fields: vec![var(1), var(2)],
1615                })),
1616                oid::RECORD,
1617            ),
1618            Expr::new(
1619                ExprKind::JoinRow(Box::new(JoinRow { alias: None, names: vec![], fields: vec![] })),
1620                oid::RECORD,
1621            ),
1622            Expr::new(ExprKind::MinMax { greatest: true, less: 66, args: vec![var(1)] }, oid::INT4),
1623            Expr::new(ExprKind::NullIf { equal: 65, args: vec![var(1), var(2)] }, oid::INT4),
1624            Expr::new(
1625                ExprKind::RowCompare(Box::new(RowCompare {
1626                    kind: RowCompareKind::LessEqual,
1627                    ops: vec![var(1), var(2)],
1628                    compares: vec![351, 2188],
1629                })),
1630                oid::BOOL,
1631            ),
1632            Expr::new(
1633                ExprKind::Distinct { equal: 65, not: true, args: vec![var(1), var(2)] },
1634                oid::BOOL,
1635            ),
1636            Expr::new(
1637                ExprKind::ScalarArrayOp { func: 65, any: false, args: vec![var(1)] },
1638                oid::BOOL,
1639            ),
1640            Expr::new(
1641                ExprKind::Array { element: oid::INT4, multidims: false, elements: vec![var(1)] },
1642                oid::INT4_ARRAY,
1643            ),
1644            Expr::new(ExprKind::SqlValue(SqlValue::CurrentTimestamp(Some(3))), oid::TIMESTAMPTZ),
1645            Expr::new(ExprKind::SqlValue(SqlValue::CurrentUser), oid::NAME),
1646            Expr::new(ExprKind::Relabel(Box::new(var(1)), CastForm::Explicit), oid::OID)
1647                .at(Some(0)),
1648            Expr::new(ExprKind::CoerceViaIo(Box::new(var(1)), CastForm::Implicit), oid::TEXT),
1649            Expr {
1650                kind: ExprKind::Func(Func {
1651                    oid: 1,
1652                    args: vec![],
1653                    form: FuncForm::ImplicitCast,
1654                    variadic: true,
1655                    retset: false,
1656                }),
1657                ty: oid::VARCHAR,
1658                typmod: 14,
1659                location: None,
1660            },
1661        ];
1662        for node in &nodes {
1663            round_trip(node);
1664        }
1665        let text = write_list(&nodes[..2]).expect("write");
1666        assert!(text.starts_with("({BOOL") && text.ends_with("})"), "{text}");
1667        assert_eq!(read_list(&text).expect("read"), nodes[..2]);
1668        assert_eq!(read_list("()").expect("read"), []);
1669    }
1670
1671    #[test]
1672    fn bad_forms() {
1673        for text in [
1674            "",
1675            "{",
1676            "{CONST}",
1677            "{CONST :type 23 :typmod -1 :location -1 :value (int4 x)}",
1678            "{VAR :type 23} x",
1679            "(\"a)",
1680        ] {
1681            assert!(read(text).is_err(), "{text}");
1682        }
1683        let param = Expr::new(ExprKind::Param(1), oid::INT4);
1684        assert!(write(&param).is_err());
1685    }
1686}