feat(infra): add not-condition to orm (#9466)

This commit is contained in:
forehalo
2025-01-02 02:32:16 +00:00
parent 4be031b311
commit 9da2844225
5 changed files with 115 additions and 10 deletions

View File

@@ -102,6 +102,61 @@ describe('ORM entity CRUD', () => {
expect(user2).toEqual(user); expect(user2).toEqual(user);
}); });
test('should be able to filter with nullable condition', t => {
const { client } = t;
client.users.create({
name: 'u1',
email: 'e1@example.com',
});
client.users.create({
name: 'u2',
});
const users = client.users.find({
email: null,
});
expect(users).toHaveLength(1);
expect(users[0].email).toBeFalsy();
const users2 = client.users.find({
email: {
not: null,
},
});
expect(users2).toHaveLength(1);
expect(users2[0].email).toEqual('e1@example.com');
});
test('should be able to filter with `not` condition', t => {
const { client } = t;
client.users.create({
name: 'u1',
email: 'e1@example.com',
});
const users = client.users.find({
email: {
not: 'e1@example.com',
},
});
expect(users).toHaveLength(0);
const users2 = client.users.find({
name: {
not: 'u2',
},
});
expect(users2).toHaveLength(1);
expect(users2[0].name).toEqual('u1');
});
test('should be able to update entity', t => { test('should be able to update entity', t => {
const { client } = t; const { client } = t;

View File

@@ -152,9 +152,26 @@ export class MemoryTableAdapter implements TableAdapter {
} }
private match(record: any, where: WhereCondition) { private match(record: any, where: WhereCondition) {
return Array.isArray(where) if (Array.isArray(where)) {
? where.every(c => record[c.field] === c.value) return where.every(c => {
: where.byKey === record[this.keyField]; const value = record[c.field] || null;
const condition = c.value;
if (typeof condition === 'object') {
if (condition === null) {
return value === null;
}
if ('not' in condition) {
return value !== condition.not;
}
}
return value === condition;
});
}
return where.byKey === record[this.keyField];
} }
private dispatch(key: string, data: any) { private dispatch(key: string, data: any) {

View File

@@ -4,9 +4,17 @@ export interface TableAdapterOptions extends TableOptions {
keyField: string; keyField: string;
} }
type WhereEqCondition = { type OrmPrimitiveValues = string | number | boolean | null;
type SimpleCondition =
| OrmPrimitiveValues
| {
not: OrmPrimitiveValues;
};
type WhereSimpleCondition = {
field: string; field: string;
value: any; value: SimpleCondition;
}; };
type WhereByKeyCondition = { type WhereByKeyCondition = {
@@ -14,8 +22,8 @@ type WhereByKeyCondition = {
}; };
// currently only support eq condition // currently only support eq condition
// TODO(@forehalo): on the way [gt, gte, lt, lte, in, notIn, like, notLike, isNull, isNotNull, And, Or] // TODO(@forehalo): on the way [gt, gte, lt, lte, in, notIn, like, notLike, Or]
export type WhereCondition = WhereEqCondition[] | WhereByKeyCondition; export type WhereCondition = Array<WhereSimpleCondition> | WhereByKeyCondition;
export type Select = '*' | 'key' | string[]; export type Select = '*' | 'key' | string[];
export type InsertQuery = { export type InsertQuery = {

View File

@@ -226,7 +226,22 @@ export class YjsTableAdapter implements TableAdapter {
(Array.isArray(where) (Array.isArray(where)
? where.length === 0 ? where.length === 0
? false ? false
: where.every(c => this.field(record, c.field) === c.value) : where.every(c => {
const field = this.field(record, c.field);
const condition = c.value;
if (typeof condition === 'object') {
if (condition === null) {
return field === null;
}
if ('not' in condition) {
return field !== condition.not;
}
}
return field === condition;
})
: where.byKey === this.keyof(record)) : where.byKey === this.keyof(record))
); );
} }
@@ -242,7 +257,14 @@ export class YjsTableAdapter implements TableAdapter {
} }
private field(ty: AbstractType<any>, field: string) { private field(ty: AbstractType<any>, field: string) {
return YMap.prototype.get.call(ty, field); const val = YMap.prototype.get.call(ty, field);
// only handle null will make the day easier
if (val === undefined) {
return null;
}
return val;
} }
private setField(ty: AbstractType<any>, field: string, value: any) { private setField(ty: AbstractType<any>, field: string, value: any) {

View File

@@ -116,7 +116,10 @@ export type FindEntityInput<T extends TableSchemaBuilder> = Pretty<
T, T,
{ {
[key in TableDefinedFieldNames<T>]?: key extends keyof TableDefinedEntity<T> [key in TableDefinedFieldNames<T>]?: key extends keyof TableDefinedEntity<T>
? TableDefinedEntity<T>[key] ?
| TableDefinedEntity<T>[key]
| { not: TableDefinedEntity<T>[key] | null }
| null
: never; : never;
} }
> >