1use crate::label::{Labels, Matchers, METRIC_NAME};
16use crate::parser::token::{
17 self, token_display, T_BOTTOMK, T_COUNT_VALUES, T_END, T_QUANTILE, T_START, T_TOPK,
18};
19use crate::parser::token::{Token, TokenId, TokenType};
20use crate::parser::value::ValueType;
21use crate::parser::{indent, Function, FunctionArgs, Prettier, MAX_CHARACTERS_PER_LINE};
22use crate::util::{display_duration, escape_string};
23use chrono::{DateTime, Utc};
24use std::fmt::{self, Write};
25use std::ops::Neg;
26use std::sync::Arc;
27use std::time::{Duration, SystemTime};
28
29#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum LabelModifier {
47 Include(Labels),
48 Exclude(Labels),
49}
50
51impl LabelModifier {
52 pub fn labels(&self) -> &Labels {
53 match self {
54 LabelModifier::Include(l) => l,
55 LabelModifier::Exclude(l) => l,
56 }
57 }
58
59 pub fn is_include(&self) -> bool {
60 matches!(*self, LabelModifier::Include(_))
61 }
62
63 pub fn include(ls: Vec<&str>) -> Self {
64 Self::Include(Labels::new(ls))
65 }
66
67 pub fn exclude(ls: Vec<&str>) -> Self {
68 Self::Exclude(Labels::new(ls))
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
75#[cfg_attr(feature = "ser", derive(serde::Serialize))]
76#[cfg_attr(feature = "ser", serde(rename_all = "kebab-case"))]
77pub enum VectorMatchCardinality {
78 OneToOne,
79 ManyToOne(Labels),
80 OneToMany(Labels),
81 ManyToMany, }
83
84impl VectorMatchCardinality {
85 pub fn labels(&self) -> Option<&Labels> {
86 match self {
87 VectorMatchCardinality::ManyToOne(l) => Some(l),
88 VectorMatchCardinality::OneToMany(l) => Some(l),
89 VectorMatchCardinality::ManyToMany => None,
90 VectorMatchCardinality::OneToOne => None,
91 }
92 }
93
94 pub fn many_to_one(ls: Vec<&str>) -> Self {
95 Self::ManyToOne(Labels::new(ls))
96 }
97
98 pub fn one_to_many(ls: Vec<&str>) -> Self {
99 Self::OneToMany(Labels::new(ls))
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Default)]
108#[cfg_attr(feature = "ser", derive(serde::Serialize))]
109pub struct VectorMatchFillValues {
110 pub rhs: Option<f64>,
111 pub lhs: Option<f64>,
112}
113
114impl VectorMatchFillValues {
115 pub fn new(lhs: f64, rhs: f64) -> Self {
116 Self {
117 rhs: Some(rhs),
118 lhs: Some(lhs),
119 }
120 }
121
122 pub fn with_rhs(mut self, rhs: f64) -> Self {
123 self.rhs = Some(rhs);
124 self
125 }
126
127 pub fn with_lhs(mut self, lhs: f64) -> Self {
128 self.lhs = Some(lhs);
129 self
130 }
131}
132
133#[derive(Debug, Clone, PartialEq)]
135pub struct BinModifier {
136 pub card: VectorMatchCardinality,
139
140 pub matching: Option<LabelModifier>,
143 pub return_bool: bool,
145 pub fill_values: VectorMatchFillValues,
148}
149
150impl fmt::Display for BinModifier {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 let mut s = String::from(self.bool_str());
153
154 if let Some(matching) = &self.matching {
155 match matching {
156 LabelModifier::Include(ls) => write!(s, "on ({ls}) ")?,
157 LabelModifier::Exclude(ls) if !ls.is_empty() => write!(s, "ignoring ({ls}) ")?,
158 _ => (),
159 }
160 }
161
162 match &self.card {
163 VectorMatchCardinality::ManyToOne(ls) => write!(s, "group_left ({ls}) ")?,
164 VectorMatchCardinality::OneToMany(ls) => write!(s, "group_right ({ls}) ")?,
165 _ => (),
166 }
167
168 if self.fill_values.rhs.is_some() || self.fill_values.lhs.is_some() {
169 if self.fill_values.rhs == self.fill_values.lhs {
170 let fill_value = self.fill_values.rhs.unwrap();
171 write!(s, "fill ({fill_value}) ")?;
172 } else {
173 if let Some(fill_value) = self.fill_values.lhs {
174 write!(s, "fill_left ({fill_value}) ")?;
175 }
176
177 if let Some(fill_value) = self.fill_values.rhs {
178 write!(s, "fill_right ({fill_value}) ")?;
179 }
180 }
181 }
182
183 if s.trim().is_empty() {
184 write!(f, "")
185 } else {
186 write!(f, " {}", s.trim_end()) }
188 }
189}
190
191impl Default for BinModifier {
192 fn default() -> Self {
193 Self {
194 card: VectorMatchCardinality::OneToOne,
195 matching: None,
196 return_bool: false,
197 fill_values: VectorMatchFillValues::default(),
198 }
199 }
200}
201
202impl BinModifier {
203 pub fn with_card(mut self, card: VectorMatchCardinality) -> Self {
204 self.card = card;
205 self
206 }
207
208 pub fn with_matching(mut self, matching: Option<LabelModifier>) -> Self {
209 self.matching = matching;
210 self
211 }
212
213 pub fn with_return_bool(mut self, return_bool: bool) -> Self {
214 self.return_bool = return_bool;
215 self
216 }
217
218 pub fn with_fill_values(mut self, fill_values: VectorMatchFillValues) -> Self {
219 self.fill_values = fill_values;
220 self
221 }
222
223 pub fn is_labels_joint(&self) -> bool {
224 matches!(
225 (self.card.labels(), &self.matching),
226 (Some(labels), Some(matching)) if labels.is_joint(matching.labels())
227 )
228 }
229
230 pub fn intersect_labels(&self) -> Option<Vec<String>> {
231 if let Some(labels) = self.card.labels() {
232 if let Some(matching) = &self.matching {
233 return Some(labels.intersect(matching.labels()).labels);
234 }
235 };
236 None
237 }
238
239 pub fn is_matching_on(&self) -> bool {
240 matches!(&self.matching, Some(matching) if matching.is_include())
241 }
242
243 pub fn is_matching_labels_not_empty(&self) -> bool {
244 matches!(&self.matching, Some(matching) if !matching.labels().is_empty())
245 }
246
247 pub fn bool_str(&self) -> &str {
248 if self.return_bool {
249 "bool "
250 } else {
251 ""
252 }
253 }
254}
255
256#[cfg(feature = "ser")]
257pub(crate) fn serialize_grouping<S>(
258 this: &Option<LabelModifier>,
259 serializer: S,
260) -> Result<S::Ok, S::Error>
261where
262 S: serde::Serializer,
263{
264 use serde::ser::SerializeMap;
265 let mut map = serializer.serialize_map(Some(2))?;
266 match this {
267 Some(LabelModifier::Include(l)) => {
268 map.serialize_entry("grouping", l)?;
269 map.serialize_entry("without", &false)?;
270 }
271 Some(LabelModifier::Exclude(l)) => {
272 map.serialize_entry("grouping", l)?;
273 map.serialize_entry("without", &true)?;
274 }
275 None => {
276 map.serialize_entry("grouping", &(vec![] as Vec<String>))?;
277 map.serialize_entry("without", &false)?;
278 }
279 }
280
281 map.end()
282}
283
284#[cfg(feature = "ser")]
285pub(crate) fn serialize_bin_modifier<S>(
286 this: &Option<BinModifier>,
287 serializer: S,
288) -> Result<S::Ok, S::Error>
289where
290 S: serde::Serializer,
291{
292 use serde::ser::SerializeMap;
293 use serde_json::json;
294
295 let mut map = serializer.serialize_map(Some(2))?;
296
297 map.serialize_entry(
298 "bool",
299 &this.as_ref().map(|t| t.return_bool).unwrap_or(false),
300 )?;
301 if let Some(t) = this {
302 if let Some(labels) = &t.matching {
303 map.serialize_key("matching")?;
304
305 match labels {
306 LabelModifier::Include(labels) => {
307 let value = json!({
308 "card": t.card,
309 "include": [],
310 "labels": labels,
311 "on": true,
312 "fillValues": t.fill_values,
313 });
314 map.serialize_value(&value)?;
315 }
316 LabelModifier::Exclude(labels) => {
317 let value = json!({
318 "card": t.card,
319 "include": [],
320 "labels": labels,
321 "on": false,
322 "fillValues": t.fill_values,
323 });
324 map.serialize_value(&value)?;
325 }
326 }
327 } else {
328 let value = json!({
329 "card": t.card,
330 "include": [],
331 "labels": [],
332 "on": false,
333 "fillValues": t.fill_values,
334 });
335 map.serialize_entry("matching", &value)?;
336 }
337 } else {
338 map.serialize_entry("matching", &None::<bool>)?;
339 }
340
341 map.end()
342}
343
344#[cfg(feature = "ser")]
345pub(crate) fn serialize_at_modifier<S>(
346 this: &Option<AtModifier>,
347 serializer: S,
348) -> Result<S::Ok, S::Error>
349where
350 S: serde::Serializer,
351{
352 use serde::ser::SerializeMap;
353 let mut map = serializer.serialize_map(Some(2))?;
354 match this {
355 Some(AtModifier::Start) => {
356 map.serialize_entry("startOrEnd", &Some("start"))?;
357 map.serialize_entry("timestamp", &None::<u128>)?;
358 }
359 Some(AtModifier::End) => {
360 map.serialize_entry("startOrEnd", &Some("end"))?;
361 map.serialize_entry("timestamp", &None::<u128>)?;
362 }
363 Some(AtModifier::At(time)) => {
364 map.serialize_entry("startOrEnd", &None::<&str>)?;
365 map.serialize_entry(
366 "timestamp",
367 &time
368 .duration_since(SystemTime::UNIX_EPOCH)
369 .unwrap_or(Duration::ZERO)
370 .as_millis(),
371 )?;
372 }
373 None => {
374 map.serialize_entry("startOrEnd", &None::<&str>)?;
375 map.serialize_entry("timestamp", &None::<u128>)?;
376 }
377 }
378
379 map.end()
380}
381
382#[derive(Debug, Clone, PartialEq)]
383pub enum Offset {
384 Pos(Duration),
385 Neg(Duration),
386}
387
388impl Offset {
389 #[cfg(feature = "ser")]
390 pub(crate) fn as_millis(&self) -> i128 {
391 match self {
392 Self::Pos(dur) => dur.as_millis() as i128,
393 Self::Neg(dur) => -(dur.as_millis() as i128),
394 }
395 }
396
397 #[cfg(feature = "ser")]
398 pub(crate) fn serialize_offset<S>(
399 offset: &Option<Self>,
400 serializer: S,
401 ) -> Result<S::Ok, S::Error>
402 where
403 S: serde::Serializer,
404 {
405 let value = offset.as_ref().map(|o| o.as_millis()).unwrap_or(0);
406 serializer.serialize_i128(value)
407 }
408}
409
410impl fmt::Display for Offset {
411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412 match self {
413 Offset::Pos(dur) => write!(f, "{}", display_duration(dur)),
414 Offset::Neg(dur) => write!(f, "-{}", display_duration(dur)),
415 }
416 }
417}
418
419#[derive(Debug, Clone, PartialEq)]
420pub enum AtModifier {
421 Start,
422 End,
423 At(SystemTime),
425}
426
427impl fmt::Display for AtModifier {
428 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429 match self {
430 AtModifier::Start => write!(f, "@ {}()", token_display(T_START)),
431 AtModifier::End => write!(f, "@ {}()", token_display(T_END)),
432 AtModifier::At(time) => {
433 let d = time
434 .duration_since(SystemTime::UNIX_EPOCH)
435 .unwrap_or(Duration::ZERO); write!(f, "@ {:.3}", d.as_secs_f64())
437 }
438 }
439 }
440}
441
442impl TryFrom<TokenId> for AtModifier {
443 type Error = String;
444
445 fn try_from(id: TokenId) -> Result<Self, Self::Error> {
446 match id {
447 T_START => Ok(AtModifier::Start),
448 T_END => Ok(AtModifier::End),
449 _ => Err(format!(
450 "invalid @ modifier preprocessor '{}', START or END is valid.",
451 token::token_display(id)
452 )),
453 }
454 }
455}
456
457impl TryFrom<Token> for AtModifier {
458 type Error = String;
459
460 fn try_from(token: Token) -> Result<Self, Self::Error> {
461 AtModifier::try_from(token.id())
462 }
463}
464
465impl TryFrom<NumberLiteral> for AtModifier {
466 type Error = String;
467
468 fn try_from(num: NumberLiteral) -> Result<Self, Self::Error> {
469 AtModifier::try_from(num.val)
470 }
471}
472
473impl TryFrom<Expr> for AtModifier {
474 type Error = String;
475
476 fn try_from(ex: Expr) -> Result<Self, Self::Error> {
477 match ex {
478 Expr::NumberLiteral(nl) => AtModifier::try_from(nl),
479 _ => Err("invalid float value after @ modifier".into()),
480 }
481 }
482}
483
484impl TryFrom<f64> for AtModifier {
485 type Error = String;
486
487 fn try_from(secs: f64) -> Result<Self, Self::Error> {
488 let err_info = format!("timestamp out of bounds for @ modifier: {secs}");
489
490 if secs.is_nan() || secs.is_infinite() || secs >= f64::MAX || secs <= f64::MIN {
491 return Err(err_info);
492 }
493 let milli = (secs * 1000f64).round().abs() as u64;
494
495 let duration = Duration::from_millis(milli);
496 let mut st = Some(SystemTime::UNIX_EPOCH);
497 if secs.is_sign_positive() {
498 st = SystemTime::UNIX_EPOCH.checked_add(duration);
499 }
500 if secs.is_sign_negative() {
501 st = SystemTime::UNIX_EPOCH.checked_sub(duration);
502 }
503
504 st.map(Self::At).ok_or(err_info)
505 }
506}
507
508#[allow(rustdoc::broken_intra_doc_links)]
511#[derive(Debug, Clone)]
512pub struct EvalStmt {
513 pub expr: Expr,
515
516 pub start: SystemTime,
519 pub end: SystemTime,
520 pub interval: Duration,
522 pub lookback_delta: Duration,
524}
525
526impl fmt::Display for EvalStmt {
527 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
528 write!(
529 f,
530 "[{}] @ [{}, {}, {}, {}]",
531 self.expr,
532 DateTime::<Utc>::from(self.start).to_rfc3339(),
533 DateTime::<Utc>::from(self.end).to_rfc3339(),
534 display_duration(&self.interval),
535 display_duration(&self.lookback_delta)
536 )
537 }
538}
539
540#[derive(Debug, Clone, PartialEq)]
548#[cfg_attr(feature = "ser", derive(serde::Serialize))]
549pub struct AggregateExpr {
550 pub op: TokenType,
552 pub expr: Box<Expr>,
554 pub param: Option<Box<Expr>>,
556 #[cfg_attr(feature = "ser", serde(flatten))]
558 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_grouping"))]
559 pub modifier: Option<LabelModifier>,
560}
561
562impl AggregateExpr {
563 fn get_op_string(&self) -> String {
564 let mut s = self.op.to_string();
565
566 if let Some(modifier) = &self.modifier {
567 match modifier {
568 LabelModifier::Exclude(ls) => write!(s, " without ({ls}) ").unwrap(),
569 LabelModifier::Include(ls) if !ls.is_empty() => write!(s, " by ({ls}) ").unwrap(),
570 _ => (),
571 }
572 }
573 s
574 }
575}
576
577impl fmt::Display for AggregateExpr {
578 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579 write!(f, "{}", self.get_op_string())?;
580
581 write!(f, "(")?;
582 if let Some(param) = &self.param {
583 write!(f, "{param}, ")?;
584 }
585 write!(f, "{})", self.expr)?;
586
587 Ok(())
588 }
589}
590
591impl Prettier for AggregateExpr {
592 fn format(&self, level: usize, max: usize) -> String {
593 let mut s = format!("{}{}(\n", indent(level), self.get_op_string());
594 if let Some(param) = &self.param {
595 writeln!(s, "{},", param.pretty(level + 1, max)).unwrap();
596 }
597 writeln!(s, "{}", self.expr.pretty(level + 1, max)).unwrap();
598 write!(s, "{})", indent(level)).unwrap();
599 s
600 }
601}
602
603#[derive(Debug, Clone, PartialEq)]
605pub struct UnaryExpr {
606 pub expr: Box<Expr>,
607}
608
609impl fmt::Display for UnaryExpr {
610 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
611 write!(f, "-{}", self.expr)
612 }
613}
614
615impl Prettier for UnaryExpr {
616 fn pretty(&self, level: usize, max: usize) -> String {
617 format!(
618 "{}-{}",
619 indent(level),
620 self.expr.pretty(level, max).trim_start()
621 )
622 }
623}
624
625#[cfg(feature = "ser")]
626impl serde::Serialize for UnaryExpr {
627 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
628 where
629 S: serde::Serializer,
630 {
631 use serde::ser::SerializeMap;
632 let mut map = serializer.serialize_map(Some(2))?;
633 map.serialize_entry("op", "-")?;
634 map.serialize_entry("expr", &self.expr)?;
635
636 map.end()
637 }
638}
639
640#[derive(Debug, Clone, PartialEq)]
648#[cfg_attr(feature = "ser", derive(serde::Serialize))]
649pub struct BinaryExpr {
650 pub op: TokenType,
652 pub lhs: Box<Expr>,
654 pub rhs: Box<Expr>,
656 #[cfg_attr(feature = "ser", serde(flatten))]
657 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_bin_modifier"))]
658 pub modifier: Option<BinModifier>,
659}
660
661impl BinaryExpr {
662 pub fn is_matching_on(&self) -> bool {
663 matches!(&self.modifier, Some(modifier) if modifier.is_matching_on())
664 }
665
666 pub fn is_matching_labels_not_empty(&self) -> bool {
667 matches!(&self.modifier, Some(modifier) if modifier.is_matching_labels_not_empty())
668 }
669
670 pub fn return_bool(&self) -> bool {
671 matches!(&self.modifier, Some(modifier) if modifier.return_bool)
672 }
673
674 pub fn is_labels_joint(&self) -> bool {
676 matches!(&self.modifier, Some(modifier) if modifier.is_labels_joint())
677 }
678
679 pub fn intersect_labels(&self) -> Option<Vec<String>> {
681 self.modifier
682 .as_ref()
683 .and_then(|modifier| modifier.intersect_labels())
684 }
685
686 fn get_op_matching_string(&self) -> String {
687 match &self.modifier {
688 Some(modifier) => format!("{}{modifier}", self.op),
689 None => self.op.to_string(),
690 }
691 }
692}
693
694impl fmt::Display for BinaryExpr {
695 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
696 write!(
697 f,
698 "{} {} {}",
699 self.lhs,
700 self.get_op_matching_string(),
701 self.rhs
702 )
703 }
704}
705
706impl Prettier for BinaryExpr {
707 fn format(&self, level: usize, max: usize) -> String {
708 format!(
709 "{}\n{}{}\n{}",
710 self.lhs.pretty(level + 1, max),
711 indent(level),
712 self.get_op_matching_string(),
713 self.rhs.pretty(level + 1, max)
714 )
715 }
716}
717
718#[derive(Debug, Clone, PartialEq)]
719#[cfg_attr(feature = "ser", derive(serde::Serialize))]
720pub struct ParenExpr {
721 pub expr: Box<Expr>,
722}
723
724impl fmt::Display for ParenExpr {
725 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
726 write!(f, "({})", self.expr)
727 }
728}
729
730impl Prettier for ParenExpr {
731 fn format(&self, level: usize, max: usize) -> String {
732 format!(
733 "{}(\n{}\n{})",
734 indent(level),
735 self.expr.pretty(level + 1, max),
736 indent(level)
737 )
738 }
739}
740
741#[derive(Debug, Clone, PartialEq)]
746#[cfg_attr(feature = "ser", derive(serde::Serialize))]
747pub struct SubqueryExpr {
748 pub expr: Box<Expr>,
749 #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
750 pub offset: Option<Offset>,
751 #[cfg_attr(feature = "ser", serde(flatten))]
752 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
753 pub at: Option<AtModifier>,
754 #[cfg_attr(
755 feature = "ser",
756 serde(serialize_with = "crate::util::duration::serialize_duration")
757 )]
758 pub range: Duration,
759 #[cfg_attr(
761 feature = "ser",
762 serde(serialize_with = "crate::util::duration::serialize_duration_opt")
763 )]
764 pub step: Option<Duration>,
765}
766
767impl SubqueryExpr {
768 fn get_time_suffix_string(&self) -> String {
769 let step = match &self.step {
770 Some(step) => display_duration(step),
771 None => String::from(""),
772 };
773 let range = display_duration(&self.range);
774
775 let mut s = format!("[{range}:{step}]");
776
777 if let Some(at) = &self.at {
778 write!(s, " {at}").unwrap();
779 }
780
781 if let Some(offset) = &self.offset {
782 write!(s, " offset {offset}").unwrap();
783 }
784 s
785 }
786}
787
788impl fmt::Display for SubqueryExpr {
789 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790 write!(f, "{}{}", self.expr, self.get_time_suffix_string())
791 }
792}
793
794impl Prettier for SubqueryExpr {
795 fn pretty(&self, level: usize, max: usize) -> String {
796 format!(
797 "{}{}",
798 self.expr.pretty(level, max),
799 self.get_time_suffix_string()
800 )
801 }
802}
803
804#[derive(Debug, Clone)]
805pub struct NumberLiteral {
806 pub val: f64,
807}
808
809impl NumberLiteral {
810 pub fn new(val: f64) -> Self {
811 Self { val }
812 }
813}
814
815impl PartialEq for NumberLiteral {
816 fn eq(&self, other: &Self) -> bool {
817 self.val == other.val || self.val.is_nan() && other.val.is_nan()
818 }
819}
820
821impl Eq for NumberLiteral {}
822
823impl Neg for NumberLiteral {
824 type Output = Self;
825
826 fn neg(self) -> Self::Output {
827 NumberLiteral { val: -self.val }
828 }
829}
830
831impl fmt::Display for NumberLiteral {
832 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
833 if self.val == f64::INFINITY {
834 write!(f, "Inf")
835 } else if self.val == f64::NEG_INFINITY {
836 write!(f, "-Inf")
837 } else if f64::is_nan(self.val) {
838 write!(f, "NaN")
839 } else {
840 write!(f, "{}", self.val)
841 }
842 }
843}
844
845#[cfg(feature = "ser")]
846impl serde::Serialize for NumberLiteral {
847 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
848 where
849 S: serde::Serializer,
850 {
851 use serde::ser::SerializeMap;
852 let mut map = serializer.serialize_map(Some(1))?;
853 map.serialize_entry("val", &self.to_string())?;
854
855 map.end()
856 }
857}
858
859impl Prettier for NumberLiteral {
860 fn needs_split(&self, _max: usize) -> bool {
861 false
862 }
863}
864
865#[derive(Debug, Clone, PartialEq)]
866#[cfg_attr(feature = "ser", derive(serde::Serialize))]
867pub struct StringLiteral {
868 pub val: String,
869}
870
871impl fmt::Display for StringLiteral {
872 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
873 write!(f, "\"{}\"", escape_string(&self.val))
874 }
875}
876
877impl Prettier for StringLiteral {
878 fn needs_split(&self, _max: usize) -> bool {
879 false
880 }
881}
882
883#[derive(Debug, Clone, PartialEq)]
884#[cfg_attr(feature = "ser", derive(serde::Serialize))]
885pub struct VectorSelector {
886 pub name: Option<String>,
887 #[cfg_attr(feature = "ser", serde(flatten))]
888 pub matchers: Matchers,
889 #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
890 pub offset: Option<Offset>,
891 #[cfg_attr(feature = "ser", serde(flatten))]
892 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
893 pub at: Option<AtModifier>,
894}
895
896impl VectorSelector {
897 pub fn new(name: Option<String>, matchers: Matchers) -> Self {
898 VectorSelector {
899 name,
900 matchers,
901 offset: None,
902 at: None,
903 }
904 }
905}
906
907impl Default for VectorSelector {
908 fn default() -> Self {
909 Self {
910 name: None,
911 matchers: Matchers::empty(),
912 offset: None,
913 at: None,
914 }
915 }
916}
917
918impl From<String> for VectorSelector {
919 fn from(name: String) -> Self {
920 VectorSelector {
921 name: Some(name),
922 offset: None,
923 at: None,
924 matchers: Matchers::empty(),
925 }
926 }
927}
928
929impl From<&str> for VectorSelector {
949 fn from(name: &str) -> Self {
950 VectorSelector::from(name.to_string())
951 }
952}
953
954impl Neg for VectorSelector {
955 type Output = UnaryExpr;
956
957 fn neg(self) -> Self::Output {
958 let ex = Expr::VectorSelector(self);
959 UnaryExpr { expr: Box::new(ex) }
960 }
961}
962
963impl fmt::Display for VectorSelector {
964 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
965 if let Some(name) = &self.name {
966 write!(f, "{name}")?;
967 }
968 let matchers = &self.matchers.to_string();
969 if !matchers.is_empty() {
970 write!(f, "{{{matchers}}}")?;
971 }
972 if let Some(at) = &self.at {
973 write!(f, " {at}")?;
974 }
975 if let Some(offset) = &self.offset {
976 write!(f, " offset {offset}")?;
977 }
978 Ok(())
979 }
980}
981
982impl Prettier for VectorSelector {
983 fn needs_split(&self, _max: usize) -> bool {
984 false
985 }
986}
987
988#[derive(Debug, Clone, PartialEq)]
989#[cfg_attr(feature = "ser", derive(serde::Serialize))]
990pub struct MatrixSelector {
991 #[cfg_attr(feature = "ser", serde(flatten))]
992 pub vs: VectorSelector,
993 #[cfg_attr(
994 feature = "ser",
995 serde(serialize_with = "crate::util::duration::serialize_duration")
996 )]
997 pub range: Duration,
998}
999
1000impl fmt::Display for MatrixSelector {
1001 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1002 if let Some(name) = &self.vs.name {
1003 write!(f, "{name}")?;
1004 }
1005
1006 let matchers = &self.vs.matchers.to_string();
1007 if !matchers.is_empty() {
1008 write!(f, "{{{matchers}}}")?;
1009 }
1010
1011 write!(f, "[{}]", display_duration(&self.range))?;
1012
1013 if let Some(at) = &self.vs.at {
1014 write!(f, " {at}")?;
1015 }
1016
1017 if let Some(offset) = &self.vs.offset {
1018 write!(f, " offset {offset}")?;
1019 }
1020
1021 Ok(())
1022 }
1023}
1024
1025impl Prettier for MatrixSelector {
1026 fn needs_split(&self, _max: usize) -> bool {
1027 false
1028 }
1029}
1030
1031#[derive(Debug, Clone, PartialEq)]
1071#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1072pub struct Call {
1073 pub func: Function,
1074 #[cfg_attr(feature = "ser", serde(flatten))]
1075 pub args: FunctionArgs,
1076}
1077
1078impl fmt::Display for Call {
1079 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1080 write!(f, "{}({})", self.func.name, self.args)
1081 }
1082}
1083
1084impl Prettier for Call {
1085 fn format(&self, level: usize, max: usize) -> String {
1086 format!(
1087 "{}{}(\n{}\n{})",
1088 indent(level),
1089 self.func.name,
1090 self.args.pretty(level + 1, max),
1091 indent(level)
1092 )
1093 }
1094}
1095
1096#[derive(Debug, Clone)]
1098pub struct Extension {
1099 pub expr: Arc<dyn ExtensionExpr>,
1100}
1101
1102pub trait ExtensionExpr: std::fmt::Debug + Send + Sync {
1104 fn as_any(&self) -> &dyn std::any::Any;
1105
1106 fn name(&self) -> &str;
1107
1108 fn value_type(&self) -> ValueType;
1109
1110 fn children(&self) -> &[Expr];
1111
1112 fn with_new_children(&self, children: Vec<Expr>) -> Arc<dyn ExtensionExpr>;
1113}
1114
1115impl PartialEq for Extension {
1116 fn eq(&self, other: &Self) -> bool {
1117 format!("{self:?}") == format!("{other:?}")
1118 }
1119}
1120
1121impl Eq for Extension {}
1122
1123#[derive(Debug, Clone, PartialEq)]
1124#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1125#[cfg_attr(feature = "ser", serde(tag = "type", rename_all = "camelCase"))]
1126pub enum Expr {
1127 #[cfg_attr(feature = "ser", serde(rename = "aggregation"))]
1129 Aggregate(AggregateExpr),
1130
1131 #[cfg_attr(feature = "ser", serde(rename = "unaryExpr"))]
1134 Unary(UnaryExpr),
1135
1136 #[cfg_attr(feature = "ser", serde(rename = "binaryExpr"))]
1138 Binary(BinaryExpr),
1139
1140 #[cfg_attr(feature = "ser", serde(rename = "parenExpr"))]
1143 Paren(ParenExpr),
1144
1145 Subquery(SubqueryExpr),
1147
1148 NumberLiteral(NumberLiteral),
1150
1151 StringLiteral(StringLiteral),
1153
1154 VectorSelector(VectorSelector),
1156
1157 MatrixSelector(MatrixSelector),
1159
1160 Call(Call),
1162
1163 #[cfg_attr(feature = "ser", serde(skip))]
1166 Extension(Extension),
1167}
1168
1169impl Expr {
1170 pub(crate) fn new_vector_selector(
1171 name: Option<String>,
1172 matchers: Matchers,
1173 ) -> Result<Self, String> {
1174 let vs = VectorSelector::new(name, matchers);
1175 Ok(Self::VectorSelector(vs))
1176 }
1177
1178 pub(crate) fn new_unary_expr(expr: Expr) -> Result<Self, String> {
1179 match expr {
1180 Expr::StringLiteral(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: string".into()),
1181 Expr::MatrixSelector(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: matrix".into()),
1182 _ => Ok(-expr),
1183 }
1184 }
1185
1186 pub(crate) fn new_subquery_expr(
1187 expr: Expr,
1188 range: Duration,
1189 step: Option<Duration>,
1190 ) -> Result<Self, String> {
1191 let se = Expr::Subquery(SubqueryExpr {
1192 expr: Box::new(expr),
1193 offset: None,
1194 at: None,
1195 range,
1196 step,
1197 });
1198 Ok(se)
1199 }
1200
1201 pub(crate) fn new_paren_expr(expr: Expr) -> Result<Self, String> {
1202 let ex = Expr::Paren(ParenExpr {
1203 expr: Box::new(expr),
1204 });
1205 Ok(ex)
1206 }
1207
1208 pub(crate) fn new_matrix_selector(expr: Expr, range: Duration) -> Result<Self, String> {
1210 match expr {
1211 Expr::VectorSelector(VectorSelector {
1212 offset: Some(_), ..
1213 }) => Err("no offset modifiers allowed before range".into()),
1214 Expr::VectorSelector(VectorSelector { at: Some(_), .. }) => {
1215 Err("no @ modifiers allowed before range".into())
1216 }
1217 Expr::VectorSelector(vs) => {
1218 let ms = Expr::MatrixSelector(MatrixSelector { vs, range });
1219 Ok(ms)
1220 }
1221 _ => Err("ranges only allowed for vector selectors".into()),
1222 }
1223 }
1224
1225 pub(crate) fn at_expr(self, at: AtModifier) -> Result<Self, String> {
1226 let already_set_err = Err("@ <timestamp> may not be set multiple times".into());
1227 match self {
1228 Expr::VectorSelector(mut vs) => match vs.at {
1229 None => {
1230 vs.at = Some(at);
1231 Ok(Expr::VectorSelector(vs))
1232 }
1233 Some(_) => already_set_err,
1234 },
1235 Expr::MatrixSelector(mut ms) => match ms.vs.at {
1236 None => {
1237 ms.vs.at = Some(at);
1238 Ok(Expr::MatrixSelector(ms))
1239 }
1240 Some(_) => already_set_err,
1241 },
1242 Expr::Subquery(mut s) => match s.at {
1243 None => {
1244 s.at = Some(at);
1245 Ok(Expr::Subquery(s))
1246 }
1247 Some(_) => already_set_err,
1248 },
1249 _ => {
1250 Err("@ modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1251 }
1252 }
1253 }
1254
1255 pub(crate) fn offset_expr(self, offset: Offset) -> Result<Self, String> {
1257 let already_set_err = Err("offset may not be set multiple times".into());
1258 match self {
1259 Expr::VectorSelector(mut vs) => match vs.offset {
1260 None => {
1261 vs.offset = Some(offset);
1262 Ok(Expr::VectorSelector(vs))
1263 }
1264 Some(_) => already_set_err,
1265 },
1266 Expr::MatrixSelector(mut ms) => match ms.vs.offset {
1267 None => {
1268 ms.vs.offset = Some(offset);
1269 Ok(Expr::MatrixSelector(ms))
1270 }
1271 Some(_) => already_set_err,
1272 },
1273 Expr::Subquery(mut s) => match s.offset {
1274 None => {
1275 s.offset = Some(offset);
1276 Ok(Expr::Subquery(s))
1277 }
1278 Some(_) => already_set_err,
1279 },
1280 _ => {
1281 Err("offset modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1282 }
1283 }
1284 }
1285
1286 pub(crate) fn new_call(func: Function, args: FunctionArgs) -> Result<Expr, String> {
1287 Ok(Expr::Call(Call { func, args }))
1288 }
1289
1290 pub(crate) fn new_binary_expr(
1291 lhs: Expr,
1292 op: TokenId,
1293 modifier: Option<BinModifier>,
1294 rhs: Expr,
1295 ) -> Result<Expr, String> {
1296 let ex = BinaryExpr {
1297 op: TokenType::new(op),
1298 lhs: Box::new(lhs),
1299 rhs: Box::new(rhs),
1300 modifier,
1301 };
1302 Ok(Expr::Binary(ex))
1303 }
1304
1305 pub(crate) fn new_aggregate_expr(
1306 op: TokenId,
1307 modifier: Option<LabelModifier>,
1308 args: FunctionArgs,
1309 ) -> Result<Expr, String> {
1310 let op = TokenType::new(op);
1311 if args.is_empty() {
1312 return Err(format!(
1313 "no arguments for aggregate expression '{op}' provided"
1314 ));
1315 }
1316 let mut desired_args_count = 1;
1317 let mut param = None;
1318 if op.is_aggregator_with_param() {
1319 desired_args_count = 2;
1320 param = args.first();
1321 }
1322 if args.len() != desired_args_count {
1323 return Err(format!(
1324 "wrong number of arguments for aggregate expression provided, expected {}, got {}",
1325 desired_args_count,
1326 args.len()
1327 ));
1328 }
1329
1330 match args.last() {
1331 Some(expr) => Ok(Expr::Aggregate(AggregateExpr {
1332 op,
1333 expr,
1334 param,
1335 modifier,
1336 })),
1337 None => Err(
1338 "aggregate operation needs a single instant vector parameter, but found none"
1339 .into(),
1340 ),
1341 }
1342 }
1343
1344 pub fn value_type(&self) -> ValueType {
1345 match self {
1346 Expr::Aggregate(_) => ValueType::Vector,
1347 Expr::Unary(ex) => ex.expr.value_type(),
1348 Expr::Binary(ex) => {
1349 if ex.lhs.value_type() == ValueType::Scalar
1350 && ex.rhs.value_type() == ValueType::Scalar
1351 {
1352 ValueType::Scalar
1353 } else {
1354 ValueType::Vector
1355 }
1356 }
1357 Expr::Paren(ex) => ex.expr.value_type(),
1358 Expr::Subquery(_) => ValueType::Matrix,
1359 Expr::NumberLiteral(_) => ValueType::Scalar,
1360 Expr::StringLiteral(_) => ValueType::String,
1361 Expr::VectorSelector(_) => ValueType::Vector,
1362 Expr::MatrixSelector(_) => ValueType::Matrix,
1363 Expr::Call(ex) => ex.func.return_type,
1364 Expr::Extension(ex) => ex.expr.value_type(),
1365 }
1366 }
1367
1368 pub(crate) fn scalar_value(&self) -> Option<f64> {
1370 match self {
1371 Expr::NumberLiteral(nl) => Some(nl.val),
1372 _ => None,
1373 }
1374 }
1375
1376 pub fn prettify(&self) -> String {
1377 self.pretty(0, MAX_CHARACTERS_PER_LINE)
1378 }
1379}
1380
1381impl From<String> for Expr {
1382 fn from(val: String) -> Self {
1383 Expr::StringLiteral(StringLiteral { val })
1384 }
1385}
1386
1387impl From<&str> for Expr {
1388 fn from(s: &str) -> Self {
1389 Expr::StringLiteral(StringLiteral { val: s.into() })
1390 }
1391}
1392
1393impl From<f64> for Expr {
1394 fn from(val: f64) -> Self {
1395 Expr::NumberLiteral(NumberLiteral { val })
1396 }
1397}
1398
1399impl From<VectorSelector> for Expr {
1415 fn from(vs: VectorSelector) -> Self {
1416 Expr::VectorSelector(vs)
1417 }
1418}
1419
1420impl Neg for Expr {
1421 type Output = Self;
1422
1423 fn neg(self) -> Self::Output {
1424 match self {
1425 Expr::NumberLiteral(nl) => Expr::NumberLiteral(-nl),
1426 _ => Expr::Unary(UnaryExpr {
1427 expr: Box::new(self),
1428 }),
1429 }
1430 }
1431}
1432
1433impl fmt::Display for Expr {
1434 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1435 match self {
1436 Expr::Aggregate(ex) => write!(f, "{ex}"),
1437 Expr::Unary(ex) => write!(f, "{ex}"),
1438 Expr::Binary(ex) => write!(f, "{ex}"),
1439 Expr::Paren(ex) => write!(f, "{ex}"),
1440 Expr::Subquery(ex) => write!(f, "{ex}"),
1441 Expr::NumberLiteral(ex) => write!(f, "{ex}"),
1442 Expr::StringLiteral(ex) => write!(f, "{ex}"),
1443 Expr::VectorSelector(ex) => write!(f, "{ex}"),
1444 Expr::MatrixSelector(ex) => write!(f, "{ex}"),
1445 Expr::Call(ex) => write!(f, "{ex}"),
1446 Expr::Extension(ext) => write!(f, "{ext:?}"),
1447 }
1448 }
1449}
1450
1451impl Prettier for Expr {
1452 fn pretty(&self, level: usize, max: usize) -> String {
1453 match self {
1454 Expr::Aggregate(ex) => ex.pretty(level, max),
1455 Expr::Unary(ex) => ex.pretty(level, max),
1456 Expr::Binary(ex) => ex.pretty(level, max),
1457 Expr::Paren(ex) => ex.pretty(level, max),
1458 Expr::Subquery(ex) => ex.pretty(level, max),
1459 Expr::NumberLiteral(ex) => ex.pretty(level, max),
1460 Expr::StringLiteral(ex) => ex.pretty(level, max),
1461 Expr::VectorSelector(ex) => ex.pretty(level, max),
1462 Expr::MatrixSelector(ex) => ex.pretty(level, max),
1463 Expr::Call(ex) => ex.pretty(level, max),
1464 Expr::Extension(ext) => format!("{ext:?}"),
1465 }
1466 }
1467}
1468
1469pub(crate) fn check_ast(expr: Expr) -> Result<Expr, String> {
1472 match expr {
1473 Expr::Binary(ex) => check_ast_for_binary_expr(ex),
1474 Expr::Aggregate(ex) => check_ast_for_aggregate_expr(ex),
1475 Expr::Call(ex) => check_ast_for_call(ex),
1476 Expr::Unary(ex) => check_ast_for_unary(ex),
1477 Expr::Subquery(ex) => check_ast_for_subquery(ex),
1478 Expr::VectorSelector(ex) => check_ast_for_vector_selector(ex),
1479 Expr::Paren(_) => Ok(expr),
1480 Expr::NumberLiteral(_) => Ok(expr),
1481 Expr::StringLiteral(_) => Ok(expr),
1482 Expr::MatrixSelector(_) => Ok(expr),
1483 Expr::Extension(_) => Ok(expr),
1484 }
1485}
1486
1487fn expect_type(
1488 expected: ValueType,
1489 actual: Option<ValueType>,
1490 context: &str,
1491) -> Result<bool, String> {
1492 match actual {
1493 Some(actual) => {
1494 if actual == expected {
1495 Ok(true)
1496 } else {
1497 Err(format!(
1498 "expected type {expected} in {context}, got {actual}"
1499 ))
1500 }
1501 }
1502 None => Err(format!("expected type {expected} in {context}, got None")),
1503 }
1504}
1505
1506fn check_ast_for_binary_expr(mut ex: BinaryExpr) -> Result<Expr, String> {
1509 if !ex.op.is_operator() {
1510 return Err(format!(
1511 "binary expression does not support operator '{}'",
1512 ex.op
1513 ));
1514 }
1515
1516 if ex.return_bool() && !ex.op.is_comparison_operator() {
1517 return Err("bool modifier can only be used on comparison operators".into());
1518 }
1519
1520 if ex.op.is_comparison_operator()
1521 && ex.lhs.value_type() == ValueType::Scalar
1522 && ex.rhs.value_type() == ValueType::Scalar
1523 && !ex.return_bool()
1524 {
1525 return Err("comparisons between scalars must use BOOL modifier".into());
1526 }
1527
1528 if ex.is_matching_on() && ex.is_labels_joint() {
1531 if let Some(labels) = ex.intersect_labels() {
1532 if let Some(label) = labels.first() {
1533 return Err(format!(
1534 "label '{label}' must not occur in ON and GROUP clause at once"
1535 ));
1536 }
1537 };
1538 }
1539
1540 if ex.op.is_set_operator() {
1541 if ex.lhs.value_type() == ValueType::Scalar || ex.rhs.value_type() == ValueType::Scalar {
1542 return Err(format!(
1543 "set operator '{}' not allowed in binary scalar expression",
1544 ex.op
1545 ));
1546 }
1547
1548 if ex.lhs.value_type() == ValueType::Vector && ex.rhs.value_type() == ValueType::Vector {
1549 if let Some(ref modifier) = ex.modifier {
1550 if matches!(modifier.card, VectorMatchCardinality::OneToMany(_))
1551 || matches!(modifier.card, VectorMatchCardinality::ManyToOne(_))
1552 {
1553 return Err(format!("no grouping allowed for '{}' operation", ex.op));
1554 }
1555 };
1556 }
1557
1558 match &mut ex.modifier {
1559 Some(modifier) => {
1560 if modifier.card == VectorMatchCardinality::OneToOne {
1561 modifier.card = VectorMatchCardinality::ManyToMany;
1562 }
1563 }
1564 None => {
1565 ex.modifier =
1566 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany));
1567 }
1568 }
1569 }
1570
1571 if ex.lhs.value_type() != ValueType::Scalar && ex.lhs.value_type() != ValueType::Vector {
1572 return Err("binary expression must contain only scalar and instant vector types".into());
1573 }
1574 if ex.rhs.value_type() != ValueType::Scalar && ex.rhs.value_type() != ValueType::Vector {
1575 return Err("binary expression must contain only scalar and instant vector types".into());
1576 }
1577
1578 if (ex.lhs.value_type() != ValueType::Vector || ex.rhs.value_type() != ValueType::Vector)
1579 && ex.is_matching_labels_not_empty()
1580 {
1581 return Err("vector matching only allowed between vectors".into());
1582 }
1583
1584 Ok(Expr::Binary(ex))
1585}
1586
1587fn check_ast_for_aggregate_expr(ex: AggregateExpr) -> Result<Expr, String> {
1588 if !ex.op.is_aggregator() {
1589 return Err(format!(
1590 "aggregation operator expected in aggregation expression but got '{}'",
1591 ex.op
1592 ));
1593 }
1594
1595 expect_type(
1596 ValueType::Vector,
1597 Some(ex.expr.value_type()),
1598 "aggregation expression",
1599 )?;
1600
1601 if matches!(ex.op.id(), T_TOPK | T_BOTTOMK | T_QUANTILE) {
1602 expect_type(
1603 ValueType::Scalar,
1604 ex.param.as_ref().map(|ex| ex.value_type()),
1605 "aggregation expression",
1606 )?;
1607 }
1608
1609 if ex.op.id() == T_COUNT_VALUES {
1610 expect_type(
1611 ValueType::String,
1612 ex.param.as_ref().map(|ex| ex.value_type()),
1613 "aggregation expression",
1614 )?;
1615 }
1616
1617 Ok(Expr::Aggregate(ex))
1618}
1619
1620fn check_ast_for_call(ex: Call) -> Result<Expr, String> {
1621 let name = ex.func.name;
1622
1623 check_call_arity(
1624 ex.func.arg_types.len(),
1625 ex.func.variadic,
1626 ex.args.len(),
1627 name,
1628 )?;
1629
1630 if name.eq("exp") {
1632 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1633 if val.is_nan() || val.is_infinite() {
1634 return Ok(Expr::Call(ex));
1635 }
1636 }
1637 } else if name.eq("ln") || name.eq("log2") || name.eq("log10") {
1638 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1639 if val.is_nan() || val.is_infinite() || val <= 0.0 {
1640 return Ok(Expr::Call(ex));
1641 }
1642 }
1643 }
1644
1645 check_args_match_types(&ex.args.args, &ex.func.arg_types, name)?;
1646 Ok(Expr::Call(ex))
1647}
1648
1649fn check_call_arity(nargs: usize, variadic: i32, actual: usize, name: &str) -> Result<(), String> {
1650 if variadic == 0 {
1651 if nargs != actual {
1652 return Err(format!(
1653 "expected {nargs} argument(s) in call to '{name}', got {actual}"
1654 ));
1655 }
1656 } else {
1657 let na = nargs.saturating_sub(1);
1658 if na > actual {
1659 return Err(format!(
1660 "expected at least {na} argument(s) in call to '{name}', got {actual}"
1661 ));
1662 } else if variadic > 0 {
1663 let nargsmax = na + variadic as usize;
1664 if nargsmax < actual {
1665 return Err(format!(
1666 "expected at most {nargsmax} argument(s) in call to '{name}', got {actual}"
1667 ));
1668 }
1669 }
1670 }
1671 Ok(())
1672}
1673
1674fn check_args_match_types(
1675 args: &[Box<Expr>],
1676 arg_types: &[ValueType],
1677 name: &str,
1678) -> Result<(), String> {
1679 for (i, actual_arg) in args.iter().enumerate() {
1680 let expected_idx = if i < arg_types.len() {
1681 i
1682 } else {
1683 arg_types.len() - 1
1684 };
1685 expect_type(
1686 arg_types[expected_idx],
1687 Some(actual_arg.value_type()),
1688 &format!("call to function '{name}'"),
1689 )?;
1690 }
1691 Ok(())
1692}
1693
1694fn check_ast_for_unary(ex: UnaryExpr) -> Result<Expr, String> {
1695 let value_type = ex.expr.value_type();
1696 if value_type != ValueType::Scalar && value_type != ValueType::Vector {
1697 return Err(format!(
1698 "unary expression only allowed on expressions of type scalar or vector, got {value_type}"
1699 ));
1700 }
1701
1702 Ok(Expr::Unary(ex))
1703}
1704
1705fn check_ast_for_subquery(ex: SubqueryExpr) -> Result<Expr, String> {
1706 let value_type = ex.expr.value_type();
1707 if value_type != ValueType::Vector {
1708 return Err(format!(
1709 "subquery is only allowed on vector, got {value_type} instead"
1710 ));
1711 }
1712
1713 Ok(Expr::Subquery(ex))
1714}
1715
1716fn check_ast_for_vector_selector(ex: VectorSelector) -> Result<Expr, String> {
1717 match ex.name {
1718 Some(ref name) => match ex.matchers.find_matcher_value(METRIC_NAME) {
1719 Some(val) => Err(format!(
1720 "metric name must not be set twice: '{name}' or '{val}'"
1721 )),
1722 None => Ok(Expr::VectorSelector(ex)),
1723 },
1724 None if ex.matchers.is_empty_matchers() => {
1725 Err("vector selector must contain at least one non-empty matcher".into())
1728 }
1729 _ => Ok(Expr::VectorSelector(ex)),
1730 }
1731}
1732
1733#[cfg(test)]
1734mod tests {
1735 use super::*;
1736 use crate::label::{MatchOp, Matcher};
1737
1738 #[test]
1739 fn test_valid_at_modifier() {
1740 let cases = vec![
1741 (0.0, 0),
1743 (1000.3, 1000300), (1000.9, 1000900), (1000.9991, 1000999), (1000.9999, 1001000), (-1000.3, 1000300), (-1000.9, 1000900), ];
1750
1751 for (secs, elapsed) in cases {
1752 match AtModifier::try_from(secs).unwrap() {
1753 AtModifier::At(st) => {
1754 if secs.is_sign_positive() || secs == 0.0 {
1755 assert_eq!(
1756 elapsed,
1757 st.duration_since(SystemTime::UNIX_EPOCH)
1758 .unwrap()
1759 .as_millis()
1760 )
1761 } else if secs.is_sign_negative() {
1762 assert_eq!(
1763 elapsed,
1764 SystemTime::UNIX_EPOCH
1765 .duration_since(st)
1766 .unwrap()
1767 .as_millis()
1768 )
1769 }
1770 }
1771 _ => panic!(),
1772 }
1773 }
1774
1775 assert_eq!(
1776 AtModifier::try_from(Expr::from(1.0)),
1777 AtModifier::try_from(1.0),
1778 );
1779 }
1780
1781 #[test]
1782 fn test_invalid_at_modifier() {
1783 let cases = vec![
1784 f64::MAX,
1785 f64::MIN,
1786 f64::NAN,
1787 f64::INFINITY,
1788 f64::NEG_INFINITY,
1789 ];
1790
1791 for secs in cases {
1792 assert!(AtModifier::try_from(secs).is_err())
1793 }
1794
1795 assert_eq!(
1796 AtModifier::try_from(token::T_ADD),
1797 Err("invalid @ modifier preprocessor '+', START or END is valid.".into())
1798 );
1799
1800 assert_eq!(
1801 AtModifier::try_from(Expr::from("string literal")),
1802 Err("invalid float value after @ modifier".into())
1803 );
1804 }
1805
1806 #[test]
1807 fn test_binary_labels() {
1808 assert_eq!(
1809 &Labels::new(vec!["foo", "bar"]),
1810 LabelModifier::Include(Labels::new(vec!["foo", "bar"])).labels()
1811 );
1812
1813 assert_eq!(
1814 &Labels::new(vec!["foo", "bar"]),
1815 LabelModifier::Exclude(Labels::new(vec!["foo", "bar"])).labels()
1816 );
1817
1818 assert_eq!(
1819 &Labels::new(vec!["foo", "bar"]),
1820 VectorMatchCardinality::OneToMany(Labels::new(vec!["foo", "bar"]))
1821 .labels()
1822 .unwrap()
1823 );
1824
1825 assert_eq!(
1826 &Labels::new(vec!["foo", "bar"]),
1827 VectorMatchCardinality::ManyToOne(Labels::new(vec!["foo", "bar"]))
1828 .labels()
1829 .unwrap()
1830 );
1831
1832 assert_eq!(VectorMatchCardinality::OneToOne.labels(), None);
1833 assert_eq!(VectorMatchCardinality::ManyToMany.labels(), None);
1834 }
1835
1836 #[test]
1837 fn test_neg() {
1838 assert_eq!(
1839 -VectorSelector::from("foo"),
1840 UnaryExpr {
1841 expr: Box::new(Expr::from(VectorSelector::from("foo")))
1842 }
1843 )
1844 }
1845
1846 #[test]
1847 fn test_scalar_value() {
1848 assert_eq!(Some(1.0), Expr::from(1.0).scalar_value());
1849 assert_eq!(None, Expr::from("1.0").scalar_value());
1850 }
1851
1852 #[test]
1853 fn test_at_expr() {
1854 assert_eq!(
1855 "@ <timestamp> may not be set multiple times",
1856 Expr::from(VectorSelector::from("foo"))
1857 .at_expr(AtModifier::try_from(1.0).unwrap())
1858 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1859 .unwrap_err()
1860 );
1861
1862 assert_eq!(
1863 "@ <timestamp> may not be set multiple times",
1864 Expr::new_matrix_selector(
1865 Expr::from(VectorSelector::from("foo")),
1866 Duration::from_secs(1),
1867 )
1868 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1869 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1870 .unwrap_err()
1871 );
1872
1873 assert_eq!(
1874 "@ <timestamp> may not be set multiple times",
1875 Expr::new_subquery_expr(
1876 Expr::from(VectorSelector::from("foo")),
1877 Duration::from_secs(1),
1878 None,
1879 )
1880 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1881 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1882 .unwrap_err()
1883 )
1884 }
1885
1886 #[test]
1887 fn test_offset_expr() {
1888 assert_eq!(
1889 "offset may not be set multiple times",
1890 Expr::from(VectorSelector::from("foo"))
1891 .offset_expr(Offset::Pos(Duration::from_secs(1000)))
1892 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1893 .unwrap_err()
1894 );
1895
1896 assert_eq!(
1897 "offset may not be set multiple times",
1898 Expr::new_matrix_selector(
1899 Expr::from(VectorSelector::from("foo")),
1900 Duration::from_secs(1),
1901 )
1902 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1903 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1904 .unwrap_err()
1905 );
1906
1907 assert_eq!(
1908 "offset may not be set multiple times",
1909 Expr::new_subquery_expr(
1910 Expr::from(VectorSelector::from("foo")),
1911 Duration::from_secs(1),
1912 None,
1913 )
1914 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1915 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1916 .unwrap_err()
1917 );
1918 }
1919
1920 #[test]
1921 fn test_expr_to_string() {
1922 let mut cases = vec![
1923 ("1", "1"),
1924 ("- 1", "-1"),
1925 ("+ 1", "1"),
1926 ("Inf", "Inf"),
1927 ("inf", "Inf"),
1928 ("+Inf", "Inf"),
1929 ("- Inf", "-Inf"),
1930 (".5", "0.5"),
1931 ("5.", "5"),
1932 ("123.4567", "123.4567"),
1933 ("5e-3", "0.005"),
1934 ("5e3", "5000"),
1935 ("0xc", "12"),
1936 ("0755", "493"),
1937 ("08", "8"),
1938 ("+5.5e-3", "0.0055"),
1939 ("-0755", "-493"),
1940 ("NaN", "NaN"),
1941 ("NAN", "NaN"),
1942 ("- 1^2", "-1 ^ 2"),
1943 ("+1 + -2 * 1", "1 + -2 * 1"),
1944 ("1 + 2/(3*1)", "1 + 2 / (3 * 1)"),
1945 ("foo*sum", "foo * sum"),
1946 ("foo * on(test,blub) bar", "foo * on (test, blub) bar"),
1947 (
1948 r#"up{job="hi", instance="in"} offset 5m @ 100"#,
1949 r#"up{instance="in",job="hi"} @ 100.000 offset 5m"#,
1950 ),
1951 (
1952 r#"up{job="hi", instance="in"}"#,
1953 r#"up{instance="in",job="hi"}"#,
1954 ),
1955 ("sum (up) by (job,instance)", "sum by (job, instance) (up)"),
1956 (
1957 "foo / on(test,blub) group_left(bar) bar",
1958 "foo / on (test, blub) group_left (bar) bar",
1959 ),
1960 (
1961 "foo / on(test,blub) group_right(bar) bar",
1962 "foo / on (test, blub) group_right (bar) bar",
1963 ),
1964 (
1965 r#"foo{a="b",foo!="bar",test=~"test",bar!~"baz"}"#,
1966 r#"foo{a="b",bar!~"baz",foo!="bar",test=~"test"}"#,
1967 ),
1968 (
1969 r#"{__name__=~"foo.+",__name__=~".*bar"}"#,
1970 r#"{__name__=~".*bar",__name__=~"foo.+"}"#,
1971 ),
1972 (
1973 r#"test{a="b"}[5y] OFFSET 3d"#,
1974 r#"test{a="b"}[5y] offset 3d"#,
1975 ),
1976 (
1977 r#"{a="b"}[5y] OFFSET 3d"#,
1978 r#"{a="b"}[5y] offset 3d"#,
1979 ),
1980 (
1981 "sum(some_metric) without(and, by, avg, count, alert, annotations)",
1982 "sum without (and, by, avg, count, alert, annotations) (some_metric)",
1983 ),
1984 (
1985 r#"floor(some_metric{foo!="bar"})"#,
1986 r#"floor(some_metric{foo!="bar"})"#,
1987 ),
1988 (
1989 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1990 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1991 ),
1992 ("rate(some_metric[5m])", "rate(some_metric[5m])"),
1993 ("round(some_metric,5)", "round(some_metric, 5)"),
1994 (
1995 r#"absent(sum(nonexistent{job="myjob"}))"#,
1996 r#"absent(sum(nonexistent{job="myjob"}))"#,
1997 ),
1998 (
1999 "histogram_quantile(0.9,rate(http_request_duration_seconds_bucket[10m]))",
2000 "histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))",
2001 ),
2002 (
2003 "histogram_quantile(0.9,sum(rate(http_request_duration_seconds_bucket[10m])) by(job,le))",
2004 "histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))",
2005 ),
2006 (
2007 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
2008 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
2009 ),
2010 (
2011 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100"#,
2012 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100.000"#,
2013 ),
2014 (
2015 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2016 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2017 ),
2018 (
2019 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2020 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2021 ),
2022 ("some_metric OFFSET 1m [10m:5s]", "some_metric offset 1m[10m:5s]"),
2023 ("some_metric @123 [10m:5s]", "some_metric @ 123.000[10m:5s]"),
2024 ("some_metric <= 1ms", "some_metric <= 0.001"),
2025 ];
2026
2027 let mut cases1 = vec![
2029 (
2030 r#"sum by() (task:errors:rate10s{job="s"})"#,
2031 r#"sum(task:errors:rate10s{job="s"})"#,
2032 ),
2033 (
2034 r#"sum by(code) (task:errors:rate10s{job="s"})"#,
2035 r#"sum by (code) (task:errors:rate10s{job="s"})"#,
2036 ),
2037 (
2038 r#"sum without() (task:errors:rate10s{job="s"})"#,
2039 r#"sum without () (task:errors:rate10s{job="s"})"#,
2040 ),
2041 (
2042 r#"sum without(instance) (task:errors:rate10s{job="s"})"#,
2043 r#"sum without (instance) (task:errors:rate10s{job="s"})"#,
2044 ),
2045 (
2046 r#"topk(5, task:errors:rate10s{job="s"})"#,
2047 r#"topk(5, task:errors:rate10s{job="s"})"#,
2048 ),
2049 (
2050 r#"count_values("value", task:errors:rate10s{job="s"})"#,
2051 r#"count_values("value", task:errors:rate10s{job="s"})"#,
2052 ),
2053 ("a - on() c", "a - on () c"),
2054 ("a - on(b) c", "a - on (b) c"),
2055 ("a - on(b) group_left(x) c", "a - on (b) group_left (x) c"),
2056 (
2057 "a - on(b) group_left(x, y) c",
2058 "a - on (b) group_left (x, y) c",
2059 ),
2060 ("a - on(b) group_left c", "a - on (b) group_left () c"),
2061 ("a - ignoring(b) c", "a - ignoring (b) c"),
2062 ("a - ignoring() c", "a - c"),
2063 ("a + fill(-23) b", "a + fill (-23) b"),
2064 ("a + fill_left(-23) b", "a + fill_left (-23) b"),
2065 ("a + fill_right(42) b", "a + fill_right (42) b"),
2066 (
2067 "a + fill_left(-23) fill_right(42) b",
2068 "a + fill_left (-23) fill_right (42) b",
2069 ),
2070 (
2071 "a + on(b) group_left fill(-23) c",
2072 "a + on (b) group_left () fill (-23) c",
2073 ),
2074 ("up > bool 0", "up > bool 0"),
2075 ("a offset 1m", "a offset 1m"),
2076 ("a offset -7m", "a offset -7m"),
2077 (r#"a{c="d"}[5m] offset 1m"#, r#"a{c="d"}[5m] offset 1m"#),
2078 ("a[5m] offset 1m", "a[5m] offset 1m"),
2079 ("a[12m] offset -3m", "a[12m] offset -3m"),
2080 ("a[1h:5m] offset 1m", "a[1h:5m] offset 1m"),
2081 (r#"{__name__="a"}"#, r#"{__name__="a"}"#),
2082 (r#"a{b!="c"}[1m]"#, r#"a{b!="c"}[1m]"#),
2083 (r#"a{b=~"c"}[1m]"#, r#"a{b=~"c"}[1m]"#),
2084 (r#"a{b!~"c"}[1m]"#, r#"a{b!~"c"}[1m]"#),
2085 ("a @ 10", "a @ 10.000"),
2086 ("a[1m] @ 10", "a[1m] @ 10.000"),
2087 ("a @ start()", "a @ start()"),
2088 ("a @ end()", "a @ end()"),
2089 ("a[1m] @ start()", "a[1m] @ start()"),
2090 ("a[1m] @ end()", "a[1m] @ end()"),
2091 ];
2092
2093 let mut cases2 = vec![
2095 (
2096 r#"test{a="b"}[5y] OFFSET 3d"#,
2097 r#"test{a="b"}[5y] offset 3d"#,
2098 ),
2099 (
2100 r#"test{a="b"}[5m] OFFSET 3600"#,
2101 r#"test{a="b"}[5m] offset 1h"#,
2102 ),
2103 ("foo[3ms] @ 2.345", "foo[3ms] @ 2.345"),
2104 ("foo[4s180ms] @ 2.345", "foo[4s180ms] @ 2.345"),
2105 ("foo[4.18] @ 2.345", "foo[4s180ms] @ 2.345"),
2106 ("foo[4s18ms] @ 2.345", "foo[4s18ms] @ 2.345"),
2107 ("foo[4.018] @ 2.345", "foo[4s18ms] @ 2.345"),
2108 ("test[5]", "test[5s]"),
2109 ("some_metric[5m] @ 1m", "some_metric[5m] @ 60.000"),
2110 ("metric @ 100s", "metric @ 100.000"),
2111 ("metric @ 1m40s", "metric @ 100.000"),
2112 ("metric @ 100 offset 50", "metric @ 100.000 offset 50s"),
2113 ("metric offset 50 @ 100", "metric @ 100.000 offset 50s"),
2114 ("metric @ 0 offset -50", "metric @ 0.000 offset -50s"),
2115 ("metric offset -50 @ 0", "metric @ 0.000 offset -50s"),
2116 (
2117 r#"sum_over_time(metric{job="1"}[100] @ 100 offset 50)"#,
2118 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2119 ),
2120 (
2121 r#"sum_over_time(metric{job="1"}[100] offset 50s @ 100)"#,
2122 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2123 ),
2124 (
2125 r#"sum_over_time(metric{job="1"}[100] @ 100) + label_replace(sum_over_time(metric{job="2"}[100] @ 100), "job", "1", "", "")"#,
2126 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000) + label_replace(sum_over_time(metric{job="2"}[1m40s] @ 100.000), "job", "1", "", "")"#,
2127 ),
2128 (
2129 r#"sum_over_time(metric{job="1"}[100:1] offset 20 @ 100)"#,
2130 r#"sum_over_time(metric{job="1"}[1m40s:1s] @ 100.000 offset 20s)"#,
2131 ),
2132 ];
2133
2134 cases.append(&mut cases1);
2135 cases.append(&mut cases2);
2136 for (input, expected) in cases {
2137 let expr = crate::parser::parse(input).unwrap();
2138 assert_eq!(expected, expr.to_string())
2139 }
2140 }
2141
2142 #[test]
2143 fn test_vector_selector_to_string() {
2144 let cases = vec![
2145 (VectorSelector::default(), ""),
2146 (VectorSelector::from("foobar"), "foobar"),
2147 (
2148 {
2149 let name = Some(String::from("foobar"));
2150 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "x"));
2151 VectorSelector::new(name, matchers)
2152 },
2153 r#"foobar{a="x"}"#,
2154 ),
2155 (
2156 {
2157 let matchers = Matchers::new(vec![
2158 Matcher::new(MatchOp::Equal, "a", "x"),
2159 Matcher::new(MatchOp::Equal, "b", "y"),
2160 ]);
2161 VectorSelector::new(None, matchers)
2162 },
2163 r#"{a="x",b="y"}"#,
2164 ),
2165 (
2166 {
2167 let matchers =
2168 Matchers::one(Matcher::new(MatchOp::Equal, METRIC_NAME, "foobar"));
2169 VectorSelector::new(None, matchers)
2170 },
2171 r#"{__name__="foobar"}"#,
2172 ),
2173 ];
2174
2175 for (vs, expect) in cases {
2176 assert_eq!(expect, vs.to_string())
2177 }
2178 }
2179
2180 #[test]
2181 fn test_aggregate_expr_pretty() {
2182 let cases = vec![
2183 ("sum(foo)", "sum(foo)"),
2184 (
2185 r#"sum by() (task:errors:rate10s{job="s"})"#,
2186 r#"sum(
2187 task:errors:rate10s{job="s"}
2188)"#,
2189 ),
2190 (
2191 r#"sum without(job,foo) (task:errors:rate10s{job="s"})"#,
2192 r#"sum without (job, foo) (
2193 task:errors:rate10s{job="s"}
2194)"#,
2195 ),
2196 (
2197 r#"sum(task:errors:rate10s{job="s"}) without(job,foo)"#,
2198 r#"sum without (job, foo) (
2199 task:errors:rate10s{job="s"}
2200)"#,
2201 ),
2202 (
2203 r#"sum by(job,foo) (task:errors:rate10s{job="s"})"#,
2204 r#"sum by (job, foo) (
2205 task:errors:rate10s{job="s"}
2206)"#,
2207 ),
2208 (
2209 r#"sum (task:errors:rate10s{job="s"}) by(job,foo)"#,
2210 r#"sum by (job, foo) (
2211 task:errors:rate10s{job="s"}
2212)"#,
2213 ),
2214 (
2215 r#"topk(10, ask:errors:rate10s{job="s"})"#,
2216 r#"topk(
2217 10,
2218 ask:errors:rate10s{job="s"}
2219)"#,
2220 ),
2221 (
2222 r#"sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2223 r#"sum by (job, foo) (
2224 sum by (job, foo) (
2225 task:errors:rate10s{job="s"}
2226 )
2227)"#,
2228 ),
2229 (
2230 r#"sum by(job,foo) (sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"})))"#,
2231 r#"sum by (job, foo) (
2232 sum by (job, foo) (
2233 sum by (job, foo) (
2234 task:errors:rate10s{job="s"}
2235 )
2236 )
2237)"#,
2238 ),
2239 (
2240 r#"sum by(job,foo)
2241(sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2242 r#"sum by (job, foo) (
2243 sum by (job, foo) (
2244 task:errors:rate10s{job="s"}
2245 )
2246)"#,
2247 ),
2248 (
2249 r#"sum by(job,foo)
2250(sum(task:errors:rate10s{job="s"}) without(job,foo))"#,
2251 r#"sum by (job, foo) (
2252 sum without (job, foo) (
2253 task:errors:rate10s{job="s"}
2254 )
2255)"#,
2256 ),
2257 (
2258 r#"sum by(job,foo) # Comment 1.
2259(sum by(job,foo) ( # Comment 2.
2260task:errors:rate10s{job="s"}))"#,
2261 r#"sum by (job, foo) (
2262 sum by (job, foo) (
2263 task:errors:rate10s{job="s"}
2264 )
2265)"#,
2266 ),
2267 ];
2268
2269 for (input, expect) in cases {
2270 let expr = crate::parser::parse(input);
2271 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2272 }
2273 }
2274
2275 #[test]
2276 fn test_binary_expr_pretty() {
2277 let cases = vec![
2278 ("a+b", "a + b"),
2279 (
2280 "a == bool 1",
2281 " a
2282== bool
2283 1",
2284 ),
2285 (
2286 "a == 1024000",
2287 " a
2288==
2289 1024000",
2290 ),
2291 (
2292 "a + ignoring(job) b",
2293 " a
2294+ ignoring (job)
2295 b",
2296 ),
2297 (
2298 "foo_1 + foo_2",
2299 " foo_1
2300+
2301 foo_2",
2302 ),
2303 (
2304 "foo_1 + foo_2 + foo_3",
2305 " foo_1
2306 +
2307 foo_2
2308+
2309 foo_3",
2310 ),
2311 (
2312 "foo + baar + foo_3",
2313 " foo + baar
2314+
2315 foo_3",
2316 ),
2317 (
2318 "foo_1 + foo_2 + foo_3 + foo_4",
2319 " foo_1
2320 +
2321 foo_2
2322 +
2323 foo_3
2324+
2325 foo_4",
2326 ),
2327 (
2328 "foo_1 + ignoring(foo) foo_2 + ignoring(job) group_left foo_3 + on(instance) group_right foo_4",
2329
2330 " foo_1
2331 + ignoring (foo)
2332 foo_2
2333 + ignoring (job) group_left ()
2334 foo_3
2335+ on (instance) group_right ()
2336 foo_4",
2337 ),
2338 ];
2339
2340 for (input, expect) in cases {
2341 let expr = crate::parser::parse(input);
2342 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2343 }
2344 }
2345
2346 #[test]
2347 fn test_call_expr_pretty() {
2348 let cases = vec![
2349 (
2350 "rate(foo[1m])",
2351 "rate(
2352 foo[1m]
2353)",
2354 ),
2355 (
2356 "sum_over_time(foo[1m])",
2357 "sum_over_time(
2358 foo[1m]
2359)",
2360 ),
2361 (
2362 "rate(long_vector_selector[10m:1m] @ start() offset 1m)",
2363 "rate(
2364 long_vector_selector[10m:1m] @ start() offset 1m
2365)",
2366 ),
2367 (
2368 "histogram_quantile(0.9, rate(foo[1m]))",
2369 "histogram_quantile(
2370 0.9,
2371 rate(
2372 foo[1m]
2373 )
2374)",
2375 ),
2376 (
2377 "histogram_quantile(0.9, rate(foo[1m] @ start()))",
2378 "histogram_quantile(
2379 0.9,
2380 rate(
2381 foo[1m] @ start()
2382 )
2383)",
2384 ),
2385 (
2386 "max_over_time(rate(demo_api_request_duration_seconds_count[1m])[1m:] @ start() offset 1m)",
2387 "max_over_time(
2388 rate(
2389 demo_api_request_duration_seconds_count[1m]
2390 )[1m:] @ start() offset 1m
2391)",
2392 ),
2393 (
2394 r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
2395 r#"label_replace(
2396 up{job="api-server",service="a:c"},
2397 "foo",
2398 "$1",
2399 "service",
2400 "(.*):.*"
2401)"#,
2402 ),
2403 (
2404 r#"label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*")"#,
2405 r#"label_replace(
2406 label_replace(
2407 up{job="api-server",service="a:c"},
2408 "foo",
2409 "$1",
2410 "service",
2411 "(.*):.*"
2412 ),
2413 "foo",
2414 "$1",
2415 "service",
2416 "(.*):.*"
2417)"#,
2418 ),
2419 ];
2420
2421 for (input, expect) in cases {
2422 let expr = crate::parser::parse(input);
2423 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2424 }
2425 }
2426
2427 #[test]
2428 fn test_paren_expr_pretty() {
2429 let cases = vec![
2430 ("(foo)", "(foo)"),
2431 (
2432 "(_foo_long_)",
2433 "(
2434 _foo_long_
2435)",
2436 ),
2437 (
2438 "((foo_long))",
2439 "(
2440 (foo_long)
2441)",
2442 ),
2443 (
2444 "((_foo_long_))",
2445 "(
2446 (
2447 _foo_long_
2448 )
2449)",
2450 ),
2451 (
2452 "(((foo_long)))",
2453 "(
2454 (
2455 (foo_long)
2456 )
2457)",
2458 ),
2459 ("(1 + 2)", "(1 + 2)"),
2460 (
2461 "(foo + bar)",
2462 "(
2463 foo + bar
2464)",
2465 ),
2466 (
2467 "(foo_long + bar_long)",
2468 "(
2469 foo_long
2470 +
2471 bar_long
2472)",
2473 ),
2474 (
2475 "(foo_long + bar_long + bar_2_long)",
2476 "(
2477 foo_long
2478 +
2479 bar_long
2480 +
2481 bar_2_long
2482)",
2483 ),
2484 (
2485 "((foo_long + bar_long) + bar_2_long)",
2486 "(
2487 (
2488 foo_long
2489 +
2490 bar_long
2491 )
2492 +
2493 bar_2_long
2494)",
2495 ),
2496 (
2497 "(1111 + 2222)",
2498 "(
2499 1111
2500 +
2501 2222
2502)",
2503 ),
2504 (
2505 "(sum_over_time(foo[1m]))",
2506 "(
2507 sum_over_time(
2508 foo[1m]
2509 )
2510)",
2511 ),
2512 (
2513 r#"(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"))"#,
2514 r#"(
2515 label_replace(
2516 up{job="api-server",service="a:c"},
2517 "foo",
2518 "$1",
2519 "service",
2520 "(.*):.*"
2521 )
2522)"#,
2523 ),
2524 (
2525 r#"(label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2526 r#"(
2527 label_replace(
2528 label_replace(
2529 up{job="api-server",service="a:c"},
2530 "foo",
2531 "$1",
2532 "service",
2533 "(.*):.*"
2534 ),
2535 "foo",
2536 "$1",
2537 "service",
2538 "(.*):.*"
2539 )
2540)"#,
2541 ),
2542 (
2543 r#"(label_replace(label_replace((up{job="api-server",service="a:c"}), "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2544 r#"(
2545 label_replace(
2546 label_replace(
2547 (
2548 up{job="api-server",service="a:c"}
2549 ),
2550 "foo",
2551 "$1",
2552 "service",
2553 "(.*):.*"
2554 ),
2555 "foo",
2556 "$1",
2557 "service",
2558 "(.*):.*"
2559 )
2560)"#,
2561 ),
2562 ];
2563
2564 for (input, expect) in cases {
2565 let expr = crate::parser::parse(input);
2566 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2567 }
2568 }
2569
2570 #[test]
2571 fn test_unary_expr_pretty() {
2572 let cases = vec![
2573 ("-1", "-1"),
2574 ("-vector_selector", "-vector_selector"),
2575 (
2576 "(-vector_selector)",
2577 "(
2578 -vector_selector
2579)",
2580 ),
2581 (
2582 "-histogram_quantile(0.9,rate(foo[1m]))",
2583 "-histogram_quantile(
2584 0.9,
2585 rate(
2586 foo[1m]
2587 )
2588)",
2589 ),
2590 (
2591 "-histogram_quantile(0.99, sum by (le) (rate(foo[1m])))",
2592 "-histogram_quantile(
2593 0.99,
2594 sum by (le) (
2595 rate(
2596 foo[1m]
2597 )
2598 )
2599)",
2600 ),
2601 (
2602 "-histogram_quantile(0.9, -rate(foo[1m] @ start()))",
2603 "-histogram_quantile(
2604 0.9,
2605 -rate(
2606 foo[1m] @ start()
2607 )
2608)",
2609 ),
2610 (
2611 "(-histogram_quantile(0.9, -rate(foo[1m] @ start())))",
2612 "(
2613 -histogram_quantile(
2614 0.9,
2615 -rate(
2616 foo[1m] @ start()
2617 )
2618 )
2619)",
2620 ),
2621 ];
2622
2623 for (input, expect) in cases {
2624 let expr = crate::parser::parse(input);
2625 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2626 }
2627 }
2628
2629 #[test]
2630 fn test_expr_pretty() {
2631 let cases = vec![
2633 (
2634 r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 40 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2635 r#"(
2636 node_filesystem_avail_bytes{fstype!="",job="node"}
2637 /
2638 node_filesystem_size_bytes{fstype!="",job="node"}
2639 *
2640 100
2641 <
2642 40
2643 and
2644 predict_linear(
2645 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2646 24 * 60
2647 *
2648 60
2649 )
2650 <
2651 0
2652 and
2653 node_filesystem_readonly{fstype!="",job="node"}
2654 ==
2655 0
2656)"#,
2657 ),
2658 (
2659 r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 20 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2660 r#"(
2661 node_filesystem_avail_bytes{fstype!="",job="node"}
2662 /
2663 node_filesystem_size_bytes{fstype!="",job="node"}
2664 *
2665 100
2666 <
2667 20
2668 and
2669 predict_linear(
2670 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2671 4 * 60
2672 *
2673 60
2674 )
2675 <
2676 0
2677 and
2678 node_filesystem_readonly{fstype!="",job="node"}
2679 ==
2680 0
2681)"#,
2682 ),
2683 (
2684 r#"(node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0)"#,
2685 r#" (
2686 node_timex_offset_seconds
2687 >
2688 0.05
2689 and
2690 deriv(
2691 node_timex_offset_seconds[5m]
2692 )
2693 >=
2694 0
2695 )
2696or
2697 (
2698 node_timex_offset_seconds
2699 <
2700 -0.05
2701 and
2702 deriv(
2703 node_timex_offset_seconds[5m]
2704 )
2705 <=
2706 0
2707 )"#,
2708 ),
2709 (
2710 r#"1 - ((node_memory_MemAvailable_bytes{job="node"} or (node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"}) ) / node_memory_MemTotal_bytes{job="node"})"#,
2711 r#" 1
2712-
2713 (
2714 (
2715 node_memory_MemAvailable_bytes{job="node"}
2716 or
2717 (
2718 node_memory_Buffers_bytes{job="node"}
2719 +
2720 node_memory_Cached_bytes{job="node"}
2721 +
2722 node_memory_MemFree_bytes{job="node"}
2723 +
2724 node_memory_Slab_bytes{job="node"}
2725 )
2726 )
2727 /
2728 node_memory_MemTotal_bytes{job="node"}
2729 )"#,
2730 ),
2731 (
2732 r#"min by (job, integration) (rate(alertmanager_notifications_failed_total{job="alertmanager", integration=~".*"}[5m]) / rate(alertmanager_notifications_total{job="alertmanager", integration="~.*"}[5m])) > 0.01"#,
2733 r#" min by (job, integration) (
2734 rate(
2735 alertmanager_notifications_failed_total{integration=~".*",job="alertmanager"}[5m]
2736 )
2737 /
2738 rate(
2739 alertmanager_notifications_total{integration="~.*",job="alertmanager"}[5m]
2740 )
2741 )
2742>
2743 0.01"#,
2744 ),
2745 (
2746 r#"(count by (job) (changes(process_start_time_seconds{job="alertmanager"}[10m]) > 4) / count by (job) (up{job="alertmanager"})) >= 0.5"#,
2747 r#" (
2748 count by (job) (
2749 changes(
2750 process_start_time_seconds{job="alertmanager"}[10m]
2751 )
2752 >
2753 4
2754 )
2755 /
2756 count by (job) (
2757 up{job="alertmanager"}
2758 )
2759 )
2760>=
2761 0.5"#,
2762 ),
2763 ];
2764
2765 for (input, expect) in cases {
2766 let expr = crate::parser::parse(input);
2767 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2768 }
2769 }
2770
2771 #[test]
2772 fn test_step_invariant_pretty() {
2773 let cases = vec![
2774 ("a @ 1", "a @ 1.000"),
2775 ("a @ start()", "a @ start()"),
2776 ("vector_selector @ start()", "vector_selector @ start()"),
2777 ];
2778
2779 for (input, expect) in cases {
2780 let expr = crate::parser::parse(input);
2781 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2782 }
2783 }
2784
2785 #[test]
2786 fn test_prettify() {
2787 let cases = vec![
2788 ("vector_selector", "vector_selector"),
2789 (
2790 r#"vector_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}"#,
2791 r#"vector_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}"#,
2792 ),
2793 (
2794 r#"matrix_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}[1y2w3d]"#,
2795 r#"matrix_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}[382d]"#,
2796 ),
2797 ];
2798
2799 for (input, expect) in cases {
2800 assert_eq!(expect, crate::parser::parse(input).unwrap().prettify());
2801 }
2802 }
2803
2804 #[test]
2805 fn test_eval_stmt_to_string() {
2806 let query = r#"http_requests_total{job="apiserver", handler="/api/comments"}[5m]"#;
2807 let start = "2024-10-08T07:15:00.022978+00:00";
2808 let end = "2024-10-08T07:15:30.012978+00:00";
2809 let expect = r#"[http_requests_total{handler="/api/comments",job="apiserver"}[5m]] @ [2024-10-08T07:15:00.022978+00:00, 2024-10-08T07:15:30.012978+00:00, 1m, 5m]"#;
2810
2811 let stmt = EvalStmt {
2812 expr: crate::parser::parse(query).unwrap(),
2813 start: DateTime::parse_from_rfc3339(start)
2814 .unwrap()
2815 .with_timezone(&Utc)
2816 .into(),
2817 end: DateTime::parse_from_rfc3339(end)
2818 .unwrap()
2819 .with_timezone(&Utc)
2820 .into(),
2821 interval: Duration::from_secs(60),
2822 lookback_delta: Duration::from_secs(300),
2823 };
2824
2825 assert_eq!(expect, stmt.to_string());
2826 }
2827
2828 fn make_call(func_name: &str, arg_count: usize) -> Call {
2829 use crate::parser::function::get_function;
2830 let func =
2831 get_function(func_name).unwrap_or_else(|| panic!("unknown function: {func_name}"));
2832 let args: Vec<Box<Expr>> = (0..arg_count)
2833 .map(|_| Box::new(Expr::VectorSelector(VectorSelector::from("foo"))))
2834 .collect();
2835 Call {
2836 func,
2837 args: FunctionArgs { args },
2838 }
2839 }
2840
2841 #[test]
2842 fn test_call_arity_variadic_zero() {
2843 assert!(check_ast(Expr::Call(make_call("floor", 1))).is_ok());
2845
2846 let err = check_ast(Expr::Call(make_call("floor", 0))).unwrap_err();
2847 assert!(
2848 err.contains("expected 1 argument(s) in call to 'floor', got 0"),
2849 "{err}"
2850 );
2851
2852 let err = check_ast(Expr::Call(make_call("floor", 2))).unwrap_err();
2853 assert!(
2854 err.contains("expected 1 argument(s) in call to 'floor', got 2"),
2855 "{err}"
2856 );
2857 }
2858
2859 #[test]
2860 fn test_call_arity_bounded_variadic_single_arg_type() {
2861 assert!(check_ast(Expr::Call(make_call("days_in_month", 1))).is_ok());
2864
2865 let err = check_ast(Expr::Call(make_call("days_in_month", 2))).unwrap_err();
2866 assert!(
2867 err.contains("expected at most 1 argument(s) in call to 'days_in_month', got 2"),
2868 "{err}"
2869 );
2870 }
2871
2872 #[test]
2873 fn test_call_arity_bounded_variadic_two_arg_types() {
2874 let err = check_ast(Expr::Call(make_call("round", 0))).unwrap_err();
2876 assert!(
2877 err.contains("expected at least 1 argument(s) in call to 'round', got 0"),
2878 "{err}"
2879 );
2880
2881 let err = check_ast(Expr::Call(make_call("round", 3))).unwrap_err();
2882 assert!(
2883 err.contains("expected at most 2 argument(s) in call to 'round', got 3"),
2884 "{err}"
2885 );
2886
2887 let err = check_ast(Expr::Call(make_call("info", 0))).unwrap_err();
2889 assert!(
2890 err.contains("expected at least 1 argument(s) in call to 'info', got 0"),
2891 "{err}"
2892 );
2893
2894 let err = check_ast(Expr::Call(make_call("info", 3))).unwrap_err();
2895 assert!(
2896 err.contains("expected at most 2 argument(s) in call to 'info', got 3"),
2897 "{err}"
2898 );
2899 }
2900
2901 #[test]
2902 fn test_call_arity_bounded_variadic_large() {
2903 let err = check_ast(Expr::Call(make_call("histogram_quantiles", 2))).unwrap_err();
2905 assert!(
2906 err.contains("expected at least 3 argument(s) in call to 'histogram_quantiles', got 2"),
2907 "{err}"
2908 );
2909
2910 let err = check_ast(Expr::Call(make_call("histogram_quantiles", 13))).unwrap_err();
2911 assert!(
2912 err.contains(
2913 "expected at most 12 argument(s) in call to 'histogram_quantiles', got 13"
2914 ),
2915 "{err}"
2916 );
2917 }
2918
2919 #[test]
2920 fn test_call_arity_unbounded_variadic() {
2921 let err = check_ast(Expr::Call(make_call("label_join", 2))).unwrap_err();
2923 assert!(
2924 err.contains("expected at least 3 argument(s) in call to 'label_join', got 2"),
2925 "{err}"
2926 );
2927
2928 let err = check_ast(Expr::Call(make_call("sort_by_label", 0))).unwrap_err();
2930 assert!(
2931 err.contains("expected at least 1 argument(s) in call to 'sort_by_label', got 0"),
2932 "{err}"
2933 );
2934 }
2935
2936 #[test]
2937 fn test_prettify_with_utf8_labels() {
2938 let cases = vec![
2940 (r#"{"some.metric"}"#, r#"{__name__="some.metric"}"#),
2942 (
2943 r#"foo{"label.with.dots"="value"}"#,
2944 r#"foo{"label.with.dots"="value"}"#,
2945 ),
2946 (
2947 r#"bar{"label-with-dashes"="test"}"#,
2948 r#"bar{"label-with-dashes"="test"}"#,
2949 ),
2950 (
2951 r#"baz{"label:with:colons"="data"}"#,
2952 r#"baz{"label:with:colons"="data"}"#,
2953 ),
2954 (
2955 r#"sum by ("service.version", foo) ({"some.metric"})"#,
2956 r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2957 ),
2958 (
2959 r#"sum by (`service.version`, foo) ({"some.metric"})"#,
2960 r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2961 ),
2962 (r#"foo{job="web"}"#, r#"foo{job="web"}"#),
2964 (
2965 r#"bar{instance_id="server1"}"#,
2966 r#"bar{instance_id="server1"}"#,
2967 ),
2968 ];
2969
2970 for (input, expected) in cases {
2971 let parsed = crate::parser::parse(input).unwrap();
2972 let prettified = parsed.prettify();
2973 assert_eq!(prettified, expected);
2974 }
2975 }
2976
2977 #[test]
2978 fn test_prettify_escape_roundtrip() {
2979 let cases = vec![
2981 (
2983 r#"{__name__="up",service=~"flagd\\.evaluation\\.v1\\.Service"}"#,
2984 r#"{__name__="up",service=~"flagd\\.evaluation\\.v1\\.Service"}"#,
2985 ),
2986 (
2988 r#"{__name__="up",tag=~"a\\|b"}"#,
2989 r#"{__name__="up",tag=~"a\\|b"}"#,
2990 ),
2991 (r#"{path="C:\\\\Windows"}"#, r#"{path="C:\\\\Windows"}"#),
2993 (r#"{msg="say \"hello\""}"#, r#"{msg="say \"hello\""}"#),
2995 ];
2996
2997 for (input, expected) in &cases {
2998 let parsed = crate::parser::parse(input).unwrap();
2999 let prettified = parsed.prettify();
3000 assert_eq!(
3001 &prettified, expected,
3002 "prettify mismatch for input: {input}"
3003 );
3004
3005 let reparsed = crate::parser::parse(&prettified).unwrap();
3007 assert_eq!(
3008 parsed.prettify(),
3009 reparsed.prettify(),
3010 "roundtrip failed for input: {input}"
3011 );
3012 }
3013 }
3014}