Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to insert and return an auto-generated value #74

Closed
chris-martin opened this issue Jun 23, 2021 · 2 comments · Fixed by #88
Closed

How to insert and return an auto-generated value #74

chris-martin opened this issue Jun 23, 2021 · 2 comments · Fixed by #88

Comments

@chris-martin
Copy link

chris-martin commented Jun 23, 2021

I have a typical sort of situation here where there's a table with an auto-incrementing ID (the "position" column in the schema below)...

data StripeCustomerQueue f = StripeCustomerQueue
  { stripeCustomerQueuePosition :: Column f StripeCustomerQueuePosition
  , stripeCustomerQueueCustomerId :: Column f StripeCustomerId
  , stripeCustomerQueueLiveMode :: Column f LiveMode
  }
  deriving stock (Generic)
  deriving anyclass (Rel8able)

... and I want to insert into the table, let the database set the position field to its default value, and return the generated value.

Insert
  { into = stripeCustomerQueueSchema
  , rows = one $ StripeCustomerQueue
      { stripeCustomerQueueLiveMode = lit mode
      , stripeCustomerQueueCustomerId = lit customerId
      , stripeCustomerQueuePosition = _
      }
  , onConflict = Abort
  , returning = Projection stripeCustomerQueuePosition
  }

What do I put in the hole above? Should I write unsafeLiteral "DEFAULT"? Or is there some other approach I'm missing?

@ocharles
Copy link
Contributor

A great question! We certainly need to document this, but here are a few solutions at the moment:

  1. Use unsafeLiteral "DEFAULT", as you mentioned. We haven't exported this as a definition (e.g., defaultValue = unsafeLiteral "DEFAULT") due to its, well, unsafeness.
  2. Don't rely on the default at all, and instead write an actual expression. In this case I don't know what the default of position would be, but in the typical case of wanting an auto-incremented id, you can use https://hackage.haskell.org/package/rel8-1.0.0.1/docs/Rel8.html#v:nextval.

Rel8 actually used to have special support for default values, with a special insertion context - but that was removed in 1eaa683. Ultimately we felt that tracking all of this at the type level was just too much. It also put the definition in the Rel8able, but a Rel8able can be used with many different tables, not all of which may share the same defaulting, so that was also slightly dubious.

I hope this helps. I'll keep this open as a reminder to add documentation about INSERT, UPDATE and DELETE.

@chris-martin
Copy link
Author

chris-martin commented Jun 23, 2021

It sure would be nice if the TableSchema could specify which columns were defaultable, but it doesn't seem particularly dissatisfying to me to use unsafeLiteral "DEFAULT" and accept the runtime error if I attempt to default something that is not defaultable. I think exporting defaultValue would be reasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants