{"version":3,"file":"clone-query.cjs","sources":["../../../../src/query/builder/clone-query.ts"],"sourcesContent":["import {\n  CollectionRef,\n  ConditionalSelect,\n  DescriptorRef,\n  IncludesSubquery,\n  QueryRef,\n  UnionAll,\n  UnionFrom,\n  isExpressionLike,\n} from '../ir.js'\nimport { isRefProxy } from './ref-proxy-identity.js'\nimport type { CollectionImpl } from '../../collection/index.js'\nimport type { CollectionOptionsIdentity } from '../../collection-options.js'\nimport type {\n  CollectionSourceRef,\n  From,\n  QueryIR,\n  Select,\n  SelectValueExpression,\n} from '../ir.js'\n\nexport type CollectionResolver = (\n  options: CollectionOptionsIdentity<any, string | number, any, any, any>,\n) => CollectionImpl<any, string | number, any, any, any>\n\ntype CloneContext = {\n  clones: WeakMap<object, object>\n  resolveDescriptor?: CollectionResolver\n}\n\n/**\n * Gives every query-source placement its own runtime source identities.\n *\n * A reused builder describes the same query meaning, but each FROM, JOIN,\n * UNION, or include placement owns an independent position in the dataflow\n * graph. Expressions are immutable and can remain shared; source refs cannot\n * because their sourceId identifies that lexical position. A supplied\n * resolver also binds any retained descriptors while cloning the plan.\n */\nexport function cloneQueryForPlacement(\n  query: QueryIR,\n  resolveCollection?: CollectionResolver,\n): QueryIR {\n  return cloneQuery(query, {\n    clones: new WeakMap(),\n    resolveDescriptor: resolveCollection,\n  })\n}\n\nfunction cloneQuery(query: QueryIR, context: CloneContext): QueryIR {\n  const { clones } = context\n  const existing = clones.get(query)\n  if (existing) return existing as QueryIR\n\n  const cloned: QueryIR = {\n    ...query,\n  }\n  clones.set(query, cloned)\n\n  cloned.from = cloneFromForPlacement(query.from, context)\n  cloned.join = query.join?.map((join) => ({\n    ...join,\n    from: cloneSourceForPlacement(join.from, context),\n  }))\n  cloned.select =\n    query.select === undefined || isExpressionLike(query.select)\n      ? query.select\n      : cloneSelectForPlacement(query.select, context)\n  return cloned\n}\n\nfunction cloneFromForPlacement(from: From, context: CloneContext): From {\n  if (from.type === `unionFrom`) {\n    return new UnionFrom(\n      from.sources.map((source) => cloneSourceForPlacement(source, context)),\n    )\n  }\n\n  if (from.type === `unionAll`) {\n    return new UnionAll(from.queries.map((query) => cloneQuery(query, context)))\n  }\n\n  return cloneSourceForPlacement(from, context)\n}\n\nfunction cloneSourceForPlacement(\n  source: CollectionSourceRef | QueryRef,\n  context: CloneContext,\n): CollectionSourceRef | QueryRef {\n  if (source.type === `collectionRef`) {\n    return new CollectionRef(source.collection, source.alias, source.bindingId)\n  }\n\n  if (source.type === `descriptorRef`) {\n    return context.resolveDescriptor\n      ? new CollectionRef(\n          context.resolveDescriptor(source.descriptor),\n          source.alias,\n          source.bindingId,\n        )\n      : new DescriptorRef(source.descriptor, source.alias, source.bindingId)\n  }\n\n  return new QueryRef(\n    cloneQuery(source.query, context),\n    source.alias,\n    source.bindingId,\n  )\n}\n\nfunction cloneSelectForPlacement(\n  select: Select,\n  context: CloneContext,\n): Select {\n  const { clones } = context\n  const existing = clones.get(select)\n  if (existing) return existing as Select\n\n  const cloned: Select = {}\n  clones.set(select, cloned)\n  for (const [field, value] of Object.entries(select)) {\n    cloned[field] = cloneSelectValueForPlacement(value, context)\n  }\n  return cloned\n}\n\nfunction cloneSelectValueForPlacement(\n  value: unknown,\n  context: CloneContext,\n): SelectValueExpression {\n  const { clones } = context\n  if (value instanceof IncludesSubquery) {\n    const existing = clones.get(value)\n    if (existing) return existing as IncludesSubquery\n\n    const cloned = new IncludesSubquery(\n      cloneQuery(value.query, context),\n      value.correlationField,\n      value.childCorrelationField,\n      value.fieldName,\n      value.parentFilters,\n      value.parentProjection,\n      value.materialization,\n      value.scalarField,\n    )\n    clones.set(value, cloned)\n    return cloned\n  }\n\n  if (value instanceof ConditionalSelect) {\n    const existing = clones.get(value)\n    if (existing) return existing as ConditionalSelect\n\n    const cloned = new ConditionalSelect(\n      value.branches.map((branch) => ({\n        ...branch,\n        value: cloneSelectValueForPlacement(branch.value, context),\n      })),\n      value.defaultValue !== undefined\n        ? cloneSelectValueForPlacement(value.defaultValue, context)\n        : undefined,\n    )\n    clones.set(value, cloned)\n    return cloned\n  }\n\n  if (value === null || typeof value !== `object` || Array.isArray(value)) {\n    return value as SelectValueExpression\n  }\n\n  if (isRefProxy(value)) {\n    return value as unknown as SelectValueExpression\n  }\n\n  return isExpressionLike(value)\n    ? (value as SelectValueExpression)\n    : cloneSelectForPlacement(value as Select, context)\n}\n"],"names":["isExpressionLike","UnionFrom","UnionAll","CollectionRef","DescriptorRef","QueryRef","IncludesSubquery","ConditionalSelect","isRefProxy"],"mappings":"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"}