orchid-orm icon indicating copy to clipboard operation
orchid-orm copied to clipboard

Support computeBatchAtRuntime consuming SQL computed columns

Open IlyaSemenov opened this issue 8 months ago • 6 comments

As a developer, I want computeBatchAtRuntime to be able to consume SQL computed fields. My particular use case is that I have a SQL computed field that calculates a certain figure with a SQL math expression, and then sometimes I also want this number converted through a currency exchange service (that needs async operations).

Disclaimer: I realise it might be impossible to achieve due to the typing loop, but I believe it could at least have some investigation.

Anyhow, this seems to work partially already, but not to full extent. The typings are not there and the query builder forgets to add the field alias:

class UserTable extends BaseTable {
  override readonly table = "user"

  override columns = this.setColumns(t => ({
    id: t.serial().primaryKey(),
    name: t.varchar(),
  }))

  computed = this.setComputed(q => ({
    upperName: sql`upper(name)`.type(t => t.varchar()),
    upperNameDoubled: q.computeBatchAtRuntime(
      // Type '"upperName"' is not assignable to type '"name" | "id"'.
      ["upperName"],
      users => users.map(u => u.upperName + "x2"),
    ),
  }))
}

await db.user.insert({ name: "Alice" })

await db.user.find(1).select("upperNameDoubled").then(console.log, console.error)
// (0.8ms) SELECT upper(name) FROM "user" WHERE "user"."id" = $1 LIMIT 1 [1]
// { upper: 'ALICE', upperNameDoubled: 'undefinedx2' }

IlyaSemenov avatar May 10 '25 13:05 IlyaSemenov

Here is my current draft:

class UserTable extends BaseTable {
  computed = setComputedV2((q) => ({

    one: sql`upper(name)`.type(t => t.varchar()),

    two() {
      return q.computeAtRuntime(this, ['one'], (record) => {
        return record.one + ' text'
      });
    },
  }));
}

It doesn't look great that you have to pass this, but it's the only way I could find, and it works - it is type safe.

romeerez avatar May 18 '25 23:05 romeerez

I see. It might be not worth pursuing in the end, this can always be implemented at application level. I just threw an idea that came to me while I was working on something.

IlyaSemenov avatar May 21 '25 04:05 IlyaSemenov

And I like the idea and I'd like to implement it. Not all the work has to be bug fixes :)

It's a cycle: add more bugs, fix some bugs, then it is balanced.

But I got you that it's not a priority for your case and can be postponed.

romeerez avatar May 24 '25 17:05 romeerez

I published the first step: you can reuse SQL computeds, documentation.

To be continued...

romeerez avatar May 25 '25 06:05 romeerez

Thanks @romeerez , just a nitpick about the docs, you reference this.one and this.two instead of hello world.

mordechaim avatar May 25 '25 14:05 mordechaim

Nitpicks are welcome, I'll edit that

romeerez avatar May 26 '25 04:05 romeerez