Skip to content

Commit

Permalink
primate/store: add projections
Browse files Browse the repository at this point in the history
  • Loading branch information
terrablue committed Mar 10, 2024
1 parent a77cdf6 commit ab16590
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 17 deletions.
37 changes: 34 additions & 3 deletions packages/store/src/drivers/base.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { primary, string, object, u8, boolean, i64, date } from "@primate/types";

const w = (document, id) => ({ ...document, id });
const defaults = {
mode: "loose",
readonly: false,
ambiguous: false,
};

const stores = [
["User", {
name: "User",
defaults,
schema: {
id: primary,
name: string,
Expand All @@ -19,7 +25,10 @@ const stores = [
}],
["StrictUser", {
name: "StrictUser",
mode: "strict",
defaults: {
...defaults,
mode: "strict",
},
schema: {
id: primary,
name: string,
Expand All @@ -34,6 +43,7 @@ const stores = [
}],
["Comment", {
name: "Comment",
defaults,
schema: {
id: primary,
},
Expand Down Expand Up @@ -170,8 +180,29 @@ export default async (test, driver, lifecycle) => {
assert(users4.find(({ id }) => id === user2$.id)).defined();

// embedded
const { id } = await User.insert({ ...traits });
assert(await User.find({ id })).equals([{ id, ...traits }]);
{
const { id } = await User.insert({ ...traits });
assert(await User.find({ id })).equals([{ id, ...traits }]);
}

const criteria = { name: "Donald", age: 20 };
// 0-field projection
{
// empty
const [users5] = await User.find(criteria);
const { id } = users5;
assert(users5).equals({ ...criteria, sex: "M", id });
}
// 1-field projection
{
const [user] = await User.find(criteria, ["name"]);
assert(user).equals({ name: "Donald" });
}
// n-field projection
{
const [user] = await User.find(criteria, ["name", "age"]);
assert(user).equals(criteria);
}
});
});

Expand Down
8 changes: 6 additions & 2 deletions packages/store/src/drivers/memory/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@ export default class Connection {
return collection.length > 0;
}

async find(name, criteria) {
return this.#filter(name, criteria);
async find(name, criteria, projection = []) {
const documents = await this.#filter(name, criteria);
return projection.length === 0
? documents
: documents.map(document => o.filter(document,
([key]) => projection.includes(key)));
}

async count(...args) {
Expand Down
16 changes: 14 additions & 2 deletions packages/store/src/drivers/mongodb/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,20 @@ export default class Facade {
return { session: this.session };
}

async find(name, criteria = {}) {
return (await this.#by(name).find(cid(criteria), this.#options).toArray())
async find(name, criteria = {}, projection = []) {
const options = {
...this.#options,
...projection.length === 0
? {}
: {
projection: {
// erase _id unless explicit in projection
_id: 0,
...Object.fromEntries(projection.map(field => [field, 1])),
},
},
};
return (await this.#by(name).find(cid(criteria), options).toArray())
.map(document => toid(document));
}

Expand Down
5 changes: 3 additions & 2 deletions packages/store/src/drivers/mysql/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ export default class Connection {
this.connection = connection;
}

async find(collection, criteria = {}) {
async find(collection, criteria = {}, projection = []) {
const { where, bindings } = predicate(criteria);
const query = `select * from ${collection} ${where}`;
const select = projection.length === 0 ? "*" : projection.join(", ");
const query = `select ${select} from ${collection} ${where}`;
const [result] = await this.connection.query(query, bindings);

return filter_nulls(result);
Expand Down
5 changes: 3 additions & 2 deletions packages/store/src/drivers/postgresql/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ export default class Connection {
this.connection = connection;
}

async find(collection, criteria = {}) {
async find(collection, criteria = {}, projection = []) {
const { connection } = this;
const select = projection.length === 0 ? "*" : projection.join(", ");
return filter_nulls(await connection`
select *
select ${connection.unsafe(select)}
from ${connection(collection)}
where ${Object.entries(criteria).reduce((acc, [key, value]) =>
connection`${acc} and ${connection(key)} = ${value}`, connection`true`)}
Expand Down
5 changes: 3 additions & 2 deletions packages/store/src/drivers/sqlite/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ export default class Connection {
this.connection = connection;
}

find(collection, criteria = {}) {
find(collection, criteria = {}, projection = []) {
const { where, bindings } = predicate(criteria);
const query = `select * from ${collection} ${where}`;
const select = projection.length === 0 ? "*" : projection.join(", ");
const query = `select ${select} from ${collection} ${where}`;
const statement = this.connection.prepare(query);
if (!is_bun) {
statement.safeIntegers(true);
Expand Down
5 changes: 3 additions & 2 deletions packages/store/src/drivers/surrealdb/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ export default class Connection {
return this.connection.query_raw(...args);
}

async find(name, criteria = {}) {
async find(name, criteria = {}, projection = []) {
const { where, bindings } = predicate(criteria);
const query = `select * from ${name} ${where}`;
const select = projection.length === 0 ? "*" : projection.join(", ");
const query = `select ${select} from ${name} ${where}`;
const [{ result }] = await this.#query(query, bindings);
return result;
}
Expand Down
7 changes: 5 additions & 2 deletions packages/store/src/wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,12 @@ export default (config, facade, types) => {
maybe(criteria).object();
return facade.count(name, criteria);
},
async find(criteria) {
async find(criteria, projection) {
maybe(criteria).object();
const documents = await facade.find(name, pack(criteria));
maybe(projection).array();

const documents = await facade.find(name, pack(criteria), projection);

return documents.map(document => unpack(document));
},
async exists(criteria) {
Expand Down

0 comments on commit ab16590

Please sign in to comment.