-
-
Notifications
You must be signed in to change notification settings - Fork 520
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
Add support for insert into ... select
#1605
base: beta
Are you sure you want to change the base?
Conversation
This PR is still work in progress. Right now, only PG has support for this syntax. |
API was approved. Need to review code as well |
@L-Mario564 this PR looks good. Could you please resolve all the conflicts so I can merge it to beta? |
Sorry, not this one, I was reviewing |
@L-Mario564 thanks for this PR. While reviewing all the changes, we found a better API, that we can use, which also can improve architecture for builders This is a proposed API that we would like to include in Drizzle. It will offer various options and usages
Option 1: Using Query Builder directly import { QueryBuilder } from 'drizzle-orm/pg-core';
const qb = new QueryBuilder();
const query = qb.select({
name: users.name
})
.from(users)
.where(eq(users.role, 'employee'))
const insertedEmployees = await db
.insert(employees)
.select(query)
.returning({
id: employees.id,
name: employees.name,
}); Option 2: Use callback inside const insertedEmployees = await db
.insert(employees)
.select((qb) => qb.select({ name: users.name }).from(users).where(eq(users.role, 'employee')))
.returning({
id: employees.id,
name: employees.name,
}); Option 3: Use sql template for custom select statement. Both callback or just sql import { sql } from 'drizzle-orm';
const insertedEmployees = await db
.insert(employees)
.select(() => sql`select * from ...`)
.returning({
id: employees.id,
name: employees.name,
});
// or
const insertedEmployees = await db
.insert(employees)
.select(sql`select * from ...`)
.returning({
id: employees.id,
name: employees.name,
}); The main concern was that I would suggest not creating return sql`insert into ${table} ${insertOrder} values ${valuesSql}${onConflictSql}${returningSql}`; You can just use this select SQL as a template param instead of |
Bumping this PR. Any chance this will get another stab any time soon? |
Addresses #398.
This PR adds support to insert rows from one table into another via the
insert into ... select
syntax.The following is valid Drizzle syntax:
And would roughly be as follows in SQL:
Everything from the
select
andinsert
statements are valid for thisinsert().select()
syntax.There's a catch
$defaultFn
realistically can't be implemented here, so there's no support for it when using this syntax. Reason being is that the default function can't be called in the query, since it's a Typescript function, not an SQL one, meaning that this can lead to issues, like for example:Using the default function to generate a UUID with Javascript. This function will only run once before the SQL query is built, meaning that, if the select part of the query returns multiple rows, it will lead to duplicate UUIDs if the column can be null, or an error will be thrown if the column can't be null. This isn't the case for SQL functions like
now()
because this is left for the database to handle instead of the Javascript runtime.