(row: NamespacedRow & { $selected?: any })
| 72 | |
| 73 | // Create a value extractor function for the orderBy operator |
| 74 | const valueExtractor = (row: NamespacedRow & { $selected?: any }) => { |
| 75 | // The namespaced row contains: |
| 76 | // 1. Table aliases as top-level properties (e.g., row["tableName"]) |
| 77 | // 2. SELECT results in $selected (e.g., row.$selected["aggregateAlias"]) |
| 78 | // The replaceAggregatesByRefs function has already transformed: |
| 79 | // - Aggregate expressions that match SELECT aggregates to use the $selected namespace |
| 80 | // - $selected ref expressions are passed through unchanged (already using the correct namespace) |
| 81 | const orderByContext = row |
| 82 | |
| 83 | if (orderByClause.length > 1) { |
| 84 | // For multiple orderBy columns, create a composite key |
| 85 | return compiledOrderBy.map((compiled) => |
| 86 | compiled.compiledExpression(orderByContext), |
| 87 | ) |
| 88 | } else if (orderByClause.length === 1) { |
| 89 | // For a single orderBy column, use the value directly |
| 90 | const compiled = compiledOrderBy[0]! |
| 91 | return compiled.compiledExpression(orderByContext) |
| 92 | } |
| 93 | |
| 94 | // Default case - no ordering |
| 95 | return null |
| 96 | } |
| 97 | |
| 98 | // Create a multi-property comparator that respects the order and direction of each property |
| 99 | const compare = (a: unknown, b: unknown) => { |
no test coverage detected