Skip to content

Commit

Permalink
If we're passed sql in update/insert don't run it through mapToDriver…
Browse files Browse the repository at this point in the history
…Value
  • Loading branch information
benmerckx committed Nov 26, 2024
1 parent 2815d89 commit 6831696
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 9 deletions.
Binary file modified bun.lockb
Binary file not shown.
6 changes: 3 additions & 3 deletions src/core/expr/Input.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {getSql, getTable, hasSql, hasTable, type HasSql} from '../Internal.ts'
import {sql, type Sql} from '../Sql.ts'
import {type HasSql, getSql, getTable, hasSql, hasTable} from '../Internal.ts'
import {type Sql, sql} from '../Sql.ts'

export type Input<T = unknown> = HasSql<T> | T

export function input<T>(value: Input<T>): Sql<T> {
if (typeof value !== 'object' || value === null) return sql.value(value)
if (hasTable(value)) return sql.identifier(getTable(value).name)
if (hasSql(value)) return getSql(value) as Sql<T>
if (hasSql(value)) return getSql(value)
return sql.value(value)
}
6 changes: 5 additions & 1 deletion src/core/query/Insert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getData,
getQuery,
getTable,
hasSql,
internalData,
internalQuery,
internalSelection
Expand Down Expand Up @@ -182,8 +183,11 @@ export class InsertInto<
Object.entries(table.columns).map(([key, column]) => {
const value = row[key]
const {$default, mapToDriverValue} = getData(column)
if (value !== undefined)
if (value !== undefined) {
if (value && typeof value === 'object' && hasSql(value))
return value
return input(mapToDriverValue?.(value) ?? value)
}
if ($default) return $default()
return defaultKeyword
}),
Expand Down
9 changes: 6 additions & 3 deletions src/core/query/Update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
type HasTable,
getData,
getTable,
hasSql,
internalData,
internalQuery,
internalSelection
Expand Down Expand Up @@ -56,9 +57,11 @@ export class UpdateTable<
Object.entries(values).map(([key, value]) => {
const column = getTable(table).columns[key]
const {mapToDriverValue} = getData(column)
return sql`${sql.identifier(key)} = ${input(
mapToDriverValue?.(value) ?? value
)}`
const expr =
value && typeof value === 'object' && hasSql(value)
? value
: input(mapToDriverValue?.(value) ?? value)
return sql`${sql.identifier(key)} = ${expr}`
}),
sql`, `
)
Expand Down
6 changes: 6 additions & 0 deletions test/core/Expr.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as e from '@/core/expr/Conditions.ts'
import {Functions} from '@/core/expr/Functions.ts'
import {jsonExpr} from '@/core/expr/Json.ts'
import {sql} from '@/index.ts'
import {suite} from '@alinea/suite'
Expand Down Expand Up @@ -119,4 +120,9 @@ suite(import.meta, test => {
const x = obj.a.x
test.equal(emit(x), 'test->>"$.a.x"')
})

test('function', () => {
const patch = Functions.json_patch({a: 1}, {b: 1})
test.equal(emit(patch), '"json_patch"({"a":1}, {"b":1})')
})
})
30 changes: 30 additions & 0 deletions test/integration/TestUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {type Database, eq} from '@/index.ts'
import type {DefineTest} from '@alinea/suite'
import {concat} from '../../src/universal.ts'
import {Node} from './schema.ts'

export function testUpdate(db: Database, test: DefineTest) {
test('update', async () => {
await db.create(Node)
try {
await db.insert(Node).values({
textField: 'hello',
bool: true
})

await db
.update(Node)
.set({textField: concat(Node.textField, ' world')})
.where(eq(Node.textField, 'hello'))

const node = await db.select().from(Node).get()
test.equal(node, {
id: 1,
textField: 'hello world',
bool: true
})
} finally {
await db.drop(Node)
}
})
}
16 changes: 14 additions & 2 deletions test/query/Update.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import {sql, table} from '@/index.ts'
import {QueryBuilder} from '@/postgres/builder.ts'
import {integer} from '@/sqlite/columns.ts'
import {integer, json} from '@/sqlite/columns.ts'
import {suite} from '@alinea/suite'
import {Functions} from '../../src/core/expr/Functions.ts'
import {builder, emit} from '../TestUtils.ts'

suite(import.meta, test => {
const definition = {
id: integer().primaryKey(),
withDefault: integer().default(2),
required: integer().notNull(),
nullable: integer()
nullable: integer(),
data: json()
}

const Node = table('Node', definition)
Expand All @@ -26,6 +28,16 @@ suite(import.meta, test => {
)
})

test('update with function', () => {
const query = builder.update(Node).set({
data: Functions.json_patch(Node.data, {a: 1})
})
test.equal(
emit(query),
'update "Node" set "data" = "json_patch"("data", {"a":1})'
)
})

test('returning', () => {
const query = new QueryBuilder()
.update(Node)
Expand Down

0 comments on commit 6831696

Please sign in to comment.