diff --git a/cozo-core/src/runtime/imperative.rs b/cozo-core/src/runtime/imperative.rs index a2ce96f5..fb9a15ff 100644 --- a/cozo-core/src/runtime/imperative.rs +++ b/cozo-core/src/runtime/imperative.rs @@ -333,28 +333,34 @@ impl SessionTx<'_> { rels: &NamedRows, cur_vld: ValidityTs, ) -> Result<()> { + let mut key_bindings = vec![]; + for k in rels.headers.iter() { + let k = k.replace('(', "_").replace(')', ""); + let k = Symbol::new(k.clone(), Default::default()); + if key_bindings.contains(&k) { + bail!("Duplicate variable name {}, please use distinct variables in `as` construct.", k); + } + key_bindings.push(k); + } + let keys = key_bindings + .iter() + .map(|s| ColumnDef { + name: s.name.clone(), + typing: NullableColType { + coltype: ColType::Any, + nullable: true, + }, + default_gen: None, + }) + .collect_vec(); + let meta = InputRelationHandle { name: Symbol::new(name, Default::default()), metadata: StoredRelationMetadata { - keys: rels - .headers - .iter() - .map(|s| ColumnDef { - name: s.into(), - typing: NullableColType { - coltype: ColType::Any, - nullable: true, - }, - default_gen: None, - }) - .collect_vec(), + keys, non_keys: vec![], }, - key_bindings: rels - .headers - .iter() - .map(|s| Symbol::new(s.clone(), Default::default())) - .collect_vec(), + key_bindings, dep_bindings: vec![], span: Default::default(), }; diff --git a/cozo-core/src/runtime/tests.rs b/cozo-core/src/runtime/tests.rs index 3365b269..049867c2 100644 --- a/cozo-core/src/runtime/tests.rs +++ b/cozo-core/src/runtime/tests.rs @@ -1322,7 +1322,9 @@ fn as_store_in_imperative_script() { ) .unwrap(); assert_eq!(res.into_json()["rows"], json!([[1, 2, 3], [4, 5, 6]])); - let res = db.run_script(r#" + let res = db + .run_script( + r#" { ?[y] <- [[1], [2], [3]] :create a {x default rand_uuid_v1() => y} @@ -1331,9 +1333,42 @@ fn as_store_in_imperative_script() { { ?[x] := *_last{_kind: 'inserted', x} } - "#, Default::default()).unwrap(); + "#, + Default::default(), + ) + .unwrap(); assert_eq!(3, res.rows.len()); for row in res.into_json()["rows"].as_array().unwrap() { println!("{}", row); } + assert!(db + .run_script( + r#" + { + ?[x, x] := x = 1 + } as _last + "#, + Default::default() + ) + .is_err()); + + let res = db + .run_script( + r#" + { + x[y] <- [[1], [2], [3]] + ?[sum(y)] := x[y] + } as _last + { + ?[sum_y] := *_last{sum_y} + } + "#, + Default::default(), + ) + .unwrap(); + assert_eq!(1, res.rows.len()); + for row in res.into_json()["rows"].as_array().unwrap() { + println!("{}", row); + } + }