Skip to content

Commit 1dcfc88

Browse files
committed
feat(expression): support repeat function
Signed-off-by: Alan Tang <jmtangcs@gmail.com>
1 parent f12ea23 commit 1dcfc88

File tree

6 files changed

+37
-1
lines changed

6 files changed

+37
-1
lines changed

src/array/ops.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,26 @@ impl ArrayImpl {
635635
Ok(A::new_string(unary_op(a.as_ref(), |s| s.replace(from, to))))
636636
}
637637

638+
pub fn repeat(&self, num: &Self) -> Result {
639+
let (A::String(a), A::Int32(b)) = (self, num) else {
640+
return Err(ConvertError::NoBinaryOp(
641+
"repeat".into(),
642+
self.type_string(),
643+
num.type_string(),
644+
));
645+
};
646+
Ok(A::new_string(binary_op(
647+
a.as_ref(),
648+
b.as_ref(),
649+
|a, b| {
650+
if *b < 0 {
651+
return String::new();
652+
}
653+
a.repeat(*b as usize)
654+
},
655+
)))
656+
}
657+
638658
pub fn vector_l2_distance(&self, other: &ArrayImpl) -> Result {
639659
let ArrayImpl::Vector(a) = self else {
640660
return Err(ConvertError::NoBinaryOp(

src/binder/expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ impl Binder {
447447
"first" => Node::First(args[0]),
448448
"last" => Node::Last(args[0]),
449449
"replace" => Node::Replace([args[0], args[1], args[2]]),
450+
"repeat" => Node::Repeat([args[0], args[1]]),
450451
"row_number" => Node::RowNumber,
451452
name => todo!("Unsupported function: {}", name),
452453
};

src/executor/evaluator.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ impl<'a> Evaluator<'a> {
132132
};
133133
a.replace(from, to)
134134
}
135+
Repeat([str, num]) => {
136+
let str = self.next(*str).eval(chunk)?;
137+
let num = self.next(*num).eval(chunk)?;
138+
str.repeat(&num)
139+
}
135140
VectorL2Distance([a, b]) => {
136141
let a = self.next(*a).eval(chunk)?;
137142
let b = self.next(*b).eval(chunk)?;

src/planner/explain.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ impl<'a> Explain<'a> {
176176
("to", self.expr(c).pretty()),
177177
],
178178
),
179+
Repeat([str, num]) => Pretty::childless_record(
180+
"Repeat",
181+
vec![
182+
("str", self.expr(str).pretty()),
183+
("num", self.expr(num).pretty()),
184+
],
185+
),
179186
Substring([str, start, len]) => Pretty::childless_record(
180187
"Substring",
181188
vec![

src/planner/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ define_language! {
6767
"extract" = Extract([Id; 2]), // (extract field expr)
6868
Field(DateTimeField),
6969
"replace" = Replace([Id; 3]), // (replace expr pattern replacement)
70+
"repeat" = Repeat([Id; 2]), // (repeat expr the specified number of times)
7071
"substring" = Substring([Id; 3]), // (substring expr start length)
7172

7273
// vector functions

src/planner/rules/type_.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ pub fn analyze_type(
132132
.then_some(DataType::String)
133133
})
134134
}
135-
135+
Repeat([str, num]) => merge(enode, [x(str)?, x(num)?], |[str, num]| {
136+
(str == DataType::String && num == DataType::Int32).then_some(DataType::String)
137+
}),
136138
// number agg
137139
Max(a) | Min(a) => x(a),
138140
Sum(a) => check(enode, x(a)?, |a| a.is_number()),

0 commit comments

Comments
 (0)