{"version":3,"sources":["../../src/query-builder/relation-count/RelationCountLoader.ts"],"names":[],"mappings":"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","file":"RelationCountLoader.js","sourcesContent":["import { ColumnMetadata } from \"../../metadata/ColumnMetadata\"\nimport { DataSource } from \"../../data-source/DataSource\"\nimport { RelationCountAttribute } from \"./RelationCountAttribute\"\nimport { RelationCountLoadResult } from \"./RelationCountLoadResult\"\nimport { QueryRunner } from \"../../query-runner/QueryRunner\"\n\nexport class RelationCountLoader {\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(\n protected connection: DataSource,\n protected queryRunner: QueryRunner | undefined,\n protected relationCountAttributes: RelationCountAttribute[],\n ) {}\n\n // -------------------------------------------------------------------------\n // Public Methods\n // -------------------------------------------------------------------------\n\n async load(rawEntities: any[]): Promise {\n const onlyUnique = (value: any, index: number, self: any) => {\n return self.indexOf(value) === index\n }\n\n const promises = this.relationCountAttributes.map(\n async (relationCountAttr) => {\n if (relationCountAttr.relation.isOneToMany) {\n // example: Post and Category\n // loadRelationCountAndMap(\"post.categoryCount\", \"post.categories\")\n // we expect it to load array of post ids\n\n // todo(dima): fix issues wit multiple primary keys and remove joinColumns[0]\n const relation = relationCountAttr.relation // \"category.posts\"\n const inverseRelation = relation.inverseRelation! // \"post.category\"\n const referenceColumnName =\n inverseRelation.joinColumns[0].referencedColumn!\n .propertyName // post id\n const inverseSideTable =\n relation.inverseEntityMetadata.target // Post\n const inverseSideTableName =\n relation.inverseEntityMetadata.tableName // post\n const inverseSideTableAlias =\n relationCountAttr.alias || inverseSideTableName // if condition (custom query builder factory) is set then relationIdAttr.alias defined\n const inverseSidePropertyName = inverseRelation.propertyName // \"category\" from \"post.category\"\n\n let referenceColumnValues = rawEntities\n .map(\n (rawEntity) =>\n rawEntity[\n relationCountAttr.parentAlias +\n \"_\" +\n referenceColumnName\n ],\n )\n .filter((value) => !!value)\n referenceColumnValues =\n referenceColumnValues.filter(onlyUnique)\n\n // ensure we won't perform redundant queries for joined data which was not found in selection\n // example: if post.category was not found in db then no need to execute query for category.imageIds\n if (referenceColumnValues.length === 0)\n return {\n relationCountAttribute: relationCountAttr,\n results: [],\n }\n\n // generate query:\n // SELECT category.post as parentId, COUNT(*) AS cnt FROM category category WHERE category.post IN (1, 2) GROUP BY category.post\n const qb = this.connection.createQueryBuilder(\n this.queryRunner,\n )\n qb.select(\n inverseSideTableAlias + \".\" + inverseSidePropertyName,\n \"parentId\",\n )\n .addSelect(\"COUNT(*)\", \"cnt\")\n .from(inverseSideTable, inverseSideTableAlias)\n .where(\n inverseSideTableAlias +\n \".\" +\n inverseSidePropertyName +\n \" IN (:...ids)\",\n )\n .addGroupBy(\n inverseSideTableAlias +\n \".\" +\n inverseSidePropertyName,\n )\n .setParameter(\"ids\", referenceColumnValues)\n\n // apply condition (custom query builder factory)\n if (relationCountAttr.queryBuilderFactory)\n relationCountAttr.queryBuilderFactory(qb)\n\n return {\n relationCountAttribute: relationCountAttr,\n results: await qb.getRawMany(),\n }\n } else {\n // example: Post and Category\n // owner side: loadRelationIdAndMap(\"post.categoryIds\", \"post.categories\")\n // inverse side: loadRelationIdAndMap(\"category.postIds\", \"category.posts\")\n // we expect it to load array of post ids\n\n let joinTableColumnName: string\n let inverseJoinColumnName: string\n let firstJunctionColumn: ColumnMetadata\n let secondJunctionColumn: ColumnMetadata\n\n if (relationCountAttr.relation.isOwning) {\n // todo fix joinColumns[0] and inverseJoinColumns[0].\n joinTableColumnName =\n relationCountAttr.relation.joinColumns[0]\n .referencedColumn!.databaseName\n inverseJoinColumnName =\n relationCountAttr.relation.inverseJoinColumns[0]\n .referencedColumn!.databaseName\n firstJunctionColumn =\n relationCountAttr.relation.junctionEntityMetadata!\n .columns[0]\n secondJunctionColumn =\n relationCountAttr.relation.junctionEntityMetadata!\n .columns[1]\n } else {\n joinTableColumnName =\n relationCountAttr.relation.inverseRelation!\n .inverseJoinColumns[0].referencedColumn!\n .databaseName\n inverseJoinColumnName =\n relationCountAttr.relation.inverseRelation!\n .joinColumns[0].referencedColumn!.databaseName\n firstJunctionColumn =\n relationCountAttr.relation.junctionEntityMetadata!\n .columns[1]\n secondJunctionColumn =\n relationCountAttr.relation.junctionEntityMetadata!\n .columns[0]\n }\n\n let referenceColumnValues = rawEntities\n .map(\n (rawEntity) =>\n rawEntity[\n relationCountAttr.parentAlias +\n \"_\" +\n joinTableColumnName\n ],\n )\n .filter((value) => !!value)\n referenceColumnValues =\n referenceColumnValues.filter(onlyUnique)\n\n // ensure we won't perform redundant queries for joined data which was not found in selection\n // example: if post.category was not found in db then no need to execute query for category.imageIds\n if (referenceColumnValues.length === 0)\n return {\n relationCountAttribute: relationCountAttr,\n results: [],\n }\n\n const junctionAlias = relationCountAttr.junctionAlias\n const inverseSideTableName =\n relationCountAttr.joinInverseSideMetadata.tableName\n const inverseSideTableAlias =\n relationCountAttr.alias || inverseSideTableName\n const junctionTableName =\n relationCountAttr.relation.junctionEntityMetadata!\n .tableName\n\n const condition =\n junctionAlias +\n \".\" +\n firstJunctionColumn.propertyName +\n \" IN (\" +\n referenceColumnValues.map((vals) =>\n isNaN(vals) ? \"'\" + vals + \"'\" : vals,\n ) +\n \")\" +\n \" AND \" +\n junctionAlias +\n \".\" +\n secondJunctionColumn.propertyName +\n \" = \" +\n inverseSideTableAlias +\n \".\" +\n inverseJoinColumnName\n\n const qb = this.connection.createQueryBuilder(\n this.queryRunner,\n )\n qb.select(\n junctionAlias + \".\" + firstJunctionColumn.propertyName,\n \"parentId\",\n )\n .addSelect(\n \"COUNT(\" +\n qb.escape(inverseSideTableAlias) +\n \".\" +\n qb.escape(inverseJoinColumnName) +\n \")\",\n \"cnt\",\n )\n .from(inverseSideTableName, inverseSideTableAlias)\n .innerJoin(junctionTableName, junctionAlias, condition)\n .addGroupBy(\n junctionAlias +\n \".\" +\n firstJunctionColumn.propertyName,\n )\n\n // apply condition (custom query builder factory)\n if (relationCountAttr.queryBuilderFactory)\n relationCountAttr.queryBuilderFactory(qb)\n\n return {\n relationCountAttribute: relationCountAttr,\n results: await qb.getRawMany(),\n }\n }\n },\n )\n\n return Promise.all(promises)\n }\n}\n"],"sourceRoot":"../.."}