@@ -7,9 +7,11 @@ import {
77} from "@tanstack/db-ivm"
88import {
99 CollectionInputNotFoundError ,
10+ InvalidJoinCondition ,
11+ InvalidJoinConditionLeftTableError ,
12+ InvalidJoinConditionRightTableError ,
1013 InvalidJoinConditionSameTableError ,
1114 InvalidJoinConditionTableMismatchError ,
12- InvalidJoinConditionWrongTablesError ,
1315 JoinCollectionNotFoundError ,
1416 UnsupportedJoinSourceTypeError ,
1517 UnsupportedJoinTypeError ,
@@ -139,10 +141,11 @@ function processJoin(
139141 )
140142
141143 // Analyze which table each expression refers to and swap if necessary
144+ const availableTableAliases = Object . keys ( tables )
142145 const { mainExpr, joinedExpr } = analyzeJoinExpressions (
143146 joinClause . left ,
144147 joinClause . right ,
145- mainTableAlias ,
148+ availableTableAliases ,
146149 joinedTableAlias
147150 )
148151
@@ -299,53 +302,65 @@ function processJoin(
299302
300303/**
301304 * Analyzes join expressions to determine which refers to which table
302- * and returns them in the correct order (main table expression first, joined table expression second)
305+ * and returns them in the correct order (available table expression first, joined table expression second)
303306 */
304307function analyzeJoinExpressions (
305308 left : BasicExpression ,
306309 right : BasicExpression ,
307- mainTableAlias : string ,
310+ allAvailableTableAliases : Array < string > ,
308311 joinedTableAlias : string
309312) : { mainExpr : BasicExpression ; joinedExpr : BasicExpression } {
313+ // Filter out the joined table alias from the available table aliases
314+ const availableTableAliases = allAvailableTableAliases . filter (
315+ ( alias ) => alias !== joinedTableAlias
316+ )
317+
310318 const leftTableAlias = getTableAliasFromExpression ( left )
311319 const rightTableAlias = getTableAliasFromExpression ( right )
312320
313- // If left expression refers to main table and right refers to joined table, keep as is
321+ // If left expression refers to an available table and right refers to joined table, keep as is
314322 if (
315- leftTableAlias === mainTableAlias &&
323+ leftTableAlias &&
324+ availableTableAliases . includes ( leftTableAlias ) &&
316325 rightTableAlias === joinedTableAlias
317326 ) {
318327 return { mainExpr : left , joinedExpr : right }
319328 }
320329
321- // If left expression refers to joined table and right refers to main table, swap them
330+ // If left expression refers to joined table and right refers to an available table, swap them
322331 if (
323332 leftTableAlias === joinedTableAlias &&
324- rightTableAlias === mainTableAlias
333+ rightTableAlias &&
334+ availableTableAliases . includes ( rightTableAlias )
325335 ) {
326336 return { mainExpr : right , joinedExpr : left }
327337 }
328338
339+ // If one expression doesn't refer to any table, this is an invalid join
340+ if ( ! leftTableAlias || ! rightTableAlias ) {
341+ // For backward compatibility, use the first available table alias in error message
342+ throw new InvalidJoinConditionTableMismatchError ( )
343+ }
344+
329345 // If both expressions refer to the same alias, this is an invalid join
330346 if ( leftTableAlias === rightTableAlias ) {
331- throw new InvalidJoinConditionSameTableError ( leftTableAlias || `unknown` )
347+ throw new InvalidJoinConditionSameTableError ( leftTableAlias )
332348 }
333349
334- // If one expression doesn't refer to either table, this is an invalid join
335- if ( ! leftTableAlias || ! rightTableAlias ) {
336- throw new InvalidJoinConditionTableMismatchError (
337- mainTableAlias ,
338- joinedTableAlias
339- )
350+ // Left side must refer to an available table
351+ // This cannot happen with the query builder as there is no way to build a ref
352+ // to an unavailable table, but just in case, but could happen with the IR
353+ if ( ! availableTableAliases . includes ( leftTableAlias ) ) {
354+ throw new InvalidJoinConditionLeftTableError ( leftTableAlias )
340355 }
341356
342- // If expressions refer to tables not involved in this join, this is an invalid join
343- throw new InvalidJoinConditionWrongTablesError (
344- leftTableAlias ,
345- rightTableAlias ,
346- mainTableAlias ,
347- joinedTableAlias
348- )
357+ // Right side must refer to the joined table
358+ if ( rightTableAlias !== joinedTableAlias ) {
359+ throw new InvalidJoinConditionRightTableError ( joinedTableAlias )
360+ }
361+
362+ // This should not be reachable given the logic above, but just in case
363+ throw new InvalidJoinCondition ( )
349364}
350365
351366/**
0 commit comments