edgedb icon indicating copy to clipboard operation
edgedb copied to clipboard

Portable shapes

Open Sikarii opened this issue 2 years ago • 7 comments

I would like to see portable shapes being implemented to EdgeQL, this would reduce the duplication of queries that operate on the same type.

A very simple demonstration of the issue:

select {
  oldest := (select Foo { id, name, created, updated, ...many others } order by .created ASC limit 5),
  newest := (select Foo { id, name, created, updated, ...many others } order by .created DESC limit 5) 
};

Proposed shape command

Allows EdgeQL to store a shape of an object type for later use.

This command requires the object type as an argument so EdgeQL can ensure the shape fits the type. It might also be possible to have anonymous shapes, however I don't know how well they would play with EdgeQL.

shape Foo {
  name,
  created 
};

# Returns a portable shape to be used for any query with `Foo`

Proposed ... operator for "spreading" shapes

Allows EdgeQL to "spread" the above shapes to queries. There needs to be a way to tell EdgeQL we're trying to use a portable shape (value) instead of the referring to the literal value.

In the simplest form this is the spread operator from JS:

myShape := (
  shape Foo {
    name,
    created 
  };
);

# Select with just the portable shape
select Foo {
  ...myShape # Just "myShape" wouldn't work here, as EdgeQL has no idea if we're trying to select "myShape" as a literal or a value.
};

# Select with the portable shape and also pick updated
select Foo {
  ...myShape,
  updated
};

Sikarii avatar Jul 05 '23 22:07 Sikarii

Link to thread: https://discord.com/channels/841451783728529451/1126251245657669743/1126251249831002202

janwirth avatar Jul 05 '23 22:07 janwirth

For reference, see earlier discussions: #180 and #5259.

IMO, now that we have support for splats, we should probably look into using that machinery instead. For example we could make the following work:

with
  myShape := Foo { bar, baz := 1 }
select
  Foo { 
    (typeof myShape).*
  };

Right now it fails because myShape is not a supertype of MyCls (rather a subtype), but that check can be fixed to allow aliases like this.

Another option that could let us move the typeof into the definition to implement #1578, so

with 
  myShape as type typeof(Foo { bar, baz := 1 })
select
  Foo { 
    myShape.*
  }

elprans avatar Jul 05 '23 22:07 elprans

On a second thought, splats might not be ideal here as they'd pick up properties not specified in the typeof shape, so :thinking:

elprans avatar Jul 05 '23 22:07 elprans

I suggest using

myShape := (
  shape Foo {
    name,
    created 
  };
);

select.spread(myShape){
  updated
}

This would translate nicely to Inserts with "spread operator like semantics" https://github.com/edgedb/edgedb/issues/5795

insert.copy(select Foo Limit 1){
  name := 'new one'
}

And of course shapes will be useful for things like insert.copy(select Foo Limit 1, myShape){ } to copy only what's in the shape.

haikyuu avatar Jul 15 '23 07:07 haikyuu

That would be nice, but seems like it's possible via aliases and splats:

abstract type ChatBase {
   required num: ChatsNumericSequence { readonly := true; constraint exclusive; };
   multi members: User;
   multi messages: Message;
}
alias BasicChatShape := (for chat in ChatBase union { num := chat.num, member_nums := chat.members.num });

# query
select BasicChatShape { ** }

will return:

[
  {
    "member_nums": [
      "1",
      "2"
    ],
    "num": "1",
    "id": "a3e61727-633c-4af9-9c06-5e225d8cb76d"
  },
  {
    "member_nums": [
      "3",
      "1"
    ],
    "num": "2",
    "id": "ec70104b-ebc1-4fe0-8a33-bd88fc65af70"
  }
]

One drawback here: it returns id field. Is there a way to omit id field with splat? And not sure, does it affect performance?

MrFoxPro avatar Nov 11 '23 20:11 MrFoxPro

Any news on this? Would highly appreciate such a feature.

NikoLandgraf avatar Feb 27 '24 10:02 NikoLandgraf

I am facing some scaling issues in my application, having lots of duplicated queries in my edgeql files. Reusable Shapes would make a huge difference in development and maintenance of my application.

jimkring avatar May 25 '24 16:05 jimkring