Repository: typeorm/typeorm
File: src/query-builder/QueryBuilder.ts (TypeScript)

Code before:
            for (const data of normalized) {
                qb.orWhere(new Brackets((qb) => qb.where(data)))
            }
        })
    }

    protected getExistsCondition(subQuery: any): [string, any[]] {
        const query = subQuery
            .clone()
            .orderBy()
            .groupBy()
            .offset(undefined)
            .limit(undefined)
            .skip(undefined)
            .take(undefined)
            .select("1")
            .setOption("disable-global-order")

        return [`EXISTS (${query.getQuery()})`, query.getParameters()]
    }

    private findColumnsForPropertyPath(
        propertyPath: string,
    ): [Alias, string[], ColumnMetadata[]] {
        // Make a helper to iterate the entity & relations?
        // Use that to set the correct alias?  Or the other way around?

        // Start with the main alias with our property paths
        let alias = this.expressionMap.mainAlias
        const root: string[] = []
        const propertyPathParts = propertyPath.split(".")

        while (propertyPathParts.length > 1) {
            const part = propertyPathParts[0]

            if (!alias?.hasMetadata) {
                // If there's no metadata, we're wasting our time
                // and can't actually look any of this up.
                break
            }

            if (alias.metadata.hasEmbeddedWithPropertyPath(part)) {
                // If this is an embedded then we should combine the two as part of our lookup.
                // Instead of just breaking, we keep going with this in case there's an embedded/relation
                // inside an embedded.
                propertyPathParts.unshift(
                    `${propertyPathParts.shift()}.${propertyPathParts.shift()}`,
                )
                continue
            }


Review comment (bug):
nit: There's another edge case when the length is 0, the generated SQL query is `column IN ()`, which is invalid as well.

Code after:
    protected getWhereInIdsCondition(
        ids: any | any[],
    ): ObjectLiteral | Brackets {
        const metadata = this.expressionMap.mainAlias!.metadata
        const normalized = (Array.isArray(ids) ? ids : [ids]).map((id) =>
            metadata.ensureEntityIdMap(id),
        )

        // using in(...ids) for single primary key entities
        if (!metadata.hasMultiplePrimaryKeys) {
            const primaryColumn = metadata.primaryColumns[0]

            // getEntityValue will try to transform `In`, it is a bug
            // todo: remove this transformer check after #2390 is fixed
            // This also fails for embedded & relation, so until that is fixed skip it.
            if (
                !primaryColumn.transformer &&
                !primaryColumn.relationMetadata &&
                !primaryColumn.embeddedMetadata
            ) {
                const values = normalized.map((id) =>
                    primaryColumn.getEntityValue(id, false),
                )
                return {
                    [primaryColumn.propertyName]:
                        values.length === 1 ? Equal(values[0]) : In(values),
                }
            }
        }

        return new Brackets((qb) => {
            for (const data of normalized) {
                qb.orWhere(new Brackets((qb) => qb.where(data)))
            }
        })
    }

    protected getExistsCondition(subQuery: any): [string, any[]] {
        const query = subQuery
            .clone()
            .orderBy()
            .groupBy()
            .offset(undefined)
            .limit(undefined)
            .skip(undefined)
            .take(undefined)
            .select("1")
            .setOption("disable-global-order")

        return [`EXISTS (${query.getQuery()})`, query.getParameters()]
    }