@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 10.3 kB
Source Map (JSON)
{"version":3,"file":"select.cjs","sources":["../../../src/query/select.ts"],"sourcesContent":["import { map } from \"@electric-sql/d2mini\"\nimport {\n evaluateOperandOnNamespacedRow,\n extractValueFromNamespacedRow,\n} from \"./extractors\"\nimport type { ConditionOperand, Query, SelectCallback } from \"./schema\"\nimport type { KeyedStream, NamespacedAndKeyedStream } from \"../types\"\n\nexport function processSelect(\n pipeline: NamespacedAndKeyedStream,\n query: Query,\n mainTableAlias: string,\n inputs: Record<string, KeyedStream>\n): KeyedStream {\n return pipeline.pipe(\n map(([key, namespacedRow]) => {\n const result: Record<string, unknown> = {}\n\n // Check if this is a grouped result (has no nested table structure)\n // If it's a grouped result, we need to handle it differently\n const isGroupedResult =\n query.groupBy &&\n Object.keys(namespacedRow).some(\n (namespaceKey) =>\n !Object.keys(inputs).includes(namespaceKey) &&\n typeof namespacedRow[namespaceKey] !== `object`\n )\n\n if (!query.select) {\n throw new Error(`Cannot process missing SELECT clause`)\n }\n\n for (const item of query.select) {\n // Handle callback functions\n if (typeof item === `function`) {\n const callback = item as SelectCallback\n const callbackResult = callback(namespacedRow)\n\n // If the callback returns an object, merge its properties into the result\n if (\n callbackResult &&\n typeof callbackResult === `object` &&\n !Array.isArray(callbackResult)\n ) {\n Object.assign(result, callbackResult)\n } else {\n // If the callback returns a primitive value, we can't merge it\n // This would need a specific key, but since we don't have one, we'll skip it\n // In practice, select callbacks should return objects with keys\n console.warn(\n `SelectCallback returned a non-object value. SelectCallbacks should return objects with key-value pairs.`\n )\n }\n continue\n }\n\n if (typeof item === `string`) {\n // Handle wildcard select - all columns from all tables\n if ((item as string) === `@*`) {\n // For grouped results, just return the row as is\n if (isGroupedResult) {\n Object.assign(result, namespacedRow)\n } else {\n // Extract all columns from all tables\n Object.assign(\n result,\n extractAllColumnsFromAllTables(namespacedRow)\n )\n }\n continue\n }\n\n // Handle @table.* syntax - all columns from a specific table\n if (\n (item as string).startsWith(`@`) &&\n (item as string).endsWith(`.*`)\n ) {\n const tableAlias = (item as string).slice(1, -2) // Remove the '@' and '.*' parts\n\n // For grouped results, check if we have columns from this table\n if (isGroupedResult) {\n // In grouped results, we don't have the nested structure anymore\n // So we can't extract by table. Just continue to the next item.\n continue\n } else {\n // Extract all columns from the specified table\n Object.assign(\n result,\n extractAllColumnsFromTable(namespacedRow, tableAlias)\n )\n }\n continue\n }\n\n // Handle simple column references like \"@table.column\" or \"@column\"\n if ((item as string).startsWith(`@`)) {\n const columnRef = (item as string).substring(1)\n const alias = columnRef\n\n // For grouped results, check if the column is directly in the row first\n if (isGroupedResult && columnRef in namespacedRow) {\n result[alias] = namespacedRow[columnRef]\n } else {\n // Extract the value from the nested structure\n result[alias] = extractValueFromNamespacedRow(\n namespacedRow,\n columnRef,\n mainTableAlias,\n undefined\n )\n }\n\n // If the alias contains a dot (table.column),\n // use just the column part as the field name\n if (alias.includes(`.`)) {\n const columnName = alias.split(`.`)[1]\n result[columnName!] = result[alias]\n delete result[alias]\n }\n }\n } else {\n // Handle aliased columns like { alias: \"@column_name\" }\n for (const [alias, expr] of Object.entries(item)) {\n if (typeof expr === `string` && (expr as string).startsWith(`@`)) {\n const columnRef = (expr as string).substring(1)\n\n // For grouped results, check if the column is directly in the row first\n if (isGroupedResult && columnRef in namespacedRow) {\n result[alias] = namespacedRow[columnRef]\n } else {\n // Extract the value from the nested structure\n result[alias] = extractValueFromNamespacedRow(\n namespacedRow,\n columnRef,\n mainTableAlias,\n undefined\n )\n }\n } else if (typeof expr === `object`) {\n // For grouped results, the aggregate results are already in the row\n if (isGroupedResult && alias in namespacedRow) {\n result[alias] = namespacedRow[alias]\n } else if ((expr as { ORDER_INDEX: unknown }).ORDER_INDEX) {\n result[alias] = namespacedRow[mainTableAlias]![alias]\n } else {\n // This might be a function call\n result[alias] = evaluateOperandOnNamespacedRow(\n namespacedRow,\n expr as ConditionOperand,\n mainTableAlias,\n undefined\n )\n }\n }\n }\n }\n }\n\n return [key, result] as [string, typeof result]\n })\n )\n}\n\n// Helper function to extract all columns from all tables in a nested row\nfunction extractAllColumnsFromAllTables(\n namespacedRow: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n // Process each table in the nested row\n for (const [tableAlias, tableData] of Object.entries(namespacedRow)) {\n if (tableData && typeof tableData === `object`) {\n // Add all columns from this table to the result\n // If there are column name conflicts, the last table's columns will overwrite previous ones\n Object.assign(\n result,\n extractAllColumnsFromTable(namespacedRow, tableAlias)\n )\n }\n }\n\n return result\n}\n\n// Helper function to extract all columns from a table in a nested row\nfunction extractAllColumnsFromTable(\n namespacedRow: Record<string, unknown>,\n tableAlias: string\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n // Get the table data\n const tableData = namespacedRow[tableAlias] as\n | Record<string, unknown>\n | null\n | undefined\n\n if (!tableData || typeof tableData !== `object`) {\n return result\n }\n\n // Add all columns from the table to the result\n for (const [columnName, value] of Object.entries(tableData)) {\n result[columnName] = value\n }\n\n return result\n}\n"],"names":["map","extractValueFromNamespacedRow","evaluateOperandOnNamespacedRow"],"mappings":"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"}