1use 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
15pub fn write(expr: &Expr) -> Result<String> {
21 let mut out = String::new();
22 write_expr(expr, &mut out)?;
23 Ok(out)
24}
25
26pub 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
40pub 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
57pub 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#[derive(Debug)]
73pub enum StoredDatum {
74 MinValue,
76 MaxValue,
78 Value(Expr),
80}
81
82#[derive(Debug)]
84pub enum StoredBound {
85 Default,
87 Hash {
89 modulus: i32,
91 remainder: i32,
93 },
94 List(Vec<Option<Expr>>),
96 Range {
98 lower: Vec<StoredDatum>,
100 upper: Vec<StoredDatum>,
102 },
103}
104
105const BOUND: &str = "PARTITIONBOUNDSPEC";
107
108pub fn is_bound(text: &str) -> bool {
110 text.trim_start().strip_prefix('{').is_some_and(|rest| rest.starts_with(BOUND))
111}
112
113pub 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
144pub 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
199fn 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 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
517const FORMAT_KINDS: [(JsonFormatKind, &str); 3] = [
519 (JsonFormatKind::Default, "default"),
520 (JsonFormatKind::Json, "json"),
521 (JsonFormatKind::Jsonb, "jsonb"),
522];
523
524const ENCODINGS: [(JsonEncoding, &str); 4] = [
526 (JsonEncoding::Default, "default"),
527 (JsonEncoding::Utf8, "utf8"),
528 (JsonEncoding::Utf16, "utf16"),
529 (JsonEncoding::Utf32, "utf32"),
530];
531
532const 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
544const ITEM_TYPES: [(JsonItemType, &str); 4] = [
546 (JsonItemType::Any, "any"),
547 (JsonItemType::Object, "object"),
548 (JsonItemType::Array, "array"),
549 (JsonItemType::Scalar, "scalar"),
550];
551
552const JSON_OPS: [(JsonExprOp, &str); 3] =
554 [(JsonExprOp::Exists, "exists"), (JsonExprOp::Query, "query"), (JsonExprOp::Value, "value")];
555
556const 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
568const WRAPPERS: [(JsonWrapper, &str); 4] = [
570 (JsonWrapper::Unspec, "unspec"),
571 (JsonWrapper::None, "none"),
572 (JsonWrapper::Conditional, "conditional"),
573 (JsonWrapper::Unconditional, "unconditional"),
574];
575
576const 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
589fn 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
601fn 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
615fn 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
623fn 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
650fn 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
666fn 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
723fn 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
731fn 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
854fn 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#[derive(Debug)]
865enum Item {
866 Atom(String),
868 Str(String),
870 List(Vec<Item>),
871 Node(String, Vec<(String, Item)>),
873}
874
875struct Tokens<'a> {
877 text: &'a str,
878 at: usize,
879}
880
881enum 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
973struct 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 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 "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
1310fn 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
1319fn 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 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 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(¶m).is_err());
1685 }
1686}