333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
{"version":3,"sources":["../browser/src/metadata-builder/RelationJoinColumnBuilder.ts"],"names":[],"mappings":"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","file":"RelationJoinColumnBuilder.js","sourcesContent":["import {MysqlDriver} from \"../driver/mysql/MysqlDriver\";\nimport {ColumnMetadata} from \"../metadata/ColumnMetadata\";\nimport {UniqueMetadata} from \"../metadata/UniqueMetadata\";\nimport {ForeignKeyMetadata} from \"../metadata/ForeignKeyMetadata\";\nimport {RelationMetadata} from \"../metadata/RelationMetadata\";\nimport {JoinColumnMetadataArgs} from \"../metadata-args/JoinColumnMetadataArgs\";\nimport {Connection} from \"../connection/Connection\";\nimport {OracleDriver} from \"../driver/oracle/OracleDriver\";\n\n/**\n * Builds join column for the many-to-one and one-to-one owner relations.\n *\n * Cases it should cover:\n * 1. when join column is set with custom name and without referenced column name\n * we need automatically set referenced column name - primary ids by default\n * @JoinColumn({ name: \"custom_name\" })\n *\n * 2. when join column is set with only referenced column name\n * we need automatically set join column name - relation name + referenced column name\n * @JoinColumn({ referencedColumnName: \"title\" })\n *\n * 3. when join column is set without both referenced column name and join column name\n * we need to automatically set both of them\n * @JoinColumn()\n *\n * 4. when join column is not set at all (as in case of @ManyToOne relation)\n * we need to create join column for it with proper referenced column name and join column name\n *\n * 5. when multiple join columns set none of referencedColumnName and name can be optional\n * both options are required\n * @JoinColumn([\n *      { name: \"category_title\", referencedColumnName: \"type\" },\n *      { name: \"category_title\", referencedColumnName: \"name\" },\n * ])\n *\n * Since for many-to-one relations having JoinColumn decorator is not required,\n * we need to go thought each many-to-one relation without join column decorator set\n * and create join column metadata args for them.\n */\nexport class RelationJoinColumnBuilder {\n\n    // -------------------------------------------------------------------------\n    // Constructor\n    // -------------------------------------------------------------------------\n\n    constructor(private connection: Connection) {\n    }\n\n    // -------------------------------------------------------------------------\n    // Public Methods\n    // -------------------------------------------------------------------------\n\n    /**\n     * Builds a foreign key of the many-to-one or one-to-one owner relations.\n     */\n    build(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata): {\n      foreignKey: ForeignKeyMetadata|undefined,\n      uniqueConstraint: UniqueMetadata|undefined,\n    } {\n        const referencedColumns = this.collectReferencedColumns(joinColumns, relation);\n        if (!referencedColumns.length)\n            return { foreignKey: undefined, uniqueConstraint: undefined }; // this case is possible only for one-to-one non owning side\n\n        const columns = this.collectColumns(joinColumns, relation, referencedColumns);\n        const foreignKey = new ForeignKeyMetadata({\n            entityMetadata: relation.entityMetadata,\n            referencedEntityMetadata: relation.inverseEntityMetadata,\n            namingStrategy: this.connection.namingStrategy,\n            columns: columns,\n            referencedColumns: referencedColumns,\n            onDelete: relation.onDelete,\n            onUpdate: relation.onUpdate,\n            deferrable: relation.deferrable,\n        });\n\n        // Oracle does not allow both primary and unique constraints on the same column\n        if (this.connection.driver instanceof OracleDriver && columns.every(column => column.isPrimary))\n            return { foreignKey, uniqueConstraint: undefined };\n\n        // CockroachDB requires UNIQUE constraints on referenced columns\n        if (referencedColumns.length > 0 && relation.isOneToOne) {\n            const uniqueConstraint = new UniqueMetadata({\n                entityMetadata: relation.entityMetadata,\n                columns: foreignKey.columns,\n                args: {\n                    name: this.connection.namingStrategy.relationConstraintName(relation.entityMetadata.tablePath, foreignKey.columns.map(c => c.databaseName)),\n                    target: relation.entityMetadata.target,\n                }\n            });\n            uniqueConstraint.build(this.connection.namingStrategy);\n            return {foreignKey, uniqueConstraint};\n        }\n\n        return { foreignKey, uniqueConstraint: undefined };\n    }\n    // -------------------------------------------------------------------------\n    // Protected Methods\n    // -------------------------------------------------------------------------\n\n    /**\n     * Collects referenced columns from the given join column args.\n     */\n    protected collectReferencedColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata): ColumnMetadata[] {\n        const hasAnyReferencedColumnName = joinColumns.find(joinColumnArgs => !!joinColumnArgs.referencedColumnName);\n        const manyToOneWithoutJoinColumn = joinColumns.length === 0 && relation.isManyToOne;\n        const hasJoinColumnWithoutAnyReferencedColumnName = joinColumns.length > 0 && !hasAnyReferencedColumnName;\n\n        if (manyToOneWithoutJoinColumn || hasJoinColumnWithoutAnyReferencedColumnName) { // covers case3 and case1\n            return relation.inverseEntityMetadata.primaryColumns;\n\n        } else { // cases with referenced columns defined\n            return joinColumns.map(joinColumn => {\n                const referencedColumn = relation.inverseEntityMetadata.ownColumns.find(column => column.propertyName === joinColumn.referencedColumnName); // todo: can we also search in relations?\n                if (!referencedColumn)\n                    throw new Error(`Referenced column ${joinColumn.referencedColumnName} was not found in entity ${relation.inverseEntityMetadata.name}`);\n\n                return referencedColumn;\n            });\n        }\n    }\n\n    /**\n     * Collects columns from the given join column args.\n     */\n    private collectColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata, referencedColumns: ColumnMetadata[]): ColumnMetadata[] {\n        return referencedColumns.map(referencedColumn => {\n\n            // in the case if relation has join column with only name set we need this check\n            const joinColumnMetadataArg = joinColumns.find(joinColumn => {\n                return (!joinColumn.referencedColumnName || joinColumn.referencedColumnName === referencedColumn.propertyName) &&\n                    !!joinColumn.name;\n            });\n            const joinColumnName = joinColumnMetadataArg ? joinColumnMetadataArg.name : this.connection.namingStrategy.joinColumnName(relation.propertyName, referencedColumn.propertyName);\n\n            let relationalColumn = relation.entityMetadata.ownColumns.find(column => column.databaseName === joinColumnName);\n            if (!relationalColumn) {\n                relationalColumn = new ColumnMetadata({\n                    connection: this.connection,\n                    entityMetadata: relation.entityMetadata,\n                    args: {\n                        target: \"\",\n                        mode: \"virtual\",\n                        propertyName: relation.propertyName,\n                        options: {\n                            name: joinColumnName,\n                            type: referencedColumn.type,\n                            length: !referencedColumn.length\n                                        && (this.connection.driver instanceof MysqlDriver)\n                                        && (referencedColumn.generationStrategy === \"uuid\" || referencedColumn.type === \"uuid\")\n                                    ? \"36\"\n                                    : referencedColumn.length, // fix https://github.com/typeorm/typeorm/issues/3604\n                            width: referencedColumn.width,\n                            charset: referencedColumn.charset,\n                            collation: referencedColumn.collation,\n                            precision: referencedColumn.precision,\n                            scale: referencedColumn.scale,\n                            zerofill: referencedColumn.zerofill,\n                            unsigned: referencedColumn.unsigned,\n                            comment: referencedColumn.comment,\n                            primary: relation.isPrimary,\n                            nullable: relation.isNullable\n                        }\n                    }\n                });\n                relation.entityMetadata.registerColumn(relationalColumn);\n            }\n            relationalColumn.referencedColumn = referencedColumn; // its important to set it here because we need to set referenced column for user defined join column\n            relationalColumn.type = referencedColumn.type; // also since types of relational column and join column must be equal we override user defined column type\n            relationalColumn.relationMetadata = relation;\n            relationalColumn.build(this.connection);\n            return relationalColumn;\n        });\n    }\n}\n"],"sourceRoot":".."}