Search...
ctrl/
Light
Dark
System
Sign in

With Blocks​

During the query rendering step, the number of occurrences of each expression are tracked. If an expression occurs more than once it is automatically extracted into a with block.

Copy
const x = e.int64(3);
const y = e.select(e.op(x, '^', x));

y.toEdgeQL();
// with x := 3
// select x ^ x

const result = await y.run(client);
// => 27

This hold for expressions of arbitrary complexity.

Copy
const robert = e.insert(e.Person, {
  name: "Robert Pattinson"
});
const colin = e.insert(e.Person, {
  name: "Colin Farrell"
});
const newMovie = e.insert(e.Movie, {
  title: "The Batman",
  actors: e.set(colin, robert)
});

/*
with
  robert := (insert Person {  name := "Robert Pattinson"}),
  colin := (insert Person {  name := "Colin Farrell"}),
insert Movie {
  title := "The Batman",
  actors := {robert, colin}
}
*/

Note that robert and colin were pulled out into a top-level with block. To force these variables to occur in an internal with block, you can short-circuit this logic with e.with.

Copy
const robert = e.insert(e.Person, {
  name: "Robert Pattinson"
});
const colin = e.insert(e.Person, {
  name: "Colin Farrell"
});
const newMovie = e.insert(e.Movie, {
  actors: e.with([robert, colin], // list "dependencies"
    e.select(e.set(robert, colin))
  )
})

/*
insert Movie {
  title := "The Batman",
  actors := (
    with
      robert := (insert Person {  name := "Robert Pattinson"}),
      colin := (insert Person {  name := "Colin Farrell"})
    select {robert, colin}
  )
}
*/

It's an error to pass an expression into multiple e.withs, or use an expression passed to e.with outside of that block.

To explicitly create a detached "alias" of another expression, use e.alias.

Copy
const a = e.set(1, 2, 3);
const b = e.alias(a);

const query = e.select(e.op(a, '*', b))
// WITH
//   a := {1, 2, 3},
//   b := a
// SELECT a + b

const result = await query.run(client);
// => [1, 2, 3, 2, 4, 6, 3, 6, 9]