Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add async/await for postgres #748

Merged
merged 8 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 2 additions & 4 deletions packages/postgres/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import {EventEmitter} from 'events';
import type {Store, StoredData} from 'keyv';

Expand All @@ -22,11 +20,11 @@ declare class KeyvPostgres<Value=any> extends EventEmitter implements Store<Valu
has?(key: string): boolean | Promise<boolean>;
}
declare namespace KeyvPostgres {
interface Options {
type Options = {
uri?: string | undefined;
table?: string | undefined;
keySize?: number | undefined;
schema?: string | 'public';
ssl?: any | undefined;
}
};
}
102 changes: 42 additions & 60 deletions packages/postgres/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,82 +37,63 @@ class KeyvPostgres extends EventEmitter {
.then(query => query(sqlString, values));
}

get(key) {
async get(key) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
return this.query(select, [key])
.then(rows => {
const row = rows[0];
if (row === undefined) {
return undefined;
}

return row.value;
});
const rows = await this.query(select, [key]);
const row = rows[0];
return row === undefined ? undefined : row.value;
}

getMany(keys) {
async getMany(keys) {
const getMany = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
return this.query(getMany, [keys]).then(rows => {
const results = [...keys];
let i = 0;
for (const key of keys) {
const rowIndex = rows.findIndex(row => row.key === key);

if (rowIndex > -1) {
results[i] = rows[rowIndex].value;
} else {
results[i] = undefined;
}

i++;
}
const rows = await this.query(getMany, [keys]);
const results = [];

for (const key of keys) {
const rowIndex = rows.findIndex(row => row.key === key);
results.push(rowIndex > -1 ? rows[rowIndex].value : undefined);
}

return results;
});
return results;
}

set(key, value) {
async set(key, value) {
const upsert = `INSERT INTO ${this.opts.schema}.${this.opts.table} (key, value)
VALUES($1, $2)
ON CONFLICT(key)
DO UPDATE SET value=excluded.value;`;
return this.query(upsert, [key, value]);
VALUES($1, $2)
ON CONFLICT(key)
DO UPDATE SET value=excluded.value;`;
await this.query(upsert, [key, value]);
}

delete(key) {
async delete(key) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
return this.query(select, [key])
.then(rows => {
const row = rows[0];
if (row === undefined) {
return false;
}

return this.query(del, [key])
.then(() => true);
});
const rows = await this.query(select, [key]);

if (rows[0] === undefined) {
return false;
}

await this.query(del, [key]);
return true;
}

deleteMany(key) {
async deleteMany(keys) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
return this.query(select, [key])
.then(rows => {
const row = rows[0];
if (row === undefined) {
return false;
}

return this.query(del, [key])
.then(() => true);
});
const rows = await this.query(select, [keys]);

if (rows[0] === undefined) {
return false;
}

await this.query(del, [keys]);
return true;
}

clear() {
async clear() {
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key LIKE $1`;
return this.query(del, [this.namespace ? `${this.namespace}:%` : '%'])
.then(() => undefined);
await this.query(del, [this.namespace ? `${this.namespace}:%` : '%']);
}

async * iterator(namespace) {
Expand All @@ -135,9 +116,10 @@ class KeyvPostgres extends EventEmitter {
yield * iterate(0, this.opts, this.query);
}

has(key) {
const exists = `SELECT EXISTS ( SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = '${key}' )`;
return this.query(exists).then(rows => rows[0].exists);
async has(key) {
const exists = `SELECT EXISTS ( SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1 )`;
const rows = await this.query(exists, [key]);
return rows[0].exists;
}

disconnect() {
Expand Down
10 changes: 9 additions & 1 deletion packages/postgres/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ const store = () => new KeyvPostgres({uri: postgresUri, iterationLimit: 2});
keyvTestSuite(test, Keyv, store);
keyvIteratorTests(test, Keyv, store);

test.serial('test schema as non public', async t => {
const keyv1 = new KeyvPostgres({uri: 'postgresql://postgres:postgres@localhost:5432/keyv_test', schema: 'keyvtest1'});
const keyv2 = new KeyvPostgres({uri: 'postgresql://postgres:postgres@localhost:5432/keyv_test', schema: 'keyvtest2'});
await keyv1.set('footest11', 'bar1');
await keyv2.set('footest22', 'bar2');
t.is(await keyv1.get('footest11'), 'bar1');
t.is(await keyv2.get('footest22'), 'bar2');
});

test.serial('iterator with default namespace', async t => {
const keyv = new KeyvPostgres({uri: postgresUri});
await keyv.set('foo', 'bar');
Expand Down Expand Up @@ -47,4 +56,3 @@ test.serial('close connection successfully', async t => {
t.pass();
}
});