@minatojs/tests
Version:
Test Cases for Minato
1,119 lines (1,116 loc) • 179 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/model.ts
import { mapValues, isNullable, deduplicate, omit } from "cosmokit";
import { $, getCell, Type, unravel } from "minato";
import { expect } from "chai";
function toBinary(source) {
return new TextEncoder().encode(source).buffer;
}
__name(toBinary, "toBinary");
function flatten(type2, prefix) {
if (typeof type2 === "object" && type2?.type === "object") {
const result = {};
for (const key in type2.inner) {
Object.assign(result, flatten(type2.inner[key], `${prefix}.${key}`));
}
return result;
} else {
return { [prefix]: type2 };
}
}
__name(flatten, "flatten");
function ModelOperations(database) {
database.define("bigint2", {
type: "string",
dump: /* @__PURE__ */ __name((value) => isNullable(value) ? value : value.toString(), "dump"),
load: /* @__PURE__ */ __name((value) => isNullable(value) ? value : BigInt(value), "load"),
initial: 123n
});
database.define("custom", {
type: "string",
dump: /* @__PURE__ */ __name((value) => isNullable(value) ? value : `${value.a}|${value.b}`, "dump"),
load: /* @__PURE__ */ __name((value) => isNullable(value) ? value : { a: value.split("|")[0], b: +value.split("|")[1] }, "load")
});
const bnum = database.define({
type: "binary",
dump: /* @__PURE__ */ __name((value) => isNullable(value) ? value : toBinary(String(value)), "dump"),
load: /* @__PURE__ */ __name((value) => isNullable(value) ? value : +Buffer.from(value), "load"),
initial: 0
});
const bstr = database.define({
type: "custom",
dump: /* @__PURE__ */ __name((value) => isNullable(value) ? value : { a: value, b: 1 }, "dump"),
load: /* @__PURE__ */ __name((value) => isNullable(value) ? value : value.a, "load"),
initial: "pooo"
});
database.define("recurx", {
type: "object",
inner: {
id: "unsigned",
y: "recury"
}
});
database.define("recury", {
type: "object",
inner: {
id: "unsigned",
x: "recurx"
}
});
const baseFields = {
id: "unsigned",
text: {
type: "string",
initial: "he`l\"'\\lo"
},
num: {
type: "integer",
initial: 233
},
double: {
type: "double",
initial: 3.14
},
decimal: {
type: "decimal",
scale: 3,
initial: 12413
},
int64: {
type: "bigint",
initial: 1n
},
bool: {
type: "boolean",
initial: true
},
list: {
type: "list",
initial: ["a`a", 'b"b', "c'c", "d\\d"]
},
array: "array",
object: {
type: "object",
inner: {
num: "unsigned",
text: "string",
json: "object",
embed: {
type: "object",
inner: {
bool: {
type: "boolean",
initial: false
},
int64: "bigint",
bigint: "bigint2",
custom: { type: "custom" },
bstr
}
}
}
},
// dot defined object
"object2.num": {
type: "unsigned",
initial: 1
},
"object2.text": {
type: "string",
initial: "2"
},
"object2.embed.bool": {
type: "boolean",
initial: true
},
"object2.embed.bigint": "bigint2",
timestamp: {
type: "timestamp",
initial: /* @__PURE__ */ new Date("1970-01-01 00:00:00")
},
date: {
type: "date",
initial: /* @__PURE__ */ new Date("1970-01-01")
},
time: {
type: "time",
initial: /* @__PURE__ */ new Date("1970-01-01 12:00:00")
},
binary: {
type: "binary",
initial: toBinary("initial buffer")
},
bigint: "bigint2",
bnum,
bnum2: {
type: "binary",
dump: /* @__PURE__ */ __name((value) => isNullable(value) ? value : toBinary(String(value)), "dump"),
load: /* @__PURE__ */ __name((value) => isNullable(value) ? value : +Buffer.from(value), "load"),
initial: 0
}
};
const baseObject = {
type: "object",
inner: { nested: { type: "object", inner: baseFields } },
initial: { nested: { id: 1 } }
};
database.extend("dtypes", {
...baseFields
}, { autoInc: true });
database.extend("dobjects", {
id: "unsigned",
foo: baseObject,
...flatten(baseObject, "bar"),
baz: {
type: "array",
inner: baseObject,
initial: []
}
}, { autoInc: true });
database.extend("recurxs", {
id: "unsigned",
y: "recury"
}, { autoInc: true });
}
__name(ModelOperations, "ModelOperations");
((ModelOperations2) => {
const magicBorn = /* @__PURE__ */ new Date("1970/08/17");
const dtypeTable = [
{ id: 1, bool: false },
{ id: 2, text: "pku" },
{ id: 3, num: 1989 },
{ id: 4, list: ["1", "1", "4"], array: [1, 1, 4] },
{ id: 5, object: { num: 10, text: "ab", embed: { bool: true, bigint: 90n, int64: 100n, bstr: "world" } } },
{ id: 6, object2: { num: 10, text: "ab", embed: { bool: false, bigint: 90n } } },
{ id: 7, timestamp: magicBorn },
{ id: 8, date: magicBorn },
{ id: 9, time: /* @__PURE__ */ new Date("1999-10-01 15:40:00") },
{ id: 10, binary: toBinary("hello") },
{ id: 11, bigint: BigInt(1e63) },
{ id: 12, decimal: 2.432, int64: 9223372036854775806n },
{ id: 13, bnum: 114514, bnum2: 12345 },
{ id: 14, object: { embed: { custom: { a: "abc", b: 123 } } } }
];
const dobjectTable = [
{ id: 1 },
{ id: 2, foo: { nested: { id: 1, int64: 123n, list: ["1", "1", "4"], array: [1, 1, 4], object: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163), custom: { a: "?", b: 8 }, bstr: "wo" } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } } },
{ id: 3, bar: { nested: { id: 1, list: ["1", "1", "4"], array: [1, 1, 4], object: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163), custom: { a: "?", b: 8 }, bstr: "wo" } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } } },
{ id: 4, baz: [{ nested: { id: 1, list: ["1", "1", "4"], array: [1, 1, 4], object: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163), custom: { a: "?", b: 8 }, bstr: "wo" } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } }, { nested: { id: 2 } }] },
{ id: 5, foo: { nested: { id: 1, list: ["1", "1", "4"], array: [1, 1, 4], object2: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163) } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } } },
{ id: 6, bar: { nested: { id: 1, list: ["1", "1", "4"], array: [1, 1, 4], object2: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163) } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } } },
{ id: 7, baz: [{ nested: { id: 1, list: ["1", "1", "4"], array: [1, 1, 4], object2: { num: 10, text: "ab", embed: { bool: false, bigint: BigInt(1e163) } }, bigint: BigInt(1e63), bnum: 114514, bnum2: 12345 } }, { nested: { id: 2 } }] }
];
async function setup2(database, name, table) {
await database.remove(name, {});
const result = [];
for (const item of table) {
result.push(await database.create(name, item));
}
return result;
}
__name(setup2, "setup");
ModelOperations2.fields = /* @__PURE__ */ __name(function Fields(database, options = {}) {
const { cast = true, typeModel = true } = options;
it("basic", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
table.forEach((row, i) => expect(row).to.have.shape(omit(dtypeTable[i], ["date", "time"])));
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
await database.remove("dtypes", {});
await database.upsert("dtypes", dtypeTable);
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
});
typeModel && it("pass view to binary", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
table[0].binary = toBinary("this is Buffer");
await database.set("dtypes", table[0].id, { binary: Buffer.from("this is Buffer") });
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
});
it("modifier", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await database.remove("dtypes", {});
await database.upsert("dtypes", dtypeTable.map(({ id }) => ({ id })));
await Promise.all(table.map(({ id, ...x }) => database.set("dtypes", id, x)));
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
});
it("dot notation in modifier", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
table[0].object = {};
await database.set("dtypes", table[0].id, (row) => ({
object: {}
}));
await expect(database.get("dtypes", table[0].id)).to.eventually.deep.eq([table[0]]);
table[0].object = {
num: 123,
json: {
num: 456
},
embed: {
bool: true,
bigint: 123n,
custom: {
a: "a",
b: 1
}
}
};
await database.set("dtypes", table[0].id, (row) => ({
"object.num": 123,
"object.json.num": 456,
"object.embed.bool": true,
"object.embed.bigint": 123n,
"object.embed.custom": { a: "a", b: 1 }
}));
await expect(database.get("dtypes", table[0].id)).to.eventually.deep.eq([table[0]]);
});
it("using expressions in modifier", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
table[0].object.json.num = 543 + (table[0].object.json.num ?? 0);
table[0].object.embed.bool = !table[0].object.embed.bool;
table[0].object.embed.bigint = 999n;
await database.set("dtypes", table[0].id, (row) => ({
"object.json.num": $.add($.ifNull(row.object.json.num, 0), 543),
"object.embed.bool": $.not(row.object.embed.bool),
"object.embed.bigint": 999n
}));
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
table[0].object.embed.bool = false;
await database.set("dtypes", table[0].id, {
"object.embed.bool": false
});
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
table[0].object.embed.bool = true;
await database.set("dtypes", table[0].id, {
"object.embed.bool": true
});
await expect(database.get("dtypes", {})).to.eventually.have.deep.members(table);
});
it("primitive", async () => {
expect(Type.fromTerm($.literal(123)).type).to.equal(Type.Number.type);
expect(Type.fromTerm($.literal("abc")).type).to.equal(Type.String.type);
expect(Type.fromTerm($.literal(true)).type).to.equal(Type.Boolean.type);
expect(Type.fromTerm($.literal(/* @__PURE__ */ new Date("1970-01-01"))).type).to.equal("timestamp");
expect(Type.fromTerm($.literal(toBinary("hello"))).type).to.equal("binary");
expect(Type.fromTerm($.literal([1, 2, 3])).type).to.equal("json");
expect(Type.fromTerm($.literal({ a: 1 })).type).to.equal("json");
});
cast && it("cast newtype", async () => {
await setup2(database, "dtypes", dtypeTable);
await expect(database.get("dtypes", (row) => $.eq(row.bigint, $.literal(234n, "bigint2")))).to.eventually.have.length(0);
await expect(database.get("dtypes", (row) => $.eq(row.bigint, $.literal(BigInt(1e63), "bigint2")))).to.eventually.have.length(1);
});
typeModel && it("$.object encoding", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await expect(database.eval("dtypes", (row) => $.array($.object(row)))).to.eventually.have.deep.members(table);
});
typeModel && it("$.object decoding", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await expect(
database.select("dtypes").project({
obj: /* @__PURE__ */ __name((row) => $.object(row), "obj")
}).project(mapValues(database.tables["dtypes"].fields, (field, key) => (row) => row.obj[key])).execute()
).to.eventually.have.deep.members(table);
});
typeModel && it("$.array encoding on cell", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await expect(database.eval("dtypes", (row) => $.array(row.object))).to.eventually.have.deep.members(table.map((x) => x.object));
await expect(database.eval("dtypes", (row) => $.array(row.object2))).to.eventually.have.deep.members(table.map((x) => x.object2));
});
it("$.array encoding", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await Promise.all(Object.keys(database.tables["dtypes"].fields).map(
(key) => expect(database.eval("dtypes", (row) => $.array(row[key]))).to.eventually.have.deep.members(table.map((x) => getCell(x, key)))
));
});
it("subquery encoding", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await Promise.all(Object.keys(database.tables["dtypes"].fields).map(
(key) => expect(
database.select("dtypes", 1).project({
x: /* @__PURE__ */ __name((row) => database.select("dtypes").evaluate(key), "x")
}).execute()
).to.eventually.have.shape([{ x: table.map((x) => getCell(x, key)) }])
));
});
it("object query", async () => {
const table = await setup2(database, "dtypes", dtypeTable);
await expect(database.get("dtypes", {
"object.embed.bool": true
})).to.eventually.have.shape([table[4]]);
await expect(database.get("dtypes", {
"object.num": {
$gte: 10
}
})).to.eventually.have.shape([table[4]]);
table[4].object.embed.bool = false;
await expect(database.set("dtypes", {
object: {
embed: {
int64: 100n
}
}
}, {
"object.embed.bool": false
})).to.eventually.fulfilled;
await expect(database.get("dtypes", {
object: {
embed: {
int64: 100n
}
}
})).to.eventually.deep.equal([table[4]]);
await expect(database.get("dtypes", {
$or: [
{
object: {
num: 10
}
},
{
object2: {
num: {
$gte: 10
}
}
}
]
})).to.eventually.have.deep.members([table[4], table[5]]);
});
it("recursive type", async () => {
const table = await setup2(database, "recurxs", [{ id: 1, y: { id: 2, x: { id: 3, y: { id: 4, x: { id: 5 } } } } }]);
await expect(database.get("recurxs", {})).to.eventually.have.deep.members(table);
});
}, "Fields");
ModelOperations2.object = /* @__PURE__ */ __name(function ObjectFields(database, options = {}) {
const { aggregateNull = true, nullableComparator = true, typeModel = true } = options;
it("basic", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await expect(database.get("dobjects", {})).to.eventually.have.deep.members(table);
await database.remove("dobjects", {});
await database.upsert("dobjects", dobjectTable);
await expect(database.get("dobjects", {})).to.eventually.have.deep.members(table);
});
it("modifier", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await database.remove("dobjects", {});
await database.upsert("dobjects", dobjectTable.map(({ id }) => ({ id })));
await Promise.all(table.map(({ id, ...x }) => database.set("dobjects", id, x)));
await expect(database.get("dobjects", {})).to.eventually.have.deep.members(table);
});
it("dot notation in modifier", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
table[0].foo.nested = { id: 1 };
await database.set("dobjects", table[0].id, (row) => ({
"foo.nested": { id: 1 }
}));
await expect(database.get("dobjects", table[0].id)).to.eventually.deep.eq([table[0]]);
table[0].foo.nested = {
id: 1,
timestamp: /* @__PURE__ */ new Date("2009/10/01 15:40:00"),
date: /* @__PURE__ */ new Date("1999/10/01"),
binary: toBinary("boom")
};
table[0].bar.nested = {
...table[0].bar?.nested,
id: 9,
timestamp: /* @__PURE__ */ new Date("2009/10/01 15:40:00"),
date: /* @__PURE__ */ new Date("1999/10/01"),
binary: toBinary("boom")
};
await database.set("dobjects", table[0].id, {
"foo.nested.timestamp": /* @__PURE__ */ new Date("2009/10/01 15:40:00"),
"foo.nested.date": /* @__PURE__ */ new Date("1999/10/01"),
"foo.nested.binary": toBinary("boom"),
"bar.nested.id": 9,
"bar.nested.timestamp": /* @__PURE__ */ new Date("2009/10/01 15:40:00"),
"bar.nested.date": /* @__PURE__ */ new Date("1999/10/01"),
"bar.nested.binary": toBinary("boom")
});
await expect(database.get("dobjects", table[0].id)).to.eventually.deep.eq([table[0]]);
table[0].baz = [{}, {}];
await database.set("dobjects", table[0].id, {
baz: [{}, {}]
});
await expect(database.get("dobjects", table[0].id)).to.eventually.deep.eq([table[0]]);
});
typeModel && it("$.object encoding", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await expect(database.eval("dobjects", (row) => $.array($.object(row)))).to.eventually.have.deep.members(table);
});
typeModel && it("$.object decoding", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await expect(
database.select("dobjects").project({
obj: /* @__PURE__ */ __name((row) => $.object(row), "obj")
}).project(mapValues(database.tables["dobjects"].fields, (field, key) => (row) => row.obj[key])).execute()
).to.eventually.have.deep.members(table);
});
aggregateNull && it("$.array encoding", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await Promise.all(Object.keys(database.tables["dobjects"].fields).map(
(key) => expect(database.eval("dobjects", (row) => $.array(row[key]))).to.eventually.have.deep.members(table.map((x) => getCell(x, key)))
));
});
it("$.array encoding boxed", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await Promise.all(Object.keys(database.tables["dobjects"].fields).map(
(key) => expect(database.eval("dobjects", (row) => $.array($.object({ x: row[key] })))).to.eventually.have.deep.members(table.map((x) => ({ x: getCell(x, key) })))
));
});
it("subquery encoding", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
await Promise.all(["baz"].map(
(key) => expect(
database.select("dobjects", 1).project({
x: /* @__PURE__ */ __name((row) => database.select("dobjects").evaluate(key), "x")
}).execute()
).to.eventually.have.shape([{ x: table.map((x) => getCell(x, key)) }])
));
});
it("project with dot notation", async () => {
const table = await setup2(database, "dobjects", dobjectTable);
const keys = deduplicate([
"foo.nested.object",
"foo.nested.object.embed",
...Object.keys(database.tables["dobjects"].fields).flatMap((k) => k.split(".").reduce((arr, c) => arr.length ? [`${arr[0]}.${c}`, ...arr] : [c], []))
]);
await Promise.all(keys.map(
(key) => expect(database.select("dobjects").project([key]).execute()).to.eventually.have.deep.members(table.map((row) => unravel({ [key]: getCell(row, key) })))
));
});
it("bitwise ops on bigint", async () => {
await setup2(database, "dobjects", dobjectTable);
await expect(database.get("dobjects", (row) => $.eq($.and(row.foo.nested.int64, 5n), 1n))).to.eventually.have.length(1);
await expect(database.get("dobjects", (row) => $.eq($.or(row.foo.nested.int64, 4n), 127n))).to.eventually.have.length(1);
await expect(database.get("dobjects", (row) => $.eq($.xor(row.foo.nested.int64, 2n), 121n))).to.eventually.have.length(1);
await expect(database.eval("dobjects", (row) => $.max($.or(row.foo.nested.int64, 9223372036854775701n)))).eventually.to.deep.equal(9223372036854775807n);
});
nullableComparator && it("nested $get", async () => {
await setup2(database, "dobjects", dobjectTable);
await expect(database.get("dobjects", (row) => $.eq(row.baz[0].nested.id, 1))).to.eventually.have.length(2);
await expect(database.get("dobjects", (row) => $.eq(row.baz[0].nested.array[0], 1))).to.eventually.have.length(2);
});
}, "ObjectFields");
})(ModelOperations || (ModelOperations = {}));
var model_default = ModelOperations;
// src/query.ts
import { $ as $2 } from "minato";
import { expect as expect2 } from "chai";
function QueryOperators(database) {
database.extend("temp1", {
id: "unsigned",
text: "string",
value: "integer",
bool: "boolean",
list: "list",
timestamp: "timestamp",
date: "date",
time: "time",
regex: "string"
}, {
autoInc: true
});
}
__name(QueryOperators, "QueryOperators");
((QueryOperators2) => {
QueryOperators2.comparison = /* @__PURE__ */ __name(function Comparison(database, options = {}) {
const { nullableComparator = true } = options;
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", {
text: "awesome foo",
timestamp: /* @__PURE__ */ new Date("2000-01-01"),
date: /* @__PURE__ */ new Date("2020-01-01"),
time: /* @__PURE__ */ new Date("2020-01-01 12:00:00")
});
await database.create("temp1", { text: "awesome bar" });
await database.create("temp1", { text: "awesome baz" });
});
it("basic support", async () => {
await expect2(database.get("temp1", {
id: { $eq: 2 }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome bar");
await expect2(database.get("temp1", {
id: { $ne: 3 }
})).eventually.to.have.length(2).with.nested.property("0.text").equal("awesome foo");
await expect2(database.get("temp1", {
id: { $gt: 1 }
})).eventually.to.have.length(2).with.nested.property("1.text").equal("awesome baz");
await expect2(database.get("temp1", {
id: { $gte: 3 }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome baz");
await expect2(database.get("temp1", {
id: { $lt: 1 }
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
id: { $lte: 2 }
})).eventually.to.have.length(2).with.nested.property("0.text").equal("awesome foo");
});
it("timestamp comparisons", async () => {
await expect2(database.get("temp1", {
timestamp: { $gt: /* @__PURE__ */ new Date("1999-01-01") }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
await expect2(database.get("temp1", {
timestamp: { $lte: /* @__PURE__ */ new Date("1999-01-01") }
})).eventually.to.have.length(0);
nullableComparator && await expect2(database.get(
"temp1",
(row) => $2.gt(row.timestamp, /* @__PURE__ */ new Date("1999-01-01"))
)).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
});
it("date comparisons", async () => {
await expect2(database.get("temp1", {
date: { $gt: /* @__PURE__ */ new Date("1999-01-01") }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
await expect2(database.get("temp1", {
date: { $lte: /* @__PURE__ */ new Date("1999-01-01") }
})).eventually.to.have.length(0);
});
it("time comparisons", async () => {
await expect2(database.get("temp1", {
// date should not matter
time: { $gt: /* @__PURE__ */ new Date("1970-01-01 11:00:00") }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
await expect2(database.get("temp1", {
time: { $lte: /* @__PURE__ */ new Date("1970-01-01 11:00:00") }
})).eventually.to.have.length(0);
});
it("shorthand syntax", async () => {
await expect2(database.get("temp1", {
id: 2
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome bar");
await expect2(database.get("temp1", {
timestamp: /* @__PURE__ */ new Date("2000-01-01")
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
});
}, "Comparison");
QueryOperators2.existence = /* @__PURE__ */ __name(function Existence(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { date: /* @__PURE__ */ new Date("2010-01-01") });
await database.create("temp1", { date: /* @__PURE__ */ new Date("2020-01-01") });
await database.create("temp1", {});
});
it("basic support", async () => {
await expect2(database.get("temp1", {
date: { $exists: true }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
date: { $exists: false }
})).eventually.to.have.length(1);
});
it("shorthand syntax", async () => {
await expect2(database.get("temp1", {
date: null
})).eventually.to.have.length(1);
});
}, "Existence");
QueryOperators2.membership = /* @__PURE__ */ __name(function Membership(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { value: 3 });
await database.create("temp1", { value: 4 });
await database.create("temp1", { value: 7 });
});
it("edge cases", async () => {
await expect2(database.get("temp1", {
value: { $in: [] }
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
value: { $nin: [] }
})).eventually.to.have.length(3);
});
it("basic support", async () => {
await expect2(database.get("temp1", {
value: { $in: [3, 4, 5] }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => {
return $2.in(row.value, [3, 4, 5]);
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
value: { $nin: [4, 5, 6] }
})).eventually.to.have.length(2);
});
it("shorthand syntax", async () => {
await expect2(database.get("temp1", {
value: []
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
value: [3, 4, 5]
})).eventually.to.have.length(2);
});
}, "Membership");
QueryOperators2.regexp = /* @__PURE__ */ __name(function RegularExpression(database, options = {}) {
const { regexBy = true, regexFor = true } = options;
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { text: "awesome foo", regex: "foo" });
await database.create("temp1", { text: "awesome bar", regex: "bar" });
await database.create("temp1", { text: "awesome foo bar", regex: "baz" });
await database.create("temp1", { text: "xxx", regex: "bAz" });
});
regexFor && it("$regexFor", async () => {
await expect2(database.get("temp1", {
regex: { $regexFor: "foo bar" }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
regex: { $regexFor: "baz" }
})).eventually.to.have.length(1);
await expect2(database.get("temp1", {
regex: { $regexFor: "bAr" }
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
regex: { $regexFor: { input: "foo bar" } }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
regex: { $regexFor: { input: "bAr", flags: "i" } }
})).eventually.to.have.length(1);
});
regexBy && it("$regexBy", async () => {
await expect2(database.get("temp1", {
text: { $regex: /^.*foo.*$/ }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
text: { $regex: /^.*bar$/ }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
text: { $regex: /^.*bAr$/ }
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
text: { $regex: /^.*bAr$/i }
})).eventually.to.have.length(2);
await expect2(database.get("temp1", {
text: { $regex: { source: "^.*foo.*$" } }
})).eventually.to.have.length(2);
});
regexBy && it("shorthand syntax", async () => {
await expect2(database.get("temp1", {
text: /^.*foo$/
})).eventually.to.have.length(1).with.nested.property("[0].text").equal("awesome foo");
});
regexBy && regexFor && it("$.regex", async () => {
await expect2(database.get("temp1", (row) => $2.regex("foo bar", row.regex))).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => $2.regex("baz", row.regex))).eventually.to.have.length(1);
await expect2(database.get("temp1", (row) => $2.regex(row.text, /^.*foo.*$/))).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => $2.regex(row.text, /^.*bar.*$/))).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => $2.regex(row.text, row.regex))).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => $2.regex(row.text, /^.*bAr.*$/i))).eventually.to.have.length(2);
await expect2(database.get("temp1", (row) => $2.regex(row.text, /^.*bAr.*$/))).eventually.to.have.length(0);
await expect2(database.get("temp1", (row) => $2.regex(row.text, "^.*bAr.*$", "i"))).eventually.to.have.length(2);
});
}, "RegularExpression");
QueryOperators2.bitwise = /* @__PURE__ */ __name(function Bitwise(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { value: 3 });
await database.create("temp1", { value: 4 });
await database.create("temp1", { value: 7 });
});
it("basic support", async () => {
await expect2(database.get("temp1", {
value: { $bitsAllSet: 3 }
})).eventually.to.have.shape([{ value: 3 }, { value: 7 }]);
await expect2(database.get("temp1", {
value: { $bitsAllClear: 9 }
})).eventually.to.have.shape([{ value: 4 }]);
await expect2(database.get("temp1", {
value: { $bitsAnySet: 4 }
})).eventually.to.have.shape([{ value: 4 }, { value: 7 }]);
await expect2(database.get("temp1", {
value: { $bitsAnyClear: 6 }
})).eventually.to.have.shape([{ value: 3 }, { value: 4 }]);
});
it("using expressions", async () => {
await expect2(database.get(
"temp1",
(row) => $2.eq($2.and(row.value, 1, 1), 1)
)).eventually.to.have.shape([{ value: 3 }, { value: 7 }]);
await expect2(database.get(
"temp1",
(row) => $2.eq($2.or(row.value, 3, 3), 7)
)).eventually.to.have.shape([{ value: 4 }, { value: 7 }]);
await expect2(database.get(
"temp1",
(row) => $2.eq($2.and(row.value, $2.not(4)), 3)
)).eventually.to.have.shape([{ value: 3 }, { value: 7 }]);
await expect2(database.get(
"temp1",
(row) => $2.eq($2.xor(0, row.value, 3), 7)
)).eventually.to.have.shape([{ value: 4 }]);
await expect2(database.eval("temp1", (_) => $2.max($2.not(2 ** 30)))).eventually.to.deep.equal(-(2 ** 30) - 1);
await expect2(database.eval("temp1", (_) => $2.max($2.not(-(2 ** 30))))).eventually.to.deep.equal(2 ** 30 - 1);
await expect2(database.eval("temp1", (_) => $2.max($2.or(-(2 ** 30), 1)))).eventually.to.deep.equal(-(2 ** 30) + 1);
await expect2(database.eval("temp1", (_) => $2.max($2.xor(2, 3, 6)))).eventually.to.deep.equal(7);
await expect2(database.eval("temp1", (_) => $2.array($2.xor(true, false)))).eventually.to.include.members([true]);
await expect2(database.eval("temp1", (_) => $2.array($2.xor(true, false, true)))).eventually.to.include.members([false]);
await expect2(database.eval("temp1", (_) => $2.max($2.not(BigInt(2 ** 40))))).eventually.to.deep.equal(BigInt(-(2 ** 40) - 1));
await expect2(database.eval("temp1", (_) => $2.max($2.and(9223372036854775701n, 9223372036854775702n)))).eventually.to.deep.equal(9223372036854775700n);
await expect2(database.eval("temp1", (_) => $2.max($2.or(9223372036854775701n, 1n)))).eventually.to.deep.equal(9223372036854775701n);
await expect2(database.eval("temp1", (_) => $2.max($2.xor(9223372036854775701n, 9223372036854775702n)))).eventually.to.deep.equal(3n);
await expect2(database.eval("temp1", (_) => $2.max($2.not(9223372036854775701n)))).eventually.to.deep.equal(-9223372036854775702n);
});
}, "Bitwise");
QueryOperators2.list = /* @__PURE__ */ __name(function List(database, options = {}) {
const { size = true, element = true, elementQuery = element } = options;
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { id: 1, list: [] });
await database.create("temp1", { id: 2, list: [23] });
await database.create("temp1", { id: 3, list: [233] });
await database.create("temp1", { id: 4, list: [233, 332] });
});
size && it("$size", async () => {
await expect2(database.get("temp1", {
list: { $size: 1 }
})).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]);
await expect2(database.get("temp1", {
list: { $size: 0 }
})).eventually.to.have.length(1).with.shape([{ id: 1 }]);
});
size && it("$.length", async () => {
await expect2(
database.select("temp1").project({ x: /* @__PURE__ */ __name((row) => $2.length(row.list), "x") }).orderBy((row) => row.x).execute()
).eventually.to.deep.equal([
{ x: 0 },
{ x: 1 },
{ x: 1 },
{ x: 2 }
]);
});
element && it("$el shorthand", async () => {
await expect2(database.get("temp1", {
list: { $el: 233 }
})).eventually.to.have.length(2).with.shape([{ id: 3 }, { id: 4 }]);
});
elementQuery && it("$el with field temp1", async () => {
await expect2(database.get("temp1", {
list: { $el: { $lt: 50 } }
})).eventually.to.have.shape([{ id: 2 }]);
});
}, "List");
QueryOperators2.evaluation = /* @__PURE__ */ __name(function Evaluation(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { id: 1, value: 8 });
await database.create("temp1", { id: 2, value: 7 });
await database.create("temp1", { id: 3, value: 9 });
});
it("arithmetic operators", async () => {
await expect2(database.get("temp1", (row) => {
return $2.eq(9, $2.add(row.id, row.value));
})).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 2 }]);
});
}, "Evaluation");
let Logical;
((Logical2) => {
Logical2.queryLevel = /* @__PURE__ */ __name(function LogicalQueryLevel(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { id: 1 });
await database.create("temp1", { id: 2 });
await database.create("temp1", { id: 3 });
});
it("edge cases", async () => {
await expect2(database.get("temp1", {})).eventually.to.have.length(3);
await expect2(database.get("temp1", { $and: [] })).eventually.to.have.length(3);
await expect2(database.get("temp1", { $or: [] })).eventually.to.have.length(0);
await expect2(database.get("temp1", { $not: {} })).eventually.to.have.length(0);
await expect2(database.get("temp1", { $not: { $and: [] } })).eventually.to.have.length(0);
await expect2(database.get("temp1", { $not: { $or: [] } })).eventually.to.have.length(3);
});
it("$or", async () => {
await expect2(database.get("temp1", {
$or: [{ id: 1 }, { id: { $ne: 2 } }]
})).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 3 }]);
await expect2(database.get("temp1", {
$or: [{ id: 1 }, { id: { $eq: 2 } }]
})).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 2 }]);
await expect2(database.get("temp1", {
$or: [{ id: { $ne: 1 } }, { id: { $ne: 2 } }]
})).eventually.to.have.length(3).with.shape([{ id: 1 }, { id: 2 }, { id: 3 }]);
});
it("$and", async () => {
await expect2(database.get("temp1", {
$and: [{ id: 1 }, { id: { $ne: 2 } }]
})).eventually.to.have.length(1).with.shape([{ id: 1 }]);
await expect2(database.get("temp1", {
$and: [{ id: 1 }, { id: { $eq: 2 } }]
})).eventually.to.have.length(0);
await expect2(database.get("temp1", {
$and: [{ id: { $ne: 1 } }, { id: { $ne: 2 } }]
})).eventually.to.have.length(1).with.shape([{ id: 3 }]);
});
it("$not", async () => {
await expect2(database.get("temp1", {
$not: { id: 1 }
})).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]);
await expect2(database.get("temp1", {
$not: { id: { $ne: 1 } }
})).eventually.to.have.length(1).with.shape([{ id: 1 }]);
});
}, "LogicalQueryLevel");
Logical2.fieldLevel = /* @__PURE__ */ __name(function LogicalFieldLevel(database) {
before(async () => {
await database.remove("temp1", {});
await database.create("temp1", { id: 1 });
await database.create("temp1", { id: 2 });
await database.create("temp1", { id: 3 });
});
it("edge cases", async () => {
await expect2(database.get("temp1", { id: {} })).eventually.to.have.length(3);
await expect2(database.get("temp1", { id: { $and: [] } })).eventually.to.have.length(3);
await expect2(database.get("temp1", { id: { $or: [] } })).eventually.to.have.length(0);
await expect2(database.get("temp1", { id: { $not: {} } })).eventually.to.have.length(0);
await expect2(database.get("temp1", { id: { $not: { $and: [] } } })).eventually.to.have.length(0);
await expect2(database.get("temp1", { id: { $not: { $or: [] } } })).eventually.to.have.length(3);
});
it("$or", async () => {
await expect2(database.get("temp1", {
id: { $or: [1, { $gt: 2 }] }
})).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 3 }]);
await expect2(database.get("temp1", {
id: { $or: [1, { $gt: 2 }], $ne: 3 }
})).eventually.to.have.length(1).with.shape([{ id: 1 }]);
});
it("$and", async () => {
await expect2(database.get("temp1", {
id: { $and: [[1, 2], { $lt: 2 }] }
})).eventually.to.have.length(1).with.shape([{ id: 1 }]);
await expect2(database.get("temp1", {
id: { $and: [[1, 2], { $lt: 2 }], $eq: 2 }
})).eventually.to.have.length(0);
});
it("$not", async () => {
await expect2(database.get("temp1", {
id: { $not: 1 }
})).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]);
await expect2(database.get("temp1", {
id: { $not: 1, $lt: 3 }
})).eventually.to.have.length(1).with.shape([{ id: 2 }]);
});
}, "LogicalFieldLevel");
})(Logical || (Logical = {}));
QueryOperators2.logical = Logical;
})(QueryOperators || (QueryOperators = {}));
var query_default = QueryOperators;
// src/update.ts
import { $ as $3 } from "minato";
import { deepEqual, omit as omit2 } from "cosmokit";
import { expect as expect3 } from "chai";
function OrmOperations(database) {
database.extend("temp2", {
id: "unsigned",
text: "string",
num: "integer",
double: "double",
bool: "boolean",
list: "list",
timestamp: "timestamp",
date: "date",
time: "time",
bigtext: "text",
binary: "binary",
bigint: {
type: "string",
dump: /* @__PURE__ */ __name((value) => value ? value.toString() : value, "dump"),
load: /* @__PURE__ */ __name((value) => value ? BigInt(value) : value, "load")
}
}, {
autoInc: true,
indexes: ["text"]
});
database.extend("temp3", {
ida: "unsigned",
idb: "string",
value: "string"
}, {
primary: ["ida", "idb"],
unique: ["value"]
});
}
__name(OrmOperations, "OrmOperations");
((OrmOperations2) => {
const merge = /* @__PURE__ */ __name((a, b) => ({ ...a, ...b }), "merge");
const magicBorn = /* @__PURE__ */ new Date("1970/08/17");
const toBinary2 = /* @__PURE__ */ __name((source) => new TextEncoder().encode(source).buffer, "toBinary");
const barTable = [
{ id: 1, bool: true },
{ id: 2, text: "pku" },
{ id: 3, num: 1989 },
{ id: 4, list: ["1", "1", "4"] },
{ id: 5, timestamp: magicBorn },
{ id: 6, date: magicBorn },
{ id: 7, time: /* @__PURE__ */ new Date("1970-01-01 12:00:00") },
{ id: 8, binary: toBinary2("hello") },
{ id: 9, bigint: BigInt(1e63) },
{ id: 10, text: "a\b \f\n\r'\"\\`b", list: ["a\b \f\n\r'\"\\`b"] }
];
const bazTable = [
{ ida: 1, idb: "a", value: "a" },
{ ida: 2, idb: "a", value: "b" },
{ ida: 1, idb: "b", value: "c" },
{ ida: 2, idb: "b", value: "d" }
];
async function setup2(database, name, table) {
await database.remove(name, {});
const result = [];
for (const item of table) {
result.push(await database.create(name, item));
}
return result;
}
__name(setup2, "setup");
OrmOperations2.create = /* @__PURE__ */ __name(function Create(database) {
it("auto increment primary key", async () => {
const table = barTable.map((bar) => merge(database.tables.temp2.create(), bar));
for (const index2 in barTable) {
const bar = await database.create("temp2", omit2(barTable[index2], ["id"]));
barTable[index2].id = bar.id;
expect3(bar).to.have.shape(table[index2]);
}
for (const obj of table) {
await expect3(database.get("temp2", { id: obj.id })).to.eventually.have.shape([obj]);
}
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
await database.remove("temp2", { id: table.length });
await expect3(database.create("temp2", {})).to.eventually.have.shape({ id: table.length + 1 });
});
it("specify primary key", async () => {
for (const obj of bazTable) {
await expect3(database.create("temp3", obj)).eventually.shape(obj);
}
for (const obj of bazTable) {
await expect3(database.get("temp3", { ida: obj.ida, idb: obj.idb })).eventually.shape([obj]);
}
});
it("missing primary key", async () => {
await expect3(database.create("temp3", { ida: 1 })).eventually.rejected;
});
it("duplicate primary key", async () => {
await expect3(database.create("temp2", { id: barTable[0].id })).eventually.rejected;
await expect3(database.create("temp3", { ida: 1, idb: "a" })).eventually.rejected;
});
it("parallel create", async () => {
await database.remove("temp2", {});
await Promise.all([...Array(5)].map(() => database.create("temp2", {})));
const result = await database.get("temp2", {});
expect3(result).length(5);
const ids = result.map((e) => e.id).sort((a, b) => a - b);
const min = Math.min(...ids);
expect3(ids.map((id) => id - min + 1)).shape([1, 2, 3, 4, 5]);
await database.remove("temp2", {});
});
it("enormous field", async () => {
const row = { id: 100, bigtext: Array(1e6).fill("a").join("") };
await database.create("temp2", row);
await expect3(database.get("temp2", 100)).to.eventually.have.nested.property("0.bigtext", row.bigtext);
});
it("advanced type", async () => {
await setup2(database, "temp2", barTable);
await expect3(database.create("temp2", { binary: toBinary2("world") })).to.eventually.have.shape({ binary: toBinary2("world") });
await expect3(database.get("temp2", { binary: { $exists: true } })).to.eventually.have.shape([
{ binary: toBinary2("hello") },
{ binary: toBinary2("world") }
]);
await expect3(database.create("temp2", { bigint: 1234567891011121314151617181920n })).to.eventually.have.shape({ bigint: 1234567891011121314151617181920n });
await expect3(database.get("temp2", { bigint: { $exists: true } })).to.eventually.have.shape([
{ bigint: BigInt(1e63) },
{ bigint: 1234567891011121314151617181920n }
]);
});
}, "Create");
OrmOperations2.set = /* @__PURE__ */ __name(function Set2(database) {
it("basic support", async () => {
const table = await setup2(database, "temp2", barTable);
const data = table.find((bar) => bar.timestamp);
data.list = ["2", "3", "3"];
data.text = `$'"%~\``;
const magicIds = table.slice(2, 4).map((data2) => {
data2.list = ["2", "3", "3"];
data2.text = `$'"%~\``;
return data2.id;
});
await expect3(database.set("temp2", {
$or: [
{ id: magicIds },
{ timestamp: magicBorn }
]
}, { list: ["2", "3", "3"], text: `$'"%~\`` })).to.eventually.have.shape({ matched: 3 });
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
it("null override", async () => {
const table = await setup2(database, "temp2", barTable);
const data = table.find((bar) => bar.timestamp);
data.text = null;
await database.set("temp2", { timestamp: { $exists: true } }, { text: null });
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
await expect3(database.get("temp2", { text: { $exists: false } })).to.eventually.have.length(1);
});
it("noop", async () => {
const table = await setup2(database, "temp2", barTable);
await database.set("temp2", {}, {});
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
await database.set("temp2", {}, { text: void 0 });
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
it("using expressions", async () => {
const table = await setup2(database, "temp2", barTable);
table[1].num = table[1].id * 2;
table[2].num = table[2].id * 2;
await database.set("temp2", [table[1].id, table[2].id, 99], (row) => ({
num: $3.multiply(2, row.id)
}));
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
it("using expressions in query", async () => {
const table = await setup2(database, "temp2", barTable);
table[1].num = table[1].id * 2;
table[2].num = table[2].id * 2;
await database.set("temp2", (row) => $3.in(row.id, [table[1].id, table[2].id, 99]), (row) => ({
num: $3.multiply(2, row.id)
}));
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
it("enormous field", async () => {
const row = await database.create("temp2", {});
row.bigtext = Array(1e6).fill("a").join("");
await database.set("temp2", row.id, { bigtext: row.bigtext });
await expect3(database.get("temp2", row.id)).to.eventually.have.nested.property("0.bigtext", row.bigtext);
});
it("advanced type", async () => {
const table = await setup2(database, "temp2", barTable);
const data1 = table.find((item) => item.id === 1);
data1.binary = toBinary2("world");
data1.bigint = 1234567891011121314151617181920n;
await database.set("temp2", { id: 1 }, { binary: toBinary2("world"), bigint: 1234567891011121314151617181920n });
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
}, "Set");
OrmOperations2.upsert = /* @__PURE__ */ __name(function Upsert(database) {
it("update existing records", async () => {
const table = await setup2(database, "temp2", barTable);
const data = [
{ id: table[0].id, text: "thu" },
{ id: table[1].id, num: 1911 },
{ id: table[2].id, list: ["2", "3", "3"] }
];
data.forEach((update) => {
const index2 = table.findIndex((obj) => obj.id === update.id);
table[index2] = merge(table[index2], update);
});
await expect3(database.upsert("temp2", data.slice(0, 2))).to.eventually.have.shape({ inserted: 0, matched: 2 });
await expect3(database.upsert("temp2", data.slice(0, 2))).to.eventually.have.shape({ inserted: 0, matched: 2 });
await expect3(database.upsert("temp2", data.slice(2))).to.eventually.have.shape({ inserted: 0, matched: 1 });
await expect3(database.get("temp2", {})).to.eventually.have.shape(table);
});
it("insert new records", async () => {
const table = await setup2(database, "temp2", barTable);
const data = [
{ id: table[table.length - 1].id + 1, text: 'wm"lake' },
{ id: table[table.length - 1].id + 2, text: "by'tower" },
{ id: table[table.length - 1].id + 3, text: "over" }
];
table.push(...data.map((bar) => merge(database.tables.temp2.create(), bar)));
await expect3(database.upsert("temp2", data.slice(0, 2))).to.eventually.have.shape({ inserted: 2, matched: 0 });
await expect3(database.upsert("temp2", data.slice(2))).to.eventually.have.shape({ inserted: 1, matched: 0 });
await expect3(database.upsert("temp2", data.slice(