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;
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, "\"{}\"", 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 expected_args_len = ex.func.arg_types.len();
1622 let name = ex.func.name;
1623 let actual_args_len = ex.args.len();
1624
1625 if ex.func.variadic == 0 {
1626 if expected_args_len != actual_args_len {
1627 return Err(format!(
1628 "expected {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1629 ));
1630 }
1631 } else {
1632 let expected_args_len_without_default = expected_args_len.saturating_sub(1);
1633 if expected_args_len_without_default > actual_args_len {
1634 return Err(format!(
1635 "expected at least {expected_args_len_without_default} argument(s) in call to '{name}', got {actual_args_len}"
1636 ));
1637 }
1638
1639 if ex.func.variadic > 0 {
1640 let expected_max_args_len =
1641 expected_args_len_without_default + ex.func.variadic as usize;
1642 if expected_max_args_len < actual_args_len {
1643 return Err(format!(
1644 "expected at most {expected_max_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1645 ));
1646 }
1647 }
1648 }
1649
1650 if name.eq("exp") {
1652 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1653 if val.is_nan() || val.is_infinite() {
1654 return Ok(Expr::Call(ex));
1655 }
1656 }
1657 } else if name.eq("ln") || name.eq("log2") || name.eq("log10") {
1658 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1659 if val.is_nan() || val.is_infinite() || val <= 0.0 {
1660 return Ok(Expr::Call(ex));
1661 }
1662 }
1663 }
1664
1665 for (mut idx, actual_arg) in ex.args.args.iter().enumerate() {
1666 if idx >= ex.func.arg_types.len() {
1668 idx = ex.func.arg_types.len() - 1;
1669 }
1670
1671 expect_type(
1672 ex.func.arg_types[idx],
1673 Some(actual_arg.value_type()),
1674 &format!("call to function '{name}'"),
1675 )?;
1676 }
1677
1678 Ok(Expr::Call(ex))
1679}
1680
1681fn check_ast_for_unary(ex: UnaryExpr) -> Result<Expr, String> {
1682 let value_type = ex.expr.value_type();
1683 if value_type != ValueType::Scalar && value_type != ValueType::Vector {
1684 return Err(format!(
1685 "unary expression only allowed on expressions of type scalar or vector, got {value_type}"
1686 ));
1687 }
1688
1689 Ok(Expr::Unary(ex))
1690}
1691
1692fn check_ast_for_subquery(ex: SubqueryExpr) -> Result<Expr, String> {
1693 let value_type = ex.expr.value_type();
1694 if value_type != ValueType::Vector {
1695 return Err(format!(
1696 "subquery is only allowed on vector, got {value_type} instead"
1697 ));
1698 }
1699
1700 Ok(Expr::Subquery(ex))
1701}
1702
1703fn check_ast_for_vector_selector(ex: VectorSelector) -> Result<Expr, String> {
1704 match ex.name {
1705 Some(ref name) => match ex.matchers.find_matcher_value(METRIC_NAME) {
1706 Some(val) => Err(format!(
1707 "metric name must not be set twice: '{name}' or '{val}'"
1708 )),
1709 None => Ok(Expr::VectorSelector(ex)),
1710 },
1711 None if ex.matchers.is_empty_matchers() => {
1712 Err("vector selector must contain at least one non-empty matcher".into())
1715 }
1716 _ => Ok(Expr::VectorSelector(ex)),
1717 }
1718}
1719
1720#[cfg(test)]
1721mod tests {
1722 use super::*;
1723 use crate::label::{MatchOp, Matcher};
1724
1725 #[test]
1726 fn test_valid_at_modifier() {
1727 let cases = vec![
1728 (0.0, 0),
1730 (1000.3, 1000300), (1000.9, 1000900), (1000.9991, 1000999), (1000.9999, 1001000), (-1000.3, 1000300), (-1000.9, 1000900), ];
1737
1738 for (secs, elapsed) in cases {
1739 match AtModifier::try_from(secs).unwrap() {
1740 AtModifier::At(st) => {
1741 if secs.is_sign_positive() || secs == 0.0 {
1742 assert_eq!(
1743 elapsed,
1744 st.duration_since(SystemTime::UNIX_EPOCH)
1745 .unwrap()
1746 .as_millis()
1747 )
1748 } else if secs.is_sign_negative() {
1749 assert_eq!(
1750 elapsed,
1751 SystemTime::UNIX_EPOCH
1752 .duration_since(st)
1753 .unwrap()
1754 .as_millis()
1755 )
1756 }
1757 }
1758 _ => panic!(),
1759 }
1760 }
1761
1762 assert_eq!(
1763 AtModifier::try_from(Expr::from(1.0)),
1764 AtModifier::try_from(1.0),
1765 );
1766 }
1767
1768 #[test]
1769 fn test_invalid_at_modifier() {
1770 let cases = vec![
1771 f64::MAX,
1772 f64::MIN,
1773 f64::NAN,
1774 f64::INFINITY,
1775 f64::NEG_INFINITY,
1776 ];
1777
1778 for secs in cases {
1779 assert!(AtModifier::try_from(secs).is_err())
1780 }
1781
1782 assert_eq!(
1783 AtModifier::try_from(token::T_ADD),
1784 Err("invalid @ modifier preprocessor '+', START or END is valid.".into())
1785 );
1786
1787 assert_eq!(
1788 AtModifier::try_from(Expr::from("string literal")),
1789 Err("invalid float value after @ modifier".into())
1790 );
1791 }
1792
1793 #[test]
1794 fn test_binary_labels() {
1795 assert_eq!(
1796 &Labels::new(vec!["foo", "bar"]),
1797 LabelModifier::Include(Labels::new(vec!["foo", "bar"])).labels()
1798 );
1799
1800 assert_eq!(
1801 &Labels::new(vec!["foo", "bar"]),
1802 LabelModifier::Exclude(Labels::new(vec!["foo", "bar"])).labels()
1803 );
1804
1805 assert_eq!(
1806 &Labels::new(vec!["foo", "bar"]),
1807 VectorMatchCardinality::OneToMany(Labels::new(vec!["foo", "bar"]))
1808 .labels()
1809 .unwrap()
1810 );
1811
1812 assert_eq!(
1813 &Labels::new(vec!["foo", "bar"]),
1814 VectorMatchCardinality::ManyToOne(Labels::new(vec!["foo", "bar"]))
1815 .labels()
1816 .unwrap()
1817 );
1818
1819 assert_eq!(VectorMatchCardinality::OneToOne.labels(), None);
1820 assert_eq!(VectorMatchCardinality::ManyToMany.labels(), None);
1821 }
1822
1823 #[test]
1824 fn test_neg() {
1825 assert_eq!(
1826 -VectorSelector::from("foo"),
1827 UnaryExpr {
1828 expr: Box::new(Expr::from(VectorSelector::from("foo")))
1829 }
1830 )
1831 }
1832
1833 #[test]
1834 fn test_scalar_value() {
1835 assert_eq!(Some(1.0), Expr::from(1.0).scalar_value());
1836 assert_eq!(None, Expr::from("1.0").scalar_value());
1837 }
1838
1839 #[test]
1840 fn test_at_expr() {
1841 assert_eq!(
1842 "@ <timestamp> may not be set multiple times",
1843 Expr::from(VectorSelector::from("foo"))
1844 .at_expr(AtModifier::try_from(1.0).unwrap())
1845 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1846 .unwrap_err()
1847 );
1848
1849 assert_eq!(
1850 "@ <timestamp> may not be set multiple times",
1851 Expr::new_matrix_selector(
1852 Expr::from(VectorSelector::from("foo")),
1853 Duration::from_secs(1),
1854 )
1855 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1856 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1857 .unwrap_err()
1858 );
1859
1860 assert_eq!(
1861 "@ <timestamp> may not be set multiple times",
1862 Expr::new_subquery_expr(
1863 Expr::from(VectorSelector::from("foo")),
1864 Duration::from_secs(1),
1865 None,
1866 )
1867 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1868 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1869 .unwrap_err()
1870 )
1871 }
1872
1873 #[test]
1874 fn test_offset_expr() {
1875 assert_eq!(
1876 "offset may not be set multiple times",
1877 Expr::from(VectorSelector::from("foo"))
1878 .offset_expr(Offset::Pos(Duration::from_secs(1000)))
1879 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1880 .unwrap_err()
1881 );
1882
1883 assert_eq!(
1884 "offset may not be set multiple times",
1885 Expr::new_matrix_selector(
1886 Expr::from(VectorSelector::from("foo")),
1887 Duration::from_secs(1),
1888 )
1889 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1890 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1891 .unwrap_err()
1892 );
1893
1894 assert_eq!(
1895 "offset may not be set multiple times",
1896 Expr::new_subquery_expr(
1897 Expr::from(VectorSelector::from("foo")),
1898 Duration::from_secs(1),
1899 None,
1900 )
1901 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1902 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1903 .unwrap_err()
1904 );
1905 }
1906
1907 #[test]
1908 fn test_expr_to_string() {
1909 let mut cases = vec![
1910 ("1", "1"),
1911 ("- 1", "-1"),
1912 ("+ 1", "1"),
1913 ("Inf", "Inf"),
1914 ("inf", "Inf"),
1915 ("+Inf", "Inf"),
1916 ("- Inf", "-Inf"),
1917 (".5", "0.5"),
1918 ("5.", "5"),
1919 ("123.4567", "123.4567"),
1920 ("5e-3", "0.005"),
1921 ("5e3", "5000"),
1922 ("0xc", "12"),
1923 ("0755", "493"),
1924 ("08", "8"),
1925 ("+5.5e-3", "0.0055"),
1926 ("-0755", "-493"),
1927 ("NaN", "NaN"),
1928 ("NAN", "NaN"),
1929 ("- 1^2", "-1 ^ 2"),
1930 ("+1 + -2 * 1", "1 + -2 * 1"),
1931 ("1 + 2/(3*1)", "1 + 2 / (3 * 1)"),
1932 ("foo*sum", "foo * sum"),
1933 ("foo * on(test,blub) bar", "foo * on (test, blub) bar"),
1934 (
1935 r#"up{job="hi", instance="in"} offset 5m @ 100"#,
1936 r#"up{instance="in",job="hi"} @ 100.000 offset 5m"#,
1937 ),
1938 (
1939 r#"up{job="hi", instance="in"}"#,
1940 r#"up{instance="in",job="hi"}"#,
1941 ),
1942 ("sum (up) by (job,instance)", "sum by (job, instance) (up)"),
1943 (
1944 "foo / on(test,blub) group_left(bar) bar",
1945 "foo / on (test, blub) group_left (bar) bar",
1946 ),
1947 (
1948 "foo / on(test,blub) group_right(bar) bar",
1949 "foo / on (test, blub) group_right (bar) bar",
1950 ),
1951 (
1952 r#"foo{a="b",foo!="bar",test=~"test",bar!~"baz"}"#,
1953 r#"foo{a="b",bar!~"baz",foo!="bar",test=~"test"}"#,
1954 ),
1955 (
1956 r#"{__name__=~"foo.+",__name__=~".*bar"}"#,
1957 r#"{__name__=~".*bar",__name__=~"foo.+"}"#,
1958 ),
1959 (
1960 r#"test{a="b"}[5y] OFFSET 3d"#,
1961 r#"test{a="b"}[5y] offset 3d"#,
1962 ),
1963 (
1964 r#"{a="b"}[5y] OFFSET 3d"#,
1965 r#"{a="b"}[5y] offset 3d"#,
1966 ),
1967 (
1968 "sum(some_metric) without(and, by, avg, count, alert, annotations)",
1969 "sum without (and, by, avg, count, alert, annotations) (some_metric)",
1970 ),
1971 (
1972 r#"floor(some_metric{foo!="bar"})"#,
1973 r#"floor(some_metric{foo!="bar"})"#,
1974 ),
1975 (
1976 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1977 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1978 ),
1979 ("rate(some_metric[5m])", "rate(some_metric[5m])"),
1980 ("round(some_metric,5)", "round(some_metric, 5)"),
1981 (
1982 r#"absent(sum(nonexistent{job="myjob"}))"#,
1983 r#"absent(sum(nonexistent{job="myjob"}))"#,
1984 ),
1985 (
1986 "histogram_quantile(0.9,rate(http_request_duration_seconds_bucket[10m]))",
1987 "histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))",
1988 ),
1989 (
1990 "histogram_quantile(0.9,sum(rate(http_request_duration_seconds_bucket[10m])) by(job,le))",
1991 "histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))",
1992 ),
1993 (
1994 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1995 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1996 ),
1997 (
1998 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100"#,
1999 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100.000"#,
2000 ),
2001 (
2002 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2003 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2004 ),
2005 (
2006 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2007 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2008 ),
2009 ("some_metric OFFSET 1m [10m:5s]", "some_metric offset 1m[10m:5s]"),
2010 ("some_metric @123 [10m:5s]", "some_metric @ 123.000[10m:5s]"),
2011 ("some_metric <= 1ms", "some_metric <= 0.001"),
2012 ];
2013
2014 let mut cases1 = vec![
2016 (
2017 r#"sum by() (task:errors:rate10s{job="s"})"#,
2018 r#"sum(task:errors:rate10s{job="s"})"#,
2019 ),
2020 (
2021 r#"sum by(code) (task:errors:rate10s{job="s"})"#,
2022 r#"sum by (code) (task:errors:rate10s{job="s"})"#,
2023 ),
2024 (
2025 r#"sum without() (task:errors:rate10s{job="s"})"#,
2026 r#"sum without () (task:errors:rate10s{job="s"})"#,
2027 ),
2028 (
2029 r#"sum without(instance) (task:errors:rate10s{job="s"})"#,
2030 r#"sum without (instance) (task:errors:rate10s{job="s"})"#,
2031 ),
2032 (
2033 r#"topk(5, task:errors:rate10s{job="s"})"#,
2034 r#"topk(5, task:errors:rate10s{job="s"})"#,
2035 ),
2036 (
2037 r#"count_values("value", task:errors:rate10s{job="s"})"#,
2038 r#"count_values("value", task:errors:rate10s{job="s"})"#,
2039 ),
2040 ("a - on() c", "a - on () c"),
2041 ("a - on(b) c", "a - on (b) c"),
2042 ("a - on(b) group_left(x) c", "a - on (b) group_left (x) c"),
2043 (
2044 "a - on(b) group_left(x, y) c",
2045 "a - on (b) group_left (x, y) c",
2046 ),
2047 ("a - on(b) group_left c", "a - on (b) group_left () c"),
2048 ("a - ignoring(b) c", "a - ignoring (b) c"),
2049 ("a - ignoring() c", "a - c"),
2050 ("a + fill(-23) b", "a + fill (-23) b"),
2051 ("a + fill_left(-23) b", "a + fill_left (-23) b"),
2052 ("a + fill_right(42) b", "a + fill_right (42) b"),
2053 (
2054 "a + fill_left(-23) fill_right(42) b",
2055 "a + fill_left (-23) fill_right (42) b",
2056 ),
2057 (
2058 "a + on(b) group_left fill(-23) c",
2059 "a + on (b) group_left () fill (-23) c",
2060 ),
2061 ("up > bool 0", "up > bool 0"),
2062 ("a offset 1m", "a offset 1m"),
2063 ("a offset -7m", "a offset -7m"),
2064 (r#"a{c="d"}[5m] offset 1m"#, r#"a{c="d"}[5m] offset 1m"#),
2065 ("a[5m] offset 1m", "a[5m] offset 1m"),
2066 ("a[12m] offset -3m", "a[12m] offset -3m"),
2067 ("a[1h:5m] offset 1m", "a[1h:5m] offset 1m"),
2068 (r#"{__name__="a"}"#, r#"{__name__="a"}"#),
2069 (r#"a{b!="c"}[1m]"#, r#"a{b!="c"}[1m]"#),
2070 (r#"a{b=~"c"}[1m]"#, r#"a{b=~"c"}[1m]"#),
2071 (r#"a{b!~"c"}[1m]"#, r#"a{b!~"c"}[1m]"#),
2072 ("a @ 10", "a @ 10.000"),
2073 ("a[1m] @ 10", "a[1m] @ 10.000"),
2074 ("a @ start()", "a @ start()"),
2075 ("a @ end()", "a @ end()"),
2076 ("a[1m] @ start()", "a[1m] @ start()"),
2077 ("a[1m] @ end()", "a[1m] @ end()"),
2078 ];
2079
2080 let mut cases2 = vec![
2082 (
2083 r#"test{a="b"}[5y] OFFSET 3d"#,
2084 r#"test{a="b"}[5y] offset 3d"#,
2085 ),
2086 (
2087 r#"test{a="b"}[5m] OFFSET 3600"#,
2088 r#"test{a="b"}[5m] offset 1h"#,
2089 ),
2090 ("foo[3ms] @ 2.345", "foo[3ms] @ 2.345"),
2091 ("foo[4s180ms] @ 2.345", "foo[4s180ms] @ 2.345"),
2092 ("foo[4.18] @ 2.345", "foo[4s180ms] @ 2.345"),
2093 ("foo[4s18ms] @ 2.345", "foo[4s18ms] @ 2.345"),
2094 ("foo[4.018] @ 2.345", "foo[4s18ms] @ 2.345"),
2095 ("test[5]", "test[5s]"),
2096 ("some_metric[5m] @ 1m", "some_metric[5m] @ 60.000"),
2097 ("metric @ 100s", "metric @ 100.000"),
2098 ("metric @ 1m40s", "metric @ 100.000"),
2099 ("metric @ 100 offset 50", "metric @ 100.000 offset 50s"),
2100 ("metric offset 50 @ 100", "metric @ 100.000 offset 50s"),
2101 ("metric @ 0 offset -50", "metric @ 0.000 offset -50s"),
2102 ("metric offset -50 @ 0", "metric @ 0.000 offset -50s"),
2103 (
2104 r#"sum_over_time(metric{job="1"}[100] @ 100 offset 50)"#,
2105 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2106 ),
2107 (
2108 r#"sum_over_time(metric{job="1"}[100] offset 50s @ 100)"#,
2109 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2110 ),
2111 (
2112 r#"sum_over_time(metric{job="1"}[100] @ 100) + label_replace(sum_over_time(metric{job="2"}[100] @ 100), "job", "1", "", "")"#,
2113 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000) + label_replace(sum_over_time(metric{job="2"}[1m40s] @ 100.000), "job", "1", "", "")"#,
2114 ),
2115 (
2116 r#"sum_over_time(metric{job="1"}[100:1] offset 20 @ 100)"#,
2117 r#"sum_over_time(metric{job="1"}[1m40s:1s] @ 100.000 offset 20s)"#,
2118 ),
2119 ];
2120
2121 cases.append(&mut cases1);
2122 cases.append(&mut cases2);
2123 for (input, expected) in cases {
2124 let expr = crate::parser::parse(input).unwrap();
2125 assert_eq!(expected, expr.to_string())
2126 }
2127 }
2128
2129 #[test]
2130 fn test_vector_selector_to_string() {
2131 let cases = vec![
2132 (VectorSelector::default(), ""),
2133 (VectorSelector::from("foobar"), "foobar"),
2134 (
2135 {
2136 let name = Some(String::from("foobar"));
2137 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "x"));
2138 VectorSelector::new(name, matchers)
2139 },
2140 r#"foobar{a="x"}"#,
2141 ),
2142 (
2143 {
2144 let matchers = Matchers::new(vec![
2145 Matcher::new(MatchOp::Equal, "a", "x"),
2146 Matcher::new(MatchOp::Equal, "b", "y"),
2147 ]);
2148 VectorSelector::new(None, matchers)
2149 },
2150 r#"{a="x",b="y"}"#,
2151 ),
2152 (
2153 {
2154 let matchers =
2155 Matchers::one(Matcher::new(MatchOp::Equal, METRIC_NAME, "foobar"));
2156 VectorSelector::new(None, matchers)
2157 },
2158 r#"{__name__="foobar"}"#,
2159 ),
2160 ];
2161
2162 for (vs, expect) in cases {
2163 assert_eq!(expect, vs.to_string())
2164 }
2165 }
2166
2167 #[test]
2168 fn test_aggregate_expr_pretty() {
2169 let cases = vec![
2170 ("sum(foo)", "sum(foo)"),
2171 (
2172 r#"sum by() (task:errors:rate10s{job="s"})"#,
2173 r#"sum(
2174 task:errors:rate10s{job="s"}
2175)"#,
2176 ),
2177 (
2178 r#"sum without(job,foo) (task:errors:rate10s{job="s"})"#,
2179 r#"sum without (job, foo) (
2180 task:errors:rate10s{job="s"}
2181)"#,
2182 ),
2183 (
2184 r#"sum(task:errors:rate10s{job="s"}) without(job,foo)"#,
2185 r#"sum without (job, foo) (
2186 task:errors:rate10s{job="s"}
2187)"#,
2188 ),
2189 (
2190 r#"sum by(job,foo) (task:errors:rate10s{job="s"})"#,
2191 r#"sum by (job, foo) (
2192 task:errors:rate10s{job="s"}
2193)"#,
2194 ),
2195 (
2196 r#"sum (task:errors:rate10s{job="s"}) by(job,foo)"#,
2197 r#"sum by (job, foo) (
2198 task:errors:rate10s{job="s"}
2199)"#,
2200 ),
2201 (
2202 r#"topk(10, ask:errors:rate10s{job="s"})"#,
2203 r#"topk(
2204 10,
2205 ask:errors:rate10s{job="s"}
2206)"#,
2207 ),
2208 (
2209 r#"sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2210 r#"sum by (job, foo) (
2211 sum by (job, foo) (
2212 task:errors:rate10s{job="s"}
2213 )
2214)"#,
2215 ),
2216 (
2217 r#"sum by(job,foo) (sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"})))"#,
2218 r#"sum by (job, foo) (
2219 sum by (job, foo) (
2220 sum by (job, foo) (
2221 task:errors:rate10s{job="s"}
2222 )
2223 )
2224)"#,
2225 ),
2226 (
2227 r#"sum by(job,foo)
2228(sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2229 r#"sum by (job, foo) (
2230 sum by (job, foo) (
2231 task:errors:rate10s{job="s"}
2232 )
2233)"#,
2234 ),
2235 (
2236 r#"sum by(job,foo)
2237(sum(task:errors:rate10s{job="s"}) without(job,foo))"#,
2238 r#"sum by (job, foo) (
2239 sum without (job, foo) (
2240 task:errors:rate10s{job="s"}
2241 )
2242)"#,
2243 ),
2244 (
2245 r#"sum by(job,foo) # Comment 1.
2246(sum by(job,foo) ( # Comment 2.
2247task:errors:rate10s{job="s"}))"#,
2248 r#"sum by (job, foo) (
2249 sum by (job, foo) (
2250 task:errors:rate10s{job="s"}
2251 )
2252)"#,
2253 ),
2254 ];
2255
2256 for (input, expect) in cases {
2257 let expr = crate::parser::parse(input);
2258 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2259 }
2260 }
2261
2262 #[test]
2263 fn test_binary_expr_pretty() {
2264 let cases = vec![
2265 ("a+b", "a + b"),
2266 (
2267 "a == bool 1",
2268 " a
2269== bool
2270 1",
2271 ),
2272 (
2273 "a == 1024000",
2274 " a
2275==
2276 1024000",
2277 ),
2278 (
2279 "a + ignoring(job) b",
2280 " a
2281+ ignoring (job)
2282 b",
2283 ),
2284 (
2285 "foo_1 + foo_2",
2286 " foo_1
2287+
2288 foo_2",
2289 ),
2290 (
2291 "foo_1 + foo_2 + foo_3",
2292 " foo_1
2293 +
2294 foo_2
2295+
2296 foo_3",
2297 ),
2298 (
2299 "foo + baar + foo_3",
2300 " foo + baar
2301+
2302 foo_3",
2303 ),
2304 (
2305 "foo_1 + foo_2 + foo_3 + foo_4",
2306 " foo_1
2307 +
2308 foo_2
2309 +
2310 foo_3
2311+
2312 foo_4",
2313 ),
2314 (
2315 "foo_1 + ignoring(foo) foo_2 + ignoring(job) group_left foo_3 + on(instance) group_right foo_4",
2316
2317 " foo_1
2318 + ignoring (foo)
2319 foo_2
2320 + ignoring (job) group_left ()
2321 foo_3
2322+ on (instance) group_right ()
2323 foo_4",
2324 ),
2325 ];
2326
2327 for (input, expect) in cases {
2328 let expr = crate::parser::parse(input);
2329 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2330 }
2331 }
2332
2333 #[test]
2334 fn test_call_expr_pretty() {
2335 let cases = vec![
2336 (
2337 "rate(foo[1m])",
2338 "rate(
2339 foo[1m]
2340)",
2341 ),
2342 (
2343 "sum_over_time(foo[1m])",
2344 "sum_over_time(
2345 foo[1m]
2346)",
2347 ),
2348 (
2349 "rate(long_vector_selector[10m:1m] @ start() offset 1m)",
2350 "rate(
2351 long_vector_selector[10m:1m] @ start() offset 1m
2352)",
2353 ),
2354 (
2355 "histogram_quantile(0.9, rate(foo[1m]))",
2356 "histogram_quantile(
2357 0.9,
2358 rate(
2359 foo[1m]
2360 )
2361)",
2362 ),
2363 (
2364 "histogram_quantile(0.9, rate(foo[1m] @ start()))",
2365 "histogram_quantile(
2366 0.9,
2367 rate(
2368 foo[1m] @ start()
2369 )
2370)",
2371 ),
2372 (
2373 "max_over_time(rate(demo_api_request_duration_seconds_count[1m])[1m:] @ start() offset 1m)",
2374 "max_over_time(
2375 rate(
2376 demo_api_request_duration_seconds_count[1m]
2377 )[1m:] @ start() offset 1m
2378)",
2379 ),
2380 (
2381 r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
2382 r#"label_replace(
2383 up{job="api-server",service="a:c"},
2384 "foo",
2385 "$1",
2386 "service",
2387 "(.*):.*"
2388)"#,
2389 ),
2390 (
2391 r#"label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*")"#,
2392 r#"label_replace(
2393 label_replace(
2394 up{job="api-server",service="a:c"},
2395 "foo",
2396 "$1",
2397 "service",
2398 "(.*):.*"
2399 ),
2400 "foo",
2401 "$1",
2402 "service",
2403 "(.*):.*"
2404)"#,
2405 ),
2406 ];
2407
2408 for (input, expect) in cases {
2409 let expr = crate::parser::parse(input);
2410 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2411 }
2412 }
2413
2414 #[test]
2415 fn test_paren_expr_pretty() {
2416 let cases = vec![
2417 ("(foo)", "(foo)"),
2418 (
2419 "(_foo_long_)",
2420 "(
2421 _foo_long_
2422)",
2423 ),
2424 (
2425 "((foo_long))",
2426 "(
2427 (foo_long)
2428)",
2429 ),
2430 (
2431 "((_foo_long_))",
2432 "(
2433 (
2434 _foo_long_
2435 )
2436)",
2437 ),
2438 (
2439 "(((foo_long)))",
2440 "(
2441 (
2442 (foo_long)
2443 )
2444)",
2445 ),
2446 ("(1 + 2)", "(1 + 2)"),
2447 (
2448 "(foo + bar)",
2449 "(
2450 foo + bar
2451)",
2452 ),
2453 (
2454 "(foo_long + bar_long)",
2455 "(
2456 foo_long
2457 +
2458 bar_long
2459)",
2460 ),
2461 (
2462 "(foo_long + bar_long + bar_2_long)",
2463 "(
2464 foo_long
2465 +
2466 bar_long
2467 +
2468 bar_2_long
2469)",
2470 ),
2471 (
2472 "((foo_long + bar_long) + bar_2_long)",
2473 "(
2474 (
2475 foo_long
2476 +
2477 bar_long
2478 )
2479 +
2480 bar_2_long
2481)",
2482 ),
2483 (
2484 "(1111 + 2222)",
2485 "(
2486 1111
2487 +
2488 2222
2489)",
2490 ),
2491 (
2492 "(sum_over_time(foo[1m]))",
2493 "(
2494 sum_over_time(
2495 foo[1m]
2496 )
2497)",
2498 ),
2499 (
2500 r#"(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"))"#,
2501 r#"(
2502 label_replace(
2503 up{job="api-server",service="a:c"},
2504 "foo",
2505 "$1",
2506 "service",
2507 "(.*):.*"
2508 )
2509)"#,
2510 ),
2511 (
2512 r#"(label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2513 r#"(
2514 label_replace(
2515 label_replace(
2516 up{job="api-server",service="a:c"},
2517 "foo",
2518 "$1",
2519 "service",
2520 "(.*):.*"
2521 ),
2522 "foo",
2523 "$1",
2524 "service",
2525 "(.*):.*"
2526 )
2527)"#,
2528 ),
2529 (
2530 r#"(label_replace(label_replace((up{job="api-server",service="a:c"}), "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2531 r#"(
2532 label_replace(
2533 label_replace(
2534 (
2535 up{job="api-server",service="a:c"}
2536 ),
2537 "foo",
2538 "$1",
2539 "service",
2540 "(.*):.*"
2541 ),
2542 "foo",
2543 "$1",
2544 "service",
2545 "(.*):.*"
2546 )
2547)"#,
2548 ),
2549 ];
2550
2551 for (input, expect) in cases {
2552 let expr = crate::parser::parse(input);
2553 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2554 }
2555 }
2556
2557 #[test]
2558 fn test_unary_expr_pretty() {
2559 let cases = vec![
2560 ("-1", "-1"),
2561 ("-vector_selector", "-vector_selector"),
2562 (
2563 "(-vector_selector)",
2564 "(
2565 -vector_selector
2566)",
2567 ),
2568 (
2569 "-histogram_quantile(0.9,rate(foo[1m]))",
2570 "-histogram_quantile(
2571 0.9,
2572 rate(
2573 foo[1m]
2574 )
2575)",
2576 ),
2577 (
2578 "-histogram_quantile(0.99, sum by (le) (rate(foo[1m])))",
2579 "-histogram_quantile(
2580 0.99,
2581 sum by (le) (
2582 rate(
2583 foo[1m]
2584 )
2585 )
2586)",
2587 ),
2588 (
2589 "-histogram_quantile(0.9, -rate(foo[1m] @ start()))",
2590 "-histogram_quantile(
2591 0.9,
2592 -rate(
2593 foo[1m] @ start()
2594 )
2595)",
2596 ),
2597 (
2598 "(-histogram_quantile(0.9, -rate(foo[1m] @ start())))",
2599 "(
2600 -histogram_quantile(
2601 0.9,
2602 -rate(
2603 foo[1m] @ start()
2604 )
2605 )
2606)",
2607 ),
2608 ];
2609
2610 for (input, expect) in cases {
2611 let expr = crate::parser::parse(input);
2612 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2613 }
2614 }
2615
2616 #[test]
2617 fn test_expr_pretty() {
2618 let cases = vec![
2620 (
2621 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)"#,
2622 r#"(
2623 node_filesystem_avail_bytes{fstype!="",job="node"}
2624 /
2625 node_filesystem_size_bytes{fstype!="",job="node"}
2626 *
2627 100
2628 <
2629 40
2630 and
2631 predict_linear(
2632 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2633 24 * 60
2634 *
2635 60
2636 )
2637 <
2638 0
2639 and
2640 node_filesystem_readonly{fstype!="",job="node"}
2641 ==
2642 0
2643)"#,
2644 ),
2645 (
2646 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)"#,
2647 r#"(
2648 node_filesystem_avail_bytes{fstype!="",job="node"}
2649 /
2650 node_filesystem_size_bytes{fstype!="",job="node"}
2651 *
2652 100
2653 <
2654 20
2655 and
2656 predict_linear(
2657 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2658 4 * 60
2659 *
2660 60
2661 )
2662 <
2663 0
2664 and
2665 node_filesystem_readonly{fstype!="",job="node"}
2666 ==
2667 0
2668)"#,
2669 ),
2670 (
2671 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)"#,
2672 r#" (
2673 node_timex_offset_seconds
2674 >
2675 0.05
2676 and
2677 deriv(
2678 node_timex_offset_seconds[5m]
2679 )
2680 >=
2681 0
2682 )
2683or
2684 (
2685 node_timex_offset_seconds
2686 <
2687 -0.05
2688 and
2689 deriv(
2690 node_timex_offset_seconds[5m]
2691 )
2692 <=
2693 0
2694 )"#,
2695 ),
2696 (
2697 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"})"#,
2698 r#" 1
2699-
2700 (
2701 (
2702 node_memory_MemAvailable_bytes{job="node"}
2703 or
2704 (
2705 node_memory_Buffers_bytes{job="node"}
2706 +
2707 node_memory_Cached_bytes{job="node"}
2708 +
2709 node_memory_MemFree_bytes{job="node"}
2710 +
2711 node_memory_Slab_bytes{job="node"}
2712 )
2713 )
2714 /
2715 node_memory_MemTotal_bytes{job="node"}
2716 )"#,
2717 ),
2718 (
2719 r#"min by (job, integration) (rate(alertmanager_notifications_failed_total{job="alertmanager", integration=~".*"}[5m]) / rate(alertmanager_notifications_total{job="alertmanager", integration="~.*"}[5m])) > 0.01"#,
2720 r#" min by (job, integration) (
2721 rate(
2722 alertmanager_notifications_failed_total{integration=~".*",job="alertmanager"}[5m]
2723 )
2724 /
2725 rate(
2726 alertmanager_notifications_total{integration="~.*",job="alertmanager"}[5m]
2727 )
2728 )
2729>
2730 0.01"#,
2731 ),
2732 (
2733 r#"(count by (job) (changes(process_start_time_seconds{job="alertmanager"}[10m]) > 4) / count by (job) (up{job="alertmanager"})) >= 0.5"#,
2734 r#" (
2735 count by (job) (
2736 changes(
2737 process_start_time_seconds{job="alertmanager"}[10m]
2738 )
2739 >
2740 4
2741 )
2742 /
2743 count by (job) (
2744 up{job="alertmanager"}
2745 )
2746 )
2747>=
2748 0.5"#,
2749 ),
2750 ];
2751
2752 for (input, expect) in cases {
2753 let expr = crate::parser::parse(input);
2754 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2755 }
2756 }
2757
2758 #[test]
2759 fn test_step_invariant_pretty() {
2760 let cases = vec![
2761 ("a @ 1", "a @ 1.000"),
2762 ("a @ start()", "a @ start()"),
2763 ("vector_selector @ start()", "vector_selector @ start()"),
2764 ];
2765
2766 for (input, expect) in cases {
2767 let expr = crate::parser::parse(input);
2768 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2769 }
2770 }
2771
2772 #[test]
2773 fn test_prettify() {
2774 let cases = vec![
2775 ("vector_selector", "vector_selector"),
2776 (
2777 r#"vector_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}"#,
2778 r#"vector_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}"#,
2779 ),
2780 (
2781 r#"matrix_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}[1y2w3d]"#,
2782 r#"matrix_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}[382d]"#,
2783 ),
2784 ];
2785
2786 for (input, expect) in cases {
2787 assert_eq!(expect, crate::parser::parse(input).unwrap().prettify());
2788 }
2789 }
2790
2791 #[test]
2792 fn test_eval_stmt_to_string() {
2793 let query = r#"http_requests_total{job="apiserver", handler="/api/comments"}[5m]"#;
2794 let start = "2024-10-08T07:15:00.022978+00:00";
2795 let end = "2024-10-08T07:15:30.012978+00:00";
2796 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]"#;
2797
2798 let stmt = EvalStmt {
2799 expr: crate::parser::parse(query).unwrap(),
2800 start: DateTime::parse_from_rfc3339(start)
2801 .unwrap()
2802 .with_timezone(&Utc)
2803 .into(),
2804 end: DateTime::parse_from_rfc3339(end)
2805 .unwrap()
2806 .with_timezone(&Utc)
2807 .into(),
2808 interval: Duration::from_secs(60),
2809 lookback_delta: Duration::from_secs(300),
2810 };
2811
2812 assert_eq!(expect, stmt.to_string());
2813 }
2814
2815 #[test]
2816 fn test_prettify_with_utf8_labels() {
2817 let cases = vec![
2819 (r#"{"some.metric"}"#, r#"{__name__="some.metric"}"#),
2821 (
2822 r#"foo{"label.with.dots"="value"}"#,
2823 r#"foo{"label.with.dots"="value"}"#,
2824 ),
2825 (
2826 r#"bar{"label-with-dashes"="test"}"#,
2827 r#"bar{"label-with-dashes"="test"}"#,
2828 ),
2829 (
2830 r#"baz{"label:with:colons"="data"}"#,
2831 r#"baz{"label:with:colons"="data"}"#,
2832 ),
2833 (
2834 r#"sum by ("service.version", foo) ({"some.metric"})"#,
2835 r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2836 ),
2837 (
2838 r#"sum by (`service.version`, foo) ({"some.metric"})"#,
2839 r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2840 ),
2841 (r#"foo{job="web"}"#, r#"foo{job="web"}"#),
2843 (
2844 r#"bar{instance_id="server1"}"#,
2845 r#"bar{instance_id="server1"}"#,
2846 ),
2847 ];
2848
2849 for (input, expected) in cases {
2850 let parsed = crate::parser::parse(input).unwrap();
2851 let prettified = parsed.prettify();
2852 assert_eq!(prettified, expected);
2853 }
2854 }
2855}