Skip to content
Open
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
58eb89a
Use correct LLVM version
gohryt Jul 30, 2025
4e02d47
Fix linting
gohryt Sep 17, 2025
b3d7129
Add zed settings
gohryt Oct 4, 2025
6ad42f7
Add COPY support
gohryt Oct 7, 2025
1d53572
Fix ASAN leak
gohryt Oct 7, 2025
65890e1
Replace local configuration with path relative to project root
gohryt Oct 7, 2025
f8d5139
Update sql.d.ts to follow implementation changes
gohryt Oct 7, 2025
f6e9fde
Update sql.d.ts to follow implementation changes
gohryt Oct 7, 2025
3165a59
Fix schema-qualified table quoting in copyTo
gohryt Oct 7, 2025
3af329b
Prevent double-free and leaks when reusing CopyInResponse
gohryt Oct 7, 2025
841a5bf
Avoid logging at ts code
gohryt Oct 7, 2025
6694a41
Migrate tests from local repo
gohryt Oct 8, 2025
f9d720d
Fix text/CSV COPY rows bypass maxBytes & progress tracking
gohryt Oct 8, 2025
d136c61
Fix don’t coerce copy limits with | 0.
gohryt Oct 8, 2025
d943356
I hate it
gohryt Oct 8, 2025
39ee964
Fix await addToBatch for raw string chunks in sync iterable loop.
gohryt Oct 9, 2025
87995d1
Fixes related to AI audit
gohryt Oct 9, 2025
68c2995
Fixes related to AI audit
gohryt Oct 9, 2025
0756879
Fixes related to AI audit
gohryt Oct 9, 2025
36155b6
Fixes related to AI audit
gohryt Oct 9, 2025
66c0421
Fixes related to AI audit
gohryt Oct 11, 2025
504ef38
Fixes related to AI audit
gohryt Oct 11, 2025
d9798bf
Fixes related to AI audit
gohryt Oct 12, 2025
ed06c16
Merge branch 'main' into gohryt-1
gohryt Oct 15, 2025
50f34c7
Fixes related to AI audit
gohryt Oct 16, 2025
f1c0184
Fixes related to AI audit
gohryt Oct 16, 2025
c1c84cf
Merge branch 'main' into gohryt-1
gohryt Oct 29, 2025
54455f6
Merge branch 'main' into gohryt-1
gohryt Nov 13, 2025
1acc43b
Merge branch 'main' into gohryt-1
gohryt Nov 14, 2025
06c1665
Revert "Use correct LLVM version"
gohryt Nov 14, 2025
11bfab3
Make it work with zig 0.15.2, fixes related to ai audit
gohryt Nov 15, 2025
549f56f
Replace direct zig and zls path with direnv
gohryt Jan 9, 2026
a38eae8
Merge branch 'main' into gohryt-1
gohryt Jan 9, 2026
8899ef7
Cleanup tests
gohryt Jan 9, 2026
b65be62
Merge branch 'main' into gohryt-1
gohryt Jan 18, 2026
53dfd5b
Fix tests for updated main
gohryt Jan 18, 2026
d3743ec
Cleanup for duplicating code, rework errors, handle large inputs
gohryt Jan 18, 2026
7dce80c
Fixes related to AI audit
gohryt Jan 18, 2026
2ad3b3c
Fixes related to AI audit
gohryt Jan 18, 2026
aa91385
Fixes related to AI audit
gohryt Jan 18, 2026
4b6cc5f
Fixes related to AI audit
gohryt Jan 18, 2026
70a1871
Fixes related to AI audit
gohryt Jan 18, 2026
9d51e90
Avoid typing to any
gohryt Jan 18, 2026
ba95f44
Fixes related to AI audit
gohryt Jan 18, 2026
951dfd9
Fixes related to AI audit
gohryt Jan 18, 2026
9ffce71
Fix typing on ts side
gohryt Jan 18, 2026
2f7f0f0
Fixes related to AI audit
gohryt Jan 18, 2026
efdfb54
Fixes related to AI audit
gohryt Jan 18, 2026
b528a2e
Fixes related to AI audit
gohryt Jan 18, 2026
59674c1
Fixes related to AI audit
gohryt Jan 19, 2026
9fe79fd
Fixes related to AI audit
gohryt Jan 19, 2026
01f88f8
Fixes related to AI audit
gohryt Jan 19, 2026
6f84feb
Fixes related to AI audit
gohryt Jan 19, 2026
6b5a71f
Fixes related to AI audit
gohryt Jan 19, 2026
dc5b996
Fixes related to AI audit
gohryt Jan 19, 2026
533f607
Fixes related to AI audit
gohryt Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
.vscode/clang*
.vscode/cpp*
.zig-cache
.ccls-cache
.bake-debug
*.a
*.bc
Expand Down
9 changes: 9 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"lsp": {
"zls": {
"settings": {
"build_on_save_args": ["-Dgenerated-code=./build/debug/codegen", "--watch", "-fincremental"],
},
},
},
}
Comment thread
gohryt marked this conversation as resolved.
237 changes: 236 additions & 1 deletion packages/bun-types/sql.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,72 @@ declare module "bun" {
* Releases the client back to the connection pool
*/
release(): void;

/**
* Register callback when server replies with CopyInResponse/CopyOutResponse
*/
onCopyStart(handler: () => void): void;

/**
* Send COPY data chunk (for COPY FROM STDIN)
*/
copySendData(data: string | Uint8Array): void;

/**
* Signal end of COPY FROM STDIN operation
*/
copyDone(): void;

/**
* Abort COPY operation with optional error message
*/
copyFail(message?: string): void;

/**
* Enable or disable streaming mode for COPY TO
* When enabled, data is not accumulated in memory and chunks are emitted via onCopyChunk
*/
setCopyStreamingMode(enable: boolean): void;

/**
* Set COPY operation timeout in milliseconds (0 to disable)
*/
setCopyTimeout(ms: number): void;

/**
* Set maximum buffer size for COPY operations in bytes
*/
setMaxCopyBufferSize(bytes: number): void;

/**
* Register callback for streaming COPY TO data chunks
*
* @returns true if the handler was registered (adapter supports streaming), otherwise false.
*/
onCopyChunk(handler: (chunk: string | ArrayBuffer | Uint8Array) => void): boolean;

/**
* Register callback when COPY TO completes
*
* @returns true if the handler was registered (adapter supports streaming), otherwise false.
*/
onCopyEnd(handler: () => void): boolean;

/**
* Get current COPY operation defaults
*/
getCopyDefaults(): {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
};

/**
* Set COPY operation defaults
*/
setCopyDefaults(defaults: {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
}): this;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

type ArrayType =
Expand All @@ -18,7 +84,6 @@ declare module "bun" {
| "CHAR"
| "NAME"
| "TEXT"
| "CHAR"
| "VARCHAR"
| "SMALLINT"
| "INT2VECTOR"
Expand Down Expand Up @@ -60,6 +125,40 @@ declare module "bun" {
| "PG_DATABASE"
| (string & {});

/**
* PostgreSQL COPY binary format base types
*/
type CopyBinaryBaseType =
| "bool"
| "int2"
| "int4"
| "int8"
| "float4"
| "float8"
| "text"
| "varchar"
| "bpchar"
| "bytea"
| "date"
| "time"
| "timestamp"
| "timestamptz"
| "uuid"
| "json"
| "jsonb"
| "numeric"
| "interval";

/**
* PostgreSQL COPY binary format array types
*/
type CopyBinaryArrayType = `${CopyBinaryBaseType}[]`;

/**
* PostgreSQL COPY binary format type tokens
*/
type CopyBinaryType = CopyBinaryBaseType | CopyBinaryArrayType;

/**
* Represents a SQL array parameter
*/
Expand Down Expand Up @@ -101,6 +200,48 @@ declare module "bun" {
constructor(message: string);
}

/**
* COPY FROM STDIN options (PostgreSQL COPY protocol)
*/
type CopyFromOptions = {
format?: "text" | "csv" | "binary";
delimiter?: string;
null?: string;
sanitizeNUL?: boolean;
replaceInvalid?: string;
signal?: AbortSignal;
onProgress?: (info: { bytesSent: number; chunksSent: number }) => void;
batchSize?: number;
/**
* When format is "binary" and passing row arrays, provide per-column type tokens
* (e.g. "int4","text","uuid","int4[]")
*/
binaryTypes?: readonly CopyBinaryType[];
/** Maximum number of bytes to send per chunk (defaults to 256 KiB) */
maxChunkSize?: number;
/** Maximum total number of bytes to send (0 = unlimited) */
maxBytes?: number;
/** COPY operation timeout in milliseconds (0 = no timeout) */
timeout?: number;
};

/**
* COPY TO STDOUT options (PostgreSQL COPY protocol)
*/
type CopyToOptions = {
table: string;
columns?: string[];
format?: "text" | "csv" | "binary";
signal?: AbortSignal;
onProgress?: (info: { bytesReceived: number; chunksReceived: number }) => void;
/** Maximum total number of bytes to receive (0 = unlimited) */
maxBytes?: number;
/** Enable streaming mode to avoid buffering (defaults to true) */
stream?: boolean;
/** COPY operation timeout in milliseconds (0 = no timeout) */
timeout?: number;
};

class PostgresError extends SQLError {
public readonly code: string;
public readonly errno?: string | undefined;
Expand Down Expand Up @@ -537,6 +678,53 @@ declare module "bun" {
* ```
*/
<T>(value: T): SQL.Helper<T>;

/** COPY FROM STDIN - bulk import helper (PostgreSQL COPY protocol) */
copyFrom(
table: string,
columns: string[],
data:
| string
| unknown[]
| Iterable<unknown[]>
| AsyncIterable<unknown[]>
| AsyncIterable<string | Uint8Array | ArrayBuffer>
| (() => Iterable<unknown[]>),
options?: SQL.CopyFromOptions,
): Promise<{ command: string | null; count: number | null }>;

/** COPY TO STDOUT - streaming export helper (PostgreSQL COPY protocol) */
copyTo(queryOrOptions: string | SQL.CopyToOptions): AsyncIterable<string | ArrayBuffer>;

/** COPY TO STDOUT piping helper - pipe stream directly to a sink */
copyToPipeTo(
queryOrOptions: string | SQL.CopyToOptions,
writable:
| WritableStream<Uint8Array | string>
| {
write: (chunk: string | ArrayBuffer | Uint8Array) => unknown | Promise<unknown>;
close?: () => unknown | Promise<unknown>;
end?: () => unknown | Promise<unknown>;
},
): Promise<void>;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Get current COPY operation defaults
*/
getCopyDefaults(): {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
};

/**
* Set COPY operation defaults
*
* Returns the SQL instance for chaining.
*/
setCopyDefaults(defaults: {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
}): this;
}

/**
Expand Down Expand Up @@ -866,6 +1054,53 @@ declare module "bun" {
* const result = await sql.file("query.sql", [1, 2, 3]);
*/
file<T = any>(filename: string, values?: any[]): SQL.Query<T>;

/** COPY FROM STDIN - bulk import helper (PostgreSQL COPY protocol) */
copyFrom(
table: string,
columns: string[],
data:
| string
| unknown[]
| Iterable<unknown[]>
| AsyncIterable<unknown[]>
| AsyncIterable<string | Uint8Array | ArrayBuffer>
| (() => Iterable<unknown[]>),
options?: SQL.CopyFromOptions,
): Promise<{ command: string | null; count: number | null }>;

/** COPY TO STDOUT - streaming export helper (PostgreSQL COPY protocol) */
copyTo(queryOrOptions: string | SQL.CopyToOptions): AsyncIterable<string | ArrayBuffer>;

/** COPY TO STDOUT piping helper - pipe stream directly to a sink */
copyToPipeTo(
queryOrOptions: string | SQL.CopyToOptions,
writable:
| WritableStream<Uint8Array | string>
| {
write: (chunk: string | ArrayBuffer | Uint8Array) => unknown | Promise<unknown>;
close?: () => unknown | Promise<unknown>;
end?: () => unknown | Promise<unknown>;
},
): Promise<void>;

/**
* Get current COPY operation defaults
*/
getCopyDefaults(): {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
};

/**
* Set COPY operation defaults
*
* Returns the SQL instance for chaining.
*/
setCopyDefaults(defaults: {
from?: { maxChunkSize?: number; maxBytes?: number; timeout?: number };
to?: { stream?: boolean; maxBytes?: number; timeout?: number };
}): this;
}

/**
Expand Down
80 changes: 49 additions & 31 deletions src/bun.js/api/sql.classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,54 @@ import { ClassDefinition, define } from "../../codegen/class-definitions";
const types = ["PostgresSQL", "MySQL"];
const classes: ClassDefinition[] = [];
for (const type of types) {
const proto: any = {
close: {
fn: "doClose",
},
connected: {
getter: "getConnected",
},
ref: {
fn: "doRef",
},
unref: {
fn: "doUnref",
},
flush: {
fn: "doFlush",
},
queries: {
getter: "getQueries",
this: true,
},
onconnect: {
getter: "getOnConnect",
setter: "setOnConnect",
this: true,
},
onclose: {
getter: "getOnClose",
setter: "setOnClose",
this: true,
},
};

// Add COPY methods only for PostgreSQL
if (type === "PostgresSQL") {
proto.sendCopyData = {
fn: "sendCopyData",
length: 1,
};
proto.sendCopyDone = {
fn: "sendCopyDone",
length: 0,
};
proto.sendCopyFail = {
fn: "sendCopyFail",
length: 1,
};
}

classes.push(
define({
name: `${type}Connection`,
Expand All @@ -19,37 +67,7 @@ for (const type of types) {
// },
},
JSType: "0b11101110",
proto: {
close: {
fn: "doClose",
},
connected: {
getter: "getConnected",
},
ref: {
fn: "doRef",
},
unref: {
fn: "doUnref",
},
flush: {
fn: "doFlush",
},
queries: {
getter: "getQueries",
this: true,
},
onconnect: {
getter: "getOnConnect",
setter: "setOnConnect",
this: true,
},
onclose: {
getter: "getOnClose",
setter: "setOnClose",
this: true,
},
},
proto,
values: ["onconnect", "onclose", "queries"],
}),
);
Expand Down
Loading