2022-05-14 12:35:08 +00:00
|
|
|
use crate::ctx::Context;
|
2022-02-06 01:14:56 +00:00
|
|
|
use crate::dbs::Options;
|
|
|
|
use crate::dbs::Statement;
|
|
|
|
use crate::doc::Document;
|
|
|
|
use crate::err::Error;
|
2022-07-16 22:23:13 +00:00
|
|
|
use crate::sql::data::Data;
|
|
|
|
use crate::sql::expression::Expression;
|
|
|
|
use crate::sql::field::{Field, Fields};
|
|
|
|
use crate::sql::idiom::Idiom;
|
2023-04-25 10:13:04 +00:00
|
|
|
use crate::sql::number::Number;
|
2022-07-16 22:23:13 +00:00
|
|
|
use crate::sql::operator::Operator;
|
|
|
|
use crate::sql::part::Part;
|
|
|
|
use crate::sql::statement::Statement as Query;
|
|
|
|
use crate::sql::statements::delete::DeleteStatement;
|
|
|
|
use crate::sql::statements::ifelse::IfelseStatement;
|
|
|
|
use crate::sql::statements::update::UpdateStatement;
|
|
|
|
use crate::sql::subquery::Subquery;
|
|
|
|
use crate::sql::thing::Thing;
|
|
|
|
use crate::sql::value::{Value, Values};
|
|
|
|
use futures::future::try_join_all;
|
|
|
|
|
|
|
|
type Ops = Vec<(Idiom, Operator, Value)>;
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
enum Action {
|
|
|
|
Create,
|
|
|
|
Update,
|
|
|
|
Delete,
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
|
2022-02-13 19:03:00 +00:00
|
|
|
impl<'a> Document<'a> {
|
2022-02-06 01:14:56 +00:00
|
|
|
pub async fn table(
|
|
|
|
&self,
|
2022-07-16 22:23:13 +00:00
|
|
|
ctx: &Context<'_>,
|
|
|
|
opt: &Options,
|
|
|
|
stm: &Statement<'_>,
|
2022-02-06 01:14:56 +00:00
|
|
|
) -> Result<(), Error> {
|
2023-07-05 21:26:13 +00:00
|
|
|
// Check tables
|
2022-07-16 22:23:13 +00:00
|
|
|
if !opt.tables {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
// Check if forced
|
|
|
|
if !opt.force && !self.changed() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
2023-01-01 12:24:47 +00:00
|
|
|
// Don't run permissions
|
2023-07-05 21:26:13 +00:00
|
|
|
let opt = &opt.new_with_perms(false);
|
2022-07-16 22:23:13 +00:00
|
|
|
// Get the record id
|
|
|
|
let rid = self.id.as_ref().unwrap();
|
|
|
|
// Get the query action
|
|
|
|
let act = if stm.is_delete() {
|
|
|
|
Action::Delete
|
|
|
|
} else if self.is_new() {
|
|
|
|
Action::Create
|
|
|
|
} else {
|
|
|
|
Action::Update
|
|
|
|
};
|
2023-06-19 18:41:13 +00:00
|
|
|
// Clone transaction
|
2023-06-21 18:31:15 +00:00
|
|
|
let txn = ctx.try_clone_transaction()?;
|
2022-07-16 22:23:13 +00:00
|
|
|
// Loop through all foreign table statements
|
2023-06-19 18:41:13 +00:00
|
|
|
for ft in self.ft(opt, &txn).await?.iter() {
|
2022-07-16 22:23:13 +00:00
|
|
|
// Get the table definition
|
|
|
|
let tb = ft.view.as_ref().unwrap();
|
|
|
|
// Check if there is a GROUP BY clause
|
|
|
|
match &tb.group {
|
|
|
|
// There is a GROUP BY clause specified
|
|
|
|
Some(group) => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let mut initial_ctx = Context::new(ctx);
|
|
|
|
initial_ctx.add_cursor_doc(&self.initial);
|
2022-07-16 22:23:13 +00:00
|
|
|
// Set the previous record id
|
|
|
|
let old = Thing {
|
|
|
|
tb: ft.name.to_raw(),
|
2023-06-19 18:41:13 +00:00
|
|
|
id: try_join_all(group.iter().map(|v| v.compute(&initial_ctx, opt)))
|
|
|
|
.await?
|
|
|
|
.into_iter()
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into(),
|
2022-07-16 22:23:13 +00:00
|
|
|
};
|
2023-06-19 18:41:13 +00:00
|
|
|
let mut current_ctx = Context::new(ctx);
|
|
|
|
current_ctx.add_cursor_doc(&self.current);
|
2022-07-16 22:23:13 +00:00
|
|
|
// Set the current record id
|
|
|
|
let rid = Thing {
|
|
|
|
tb: ft.name.to_raw(),
|
2023-06-19 18:41:13 +00:00
|
|
|
id: try_join_all(group.iter().map(|v| v.compute(¤t_ctx, opt)))
|
|
|
|
.await?
|
|
|
|
.into_iter()
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into(),
|
2022-07-16 22:23:13 +00:00
|
|
|
};
|
|
|
|
// Check if a WHERE clause is specified
|
|
|
|
match &tb.cond {
|
|
|
|
// There is a WHERE clause specified
|
|
|
|
Some(cond) => {
|
2023-06-19 18:41:13 +00:00
|
|
|
match cond.compute(¤t_ctx, opt).await? {
|
2022-07-16 22:23:13 +00:00
|
|
|
v if v.is_truthy() => {
|
|
|
|
if !opt.force && act != Action::Create {
|
|
|
|
// Delete the old value
|
|
|
|
let act = Action::Delete;
|
|
|
|
// Modify the value in the table
|
|
|
|
let stm = UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(old)]),
|
2023-06-19 18:41:13 +00:00
|
|
|
data: Some(self.data(ctx, opt, act, &tb.expr).await?),
|
2022-07-16 22:23:13 +00:00
|
|
|
..UpdateStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
if act != Action::Delete {
|
|
|
|
// Update the new value
|
|
|
|
let act = Action::Update;
|
|
|
|
// Modify the value in the table
|
|
|
|
let stm = UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
2023-06-19 18:41:13 +00:00
|
|
|
data: Some(self.data(ctx, opt, act, &tb.expr).await?),
|
2022-07-16 22:23:13 +00:00
|
|
|
..UpdateStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
if !opt.force && act != Action::Create {
|
|
|
|
// Update the new value
|
|
|
|
let act = Action::Update;
|
|
|
|
// Modify the value in the table
|
|
|
|
let stm = UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(old)]),
|
2023-06-19 18:41:13 +00:00
|
|
|
data: Some(self.data(ctx, opt, act, &tb.expr).await?),
|
2022-07-16 22:23:13 +00:00
|
|
|
..UpdateStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No WHERE clause is specified
|
|
|
|
None => {
|
|
|
|
if !opt.force && act != Action::Create {
|
|
|
|
// Delete the old value
|
|
|
|
let act = Action::Delete;
|
|
|
|
// Modify the value in the table
|
|
|
|
let stm = UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(old)]),
|
2023-06-19 18:41:13 +00:00
|
|
|
data: Some(self.data(ctx, opt, act, &tb.expr).await?),
|
2022-07-16 22:23:13 +00:00
|
|
|
..UpdateStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
if act != Action::Delete {
|
|
|
|
// Update the new value
|
|
|
|
let act = Action::Update;
|
|
|
|
// Modify the value in the table
|
|
|
|
let stm = UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
2023-06-19 18:41:13 +00:00
|
|
|
data: Some(self.data(ctx, opt, act, &tb.expr).await?),
|
2022-07-16 22:23:13 +00:00
|
|
|
..UpdateStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No GROUP BY clause is specified
|
|
|
|
None => {
|
|
|
|
// Set the current record id
|
|
|
|
let rid = Thing {
|
|
|
|
tb: ft.name.to_raw(),
|
|
|
|
id: rid.id.clone(),
|
|
|
|
};
|
|
|
|
// Use the current record data
|
2023-06-19 18:41:13 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
|
|
|
ctx.add_cursor_doc(&self.current);
|
2022-07-16 22:23:13 +00:00
|
|
|
// Check if a WHERE clause is specified
|
|
|
|
match &tb.cond {
|
|
|
|
// There is a WHERE clause specified
|
|
|
|
Some(cond) => {
|
2023-06-19 18:41:13 +00:00
|
|
|
match cond.compute(&ctx, opt).await? {
|
2022-07-16 22:23:13 +00:00
|
|
|
v if v.is_truthy() => {
|
|
|
|
// Define the statement
|
|
|
|
let stm = match act {
|
|
|
|
// Delete the value in the table
|
|
|
|
Action::Delete => Query::Delete(DeleteStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
|
|
|
..DeleteStatement::default()
|
|
|
|
}),
|
|
|
|
// Update the value in the table
|
|
|
|
_ => Query::Update(UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
|
|
|
data: Some(Data::ReplaceExpression(
|
2023-06-19 18:41:13 +00:00
|
|
|
tb.expr.compute(&ctx, opt, false).await?,
|
2022-07-16 22:23:13 +00:00
|
|
|
)),
|
|
|
|
..UpdateStatement::default()
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(&ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// Delete the value in the table
|
|
|
|
let stm = DeleteStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
|
|
|
..DeleteStatement::default()
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(&ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No WHERE clause is specified
|
|
|
|
None => {
|
|
|
|
// Define the statement
|
|
|
|
let stm = match act {
|
|
|
|
// Delete the value in the table
|
|
|
|
Action::Delete => Query::Delete(DeleteStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
|
|
|
..DeleteStatement::default()
|
|
|
|
}),
|
|
|
|
// Update the value in the table
|
|
|
|
_ => Query::Update(UpdateStatement {
|
|
|
|
what: Values(vec![Value::from(rid)]),
|
|
|
|
data: Some(Data::ReplaceExpression(
|
2023-06-19 18:41:13 +00:00
|
|
|
tb.expr.compute(&ctx, opt, false).await?,
|
2022-07-16 22:23:13 +00:00
|
|
|
)),
|
|
|
|
..UpdateStatement::default()
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
// Execute the statement
|
2023-06-19 18:41:13 +00:00
|
|
|
stm.compute(&ctx, opt).await?;
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Carry on
|
2022-02-06 01:14:56 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2022-07-16 22:23:13 +00:00
|
|
|
//
|
|
|
|
async fn data(
|
|
|
|
&self,
|
|
|
|
ctx: &Context<'_>,
|
|
|
|
opt: &Options,
|
|
|
|
act: Action,
|
|
|
|
exp: &Fields,
|
|
|
|
) -> Result<Data, Error> {
|
|
|
|
//
|
|
|
|
let mut ops: Ops = vec![];
|
2023-06-19 18:41:13 +00:00
|
|
|
// Create a new context with the initial or the current doc
|
|
|
|
let mut ctx = Context::new(ctx);
|
|
|
|
match act {
|
|
|
|
Action::Delete => ctx.add_cursor_doc(self.initial.as_ref()),
|
|
|
|
Action::Update => ctx.add_cursor_doc(self.current.as_ref()),
|
2022-07-16 22:23:13 +00:00
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
//
|
|
|
|
for field in exp.other() {
|
2023-06-10 20:23:22 +00:00
|
|
|
// Process the field
|
|
|
|
if let Field::Single {
|
|
|
|
expr,
|
|
|
|
alias,
|
|
|
|
} = field
|
|
|
|
{
|
|
|
|
let idiom = alias.clone().unwrap_or_else(|| expr.to_idiom());
|
|
|
|
match expr {
|
2022-07-16 22:23:13 +00:00
|
|
|
Value::Function(f) if f.is_rolling() => match f.name() {
|
|
|
|
"count" => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = f.compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.chg(&mut ops, &act, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
"math::sum" => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = f.args()[0].compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.chg(&mut ops, &act, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
"math::min" => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = f.args()[0].compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.min(&mut ops, &act, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
"math::max" => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = f.args()[0].compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.max(&mut ops, &act, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
"math::mean" => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = f.args()[0].compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.mean(&mut ops, &act, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
_ => {
|
2023-06-19 18:41:13 +00:00
|
|
|
let val = expr.compute(&ctx, opt).await?;
|
2023-06-10 20:23:22 +00:00
|
|
|
self.set(&mut ops, idiom, val);
|
2022-07-16 22:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
Ok(Data::SetExpression(ops))
|
|
|
|
}
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Set the field in the foreign table
|
2022-07-16 22:23:13 +00:00
|
|
|
fn set(&self, ops: &mut Ops, key: Idiom, val: Value) {
|
|
|
|
ops.push((key, Operator::Equal, val));
|
|
|
|
}
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Increment or decrement the field in the foreign table
|
2022-07-16 22:23:13 +00:00
|
|
|
fn chg(&self, ops: &mut Ops, act: &Action, key: Idiom, val: Value) {
|
|
|
|
ops.push((
|
|
|
|
key,
|
|
|
|
match act {
|
|
|
|
Action::Delete => Operator::Dec,
|
|
|
|
Action::Update => Operator::Inc,
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
val,
|
|
|
|
));
|
|
|
|
}
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Set the new minimum value for the field in the foreign table
|
2022-07-16 22:23:13 +00:00
|
|
|
fn min(&self, ops: &mut Ops, act: &Action, key: Idiom, val: Value) {
|
|
|
|
if act == &Action::Update {
|
|
|
|
ops.push((
|
|
|
|
key.clone(),
|
|
|
|
Operator::Equal,
|
|
|
|
Value::Subquery(Box::new(Subquery::Ifelse(IfelseStatement {
|
|
|
|
exprs: vec![(
|
2023-06-20 23:31:23 +00:00
|
|
|
Value::Expression(Box::new(Expression::Binary {
|
2022-07-16 22:23:13 +00:00
|
|
|
l: Value::Idiom(key.clone()),
|
|
|
|
o: Operator::MoreThan,
|
|
|
|
r: val.clone(),
|
|
|
|
})),
|
|
|
|
val,
|
|
|
|
)],
|
|
|
|
close: Some(Value::Idiom(key)),
|
|
|
|
}))),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Set the new maximum value for the field in the foreign table
|
2022-07-16 22:23:13 +00:00
|
|
|
fn max(&self, ops: &mut Ops, act: &Action, key: Idiom, val: Value) {
|
|
|
|
if act == &Action::Update {
|
|
|
|
ops.push((
|
|
|
|
key.clone(),
|
|
|
|
Operator::Equal,
|
|
|
|
Value::Subquery(Box::new(Subquery::Ifelse(IfelseStatement {
|
|
|
|
exprs: vec![(
|
2023-06-20 23:31:23 +00:00
|
|
|
Value::Expression(Box::new(Expression::Binary {
|
2022-07-16 22:23:13 +00:00
|
|
|
l: Value::Idiom(key.clone()),
|
|
|
|
o: Operator::LessThan,
|
|
|
|
r: val.clone(),
|
|
|
|
})),
|
|
|
|
val,
|
|
|
|
)],
|
|
|
|
close: Some(Value::Idiom(key)),
|
|
|
|
}))),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Set the new average value for the field in the foreign table
|
2022-07-16 22:23:13 +00:00
|
|
|
fn mean(&self, ops: &mut Ops, act: &Action, key: Idiom, val: Value) {
|
|
|
|
//
|
|
|
|
let mut key_c = Idiom::from(vec![Part::from("__")]);
|
|
|
|
key_c.0.push(Part::from(key.to_hash()));
|
|
|
|
key_c.0.push(Part::from("c"));
|
|
|
|
//
|
|
|
|
ops.push((
|
|
|
|
key.clone(),
|
|
|
|
Operator::Equal,
|
2023-06-20 23:31:23 +00:00
|
|
|
Value::Expression(Box::new(Expression::Binary {
|
2022-07-16 22:23:13 +00:00
|
|
|
l: Value::Subquery(Box::new(Subquery::Value(Value::Expression(Box::new(
|
2023-06-20 23:31:23 +00:00
|
|
|
Expression::Binary {
|
2022-07-16 22:23:13 +00:00
|
|
|
l: Value::Subquery(Box::new(Subquery::Value(Value::Expression(Box::new(
|
2023-06-20 23:31:23 +00:00
|
|
|
Expression::Binary {
|
2023-04-25 10:13:04 +00:00
|
|
|
l: Value::Subquery(Box::new(Subquery::Value(Value::Expression(
|
2023-06-20 23:31:23 +00:00
|
|
|
Box::new(Expression::Binary {
|
2023-04-25 10:13:04 +00:00
|
|
|
l: Value::Idiom(key),
|
|
|
|
o: Operator::Nco,
|
|
|
|
r: Value::Number(Number::Int(0)),
|
|
|
|
}),
|
|
|
|
)))),
|
2022-07-16 22:23:13 +00:00
|
|
|
o: Operator::Mul,
|
2023-04-25 10:13:04 +00:00
|
|
|
r: Value::Subquery(Box::new(Subquery::Value(Value::Expression(
|
2023-06-20 23:31:23 +00:00
|
|
|
Box::new(Expression::Binary {
|
2023-04-25 10:13:04 +00:00
|
|
|
l: Value::Idiom(key_c.clone()),
|
|
|
|
o: Operator::Nco,
|
|
|
|
r: Value::Number(Number::Int(0)),
|
|
|
|
}),
|
|
|
|
)))),
|
2022-07-16 22:23:13 +00:00
|
|
|
},
|
|
|
|
))))),
|
|
|
|
o: match act {
|
|
|
|
Action::Delete => Operator::Sub,
|
|
|
|
Action::Update => Operator::Add,
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
r: val,
|
|
|
|
},
|
|
|
|
))))),
|
|
|
|
o: Operator::Div,
|
|
|
|
r: Value::Subquery(Box::new(Subquery::Value(Value::Expression(Box::new(
|
2023-06-20 23:31:23 +00:00
|
|
|
Expression::Binary {
|
2023-04-25 10:13:04 +00:00
|
|
|
l: Value::Subquery(Box::new(Subquery::Value(Value::Expression(Box::new(
|
2023-06-20 23:31:23 +00:00
|
|
|
Expression::Binary {
|
2023-04-25 10:13:04 +00:00
|
|
|
l: Value::Idiom(key_c.clone()),
|
|
|
|
o: Operator::Nco,
|
|
|
|
r: Value::Number(Number::Int(0)),
|
|
|
|
},
|
|
|
|
))))),
|
2022-07-16 22:23:13 +00:00
|
|
|
o: match act {
|
|
|
|
Action::Delete => Operator::Sub,
|
|
|
|
Action::Update => Operator::Add,
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
r: Value::from(1),
|
|
|
|
},
|
|
|
|
))))),
|
|
|
|
})),
|
|
|
|
));
|
|
|
|
//
|
|
|
|
ops.push((
|
|
|
|
key_c.clone(),
|
|
|
|
match act {
|
|
|
|
Action::Delete => Operator::Dec,
|
|
|
|
Action::Update => Operator::Inc,
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
Value::from(1),
|
|
|
|
));
|
|
|
|
}
|
2022-02-06 01:14:56 +00:00
|
|
|
}
|