mirror of
https://github.com/oven-sh/bun
synced 2026-02-11 03:18:53 +00:00
fix(Bun.SQL) fix IN, UPDATE support in helpers, and fix JSONB/JSON serialization (#22700)
### What does this PR do? Fixes https://github.com/oven-sh/bun/issues/20669 Fixes https://github.com/oven-sh/bun/issues/18775 Fixes https://github.com/oven-sh/bun/issues/22156 Fixes https://github.com/oven-sh/bun/issues/22164 Fixes https://github.com/oven-sh/bun/issues/18254 Fixes https://github.com/oven-sh/bun/issues/21267 Fixes https://github.com/oven-sh/bun/issues/20669 Fixes https://github.com/oven-sh/bun/issues/1317 Fixes https://github.com/oven-sh/bun/pull/22700 Partially Fixes https://github.com/oven-sh/bun/issues/22757 (sqlite pending, need a followup and probably @alii help here) ### How did you verify your code works? Tests --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { SQL } from "bun";
|
||||
import { randomUUIDv7, SQL } from "bun";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import { tempDirWithFiles } from "harness";
|
||||
import { existsSync } from "node:fs";
|
||||
@@ -1311,6 +1311,130 @@ describe("SQL helpers", () => {
|
||||
expect(results[0].value).toBe("test");
|
||||
});
|
||||
|
||||
test("insert into with select helper using where IN", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
{
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql({ id: 1, name: "John", age: 30 })}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("John");
|
||||
expect(result[0].age).toBe(30);
|
||||
}
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name + "2")} (id int, name text, age int)`;
|
||||
{
|
||||
await sql`INSERT INTO ${sql(random_name + "2")} (id, name, age) SELECT id, name, age FROM ${sql(random_name)} WHERE id IN ${sql([1, 2])}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name + "2")}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("John");
|
||||
expect(result[0].age).toBe(30);
|
||||
}
|
||||
});
|
||||
|
||||
test("update helper with undefined values", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
const users = [
|
||||
{ id: 1, name: "John", age: 30 },
|
||||
{ id: 2, name: "Jane", age: 25 },
|
||||
];
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql(users)}`;
|
||||
|
||||
await sql`UPDATE ${sql(random_name)} SET ${sql({ name: "Mary", age: undefined })} WHERE id IN ${sql([1, 2])}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("Mary");
|
||||
expect(result[0].age).toBe(30);
|
||||
expect(result[1].id).toBe(2);
|
||||
expect(result[1].name).toBe("Mary");
|
||||
expect(result[1].age).toBe(25);
|
||||
});
|
||||
test("update helper that starts with undefined values", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
const users = [
|
||||
{ id: 1, name: "John", age: 30 },
|
||||
{ id: 2, name: "Jane", age: 25 },
|
||||
];
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql(users)}`;
|
||||
|
||||
await sql`UPDATE ${sql(random_name)} SET ${sql({ name: undefined, age: 19 })} WHERE id IN ${sql([1, 2])}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("John");
|
||||
expect(result[0].age).toBe(19);
|
||||
expect(result[1].id).toBe(2);
|
||||
expect(result[1].name).toBe("Jane");
|
||||
expect(result[1].age).toBe(19);
|
||||
});
|
||||
|
||||
test("update helper with undefined values and no columns", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
const users = [
|
||||
{ id: 1, name: "John", age: 30 },
|
||||
{ id: 2, name: "Jane", age: 25 },
|
||||
];
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql(users)}`;
|
||||
|
||||
try {
|
||||
await sql`UPDATE ${sql(random_name)} SET ${sql({ name: undefined, age: undefined })} WHERE id IN ${sql([1, 2])}`;
|
||||
expect.unreachable();
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(SyntaxError);
|
||||
expect(e.message).toBe("Update needs to have at least one column");
|
||||
}
|
||||
});
|
||||
|
||||
test("update helper with IN and column name", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
const users = [
|
||||
{ id: 1, name: "John", age: 30 },
|
||||
{ id: 2, name: "Jane", age: 25 },
|
||||
];
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql(users)}`;
|
||||
|
||||
await sql`UPDATE ${sql(random_name)} SET ${sql({ name: "Mary", age: 18 })} WHERE id IN ${sql(users, "id")}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("Mary");
|
||||
expect(result[0].age).toBe(18);
|
||||
expect(result[1].id).toBe(2);
|
||||
expect(result[1].name).toBe("Mary");
|
||||
expect(result[1].age).toBe(18);
|
||||
});
|
||||
|
||||
test("select helper with IN using fragment", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql({ id: 1, name: "John", age: 30 })}`;
|
||||
const fragment = sql`id IN ${sql([1, 2])}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)} WHERE ${fragment}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("John");
|
||||
expect(result[0].age).toBe(30);
|
||||
});
|
||||
|
||||
test("update helper with AND IN", async () => {
|
||||
const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", "");
|
||||
await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text, age int)`;
|
||||
const users = [
|
||||
{ id: 1, name: "John", age: 30 },
|
||||
{ id: 2, name: "Jane", age: 25 },
|
||||
];
|
||||
await sql`INSERT INTO ${sql(random_name)} ${sql(users)}`;
|
||||
|
||||
await sql`UPDATE ${sql(random_name)} SET ${sql({ name: "Mary", age: 18 })} WHERE 1=1 AND id IN ${sql([1, 2])}`;
|
||||
const result = await sql`SELECT * FROM ${sql(random_name)}`;
|
||||
expect(result[0].id).toBe(1);
|
||||
expect(result[0].name).toBe("Mary");
|
||||
expect(result[0].age).toBe(18);
|
||||
expect(result[1].id).toBe(2);
|
||||
expect(result[1].name).toBe("Mary");
|
||||
expect(result[1].age).toBe(18);
|
||||
});
|
||||
|
||||
test("file execution", async () => {
|
||||
const dir = tempDirWithFiles("sql-files", {
|
||||
"schema.sql": `
|
||||
|
||||
Reference in New Issue
Block a user