Skip to content

Commit ff8ffac

Browse files
committed
Fix COPY TO/FROM /dev/blob device
1 parent da39ce8 commit ff8ffac

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

packages/pglite/src/pglite.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,58 @@ export class PGlite implements PGliteInterface {
145145
? { print: console.info, printErr: console.error }
146146
: { print: () => {}, printErr: () => {} }),
147147
locateFile: await makeLocateFile(),
148+
preRun: [
149+
(mod: any) => {
150+
// Register /dev/blob device
151+
// This is used to read and write blobs when used in COPY TO/FROM
152+
// e.g. COPY mytable TO '/dev/blob' WITH (FORMAT binary)
153+
// The data is returned by the query as a `blob` property in the results
154+
const devId = mod.FS.makedev(64, 0);
155+
let callCounter = 0;
156+
const devOpt = {
157+
open: (stream: any) => {},
158+
close: (stream: any) => {},
159+
read: (
160+
stream: any,
161+
buffer: Uint8Array,
162+
offset: number,
163+
length: number,
164+
position: number,
165+
) => {
166+
const buf = this.#queryReadBuffer;
167+
if (!buf) {
168+
throw new Error("No File or Blob provided to read from");
169+
}
170+
const contents = new Uint8Array(buf);
171+
if (position >= contents.length) return 0;
172+
const size = Math.min(contents.length - position, length);
173+
for (let i = 0; i < size; i++) {
174+
buffer[offset + i] = contents[position + i];
175+
}
176+
return size;
177+
},
178+
write: (
179+
stream: any,
180+
buffer: Uint8Array,
181+
offset: number,
182+
length: number,
183+
position: number,
184+
) => {
185+
callCounter++;
186+
this.#queryWriteChunks ??= [];
187+
this.#queryWriteChunks.push(
188+
buffer.slice(offset, offset + length),
189+
);
190+
return length;
191+
},
192+
llseek: (stream: any, offset: number, whence: number) => {
193+
throw new Error("Cannot seek /dev/blob");
194+
},
195+
};
196+
mod.FS.registerDevice(devId, devOpt);
197+
mod.FS.mkdev("/dev/blob", devId);
198+
},
199+
],
148200
};
149201

150202
emscriptenOpts = await this.fs!.emscriptenOpts(emscriptenOpts);

packages/pglite/tests/basic.test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,6 @@ test("basic transaction", async (t) => {
320320
});
321321
});
322322

323-
/*
324323
test("basic copy to/from blob", async (t) => {
325324
const db = new PGlite();
326325
await db.exec(`
@@ -372,4 +371,3 @@ test("basic copy to/from blob", async (t) => {
372371
affectedRows: 0,
373372
});
374373
});
375-
*/

0 commit comments

Comments
 (0)