From f94d5919240849ff54e9a11679816a9ba1bbc65e Mon Sep 17 00:00:00 2001 From: Tudor Zaharia <37596026+copiltembel@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:21:08 +0100 Subject: [PATCH] Simple clone impl only on PGlite (#526) * simple clone impl on PGlite --------- Co-authored-by: tudor --- .changeset/mighty-grapes-refuse.md | 5 ++++ docs/docs/api.md | 5 ++++ packages/pglite/src/pglite.ts | 5 ++++ packages/pglite/tests/clone.test.js | 42 +++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 .changeset/mighty-grapes-refuse.md create mode 100644 packages/pglite/tests/clone.test.js diff --git a/.changeset/mighty-grapes-refuse.md b/.changeset/mighty-grapes-refuse.md new file mode 100644 index 00000000..db36b19d --- /dev/null +++ b/.changeset/mighty-grapes-refuse.md @@ -0,0 +1,5 @@ +--- +'@electric-sql/pglite': patch +--- + +added clone() method to pglite API. clones an instance such that it can be reused (for example running tests on existing data without readding all data) diff --git a/docs/docs/api.md b/docs/docs/api.md index 5c5673d7..df3b3d90 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -361,6 +361,11 @@ await pg.describeQuery('SELECT * FROM test WHERE name = $1', ['test']) } ``` +### clone +`.clone(): Promise` + +Clones the current instance. This is useful when a series of operations, like unit or integration test, need to be run on the same database without having to recreate the database each time, or for each test. + ## Properties ### ready diff --git a/packages/pglite/src/pglite.ts b/packages/pglite/src/pglite.ts index 8cad5813..5eb8ff54 100644 --- a/packages/pglite/src/pglite.ts +++ b/packages/pglite/src/pglite.ts @@ -794,4 +794,9 @@ export class PGlite _runExclusiveTransaction(fn: () => Promise): Promise { return this.#transactionMutex.runExclusive(fn) } + + async clone(): Promise { + const dump = await this.dumpDataDir('none') + return new PGlite({ loadDataDir: dump }) + } } diff --git a/packages/pglite/tests/clone.test.js b/packages/pglite/tests/clone.test.js new file mode 100644 index 00000000..81283f66 --- /dev/null +++ b/packages/pglite/tests/clone.test.js @@ -0,0 +1,42 @@ +import { describe, it, expect } from 'vitest' +import { PGlite } from '../dist/index.js' + +describe('clone', () => { + it('clone pglite instance', async () => { + const pg1 = new PGlite() + await pg1.exec(` + CREATE TABLE IF NOT EXISTS test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await pg1.exec("INSERT INTO test (name) VALUES ('test');") + + const pg2 = await pg1.clone() + + const ret1 = await pg1.query('SELECT * FROM test;') + const ret2 = await pg2.query('SELECT * FROM test;') + + expect(ret1).toEqual(ret2) + }) + + it('clone pglite instance - insert into pg2', async () => { + const pg1 = new PGlite() + await pg1.exec(` + CREATE TABLE IF NOT EXISTS test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await pg1.exec("INSERT INTO test (name) VALUES ('test');") + + const pg2 = await pg1.clone() + await pg2.exec("INSERT INTO test (name) VALUES ('2-test');") + + const ret1 = await pg1.query('SELECT * FROM test;') + const ret2 = await pg2.query('SELECT * FROM test;') + + expect(ret1.rows.length).toBe(1) + expect(ret2.rows.length).toBe(2) + }) +})