{"version":3,"file":"predicate-utils.cjs","sources":["../../../src/query/predicate-utils.ts"],"sourcesContent":["import { Func, Value } from './ir.js'\nimport type { BasicExpression, OrderBy, PropRef } from './ir.js'\nimport type { LoadSubsetOptions } from '../types.js'\n\n/**\n * Check if one where clause is a logical subset of another.\n * Returns true if the subset predicate is more restrictive than (or equal to) the superset predicate.\n *\n * @example\n * // age > 20 is subset of age > 10 (more restrictive)\n * isWhereSubset(gt(ref('age'), val(20)), gt(ref('age'), val(10))) // true\n *\n * @example\n * // age > 10 AND name = 'X' is subset of age > 10 (more conditions)\n * isWhereSubset(and(gt(ref('age'), val(10)), eq(ref('name'), val('X'))), gt(ref('age'), val(10))) // true\n *\n * @param subset - The potentially more restrictive predicate\n * @param superset - The potentially less restrictive predicate\n * @returns true if subset logically implies superset\n */\nexport function isWhereSubset(\n  subset: BasicExpression<boolean> | undefined,\n  superset: BasicExpression<boolean> | undefined,\n): boolean {\n  // undefined/missing where clause means \"no filter\" (all data)\n  // Both undefined means subset relationship holds (all data ⊆ all data)\n  if (subset === undefined && superset === undefined) {\n    return true\n  }\n\n  // If subset is undefined but superset is not, we're requesting ALL data\n  // but have only loaded SOME data - subset relationship does NOT hold\n  if (subset === undefined && superset !== undefined) {\n    return false\n  }\n\n  // If superset is undefined (no filter = all data loaded),\n  // then any constrained subset is contained\n  if (superset === undefined && subset !== undefined) {\n    return true\n  }\n\n  return isWhereSubsetInternal(subset!, superset!)\n}\n\nfunction makeDisjunction(\n  preds: Array<BasicExpression<boolean>>,\n): BasicExpression<boolean> {\n  if (preds.length === 0) {\n    return new Value(false)\n  }\n  if (preds.length === 1) {\n    return preds[0]!\n  }\n  return new Func(`or`, preds)\n}\n\nfunction convertInToOr(inField: InField) {\n  const equalities = inField.values.map(\n    (value) => new Func(`eq`, [inField.ref, new Value(value)]),\n  )\n  return makeDisjunction(equalities)\n}\n\nfunction isWhereSubsetInternal(\n  subset: BasicExpression<boolean>,\n  superset: BasicExpression<boolean>,\n): boolean {\n  // If subset is false it is requesting no data,\n  // thus the result set is empty\n  // and the empty set is a subset of any set\n  if (subset.type === `val` && subset.value === false) {\n    return true\n  }\n\n  // If expressions are structurally equal, subset relationship holds\n  if (areExpressionsEqual(subset, superset)) {\n    return true\n  }\n\n  // Handle superset being an AND: subset must imply ALL conjuncts\n  // If superset is (A AND B), then subset ⊆ (A AND B) only if subset ⊆ A AND subset ⊆ B\n  // Example: (age > 20) ⊆ (age > 10 AND status = 'active') is false (doesn't imply status condition)\n  if (superset.type === `func` && superset.name === `and`) {\n    return superset.args.every((arg) =>\n      isWhereSubsetInternal(subset, arg as BasicExpression<boolean>),\n    )\n  }\n\n  // Handle OR in subset: (A OR B) ⊆ C only if both A ⊆ C and B ⊆ C.\n  // Must be checked before OR superset so that or(A, B) ⊆ or(C, D)\n  // decomposes the subset first: A ⊆ or(C, D) AND B ⊆ or(C, D).\n  if (subset.type === `func` && subset.name === `or`) {\n    return subset.args.every((arg) =>\n      isWhereSubsetInternal(arg as BasicExpression<boolean>, superset),\n    )\n  }\n\n  // Handle OR in superset: subset ⊆ (A OR B) if subset ⊆ A or subset ⊆ B.\n  // Must be checked before decomposing AND subsets so that and(A, B) can\n  // match a structurally equal disjunct via areExpressionsEqual.\n  if (superset.type === `func` && superset.name === `or`) {\n    return superset.args.some((arg) =>\n      isWhereSubsetInternal(subset, arg as BasicExpression<boolean>),\n    )\n  }\n\n  // Handle subset being an AND: (A AND B) implies both A and B\n  if (subset.type === `func` && subset.name === `and`) {\n    // For (A AND B) ⊆ C, since (A AND B) implies A, we check if any conjunct implies C\n    return subset.args.some((arg) =>\n      isWhereSubsetInternal(arg as BasicExpression<boolean>, superset),\n    )\n  }\n\n  // Turn x IN [A, B, C] into x = A OR x = B OR x = C\n  // for unified handling of IN and OR\n  if (subset.type === `func` && subset.name === `in`) {\n    const inField = extractInField(subset)\n    if (inField) {\n      return isWhereSubsetInternal(convertInToOr(inField), superset)\n    }\n  }\n\n  if (superset.type === `func` && superset.name === `in`) {\n    const inField = extractInField(superset)\n    if (inField) {\n      return isWhereSubsetInternal(subset, convertInToOr(inField))\n    }\n  }\n\n  // Handle comparison operators on the same field\n  if (subset.type === `func` && superset.type === `func`) {\n    const subsetFunc = subset as Func\n    const supersetFunc = superset as Func\n\n    // Check if both are comparisons on the same field\n    const subsetField = extractComparisonField(subsetFunc)\n    const supersetField = extractComparisonField(supersetFunc)\n\n    if (\n      subsetField &&\n      supersetField &&\n      areRefsEqual(subsetField.ref, supersetField.ref)\n    ) {\n      return isComparisonSubset(\n        subsetFunc,\n        subsetField.value,\n        supersetFunc,\n        supersetField.value,\n      )\n    }\n\n    /*\n    // Handle eq vs in\n    if (subsetFunc.name === `eq` && supersetFunc.name === `in`) {\n      const subsetFieldEq = extractEqualityField(subsetFunc)\n      const supersetFieldIn = extractInField(supersetFunc)\n      if (\n        subsetFieldEq &&\n        supersetFieldIn &&\n        areRefsEqual(subsetFieldEq.ref, supersetFieldIn.ref)\n      ) {\n        // field = X is subset of field IN [X, Y, Z] if X is in the array\n        // Use cached primitive set and metadata from extraction\n        return arrayIncludesWithSet(\n          supersetFieldIn.values,\n          subsetFieldEq.value,\n          supersetFieldIn.primitiveSet ?? null,\n          supersetFieldIn.areAllPrimitives\n        )\n      }\n    }\n\n    // Handle in vs in\n    if (subsetFunc.name === `in` && supersetFunc.name === `in`) {\n      const subsetFieldIn = extractInField(subsetFunc)\n      const supersetFieldIn = extractInField(supersetFunc)\n      if (\n        subsetFieldIn &&\n        supersetFieldIn &&\n        areRefsEqual(subsetFieldIn.ref, supersetFieldIn.ref)\n      ) {\n        // field IN [A, B] is subset of field IN [A, B, C] if all values in subset are in superset\n        // Use cached primitive set and metadata from extraction\n        return subsetFieldIn.values.every((subVal) =>\n          arrayIncludesWithSet(\n            supersetFieldIn.values,\n            subVal,\n            supersetFieldIn.primitiveSet ?? null,\n            supersetFieldIn.areAllPrimitives\n          )\n        )\n      }\n    }\n    */\n  }\n\n  // Conservative: if we can't determine, return false\n  return false\n}\n\n/**\n * Helper to combine where predicates with common logic for AND/OR operations\n */\nfunction combineWherePredicates(\n  predicates: Array<BasicExpression<boolean>>,\n  operation: `and` | `or`,\n  simplifyFn: (\n    preds: Array<BasicExpression<boolean>>,\n  ) => BasicExpression<boolean> | null,\n): BasicExpression<boolean> {\n  const emptyValue = operation === `and` ? true : false\n  const identityValue = operation === `and` ? true : false\n\n  if (predicates.length === 0) {\n    return { type: `val`, value: emptyValue } as BasicExpression<boolean>\n  }\n\n  if (predicates.length === 1) {\n    return predicates[0]!\n  }\n\n  // Flatten nested expressions of the same operation\n  const flatPredicates: Array<BasicExpression<boolean>> = []\n  for (const pred of predicates) {\n    if (pred.type === `func` && pred.name === operation) {\n      flatPredicates.push(...pred.args)\n    } else {\n      flatPredicates.push(pred)\n    }\n  }\n\n  // Group predicates by field for simplification\n  const grouped = groupPredicatesByField(flatPredicates)\n\n  // Simplify each group\n  const simplified: Array<BasicExpression<boolean>> = []\n  for (const [field, preds] of grouped.entries()) {\n    if (field === null) {\n      // Complex predicates that we can't group by field\n      simplified.push(...preds)\n    } else {\n      // Try to simplify same-field predicates\n      const result = simplifyFn(preds)\n\n      // For intersection: check for empty set (contradiction)\n      if (\n        operation === `and` &&\n        result &&\n        result.type === `val` &&\n        result.value === false\n      ) {\n        // Intersection is empty (conflicting constraints) - entire AND is false\n        return { type: `val`, value: false } as BasicExpression<boolean>\n      }\n\n      // For union: result may be null if simplification failed\n      if (result) {\n        simplified.push(result)\n      }\n    }\n  }\n\n  if (simplified.length === 0) {\n    return { type: `val`, value: identityValue } as BasicExpression<boolean>\n  }\n\n  if (simplified.length === 1) {\n    return simplified[0]!\n  }\n\n  // Return combined predicate\n  return {\n    type: `func`,\n    name: operation,\n    args: simplified,\n  } as BasicExpression<boolean>\n}\n\n/**\n * Combine multiple where predicates with OR logic (union).\n * Returns a predicate that is satisfied when any input predicate is satisfied.\n * Simplifies when possible (e.g., age > 10 OR age > 20 → age > 10).\n *\n * @example\n * // Take least restrictive\n * unionWherePredicates([gt(ref('age'), val(10)), gt(ref('age'), val(20))]) // age > 10\n *\n * @example\n * // Combine equals into IN\n * unionWherePredicates([eq(ref('age'), val(5)), eq(ref('age'), val(10))]) // age IN [5, 10]\n *\n * @param predicates - Array of where predicates to union\n * @returns Combined predicate representing the union\n */\nexport function unionWherePredicates(\n  predicates: Array<BasicExpression<boolean>>,\n): BasicExpression<boolean> {\n  return combineWherePredicates(predicates, `or`, unionSameFieldPredicates)\n}\n\n/**\n * Compute the difference between two where predicates: `fromPredicate AND NOT(subtractPredicate)`.\n * Returns the simplified predicate, or null if the difference cannot be simplified\n * (in which case the caller should fetch the full fromPredicate).\n *\n * @example\n * // Range difference\n * minusWherePredicates(\n *   gt(ref('age'), val(10)),      // age > 10\n *   gt(ref('age'), val(20))       // age > 20\n * ) // → age > 10 AND age <= 20\n *\n * @example\n * // Set difference\n * minusWherePredicates(\n *   inOp(ref('status'), ['A', 'B', 'C', 'D']),  // status IN ['A','B','C','D']\n *   inOp(ref('status'), ['B', 'C'])             // status IN ['B','C']\n * ) // → status IN ['A', 'D']\n *\n * @example\n * // Common conditions\n * minusWherePredicates(\n *   and(gt(ref('age'), val(10)), eq(ref('status'), val('active'))),  // age > 10 AND status = 'active'\n *   and(gt(ref('age'), val(20)), eq(ref('status'), val('active')))   // age > 20 AND status = 'active'\n * ) // → age > 10 AND age <= 20 AND status = 'active'\n *\n * @example\n * // Complete overlap - empty result\n * minusWherePredicates(\n *   gt(ref('age'), val(20)),     // age > 20\n *   gt(ref('age'), val(10))      // age > 10\n * ) // → {type: 'val', value: false} (empty set)\n *\n * @param fromPredicate - The predicate to subtract from\n * @param subtractPredicate - The predicate to subtract\n * @returns The simplified difference, or null if cannot be simplified\n */\nexport function minusWherePredicates(\n  fromPredicate: BasicExpression<boolean> | undefined,\n  subtractPredicate: BasicExpression<boolean> | undefined,\n): BasicExpression<boolean> | null {\n  // If nothing to subtract, return the original\n  if (subtractPredicate === undefined) {\n    return (\n      fromPredicate ??\n      ({ type: `val`, value: true } as BasicExpression<boolean>)\n    )\n  }\n\n  // If from is undefined then we are asking for all data\n  // so we need to load all data minus what we already loaded\n  // i.e. we need to load NOT(subtractPredicate)\n  if (fromPredicate === undefined) {\n    return {\n      type: `func`,\n      name: `not`,\n      args: [subtractPredicate],\n    } as BasicExpression<boolean>\n  }\n\n  // Check if fromPredicate is entirely contained in subtractPredicate\n  // In that case, fromPredicate AND NOT(subtractPredicate) = empty set\n  if (isWhereSubset(fromPredicate, subtractPredicate)) {\n    return { type: `val`, value: false } as BasicExpression<boolean>\n  }\n\n  // Try to detect and handle common conditions\n  const commonConditions = findCommonConditions(\n    fromPredicate,\n    subtractPredicate,\n  )\n  if (commonConditions.length > 0) {\n    // Extract predicates without common conditions\n    const fromWithoutCommon = removeConditions(fromPredicate, commonConditions)\n    const subtractWithoutCommon = removeConditions(\n      subtractPredicate,\n      commonConditions,\n    )\n\n    // Recursively compute difference on simplified predicates\n    const simplifiedDifference = minusWherePredicates(\n      fromWithoutCommon,\n      subtractWithoutCommon,\n    )\n\n    if (simplifiedDifference !== null) {\n      // Combine the simplified difference with common conditions\n      return combineConditions([...commonConditions, simplifiedDifference])\n    }\n  }\n\n  // Check if they are on the same field - if so, we can try to simplify\n  if (fromPredicate.type === `func` && subtractPredicate.type === `func`) {\n    const result = minusSameFieldPredicates(fromPredicate, subtractPredicate)\n    if (result !== null) {\n      return result\n    }\n  }\n\n  // Can't simplify - return null to indicate caller should fetch full fromPredicate\n  return null\n}\n\n/**\n * Helper function to compute difference for same-field predicates\n */\nfunction minusSameFieldPredicates(\n  fromPred: Func,\n  subtractPred: Func,\n): BasicExpression<boolean> | null {\n  // Extract field information\n  const fromField =\n    extractComparisonField(fromPred) ||\n    extractEqualityField(fromPred) ||\n    extractInField(fromPred)\n  const subtractField =\n    extractComparisonField(subtractPred) ||\n    extractEqualityField(subtractPred) ||\n    extractInField(subtractPred)\n\n  // Must be on the same field\n  if (\n    !fromField ||\n    !subtractField ||\n    !areRefsEqual(fromField.ref, subtractField.ref)\n  ) {\n    return null\n  }\n\n  // Handle IN minus IN: status IN [A,B,C,D] - status IN [B,C] = status IN [A,D]\n  if (fromPred.name === `in` && subtractPred.name === `in`) {\n    const fromInField = fromField as InField\n    const subtractInField = subtractField as InField\n\n    // Filter out values that are in the subtract set\n    const remainingValues = fromInField.values.filter(\n      (v) =>\n        !arrayIncludesWithSet(\n          subtractInField.values,\n          v,\n          subtractInField.primitiveSet ?? null,\n          subtractInField.areAllPrimitives,\n        ),\n    )\n\n    if (remainingValues.length === 0) {\n      return { type: `val`, value: false } as BasicExpression<boolean>\n    }\n\n    if (remainingValues.length === 1) {\n      return {\n        type: `func`,\n        name: `eq`,\n        args: [fromField.ref, { type: `val`, value: remainingValues[0] }],\n      } as BasicExpression<boolean>\n    }\n\n    return {\n      type: `func`,\n      name: `in`,\n      args: [fromField.ref, { type: `val`, value: remainingValues }],\n    } as BasicExpression<boolean>\n  }\n\n  // Handle IN minus equality: status IN [A,B,C] - status = B = status IN [A,C]\n  if (fromPred.name === `in` && subtractPred.name === `eq`) {\n    const fromInField = fromField as InField\n    const subtractValue = (subtractField as { ref: PropRef; value: any }).value\n\n    const remainingValues = fromInField.values.filter(\n      (v) => !areValuesEqual(v, subtractValue),\n    )\n\n    if (remainingValues.length === 0) {\n      return { type: `val`, value: false } as BasicExpression<boolean>\n    }\n\n    if (remainingValues.length === 1) {\n      return {\n        type: `func`,\n        name: `eq`,\n        args: [fromField.ref, { type: `val`, value: remainingValues[0] }],\n      } as BasicExpression<boolean>\n    }\n\n    return {\n      type: `func`,\n      name: `in`,\n      args: [fromField.ref, { type: `val`, value: remainingValues }],\n    } as BasicExpression<boolean>\n  }\n\n  // Handle equality minus equality: age = 15 - age = 15 = empty, age = 15 - age = 20 = age = 15\n  if (fromPred.name === `eq` && subtractPred.name === `eq`) {\n    const fromValue = (fromField as { ref: PropRef; value: any }).value\n    const subtractValue = (subtractField as { ref: PropRef; value: any }).value\n\n    if (areValuesEqual(fromValue, subtractValue)) {\n      return { type: `val`, value: false } as BasicExpression<boolean>\n    }\n\n    // No overlap - return original\n    return fromPred as BasicExpression<boolean>\n  }\n\n  // Handle range minus range: age > 10 - age > 20 = age > 10 AND age <= 20\n  const fromComp = extractComparisonField(fromPred)\n  const subtractComp = extractComparisonField(subtractPred)\n\n  if (\n    fromComp &&\n    subtractComp &&\n    areRefsEqual(fromComp.ref, subtractComp.ref)\n  ) {\n    // Try to compute the difference using range logic\n    const result = minusRangePredicates(\n      fromPred,\n      fromComp.value,\n      subtractPred,\n      subtractComp.value,\n    )\n    return result\n  }\n\n  // Can't simplify\n  return null\n}\n\n/**\n * Helper to compute difference between range predicates\n */\nfunction minusRangePredicates(\n  fromFunc: Func,\n  fromValue: any,\n  subtractFunc: Func,\n  subtractValue: any,\n): BasicExpression<boolean> | null {\n  const fromOp = fromFunc.name as `gt` | `gte` | `lt` | `lte` | `eq`\n  const subtractOp = subtractFunc.name as `gt` | `gte` | `lt` | `lte` | `eq`\n  const ref = (extractComparisonField(fromFunc) ||\n    extractEqualityField(fromFunc))!.ref\n\n  // age > 10 - age > 20 = (age > 10 AND age <= 20)\n  if (fromOp === `gt` && subtractOp === `gt`) {\n    if (fromValue < subtractValue) {\n      // Result is: fromValue < field <= subtractValue\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          fromFunc as BasicExpression<boolean>,\n          {\n            type: `func`,\n            name: `lte`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    // fromValue >= subtractValue means no overlap\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age >= 10 - age >= 20 = (age >= 10 AND age < 20)\n  if (fromOp === `gte` && subtractOp === `gte`) {\n    if (fromValue < subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          fromFunc as BasicExpression<boolean>,\n          {\n            type: `func`,\n            name: `lt`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age > 10 - age >= 20 = (age > 10 AND age < 20)\n  if (fromOp === `gt` && subtractOp === `gte`) {\n    if (fromValue < subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          fromFunc as BasicExpression<boolean>,\n          {\n            type: `func`,\n            name: `lt`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age >= 10 - age > 20 = (age >= 10 AND age <= 20)\n  if (fromOp === `gte` && subtractOp === `gt`) {\n    if (fromValue <= subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          fromFunc as BasicExpression<boolean>,\n          {\n            type: `func`,\n            name: `lte`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age < 30 - age < 20 = (age >= 20 AND age < 30)\n  if (fromOp === `lt` && subtractOp === `lt`) {\n    if (fromValue > subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          {\n            type: `func`,\n            name: `gte`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n          fromFunc as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age <= 30 - age <= 20 = (age > 20 AND age <= 30)\n  if (fromOp === `lte` && subtractOp === `lte`) {\n    if (fromValue > subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          {\n            type: `func`,\n            name: `gt`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n          fromFunc as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age < 30 - age <= 20 = (age > 20 AND age < 30)\n  if (fromOp === `lt` && subtractOp === `lte`) {\n    if (fromValue > subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          {\n            type: `func`,\n            name: `gt`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n          fromFunc as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // age <= 30 - age < 20 = (age >= 20 AND age <= 30)\n  if (fromOp === `lte` && subtractOp === `lt`) {\n    if (fromValue >= subtractValue) {\n      return {\n        type: `func`,\n        name: `and`,\n        args: [\n          {\n            type: `func`,\n            name: `gte`,\n            args: [ref, { type: `val`, value: subtractValue }],\n          } as BasicExpression<boolean>,\n          fromFunc as BasicExpression<boolean>,\n        ],\n      } as BasicExpression<boolean>\n    }\n    return fromFunc as BasicExpression<boolean>\n  }\n\n  // Can't simplify other combinations\n  return null\n}\n\n/**\n * Check if one orderBy clause is a subset of another.\n * Returns true if the subset ordering requirements are satisfied by the superset ordering.\n *\n * @example\n * // Subset is prefix of superset\n * isOrderBySubset([{expr: age, asc}], [{expr: age, asc}, {expr: name, desc}]) // true\n *\n * @param subset - The ordering requirements to check\n * @param superset - The ordering that might satisfy the requirements\n * @returns true if subset is satisfied by superset\n */\nexport function isOrderBySubset(\n  subset: OrderBy | undefined,\n  superset: OrderBy | undefined,\n): boolean {\n  // No ordering requirement is always satisfied\n  if (!subset || subset.length === 0) {\n    return true\n  }\n\n  // If there's no superset ordering but subset requires ordering, not satisfied\n  if (!superset || superset.length === 0) {\n    return false\n  }\n\n  // Check if subset is a prefix of superset with matching expressions and compare options\n  if (subset.length > superset.length) {\n    return false\n  }\n\n  for (let i = 0; i < subset.length; i++) {\n    const subClause = subset[i]!\n    const superClause = superset[i]!\n\n    // Check if expressions match\n    if (!areExpressionsEqual(subClause.expression, superClause.expression)) {\n      return false\n    }\n\n    // Check if compare options match\n    if (\n      !areCompareOptionsEqual(\n        subClause.compareOptions,\n        superClause.compareOptions,\n      )\n    ) {\n      return false\n    }\n  }\n\n  return true\n}\n\n/**\n * Check if one limit is a subset of another.\n * Returns true if the subset limit requirements are satisfied by the superset limit.\n *\n * Note: This function does NOT consider offset. For offset-aware subset checking,\n * use `isOffsetLimitSubset` instead.\n *\n * @example\n * isLimitSubset(10, 20) // true (requesting 10 items when 20 are available)\n * isLimitSubset(20, 10) // false (requesting 20 items when only 10 are available)\n * isLimitSubset(10, undefined) // true (requesting 10 items when unlimited are available)\n *\n * @param subset - The limit requirement to check\n * @param superset - The limit that might satisfy the requirement\n * @returns true if subset is satisfied by superset\n */\nexport function isLimitSubset(\n  subset: number | undefined,\n  superset: number | undefined,\n): boolean {\n  // Unlimited superset satisfies any limit requirement\n  if (superset === undefined) {\n    return true\n  }\n\n  // If requesting all data (no limit), we need unlimited data to satisfy it\n  // But we know superset is not unlimited so we return false\n  if (subset === undefined) {\n    return false\n  }\n\n  // Otherwise, subset must be less than or equal to superset\n  return subset <= superset\n}\n\n/**\n * Check if one offset+limit range is a subset of another.\n * Returns true if the subset range is fully contained within the superset range.\n *\n * A query with `{limit: 10, offset: 0}` loads rows [0, 10).\n * A query with `{limit: 10, offset: 20}` loads rows [20, 30).\n *\n * For subset to be satisfied by superset:\n * - Superset must start at or before subset (superset.offset <= subset.offset)\n * - Superset must end at or after subset (superset.offset + superset.limit >= subset.offset + subset.limit)\n *\n * @example\n * isOffsetLimitSubset({ offset: 0, limit: 5 }, { offset: 0, limit: 10 }) // true\n * isOffsetLimitSubset({ offset: 5, limit: 5 }, { offset: 0, limit: 10 }) // true (rows 5-9 within 0-9)\n * isOffsetLimitSubset({ offset: 5, limit: 10 }, { offset: 0, limit: 10 }) // false (rows 5-14 exceed 0-9)\n * isOffsetLimitSubset({ offset: 20, limit: 10 }, { offset: 0, limit: 10 }) // false (rows 20-29 outside 0-9)\n *\n * @param subset - The offset+limit requirements to check\n * @param superset - The offset+limit that might satisfy the requirements\n * @returns true if subset range is fully contained within superset range\n */\nexport function isOffsetLimitSubset(\n  subset: { offset?: number; limit?: number },\n  superset: { offset?: number; limit?: number },\n): boolean {\n  const subsetOffset = subset.offset ?? 0\n  const supersetOffset = superset.offset ?? 0\n\n  // Superset must start at or before subset\n  if (supersetOffset > subsetOffset) {\n    return false\n  }\n\n  // If superset is unlimited, it covers everything from its offset onwards\n  if (superset.limit === undefined) {\n    return true\n  }\n\n  // If subset is unlimited but superset has a limit, subset can't be satisfied\n  if (subset.limit === undefined) {\n    return false\n  }\n\n  // Both have limits - check if subset range is within superset range\n  const subsetEnd = subsetOffset + subset.limit\n  const supersetEnd = supersetOffset + superset.limit\n\n  return subsetEnd <= supersetEnd\n}\n\n/**\n * Check if one predicate (where + orderBy + limit + offset) is a subset of another.\n * Returns true if all aspects of the subset predicate are satisfied by the superset.\n *\n * @example\n * isPredicateSubset(\n *   { where: gt(ref('age'), val(20)), limit: 10 },\n *   { where: gt(ref('age'), val(10)), limit: 20 }\n * ) // true\n *\n * @param subset - The predicate requirements to check\n * @param superset - The predicate that might satisfy the requirements\n * @returns true if subset is satisfied by superset\n */\nexport function isPredicateSubset(\n  subset: LoadSubsetOptions,\n  superset: LoadSubsetOptions,\n): boolean {\n  // When the superset has a limit, we can only determine subset relationship\n  // if the where clauses are equal (not just subset relationship).\n  //\n  // This is because a limited query only loads a portion of the matching rows.\n  // A more restrictive where clause might require rows outside that portion.\n  //\n  // Example: superset = {where: undefined, limit: 10, orderBy: desc}\n  //          subset = {where: LIKE 'search%', limit: 10, orderBy: desc}\n  // The top 10 items matching 'search%' might include items outside the overall top 10.\n  //\n  // However, if the where clauses are equal, then the subset relationship can\n  // be determined by orderBy, limit, and offset:\n  // Example: superset = {where: status='active', limit: 10, offset: 0, orderBy: desc}\n  //          subset = {where: status='active', limit: 5, offset: 0, orderBy: desc}\n  // The top 5 active items ARE contained in the top 10 active items.\n  if (superset.limit !== undefined) {\n    // For limited supersets, where clauses must be equal\n    if (!areWhereClausesEqual(subset.where, superset.where)) {\n      return false\n    }\n    return (\n      isOrderBySubset(subset.orderBy, superset.orderBy) &&\n      isOffsetLimitSubset(subset, superset)\n    )\n  }\n\n  // For unlimited supersets, use the normal subset logic\n  // Still need to consider offset - an unlimited query with offset only covers\n  // rows from that offset onwards\n  return (\n    isWhereSubset(subset.where, superset.where) &&\n    isOrderBySubset(subset.orderBy, superset.orderBy) &&\n    isOffsetLimitSubset(subset, superset)\n  )\n}\n\n/**\n * Check if two where clauses are structurally equal.\n * Used for limited query subset checks where subset relationship isn't sufficient.\n */\nfunction areWhereClausesEqual(\n  a: BasicExpression<boolean> | undefined,\n  b: BasicExpression<boolean> | undefined,\n): boolean {\n  if (a === undefined && b === undefined) {\n    return true\n  }\n  if (a === undefined || b === undefined) {\n    return false\n  }\n  return areExpressionsEqual(a, b)\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\n/**\n * Find common conditions between two predicates.\n * Returns an array of conditions that appear in both predicates.\n */\nfunction findCommonConditions(\n  predicate1: BasicExpression<boolean>,\n  predicate2: BasicExpression<boolean>,\n): Array<BasicExpression<boolean>> {\n  const conditions1 = extractAllConditions(predicate1)\n  const conditions2 = extractAllConditions(predicate2)\n\n  const common: Array<BasicExpression<boolean>> = []\n\n  for (const cond1 of conditions1) {\n    for (const cond2 of conditions2) {\n      if (areExpressionsEqual(cond1, cond2)) {\n        // Avoid duplicates\n        if (!common.some((c) => areExpressionsEqual(c, cond1))) {\n          common.push(cond1)\n        }\n        break\n      }\n    }\n  }\n\n  return common\n}\n\n/**\n * Extract all individual conditions from a predicate, flattening AND operations.\n */\nfunction extractAllConditions(\n  predicate: BasicExpression<boolean>,\n): Array<BasicExpression<boolean>> {\n  if (predicate.type === `func` && predicate.name === `and`) {\n    const conditions: Array<BasicExpression<boolean>> = []\n    for (const arg of predicate.args) {\n      conditions.push(...extractAllConditions(arg as BasicExpression<boolean>))\n    }\n    return conditions\n  }\n\n  return [predicate]\n}\n\n/**\n * Remove specified conditions from a predicate.\n * Returns the predicate with the specified conditions removed, or undefined if all conditions are removed.\n */\nfunction removeConditions(\n  predicate: BasicExpression<boolean>,\n  conditionsToRemove: Array<BasicExpression<boolean>>,\n): BasicExpression<boolean> | undefined {\n  if (predicate.type === `func` && predicate.name === `and`) {\n    const remainingArgs = predicate.args.filter(\n      (arg) =>\n        !conditionsToRemove.some((cond) =>\n          areExpressionsEqual(arg as BasicExpression<boolean>, cond),\n        ),\n    )\n\n    if (remainingArgs.length === 0) {\n      return undefined\n    } else if (remainingArgs.length === 1) {\n      return remainingArgs[0]!\n    } else {\n      return {\n        type: `func`,\n        name: `and`,\n        args: remainingArgs,\n      } as BasicExpression<boolean>\n    }\n  }\n\n  // For non-AND predicates, don't remove anything\n  return predicate\n}\n\n/**\n * Combine multiple conditions into a single predicate using AND logic.\n * Flattens nested AND operations to avoid unnecessary nesting.\n */\nfunction combineConditions(\n  conditions: Array<BasicExpression<boolean>>,\n): BasicExpression<boolean> {\n  if (conditions.length === 0) {\n    return { type: `val`, value: true } as BasicExpression<boolean>\n  } else if (conditions.length === 1) {\n    return conditions[0]!\n  } else {\n    // Flatten all conditions, including those that are already AND operations\n    const flattenedConditions: Array<BasicExpression<boolean>> = []\n\n    for (const condition of conditions) {\n      if (condition.type === `func` && condition.name === `and`) {\n        // Flatten nested AND operations\n        flattenedConditions.push(...condition.args)\n      } else {\n        flattenedConditions.push(condition)\n      }\n    }\n\n    if (flattenedConditions.length === 1) {\n      return flattenedConditions[0]!\n    } else {\n      return {\n        type: `func`,\n        name: `and`,\n        args: flattenedConditions,\n      } as BasicExpression<boolean>\n    }\n  }\n}\n\n/**\n * Find a predicate with a specific operator and value\n */\nfunction findPredicateWithOperator(\n  predicates: Array<BasicExpression<boolean>>,\n  operator: string,\n  value: any,\n): BasicExpression<boolean> | undefined {\n  return predicates.find((p) => {\n    if (p.type === `func`) {\n      const f = p as Func\n      const field = extractComparisonField(f)\n      return f.name === operator && field && areValuesEqual(field.value, value)\n    }\n    return false\n  })\n}\n\nfunction areExpressionsEqual(a: BasicExpression, b: BasicExpression): boolean {\n  if (a.type !== b.type) {\n    return false\n  }\n\n  if (a.type === `val` && b.type === `val`) {\n    return areValuesEqual(a.value, b.value)\n  }\n\n  if (a.type === `ref` && b.type === `ref`) {\n    return areRefsEqual(a, b)\n  }\n\n  if (a.type === `func` && b.type === `func`) {\n    const aFunc = a\n    const bFunc = b\n    if (aFunc.name !== bFunc.name) {\n      return false\n    }\n    if (aFunc.args.length !== bFunc.args.length) {\n      return false\n    }\n    return aFunc.args.every((arg, i) =>\n      areExpressionsEqual(arg, bFunc.args[i]!),\n    )\n  }\n\n  return false\n}\n\nfunction areValuesEqual(a: any, b: any): boolean {\n  // Simple equality check - could be enhanced for deep object comparison\n  if (a === b) {\n    return true\n  }\n\n  // Handle NaN\n  if (typeof a === `number` && typeof b === `number` && isNaN(a) && isNaN(b)) {\n    return true\n  }\n\n  // Handle Date objects\n  if (a instanceof Date && b instanceof Date) {\n    return a.getTime() === b.getTime()\n  }\n\n  // For arrays and objects, use reference equality\n  // (In practice, we don't need deep equality for these cases -\n  // same object reference means same value for our use case)\n  if (\n    typeof a === `object` &&\n    typeof b === `object` &&\n    a !== null &&\n    b !== null\n  ) {\n    return a === b\n  }\n\n  return false\n}\n\nfunction areRefsEqual(a: PropRef, b: PropRef): boolean {\n  if (a.path.length !== b.path.length) {\n    return false\n  }\n  return a.path.every((segment, i) => segment === b.path[i])\n}\n\n/**\n * Check if a value is a primitive (string, number, boolean, null, undefined)\n * Primitives can use Set for fast lookups\n */\nfunction isPrimitive(value: any): boolean {\n  return (\n    value === null ||\n    value === undefined ||\n    typeof value === `string` ||\n    typeof value === `number` ||\n    typeof value === `boolean`\n  )\n}\n\n/**\n * Check if all values in an array are primitives\n */\nfunction areAllPrimitives(values: Array<any>): boolean {\n  return values.every(isPrimitive)\n}\n\n/**\n * Check if a value is in an array, with optional pre-built Set for optimization.\n * The primitiveSet is cached in InField during extraction and reused for all lookups.\n */\nfunction arrayIncludesWithSet(\n  array: Array<any>,\n  value: any,\n  primitiveSet: Set<any> | null,\n  arrayIsAllPrimitives?: boolean,\n): boolean {\n  // Fast path: use pre-built Set for O(1) lookup\n  if (primitiveSet) {\n    // Skip isPrimitive check if we know the value must be primitive for a match\n    // (if array is all primitives, only primitives can match)\n    if (arrayIsAllPrimitives || isPrimitive(value)) {\n      return primitiveSet.has(value)\n    }\n    return false // Non-primitive can't be in primitive-only set\n  }\n\n  // Fallback: use areValuesEqual for Dates and objects\n  return array.some((v) => areValuesEqual(v, value))\n}\n\n/**\n * Get the maximum of two values, handling both numbers and Dates\n */\nfunction maxValue(a: any, b: any): any {\n  if (a instanceof Date && b instanceof Date) {\n    return a.getTime() > b.getTime() ? a : b\n  }\n  return Math.max(a, b)\n}\n\n/**\n * Get the minimum of two values, handling both numbers and Dates\n */\nfunction minValue(a: any, b: any): any {\n  if (a instanceof Date && b instanceof Date) {\n    return a.getTime() < b.getTime() ? a : b\n  }\n  return Math.min(a, b)\n}\n\nfunction areCompareOptionsEqual(\n  a: { direction?: `asc` | `desc`; [key: string]: any },\n  b: { direction?: `asc` | `desc`; [key: string]: any },\n): boolean {\n  // For now, just compare direction - could be enhanced for other options\n  return a.direction === b.direction\n}\n\ninterface ComparisonField {\n  ref: PropRef\n  value: any\n}\n\nfunction extractComparisonField(func: Func): ComparisonField | null {\n  // Handle comparison operators: eq, gt, gte, lt, lte\n  if ([`eq`, `gt`, `gte`, `lt`, `lte`].includes(func.name)) {\n    // Assume first arg is ref, second is value\n    const firstArg = func.args[0]\n    const secondArg = func.args[1]\n\n    if (firstArg?.type === `ref` && secondArg?.type === `val`) {\n      return {\n        ref: firstArg,\n        value: secondArg.value,\n      }\n    }\n  }\n\n  return null\n}\n\nfunction extractEqualityField(func: Func): ComparisonField | null {\n  if (func.name === `eq`) {\n    const firstArg = func.args[0]\n    const secondArg = func.args[1]\n\n    if (firstArg?.type === `ref` && secondArg?.type === `val`) {\n      return {\n        ref: firstArg,\n        value: secondArg.value,\n      }\n    }\n  }\n  return null\n}\n\ninterface InField {\n  ref: PropRef\n  values: Array<any>\n  // Cached optimization data (computed once, reused many times)\n  areAllPrimitives?: boolean\n  primitiveSet?: Set<any> | null\n}\n\nfunction extractInField(func: Func): InField | null {\n  if (func.name === `in`) {\n    const firstArg = func.args[0]\n    const secondArg = func.args[1]\n\n    if (\n      firstArg?.type === `ref` &&\n      secondArg?.type === `val` &&\n      Array.isArray(secondArg.value)\n    ) {\n      let values = secondArg.value\n      // Precompute optimization metadata once\n      const allPrimitives = areAllPrimitives(values)\n      let primitiveSet: Set<any> | null = null\n\n      if (allPrimitives && values.length > 10) {\n        // Build Set and dedupe values at the same time\n        primitiveSet = new Set(values)\n        // If we found duplicates, use the deduped array going forward\n        if (primitiveSet.size < values.length) {\n          values = Array.from(primitiveSet)\n        }\n      }\n\n      return {\n        ref: firstArg,\n        values,\n        areAllPrimitives: allPrimitives,\n        primitiveSet,\n      }\n    }\n  }\n  return null\n}\n\nfunction isComparisonSubset(\n  subsetFunc: Func,\n  subsetValue: any,\n  supersetFunc: Func,\n  supersetValue: any,\n): boolean {\n  const subOp = subsetFunc.name\n  const superOp = supersetFunc.name\n\n  // Handle same operator\n  if (subOp === superOp) {\n    if (subOp === `eq`) {\n      // field = X is subset of field = X only\n      // Fast path: primitives can use strict equality\n      if (isPrimitive(subsetValue) && isPrimitive(supersetValue)) {\n        return subsetValue === supersetValue\n      }\n      return areValuesEqual(subsetValue, supersetValue)\n    } else if (subOp === `gt`) {\n      // field > 20 is subset of field > 10 if 20 > 10\n      return subsetValue >= supersetValue\n    } else if (subOp === `gte`) {\n      // field >= 20 is subset of field >= 10 if 20 >= 10\n      return subsetValue >= supersetValue\n    } else if (subOp === `lt`) {\n      // field < 10 is subset of field < 20 if 10 <= 20\n      return subsetValue <= supersetValue\n    } else if (subOp === `lte`) {\n      // field <= 10 is subset of field <= 20 if 10 <= 20\n      return subsetValue <= supersetValue\n    }\n  }\n\n  // Handle different operators on same field\n  // eq vs gt/gte: field = 15 is subset of field > 10 if 15 > 10\n  if (subOp === `eq` && superOp === `gt`) {\n    return subsetValue > supersetValue\n  }\n  if (subOp === `eq` && superOp === `gte`) {\n    return subsetValue >= supersetValue\n  }\n  if (subOp === `eq` && superOp === `lt`) {\n    return subsetValue < supersetValue\n  }\n  if (subOp === `eq` && superOp === `lte`) {\n    return subsetValue <= supersetValue\n  }\n\n  // gt/gte vs gte/gt\n  if (subOp === `gt` && superOp === `gte`) {\n    // field > 10 is subset of field >= 10 if 10 >= 10 (always true for same value)\n    return subsetValue >= supersetValue\n  }\n  if (subOp === `gte` && superOp === `gt`) {\n    // field >= 11 is subset of field > 10 if 11 > 10\n    return subsetValue > supersetValue\n  }\n\n  // lt/lte vs lte/lt\n  if (subOp === `lt` && superOp === `lte`) {\n    // field < 10 is subset of field <= 10 if 10 <= 10\n    return subsetValue <= supersetValue\n  }\n  if (subOp === `lte` && superOp === `lt`) {\n    // field <= 9 is subset of field < 10 if 9 < 10\n    return subsetValue < supersetValue\n  }\n\n  return false\n}\n\nfunction groupPredicatesByField(\n  predicates: Array<BasicExpression<boolean>>,\n): Map<string | null, Array<BasicExpression<boolean>>> {\n  const groups = new Map<string | null, Array<BasicExpression<boolean>>>()\n\n  for (const pred of predicates) {\n    let fieldKey: string | null = null\n\n    if (pred.type === `func`) {\n      const func = pred as Func\n      const field =\n        extractComparisonField(func) ||\n        extractEqualityField(func) ||\n        extractInField(func)\n      if (field) {\n        fieldKey = field.ref.path.join(`.`)\n      }\n    }\n\n    const group = groups.get(fieldKey) || []\n    group.push(pred)\n    groups.set(fieldKey, group)\n  }\n\n  return groups\n}\n\nfunction unionSameFieldPredicates(\n  predicates: Array<BasicExpression<boolean>>,\n): BasicExpression<boolean> | null {\n  if (predicates.length === 1) {\n    return predicates[0]!\n  }\n\n  // Try to extract range constraints\n  let maxGt: number | null = null\n  let maxGte: number | null = null\n  let minLt: number | null = null\n  let minLte: number | null = null\n  const eqValues: Set<any> = new Set()\n  const inValues: Set<any> = new Set()\n  const otherPredicates: Array<BasicExpression<boolean>> = []\n\n  for (const pred of predicates) {\n    if (pred.type === `func`) {\n      const func = pred as Func\n      const field = extractComparisonField(func)\n\n      if (field) {\n        const value = field.value\n        if (func.name === `gt`) {\n          maxGt = maxGt === null ? value : minValue(maxGt, value)\n        } else if (func.name === `gte`) {\n          maxGte = maxGte === null ? value : minValue(maxGte, value)\n        } else if (func.name === `lt`) {\n          minLt = minLt === null ? value : maxValue(minLt, value)\n        } else if (func.name === `lte`) {\n          minLte = minLte === null ? value : maxValue(minLte, value)\n        } else if (func.name === `eq`) {\n          eqValues.add(value)\n        } else {\n          otherPredicates.push(pred)\n        }\n      } else {\n        const inField = extractInField(func)\n        if (inField) {\n          for (const val of inField.values) {\n            inValues.add(val)\n          }\n        } else {\n          otherPredicates.push(pred)\n        }\n      }\n    } else {\n      otherPredicates.push(pred)\n    }\n  }\n\n  // If we have multiple equality values, combine into IN\n  if (eqValues.size > 1 || (eqValues.size > 0 && inValues.size > 0)) {\n    const allValues = [...eqValues, ...inValues]\n    const ref = predicates.find((p) => {\n      if (p.type === `func`) {\n        const field =\n          extractComparisonField(p as Func) || extractInField(p as Func)\n        return field !== null\n      }\n      return false\n    })\n\n    if (ref && ref.type === `func`) {\n      const field =\n        extractComparisonField(ref as Func) || extractInField(ref as Func)\n      if (field) {\n        return {\n          type: `func`,\n          name: `in`,\n          args: [\n            field.ref,\n            { type: `val`, value: allValues } as BasicExpression,\n          ],\n        } as BasicExpression<boolean>\n      }\n    }\n  }\n\n  // Build the least restrictive range\n  const result: Array<BasicExpression<boolean>> = []\n\n  // Choose the least restrictive lower bound\n  if (maxGt !== null && maxGte !== null) {\n    // Take the smaller one (less restrictive)\n    const pred =\n      maxGte <= maxGt\n        ? findPredicateWithOperator(predicates, `gte`, maxGte)\n        : findPredicateWithOperator(predicates, `gt`, maxGt)\n    if (pred) result.push(pred)\n  } else if (maxGt !== null) {\n    const pred = findPredicateWithOperator(predicates, `gt`, maxGt)\n    if (pred) result.push(pred)\n  } else if (maxGte !== null) {\n    const pred = findPredicateWithOperator(predicates, `gte`, maxGte)\n    if (pred) result.push(pred)\n  }\n\n  // Choose the least restrictive upper bound\n  if (minLt !== null && minLte !== null) {\n    const pred =\n      minLte >= minLt\n        ? findPredicateWithOperator(predicates, `lte`, minLte)\n        : findPredicateWithOperator(predicates, `lt`, minLt)\n    if (pred) result.push(pred)\n  } else if (minLt !== null) {\n    const pred = findPredicateWithOperator(predicates, `lt`, minLt)\n    if (pred) result.push(pred)\n  } else if (minLte !== null) {\n    const pred = findPredicateWithOperator(predicates, `lte`, minLte)\n    if (pred) result.push(pred)\n  }\n\n  // Add single eq value\n  if (eqValues.size === 1 && inValues.size === 0) {\n    const pred = findPredicateWithOperator(predicates, `eq`, [...eqValues][0])\n    if (pred) result.push(pred)\n  }\n\n  // Add IN if only IN values\n  if (eqValues.size === 0 && inValues.size > 0) {\n    result.push(\n      predicates.find((p) => {\n        if (p.type === `func`) {\n          return (p as Func).name === `in`\n        }\n        return false\n      })!,\n    )\n  }\n\n  // Add other predicates\n  result.push(...otherPredicates)\n\n  if (result.length === 0) {\n    return { type: `val`, value: true } as BasicExpression<boolean>\n  }\n\n  if (result.length === 1) {\n    return result[0]!\n  }\n\n  return {\n    type: `func`,\n    name: `or`,\n    args: result,\n  } as BasicExpression<boolean>\n}\n"],"names":["Value","Func"],"mappings":"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"}