Skip to content

Commit

Permalink
Merge pull request #133 from libsql/add-support-for-in-memory-db
Browse files Browse the repository at this point in the history
Add support for in-memory databases
  • Loading branch information
LucioFranco authored Nov 21, 2023
2 parents 50f190d + 81b0294 commit e7d1f20
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 52 deletions.
82 changes: 41 additions & 41 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,50 +126,50 @@ jobs:
# run: "cd smoke_test/workers && python ../../hrana-test-server/server_v3.py node test.js"
# env: {"LOCAL": "0", "URL": "http://localhost:8080"}

"vercel-test":
name: "Build and test with Vercel Edge Functions"
runs-on: ubuntu-latest
env:
VERCEL_TOKEN: "${{ secrets.VERCEL_TOKEN }}"
VERCEL_PROJECT_NAME: "smoke-test"
steps:
- name: "Checkout this repo"
uses: actions/checkout@v3
- name: "Setup Node.js"
uses: actions/setup-node@v3
with:
node-version: "lts/Hydrogen"
cache: "npm"
- name: "Install npm dependencies"
run: "npm ci"
# "vercel-test":
# name: "Build and test with Vercel Edge Functions"
# runs-on: ubuntu-latest
# env:
# VERCEL_TOKEN: "${{ secrets.VERCEL_TOKEN }}"
# VERCEL_PROJECT_NAME: "smoke-test"
# steps:
# - name: "Checkout this repo"
# uses: actions/checkout@v3
# - name: "Setup Node.js"
# uses: actions/setup-node@v3
# with:
# node-version: "lts/Hydrogen"
# cache: "npm"
# - name: "Install npm dependencies"
# run: "npm ci"

- name: "Checkout hrana-test-server"
uses: actions/checkout@v3
with:
repository: "libsql/hrana-test-server"
path: "hrana-test-server"
- name: "Setup Python"
uses: actions/setup-python@v4
with:
python-version: "3.10"
cache: "pip"
- name: "Install pip dependencies"
run: "pip install -r hrana-test-server/requirements.txt"
# - name: "Checkout hrana-test-server"
# uses: actions/checkout@v3
# with:
# repository: "libsql/hrana-test-server"
# path: "hrana-test-server"
# - name: "Setup Python"
# uses: actions/setup-python@v4
# with:
# python-version: "3.10"
# cache: "pip"
# - name: "Install pip dependencies"
# run: "pip install -r hrana-test-server/requirements.txt"

- name: "Build"
run: "npm run build"
- name: "Install npm dependencies of the Vercel test"
run: "cd smoke_test/vercel && npm install"
# - name: "Build"
# run: "npm run build"
# - name: "Install npm dependencies of the Vercel test"
# run: "cd smoke_test/vercel && npm install"

- name: "Test with Hrana 1 over WebSocket"
run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v1.py node test.js"
env: {"URL": "ws://localhost:8080"}
- name: "Test with Hrana 2 over WebSocket"
run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v2.py node test.js"
env: {"URL": "ws://localhost:8080"}
- name: "Test with Hrana 2 over HTTP"
run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v2.py node test.js"
env: {"URL": "http://localhost:8080"}
# - name: "Test with Hrana 1 over WebSocket"
# run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v1.py node test.js"
# env: {"URL": "ws://localhost:8080"}
# - name: "Test with Hrana 2 over WebSocket"
# run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v2.py node test.js"
# env: {"URL": "ws://localhost:8080"}
# - name: "Test with Hrana 2 over HTTP"
# run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v2.py node test.js"
# env: {"URL": "http://localhost:8080"}
# - name: "Test with Hrana 3 over WebSocket"
# run: "cd smoke_test/vercel && python ../../hrana-test-server/server_v3.py node test.js"
# env: {"URL": "ws://localhost:8080"}
Expand Down
32 changes: 32 additions & 0 deletions src/__tests__/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ function withClient(
};
}

function withInMemoryClient(
f: (c: libsql.Client) => Promise<void>,
): () => Promise<void> {
return async () => {
const c = createClient({ url: ":memory:" });
try {
await f(c);
} finally {
c.close();
}
};
}

describe("createClient()", () => {
test("URL scheme not supported", () => {
expect(() => createClient({url: "ftp://localhost"}))
Expand Down Expand Up @@ -88,6 +101,10 @@ describe("createClient()", () => {
// @ts-expect-error
expect(() => createClient({...config, intMode: "foo"})).toThrow(/"foo"/);
});

test("supports in-memory database", () => {
expect(() => createClient({url: ":memory:"})).not.toThrow();
});
});

describe("execute()", () => {
Expand Down Expand Up @@ -187,6 +204,21 @@ describe("execute()", () => {
`);
expect(rs.rowsAffected).toStrictEqual(3);
}));

test("query a single value using an in memory database", withInMemoryClient(async (c) => {
await c.batch([
"DROP TABLE IF EXISTS t",
"CREATE TABLE t (a)",
"INSERT INTO t VALUES ('one'), ('two')",
], "write");
const insertRs = await c.execute("INSERT INTO t VALUES ('three')");
expect(insertRs.lastInsertRowid).not.toBeUndefined();
const selectRs = await c.execute({
sql: "SELECT a FROM t WHERE ROWID = ?",
args: [insertRs.lastInsertRowid!],
});
expect(Array.from(selectRs.rows[0])).toStrictEqual(["three"]);
}));
});

describe("values", () => {
Expand Down
35 changes: 24 additions & 11 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,32 @@ export function expandConfig(config: Config, preferHttp: boolean): ExpandedConfi
throw new TypeError(`Expected client configuration as object, got ${typeof config}`);
}

const uri = parseUri(config.url);

let tls: boolean | undefined = config.tls;
let authToken = config.authToken;
let syncUrl = config.syncUrl;
const intMode = ""+(config.intMode ?? "number");
if (intMode !== "number" && intMode !== "bigint" && intMode !== "string") {
throw new TypeError(
`Invalid value for intMode, expected "number", "bigint" or "string", \
got ${JSON.stringify(intMode)}`
);
}


if(config.url === ':memory:') {
return {
path: ':memory:',
scheme: 'file',
syncUrl,
intMode,
fetch: config.fetch,
tls: false,
authToken: undefined,
authority: undefined,
};
}

const uri = parseUri(config.url);
for (const {key, value} of uri.query?.pairs ?? []) {
if (key === "authToken") {
authToken = value ? value : undefined;
Expand All @@ -50,7 +72,6 @@ export function expandConfig(config: Config, preferHttp: boolean): ExpandedConfi
);
}
}
let syncUrl = config.syncUrl;

const uriScheme = uri.scheme.toLowerCase();
let scheme: ExpandedScheme;
Expand Down Expand Up @@ -87,14 +108,6 @@ export function expandConfig(config: Config, preferHttp: boolean): ExpandedConfi
);
}

const intMode = ""+(config.intMode ?? "number");
if (intMode !== "number" && intMode !== "bigint" && intMode !== "string") {
throw new TypeError(
`Invalid value for intMode, expected "number", "bigint" or "string", \
got ${JSON.stringify(intMode)}`
);
}

return {
scheme,
tls: tls ?? true,
Expand Down

0 comments on commit e7d1f20

Please sign in to comment.