Postgres client - more progress (#15086)

This commit is contained in:
Jarred Sumner
2024-11-11 14:40:02 -08:00
committed by GitHub
parent 4cf9851747
commit b49f6d143e
13 changed files with 2657 additions and 2042 deletions

View File

@@ -1,6 +1,8 @@
import { postgres, sql } from "bun:sql";
import { expect, test } from "bun:test";
import { isCI } from "harness";
import { $ } from "bun";
import { bunExe, isCI, withoutAggressiveGC } from "harness";
import path from "path";
if (!isCI) {
require("./bootstrap.js");
@@ -100,12 +102,13 @@ if (!isCI) {
expect((await sql`select ${null} as x`)[0].x).toBeNull();
});
test("Unsigned Integer", async () => {
test.todo("Unsigned Integer", async () => {
expect((await sql`select ${0x7fffffff + 2} as x`)[0].x).toBe(0x7fffffff + 2);
});
test("Signed Integer", async () => {
expect((await sql`select ${-1} as x`)[0].x).toBe(-1);
expect((await sql`select ${1} as x`)[0].x).toBe(1);
});
test("Double", async () => {
@@ -120,12 +123,18 @@ if (!isCI) {
test("Boolean true", async () => expect((await sql`select ${true} as x`)[0].x).toBe(true));
test("Date", async () => {
test("Date (timestamp)", async () => {
const now = new Date();
const then = (await sql`select ${now}::timestamp as x`)[0].x;
expect(then).toEqual(now);
});
test("Date (timestamptz)", async () => {
const now = new Date();
const then = (await sql`select ${now}::timestamptz as x`)[0].x;
expect(then).toEqual(now);
});
// t("Json", async () => {
// const x = (await sql`select ${sql.json({ a: "hello", b: 42 })} as x`)[0].x;
// return ["hello,42", [x.a, x.b].join()];
@@ -142,6 +151,23 @@ if (!isCI) {
expect([x.a, x.b].join(",")).toBe("hello,42");
});
test("bulk insert nested sql()", async () => {
await sql`create table users (name text, age int)`;
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
];
try {
const result = await sql`insert into users ${sql(users)} RETURNING *`;
expect(result).toEqual([
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
]);
} finally {
await sql`drop table users`;
}
});
// t("Empty array", async () => [true, Array.isArray((await sql`select ${sql.array([], 1009)} as x`)[0].x)]);
test("string arg with ::int -> Array<int>", async () =>
@@ -991,16 +1017,46 @@ if (!isCI) {
// }`.catch(e => e.code)), await sql`drop table test`]
// })
test("let postgres do implicit cast of unknown types", async () => {
test("timestamp with time zone is consistent", async () => {
await sql`create table test (x timestamp with time zone)`;
try {
const [{ x }] = await sql`insert into test values (${new Date().toISOString()}) returning *`;
const date = new Date();
const [{ x }] = await sql`insert into test values (${date}) returning *`;
expect(x instanceof Date).toBe(true);
expect(x.toISOString()).toBe(date.toISOString());
} finally {
await sql`drop table test`;
}
});
test("timestamp is consistent", async () => {
await sql`create table test2 (x timestamp)`;
try {
const date = new Date();
const [{ x }] = await sql`insert into test2 values (${date}) returning *`;
expect(x instanceof Date).toBe(true);
expect(x.toISOString()).toBe(date.toISOString());
} finally {
await sql`drop table test2`;
}
});
test(
"let postgres do implicit cast of unknown types",
async () => {
await sql`create table test3 (x timestamp with time zone)`;
try {
const date = new Date("2024-01-01T00:00:00Z");
const [{ x }] = await sql`insert into test3 values (${date.toISOString()}) returning *`;
expect(x instanceof Date).toBe(true);
expect(x.toISOString()).toBe(date.toISOString());
} finally {
await sql`drop table test3`;
}
},
{ timeout: 1000000 },
);
// t('only allows one statement', async() =>
// ['42601', await sql`select 1; select 2`.catch(e => e.code)]
// )
@@ -1580,9 +1636,17 @@ if (!isCI) {
// return [1, (await sql`select 1 as x`)[0].x]
// })
// t('Big result', async() => {
// return [100000, (await sql`select * from generate_series(1, 100000)`).count]
// })
test("Big result", async () => {
const result = await sql`select * from generate_series(1, 100000)`;
expect(result.count).toBe(100000);
let i = 1;
for (const row of result) {
if (row.generate_series !== i++) {
throw new Error(`Row out of order at index ${i - 1}`);
}
}
});
// t('Debug', async() => {
// let result
@@ -1601,15 +1665,14 @@ if (!isCI) {
// typeof (await sql`select 9223372036854777 as x`)[0].x
// ])
// t('int is returned as Number', async() => [
// 'number',
// typeof (await sql`select 123 as x`)[0].x
// ])
test("int is returned as Number", async () => {
expect((await sql`select 123 as x`)[0].x).toBe(123);
});
// t('numeric is returned as string', async() => [
// 'string',
// typeof (await sql`select 1.2 as x`)[0].x
// ])
test("numeric is returned as string", async () => {
const result = (await sql`select 1.2 as x`)[0].x;
expect(result).toBe("1.2");
});
// t('Async stack trace', async() => {
// const sql = postgres({ ...options, debug: false })
@@ -1733,9 +1796,9 @@ if (!isCI) {
// [true, (await sql`bad keyword`.catch(e => e)) instanceof sql.PostgresError]
// )
// t('Result has columns spec', async() =>
// ['x', (await sql`select 1 as x`).columns[0].name]
// )
test.todo("Result has columns spec", async () => {
expect((await sql`select 1 as x`).columns[0].name).toBe("x");
});
// t('forEach has result as second argument', async() => {
// let x
@@ -1921,9 +1984,9 @@ if (!isCI) {
// ]
// })
// t('Array returns rows as arrays of columns', async() => {
// return [(await sql`select 1`.values())[0][0], 1]
// })
test("Array returns rows as arrays of columns", async () => {
return [(await sql`select 1`.values())[0][0], 1];
});
// t('Copy read', async() => {
// const result = []
@@ -2586,4 +2649,11 @@ if (!isCI) {
// xs.map(x => x.x).join('')
// ]
// })
test("keeps process alive when it should", async () => {
const file = path.posix.join(__dirname, "sql-fixture-ref.ts");
const result = await $`DATABASE_URL=${process.env.DATABASE_URL} ${bunExe()} ${file}`;
expect(result.exitCode).toBe(0);
expect(result.stdout.toString().split("\n")).toEqual(["1", "2", ""]);
});
}