fix many to many reference query

This commit is contained in:
dswbx
2025-02-27 11:43:12 +01:00
parent dd48962901
commit 3e28124494
7 changed files with 22 additions and 19 deletions

View File

@@ -48,6 +48,7 @@ function __tty(type: any, args: any[]) {
}, },
debug: { debug: {
prefix: colors.yellow, prefix: colors.yellow,
args: colors.dim,
}, },
} as const; } as const;
const prefix = styles[type].prefix(`[${type.toUpperCase()}]`); const prefix = styles[type].prefix(`[${type.toUpperCase()}]`);

View File

@@ -166,13 +166,15 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
if (options.limit) validated.limit = options.limit; if (options.limit) validated.limit = options.limit;
if (options.offset) validated.offset = options.offset; if (options.offset) validated.offset = options.offset;
//$console.debug("Repository: options", { entity: entity.name, options, validated });
return validated; return validated;
} }
protected async performQuery(qb: RepositoryQB): Promise<RepositoryResponse> { protected async performQuery(qb: RepositoryQB): Promise<RepositoryResponse> {
const entity = this.entity; const entity = this.entity;
const compiled = qb.compile(); const compiled = qb.compile();
//$console.log("performQuery", compiled.sql, compiled.parameters); //$console.debug(`Repository: query\n${compiled.sql}\n`, compiled.parameters);
const start = performance.now(); const start = performance.now();
const selector = (as = "count") => this.conn.fn.countAll<number>().as(as); const selector = (as = "count") => this.conn.fn.countAll<number>().as(as);

View File

@@ -79,26 +79,29 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
return selfField; return selfField;
} }
private getQueryInfo(entity: Entity) { protected getQueryInfo(entity: Entity) {
const other = this.other(entity); const other = this.other(entity);
const conn = this.connectionEntity; const conn = this.connectionEntity;
const entityField = this.getField(entity); const entityField = this.getField(entity);
const otherField = this.getField(other.entity); const otherField = this.getField(other.entity);
const entityRef = `${entity.name}.${entity.getPrimaryField().name}`;
const selfRef = `${conn.name}.${entityField.name}`;
const otherRef = `${conn.name}.${otherField.name}`;
const join = [ const join = [
conn.name, conn.name,
`${other.entity.name}.${other.entity.getPrimaryField().name}`, `${other.entity.name}.${other.entity.getPrimaryField().name}`,
`${conn.name}.${otherField.name}`, otherRef,
] as const; ] as const;
const entityRef = `${entity.name}.${entity.getPrimaryField().name}`;
const otherRef = `${conn.name}.${entityField.name}`;
const groupBy = `${entity.name}.${entity.getPrimaryField().name}`; const groupBy = `${entity.name}.${entity.getPrimaryField().name}`;
return { return {
other, other,
join, join,
entityRef, entityRef,
selfRef,
otherRef, otherRef,
groupBy, groupBy,
}; };
@@ -116,10 +119,10 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
} }
buildJoin(entity: Entity, qb: KyselyQueryBuilder) { buildJoin(entity: Entity, qb: KyselyQueryBuilder) {
const { other, join, entityRef, otherRef, groupBy } = this.getQueryInfo(entity); const { other, join, entityRef, selfRef, groupBy } = this.getQueryInfo(entity);
return qb return qb
.innerJoin(other.entity.name, entityRef, otherRef) .innerJoin(other.entity.name, entityRef, selfRef)
.innerJoin(...join) .innerJoin(...join)
.groupBy(groupBy); .groupBy(groupBy);
} }
@@ -134,7 +137,7 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
} }
const limit = 5; const limit = 5;
const { other, join, entityRef, otherRef } = this.getQueryInfo(entity); const { other, join, entityRef, selfRef } = this.getQueryInfo(entity);
const additionalFields = this.connectionEntity.fields.filter( const additionalFields = this.connectionEntity.fields.filter(
(f) => !(f instanceof RelationField || f instanceof PrimaryField), (f) => !(f instanceof RelationField || f instanceof PrimaryField),
); );
@@ -157,7 +160,7 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
return select; return select;
}) })
.whereRef(entityRef, "=", otherRef) .whereRef(entityRef, "=", selfRef)
.innerJoin(...join) .innerJoin(...join)
.limit(limit); .limit(limit);
} }

View File

@@ -107,7 +107,7 @@ export class ManyToOneRelation extends EntityRelation<typeof ManyToOneRelation.s
return field; return field;
} }
private queryInfo(entity: Entity, reference: string) { protected queryInfo(entity: Entity, reference: string) {
const side = this.source.reference === reference ? "source" : "target"; const side = this.source.reference === reference ? "source" : "target";
const self = this[side]; const self = this[side];
const other = this[side === "source" ? "target" : "source"]; const other = this[side === "source" ? "target" : "source"];

View File

@@ -9,12 +9,6 @@ import { type RelationType, RelationTypes } from "./relation-types";
*/ */
export type OneToOneRelationConfig = ManyToOneRelationConfig; export type OneToOneRelationConfig = ManyToOneRelationConfig;
/* export type OneToOneRelationConfig = {
mappedBy?: string; // author|users
inversedBy?: string; // posts
required?: boolean;
}; */
export class OneToOneRelation extends ManyToOneRelation { export class OneToOneRelation extends ManyToOneRelation {
constructor(source: Entity, target: Entity, config?: OneToOneRelationConfig) { constructor(source: Entity, target: Entity, config?: OneToOneRelationConfig) {
const { mappedBy, inversedBy, required } = config || {}; const { mappedBy, inversedBy, required } = config || {};

View File

@@ -50,7 +50,10 @@ export class RelationAccessor {
*/ */
relationOf(entity: Entity, reference: string): EntityRelation | undefined { relationOf(entity: Entity, reference: string): EntityRelation | undefined {
return this.relationsOf(entity).find((r) => { return this.relationsOf(entity).find((r) => {
return r.source.reference === reference || r.target.reference === reference; return (
(r.target.entity.name === entity.name && r.source.reference === reference) ||
(r.source.entity.name === entity.name && r.target.reference === reference)
);
}); });
} }

View File

@@ -33,6 +33,6 @@
"bknd": ["./src/*"] "bknd": ["./src/*"]
} }
}, },
"include": ["./src/**/*.ts", "./src/**/*.tsx", "vite.dev.ts", "build.ts"], "include": ["./src/**/*.ts", "./src/**/*.tsx", "vite.dev.ts", "build.ts", "__test__"],
"exclude": ["node_modules", "dist", "dist/types", "**/*.d.ts"] "exclude": ["node_modules", "dist", "dist/types", "**/*.d.ts"]
} }