Repository: genjidb/genji (go)

Issue:
Allow reference to other fields when inserting or updating a document
```js
genji> insert into foo values {
  base: 379.99,
  vat: 20,
  total: base + base * vat / 100
};
```


Pull request:
Add reference to current document to eval context
This PR fixes #65 by adding the current field buffer to the eval stack whenever we are evaluating a KVPairs into a document.

Patch:
diff --git a/sql/query/expr/literal.go b/sql/query/expr/literal.go
index a00ce8a1..61bb6d1c 100644
--- a/sql/query/expr/literal.go
+++ b/sql/query/expr/literal.go
@@ -170,6 +170,9 @@ func (kvp KVPairs) IsEqual(other Expr) bool {
 // Eval turns a list of KVPairs into a document.
 func (kvp KVPairs) Eval(ctx EvalStack) (document.Value, error) {
 	var fb document.FieldBuffer
+	if ctx.Document == nil {
+		ctx.Document = &fb
+	}
 
 	for _, kv := range kvp {
 		v, err := kv.V.Eval(ctx)


Test patch:
diff --git a/sql/query/insert_test.go b/sql/query/insert_test.go
index 5736ca99..15ccd230 100644
--- a/sql/query/insert_test.go
+++ b/sql/query/insert_test.go
@@ -29,12 +29,14 @@ func TestInsertStmt(t *testing.T) {
 		{"Values / Named Params", "INSERT INTO test (a, b, c) VALUES ($d, 'e', $f)", false, `{"pk()":1,"a":"d","b":"e","c":"f"}`, []interface{}{sql.Named("f", "f"), sql.Named("d", "d")}},
 		{"Values / Invalid params", "INSERT INTO test (a, b, c) VALUES ('d', ?)", true, "", []interface{}{'e'}},
 		{"Values / List", `INSERT INTO test (a, b, c) VALUES ("a", 'b', [1, 2, 3])`, false, `{"pk()":1,"a":"a","b":"b","c":[1,2,3]}`, nil},
+		{"Values / Document", `INSERT INTO test (a, b, c) VALUES ("a", 'b', {c: 1, d: c + 1})`, false, `{"pk()":1,"a":"a","b":"b","c":{"c":1,"d":2}}`, nil},
 		{"Documents", "INSERT INTO test VALUES {a: 'a', b: 2.3, c: 1 = 1}", false, `{"pk()":1,"a":"a","b":2.3,"c":true}`, nil},
 		{"Documents / Positional Params", "INSERT INTO test VALUES {a: ?, b: 2.3, c: ?}", false, `{"pk()":1,"a":"a","b":2.3,"c":true}`, []interface{}{"a", true}},
 		{"Documents / Named Params", "INSERT INTO test VALUES {a: $a, b: 2.3, c: $c}", false, `{"pk()":1,"a":1,"b":2.3,"c":true}`, []interface{}{sql.Named("c", true), sql.Named("a", 1)}},
 		{"Documents / List ", "INSERT INTO test VALUES {a: [1, 2, 3]}", false, `{"pk()":1,"a":[1,2,3]}`, nil},
 		{"Documents / strings", `INSERT INTO test VALUES {'a': 'a', b: 2.3}`, false, `{"pk()":1,"a":"a","b":2.3}`, nil},
 		{"Documents / double quotes", `INSERT INTO test VALUES {"a": "b"}`, false, `{"pk()":1,"a":"b"}`, nil},
+		{"Documents / with reference to other fields", `INSERT INTO test VALUES {a: 400, b: a * 4}`, false, `{"pk()":1,"a":400,"b":1600}`, nil},
 	}
 
 	for _, test := range tests {