fun warmUpReferences()

in exposed-dao/src/main/kotlin/org/jetbrains/exposed/v1/dao/EntityClass.kt [849:914]


    fun <SID> warmUpReferences(
        references: List<SID>,
        refColumn: Column<SID>,
        forUpdate: Boolean? = null,
        orderBy: Array<Pair<Expression<*>, SortOrder>>? = null
    ): List<T> {
        val parentTable = refColumn.referee?.table as? IdTable<*>
        requireNotNull(parentTable) { "RefColumn should have reference to IdTable" }
        if (references.isEmpty()) return emptyList()
        val distinctRefIds = references.distinct()
        val transaction = TransactionManager.current()
        val cache = transaction.entityCache
        val keepLoadedReferenceOutOfTransaction = transaction.db.config.keepLoadedReferencesOutOfTransaction
        if (refColumn.columnType is EntityIDColumnType<*>) {
            refColumn as Column<EntityID<*>>
            distinctRefIds as List<EntityID<ID>>
            val toLoad: List<EntityID<ID>> = distinctRefIds.filter {
                cache.referrers[refColumn]?.containsKey(it)?.not() ?: true
            }
            if (toLoad.isNotEmpty()) {
                val findQuery = find { refColumn inList toLoad }
                    .orderBy(order = orderBy ?: emptyArray())
                val entities = getEntities(forUpdate, findQuery)

                val result = entities.groupByReference(refColumn = refColumn)

                distinctRefIds.forEach { id ->
                    cache.getOrPutReferrers(id, refColumn) { result[id]?.let { SizedCollection(it) } ?: emptySized() }.also {
                        if (keepLoadedReferenceOutOfTransaction) {
                            cache.find(this, id)?.storeReferenceInCache(refColumn, it)
                        }
                    }
                }
            }

            return distinctRefIds.flatMap { cache.getReferrers<T>(it, refColumn)?.toList().orEmpty() }
        } else {
            val baseQuery = searchQuery(refColumn inList distinctRefIds)
            val finalQuery = if (parentTable.id in baseQuery.set.fields) {
                baseQuery
            } else {
                baseQuery.adjustSelect { select(fields + parentTable.id) }
                    .adjustColumnSet { innerJoin(parentTable, { refColumn }, { refColumn.referee!! }) }
            }
                .orderBy(order = orderBy ?: emptyArray())

            val findQuery = wrapRows(finalQuery)
            val entities = getEntities(forUpdate, findQuery).distinct()

            entities.groupByReference(refColumn = refColumn).forEach { (id, values) ->
                val castReferee = refColumn.referee
                    .takeUnless { it?.columnType is EntityIDColumnType<*> && id !is EntityID<*> }
                    ?: (refColumn.referee?.columnType as EntityIDColumnType<*>).idColumn
                val parentEntityId: EntityID<*> = parentTable.selectAll().where { castReferee as Column<SID> eq id }
                    .single()[parentTable.id]

                cache.getOrPutReferrers(parentEntityId, refColumn) { SizedCollection(values) }.also {
                    if (keepLoadedReferenceOutOfTransaction) {
                        val childEntity = find { refColumn eq id }.firstOrNull()
                        childEntity?.storeReferenceInCache(refColumn, it)
                    }
                }
            }
            return entities
        }
    }