Skip to content

Commit 2baf215

Browse files
authored
fix: compatible with null value during foreach and get field (#1174)
1 parent c316ce8 commit 2baf215

File tree

1 file changed

+44
-32
lines changed

1 file changed

+44
-32
lines changed

src/execution/evaluator.rs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -202,56 +202,61 @@ impl<'a> ScopeEntry<'a> {
202202
fn get_local_key_field<'b>(
203203
key_val: &'b value::KeyPart,
204204
indices: &'_ [u32],
205-
) -> &'b value::KeyPart {
206-
if indices.is_empty() {
205+
) -> Result<&'b value::KeyPart> {
206+
let result = if indices.is_empty() {
207207
key_val
208208
} else if let value::KeyPart::Struct(fields) = key_val {
209-
Self::get_local_key_field(&fields[indices[0] as usize], &indices[1..])
209+
Self::get_local_key_field(&fields[indices[0] as usize], &indices[1..])?
210210
} else {
211-
panic!("Only struct can be accessed by sub field");
212-
}
211+
bail!("Only struct can be accessed by sub field");
212+
};
213+
Ok(result)
213214
}
214215

215216
fn get_local_field<'b>(
216217
val: &'b value::Value<ScopeValueBuilder>,
217218
indices: &'_ [u32],
218-
) -> &'b value::Value<ScopeValueBuilder> {
219-
if indices.is_empty() {
219+
) -> Result<&'b value::Value<ScopeValueBuilder>> {
220+
let result = if indices.is_empty() {
221+
val
222+
} else if let value::Value::Null = val {
220223
val
221224
} else if let value::Value::Struct(fields) = val {
222-
Self::get_local_field(&fields.fields[indices[0] as usize], &indices[1..])
225+
Self::get_local_field(&fields.fields[indices[0] as usize], &indices[1..])?
223226
} else {
224-
panic!("Only struct can be accessed by sub field");
225-
}
227+
bail!("Only struct can be accessed by sub field");
228+
};
229+
Ok(result)
226230
}
227231

228232
fn get_value_field_builder(
229233
&self,
230234
field_ref: &AnalyzedLocalFieldReference,
231-
) -> &value::Value<ScopeValueBuilder> {
235+
) -> Result<&value::Value<ScopeValueBuilder>> {
232236
let first_index = field_ref.fields_idx[0] as usize;
233237
let index_base = self.key.value_field_index_base();
234238
let val = self.value.fields[(first_index - index_base) as usize]
235239
.get()
236-
.unwrap();
240+
.ok_or_else(|| anyhow!("Field {} is not set", first_index))?;
237241
Self::get_local_field(val, &field_ref.fields_idx[1..])
238242
}
239243

240-
fn get_field(&self, field_ref: &AnalyzedLocalFieldReference) -> value::Value {
244+
fn get_field(&self, field_ref: &AnalyzedLocalFieldReference) -> Result<value::Value> {
241245
let first_index = field_ref.fields_idx[0] as usize;
242246
let index_base = self.key.value_field_index_base();
243-
if first_index < index_base {
244-
let key_val = self.key.key().unwrap();
247+
let result = if first_index < index_base {
248+
let key_val = self.key.key().ok_or_else(|| anyhow!("Key is not set"))?;
245249
let key_part =
246-
Self::get_local_key_field(&key_val[first_index], &field_ref.fields_idx[1..]);
250+
Self::get_local_key_field(&key_val[first_index], &field_ref.fields_idx[1..])?;
247251
key_part.clone().into()
248252
} else {
249253
let val = self.value.fields[(first_index - index_base) as usize]
250254
.get()
251-
.unwrap();
252-
let val_part = Self::get_local_field(val, &field_ref.fields_idx[1..]);
255+
.ok_or_else(|| anyhow!("Field {} is not set", first_index))?;
256+
let val_part = Self::get_local_field(val, &field_ref.fields_idx[1..])?;
253257
value::Value::from_alternative_ref(val_part)
254-
}
258+
};
259+
Ok(result)
255260
}
256261

257262
fn get_field_schema(
@@ -289,28 +294,29 @@ impl<'a> ScopeEntry<'a> {
289294
fn assemble_value(
290295
value_mapping: &AnalyzedValueMapping,
291296
scoped_entries: RefList<'_, &ScopeEntry<'_>>,
292-
) -> value::Value {
293-
match value_mapping {
297+
) -> Result<value::Value> {
298+
let result = match value_mapping {
294299
AnalyzedValueMapping::Constant { value } => value.clone(),
295300
AnalyzedValueMapping::Field(field_ref) => scoped_entries
296301
.headn(field_ref.scope_up_level as usize)
297-
.unwrap()
298-
.get_field(&field_ref.local),
302+
.ok_or_else(|| anyhow!("Invalid scope_up_level: {}", field_ref.scope_up_level))?
303+
.get_field(&field_ref.local)?,
299304
AnalyzedValueMapping::Struct(mapping) => {
300305
let fields = mapping
301306
.fields
302307
.iter()
303308
.map(|f| assemble_value(f, scoped_entries))
304-
.collect();
309+
.collect::<Result<Vec<_>>>()?;
305310
value::Value::Struct(value::FieldValues { fields })
306311
}
307-
}
312+
};
313+
Ok(result)
308314
}
309315

310316
fn assemble_input_values<'a>(
311317
value_mappings: &'a [AnalyzedValueMapping],
312318
scoped_entries: RefList<'a, &ScopeEntry<'a>>,
313-
) -> impl Iterator<Item = value::Value> + 'a {
319+
) -> impl Iterator<Item = Result<value::Value>> + 'a {
314320
value_mappings
315321
.iter()
316322
.map(move |value_mapping| assemble_value(value_mapping, scoped_entries))
@@ -370,8 +376,9 @@ async fn evaluate_op_scope(
370376
}
371377

372378
let mut input_values = Vec::with_capacity(op.inputs.len());
373-
input_values
374-
.extend(assemble_input_values(&op.inputs, scoped_entries).collect::<Vec<_>>());
379+
for value in assemble_input_values(&op.inputs, scoped_entries) {
380+
input_values.push(value?);
381+
}
375382

376383
let result = if op.function_exec_info.enable_cache {
377384
let output_value_cell = memory.get_cache_entry(
@@ -416,8 +423,9 @@ async fn evaluate_op_scope(
416423
_ => bail!("Expect target field to be a table"),
417424
};
418425

419-
let target_field = head_scope.get_value_field_builder(&op.local_field_ref);
426+
let target_field = head_scope.get_value_field_builder(&op.local_field_ref)?;
420427
let task_futs = match target_field {
428+
value::Value::Null => vec![],
421429
value::Value::UTable(v) => v
422430
.iter()
423431
.map(|item| {
@@ -489,7 +497,9 @@ async fn evaluate_op_scope(
489497
let field_values_iter = assemble_input_values(&op.input.fields, scoped_entries);
490498
if op.has_auto_uuid_field {
491499
field_values.push(value::Value::Null);
492-
field_values.extend(field_values_iter);
500+
for value in field_values_iter {
501+
field_values.push(value?);
502+
}
493503
let uuid = memory.next_uuid(
494504
op.fingerprinter
495505
.clone()
@@ -498,7 +508,9 @@ async fn evaluate_op_scope(
498508
)?;
499509
field_values[0] = value::Value::Basic(value::BasicValue::Uuid(uuid));
500510
} else {
501-
field_values.extend(field_values_iter);
511+
for value in field_values_iter {
512+
field_values.push(value?);
513+
}
502514
};
503515
let collector_entry = scoped_entries
504516
.headn(op.collector_ref.scope_up_level as usize)
@@ -639,6 +651,6 @@ pub async fn evaluate_transient_flow(
639651
let output_value = assemble_value(
640652
&flow.execution_plan.output_value,
641653
RefList::Nil.prepend(&root_scope_entry),
642-
);
654+
)?;
643655
Ok(output_value)
644656
}

0 commit comments

Comments
 (0)