Skip to content

Commit

Permalink
feat: enhance insert method to support multiple row insertion in Quer…
Browse files Browse the repository at this point in the history
…yBuilder
  • Loading branch information
zfben committed Feb 9, 2025
1 parent 5c9b185 commit 7fc4410
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
23 changes: 20 additions & 3 deletions src/__tests__/query-builder/mutation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ describe('QueryBuilder/mutation', () => {

expect(result).toEqual(['Alice', 'Bob', 'Charlie'])
})

it('inserts multiple rows', async () => {
const returning = await new QueryBuilder(client, 'mutation').insert(
[
{ id: 3, name: 'Charlie', metadata: { age: 50 } },
{ id: 4, name: 'David', metadata: { age: 25 } },
],
{ returning: ['name', 'metadata'] }
)

expect(returning).toEqual([
{ name: 'Charlie', metadata: { age: 50 } },
{ name: 'David', metadata: { age: 25 } },
])

const result = await new QueryBuilder(client, 'mutation').pluck('name')

expect(result).toEqual(['Alice', 'Bob', 'Charlie', 'David'])
})
})

describe('update', () => {
Expand All @@ -67,9 +86,7 @@ describe('QueryBuilder/mutation', () => {

describe('delete', () => {
it('deletes a row', async () => {
await new QueryBuilder(client, 'mutation')
.where('name', 'Alice')
.delete()
await new QueryBuilder(client, 'mutation').where('name', 'Alice').delete()

const result = await new QueryBuilder(client, 'mutation').pluck('name')

Expand Down
20 changes: 11 additions & 9 deletions src/query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,10 @@ export class QueryBuilder<
return result.map((row: any) => row[column])
}

async insert<Returning extends (keyof TableType<T>)[] | ['*']>(
values: Partial<TableType<T>>,
async insert<FirstValue extends Partial<TableType<T>>, Returning extends (keyof TableType<T>)[] | ['*']>(
values: FirstValue | [FirstValue, ...{
[K in Extract<keyof FirstValue, string | ColumnName<T>>]: ColumnValue<T, K>
}[]],
options: { returning?: Returning } = {}
): Promise<
Returning extends ['*']
Expand All @@ -319,16 +321,16 @@ export class QueryBuilder<
? Pick<TableType<T>, Returning[number]>
: Record<string, any>[]
> {
const valuesArray = Array.isArray(values) ? values : [values]

const sql = [
'INSERT INTO',
escapeIdentifier(this.table),
'(',
Object.keys(values).map(escapeIdentifier).join(','),
') VALUES (',
Object.values(values)
.map(() => '?')
.join(','),
')',
Object.keys(valuesArray[0]).map(escapeIdentifier).join(','),
') VALUES',

valuesArray.map((v) => `(${Object.keys(v).map(() => '?').join(',')})`).join(',')
]

if (options.returning?.length)
Expand All @@ -339,7 +341,7 @@ export class QueryBuilder<
.join(',')
)

return this.client.raw(sql.join(' '), ...Object.values(values)) as any
return this.client.raw(sql.join(' '), ...(valuesArray.map(v => Object.values(v))).flat()) as any
}

async update<Returning extends (keyof TableType<T>)[] | ['*']>(
Expand Down

0 comments on commit 7fc4410

Please sign in to comment.