* Builds an IncludesSubquery IR node from a child query builder. * Extracts the correlation condition from the child's WHERE clauses by finding * an eq() predicate that references both a parent alias and a child alias.
( childBuilder: BaseQueryBuilder, fieldName: string, parentAliases: Array<string>, materialization: IncludesMaterialization, )
| 1120 | * an eq() predicate that references both a parent alias and a child alias. |
| 1121 | */ |
| 1122 | function buildIncludesSubquery( |
| 1123 | childBuilder: BaseQueryBuilder, |
| 1124 | fieldName: string, |
| 1125 | parentAliases: Array<string>, |
| 1126 | materialization: IncludesMaterialization, |
| 1127 | ): IncludesSubquery { |
| 1128 | const childQuery = childBuilder._getQuery() |
| 1129 | |
| 1130 | // Collect child's own aliases |
| 1131 | const childAliases = collectQueryAliases(childQuery) |
| 1132 | |
| 1133 | // Walk child's WHERE clauses to find the correlation condition. |
| 1134 | // The correlation eq() may be a standalone WHERE or nested inside a top-level and(). |
| 1135 | let parentRef: PropRef | undefined |
| 1136 | let childRef: PropRef | undefined |
| 1137 | let correlationWhereIndex = -1 |
| 1138 | let correlationAndArgIndex = -1 // >= 0 when found inside an and() |
| 1139 | |
| 1140 | if (childQuery.where) { |
| 1141 | for (let i = 0; i < childQuery.where.length; i++) { |
| 1142 | const where = childQuery.where[i]! |
| 1143 | const expr = |
| 1144 | typeof where === `object` && `expression` in where |
| 1145 | ? where.expression |
| 1146 | : where |
| 1147 | |
| 1148 | // Try standalone eq() |
| 1149 | if ( |
| 1150 | expr.type === `func` && |
| 1151 | expr.name === `eq` && |
| 1152 | expr.args.length === 2 |
| 1153 | ) { |
| 1154 | const result = extractCorrelation( |
| 1155 | expr.args[0]!, |
| 1156 | expr.args[1]!, |
| 1157 | parentAliases, |
| 1158 | childAliases, |
| 1159 | ) |
| 1160 | if (result) { |
| 1161 | parentRef = result.parentRef |
| 1162 | childRef = result.childRef |
| 1163 | correlationWhereIndex = i |
| 1164 | break |
| 1165 | } |
| 1166 | } |
| 1167 | |
| 1168 | // Try inside top-level and() |
| 1169 | if ( |
| 1170 | expr.type === `func` && |
| 1171 | expr.name === `and` && |
| 1172 | expr.args.length >= 2 |
| 1173 | ) { |
| 1174 | for (let j = 0; j < expr.args.length; j++) { |
| 1175 | const arg = expr.args[j]! |
| 1176 | if ( |
| 1177 | arg.type === `func` && |
| 1178 | arg.name === `eq` && |
| 1179 | arg.args.length === 2 |
no test coverage detected
searching dependent graphs…