rawsql-ts 0.26.1 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/esm/index.d.ts +1 -0
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/index.min.js +1 -1
  4. package/dist/esm/index.min.js.map +3 -3
  5. package/dist/esm/transformers/ConditionOptimization.d.ts +1 -0
  6. package/dist/esm/transformers/ConditionOptimization.js +97 -57
  7. package/dist/esm/transformers/ConditionOptimization.js.map +1 -1
  8. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.d.ts +26 -7
  9. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js +408 -138
  10. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
  11. package/dist/esm/transformers/SqlComponentFormatter.d.ts +9 -1
  12. package/dist/esm/transformers/SqlComponentFormatter.js +10 -1
  13. package/dist/esm/transformers/SqlComponentFormatter.js.map +1 -1
  14. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.d.ts +22 -4
  15. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js +332 -95
  16. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js.map +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +3 -3
  20. package/dist/src/index.d.ts +1 -0
  21. package/dist/src/transformers/ConditionOptimization.d.ts +1 -0
  22. package/dist/src/transformers/ParameterConditionPlacementOptimizer.d.ts +26 -7
  23. package/dist/src/transformers/SqlComponentFormatter.d.ts +9 -1
  24. package/dist/src/transformers/StaticPredicatePlacementOptimizer.d.ts +22 -4
  25. package/dist/transformers/ConditionOptimization.js +107 -54
  26. package/dist/transformers/ConditionOptimization.js.map +1 -1
  27. package/dist/transformers/ParameterConditionPlacementOptimizer.js +406 -136
  28. package/dist/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
  29. package/dist/transformers/SqlComponentFormatter.js +12 -2
  30. package/dist/transformers/SqlComponentFormatter.js.map +1 -1
  31. package/dist/transformers/StaticPredicatePlacementOptimizer.js +330 -93
  32. package/dist/transformers/StaticPredicatePlacementOptimizer.js.map +1 -1
  33. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  34. package/package.json +1 -1
package/dist/index.min.js CHANGED
@@ -46,7 +46,7 @@ ${query}`}addRestorationComments(sql,targetNode,warnings){let comments=[];return
46
46
  `),charIndex=0;for(let i=0;i<position.line-1&&i<lines.length;i++)charIndex+=lines[i].length+1;return charIndex+=position.column-1,Math.min(charIndex,sql.length-1)}isInsideStringLiteral(sql,charPosition){let inString=!1;for(let i=0;i<charPosition&&i<sql.length;i++)sql[i]==="'"&&(inString=!inString);return inString}getIdentifierAtPosition(sql,charPosition){if(charPosition>=sql.length)return null;let start=charPosition;for(;start>0&&this.isIdentifierChar(sql.charCodeAt(start-1));)start--;let end=charPosition;for(;end<sql.length&&this.isIdentifierChar(sql.charCodeAt(end));)end++;return start===end?null:sql.slice(start,end)}determineIdentifierType(sql,charPosition,identifier){let beforePosition=sql.slice(0,charPosition),afterPosition=sql.slice(charPosition),beforeUpper=beforePosition.toUpperCase(),afterUpper=afterPosition.toUpperCase();if(beforeUpper.lastIndexOf("WITH")!==-1){let start=charPosition;for(;start>0&&this.isIdentifierChar(sql.charCodeAt(start-1));)start--;let end=charPosition;for(;end<sql.length&&this.isIdentifierChar(sql.charCodeAt(end));)end++;if(sql.slice(end).toUpperCase().trim().startsWith("AS ("))return"cte"}let beforeLines=beforePosition.split(`
47
47
  `),currentLine=beforeLines[beforeLines.length-1].toUpperCase();if(currentLine.includes("FROM ")||currentLine.includes("JOIN "))return"table_alias";let contextBefore=beforePosition.slice(Math.max(0,charPosition-50)),contextAfter=afterPosition.slice(0,50),fullContext=(contextBefore+identifier+contextAfter).toUpperCase();return fullContext.includes(" AS "+identifier.toUpperCase())||fullContext.includes(" "+identifier.toUpperCase()+" ON")||fullContext.includes(" "+identifier.toUpperCase()+`
48
48
  `),"table_alias"}calculateScopeRange(sql,charPosition,type){if(type==="cte")return{start:0,end:sql.length};let beforePosition=sql.slice(0,charPosition),afterPosition=sql.slice(charPosition),lastSelect=beforePosition.toUpperCase().lastIndexOf("SELECT"),start=lastSelect!==-1?lastSelect:0,nextMajorClause=afterPosition.search(/\b(SELECT|WITH|UNION)\b/i),end=nextMajorClause!==-1?charPosition+nextMajorClause:sql.length;return{start,end}}replaceIdentifierSafely(sql,oldIdentifier,newIdentifier){if(oldIdentifier===newIdentifier||oldIdentifier.length===0)return sql;let result=[],position=0,sqlLength=sql.length,oldIdLength=oldIdentifier.length;for(;position<sqlLength;){let char=sql[position],charCode=char.charCodeAt(0);if(charCode===34||charCode===96||charCode===91){let{content,nextPosition}=this.extractAndReplaceQuotedIdentifier(sql,position,char,oldIdentifier,newIdentifier);result.push(content),position=nextPosition;continue}if(charCode===39){let{content,nextPosition}=this.extractQuotedString(sql,position,char);result.push(content),position=nextPosition;continue}if(charCode===45&&position+1<sqlLength&&sql.charCodeAt(position+1)===45){let{content,nextPosition}=this.extractLineComment(sql,position);result.push(content),position=nextPosition;continue}if(charCode===47&&position+1<sqlLength&&sql.charCodeAt(position+1)===42){let{content,nextPosition}=this.extractBlockComment(sql,position);result.push(content),position=nextPosition;continue}if(this.isIdentifierStartChar(charCode)&&this.matchesIdentifierAt(sql,position,oldIdentifier)){let beforePosition=position-1,afterPosition=position+oldIdLength,beforeChar=beforePosition>=0?sql[beforePosition]:null,afterChar=afterPosition<sqlLength?sql[afterPosition]:null;if(this.hasValidWordBoundaries(beforeChar,afterChar)){result.push(newIdentifier),position+=oldIdLength;continue}}result.push(char),position++}return result.join("")}validateRename(originalSql,modifiedSql,oldIdentifier,newIdentifier){if(originalSql===modifiedSql||!modifiedSql.includes(newIdentifier))return!1;let originalOccurrences=this.countWordOccurrences(originalSql,oldIdentifier);return this.countWordOccurrences(modifiedSql,oldIdentifier)<originalOccurrences}extractAndReplaceQuotedIdentifier(sql,startPosition,quoteChar,oldIdentifier,newIdentifier){if(quoteChar==="[")return this.extractAndReplaceBracketedIdentifier(sql,startPosition,oldIdentifier,newIdentifier);let result=[quoteChar],position=startPosition+1,identifierStart=position;for(;position<sql.length;){let char=sql[position];if(char===quoteChar){if(position+1<sql.length&&sql[position+1]===quoteChar){result.push(char),result.push(sql[position+1]),position+=2;continue}let quotedContent=sql.slice(identifierStart,position);quotedContent.toLowerCase()===oldIdentifier.toLowerCase()?result.push(newIdentifier):result.push(quotedContent),result.push(char);break}position++}return{content:result.join(""),nextPosition:position+1}}extractAndReplaceBracketedIdentifier(sql,startPosition,oldIdentifier,newIdentifier){let result=["["],position=startPosition+1,identifierStart=position;for(;position<sql.length;){let char=sql[position];if(char==="]"){let bracketedContent=sql.slice(identifierStart,position);bracketedContent.toLowerCase()===oldIdentifier.toLowerCase()?result.push(newIdentifier):result.push(bracketedContent),result.push(char);break}position++}return{content:result.join(""),nextPosition:position+1}}extractQuotedString(sql,startPosition,quoteChar){let result=[quoteChar],position=startPosition+1;for(;position<sql.length;){let char=sql[position];if(result.push(char),char===quoteChar){if(position+1<sql.length&&sql[position+1]===quoteChar){result.push(sql[position+1]),position+=2;continue}break}position++}return{content:result.join(""),nextPosition:position+1}}extractLineComment(sql,startPosition){let result=[],position=startPosition;for(;position<sql.length&&sql.charCodeAt(position)!==10&&sql.charCodeAt(position)!==13;)result.push(sql[position]),position++;return position<sql.length&&(sql.charCodeAt(position)===10||sql.charCodeAt(position)===13)&&(result.push(sql[position]),position++),{content:result.join(""),nextPosition:position}}extractBlockComment(sql,startPosition){let result=["/","*"],position=startPosition+2;for(;position<sql.length-1;){let char=sql[position];if(result.push(char),char==="*"&&sql[position+1]==="/"){result.push("/"),position+=2;break}position++}return{content:result.join(""),nextPosition:position}}isIdentifierStartChar(charCode){return charCode>=65&&charCode<=90||charCode>=97&&charCode<=122||charCode===95}isIdentifierChar(charCode){return charCode>=65&&charCode<=90||charCode>=97&&charCode<=122||charCode>=48&&charCode<=57||charCode===95}matchesIdentifierAt(sql,position,identifier){if(position+identifier.length>sql.length)return!1;for(let i=0;i<identifier.length;i++){let sqlChar=sql.charCodeAt(position+i),idChar=identifier.charCodeAt(i),sqlLower=sqlChar>=65&&sqlChar<=90?sqlChar+32:sqlChar,idLower=idChar>=65&&idChar<=90?idChar+32:idChar;if(sqlLower!==idLower)return!1}return!0}hasValidWordBoundaries(beforeChar,afterChar){let isValidBefore=beforeChar===null||!this.isIdentifierChar(beforeChar.charCodeAt(0)),isValidAfter=afterChar===null||!this.isIdentifierChar(afterChar.charCodeAt(0));return isValidBefore&&isValidAfter}countWordOccurrences(sql,identifier){let count=0,position=0,sqlLength=sql.length,idLength=identifier.length;for(;position<=sqlLength-idLength;){if(this.matchesIdentifierAt(sql,position,identifier)){let beforePosition=position-1,afterPosition=position+idLength,beforeChar=beforePosition>=0?sql[beforePosition]:null,afterChar=afterPosition<sqlLength?sql[afterPosition]:null;this.hasValidWordBoundaries(beforeChar,afterChar)&&count++}position++}return count}};var SmartRenamer=class{constructor(){this.cteRenamer=new CTERenamer,this.aliasRenamer=new AliasRenamer,this.identifierRenamer=new SqlIdentifierRenamer}isRenameable(sql,position){try{if(!sql?.trim())return{renameable:!1,renamerType:"none",reason:"Empty SQL"};if(!position||position.line<1||position.column<1)return{renameable:!1,renamerType:"none",reason:"Invalid position"};let lexeme=LexemeCursor.findLexemeAtLineColumn(sql,position);if(!lexeme)return{renameable:!1,renamerType:"none",reason:"No token found"};if(!(lexeme.type&2112))return{renameable:!1,renamerType:"none",tokenName:lexeme.value,reason:`Token '${lexeme.value}' is not an identifier`};let tokenName=lexeme.value,renamerType=this.detectRenamerType(sql,tokenName);return renamerType==="unknown"?{renameable:!1,renamerType:"none",tokenName,reason:`Cannot determine if '${tokenName}' is renameable`}:{renameable:!0,renamerType,tokenName}}catch(error){return{renameable:!1,renamerType:"none",reason:`Error: ${error instanceof Error?error.message:String(error)}`}}}rename(sql,position,newName,options){try{if(!sql?.trim())return this.createErrorResult(sql,newName,"unknown","","SQL cannot be empty");if(!position||position.line<1||position.column<1)return this.createErrorResult(sql,newName,"unknown","","Position must be valid line/column (1-based)");if(!newName?.trim())return this.createErrorResult(sql,newName,"unknown","","New name cannot be empty");let lexeme=LexemeCursor.findLexemeAtLineColumn(sql,position);if(!lexeme)return this.createErrorResult(sql,newName,"unknown","",`No identifier found at line ${position.line}, column ${position.column}`);if(!(lexeme.type&64))return this.createErrorResult(sql,newName,"unknown",lexeme.value,`Token '${lexeme.value}' is not renameable`);let originalName=lexeme.value,preserveFormatting=options?.preserveFormatting??!1,renamerType=this.detectRenamerType(sql,originalName);if(preserveFormatting)try{let formatPreservedResult=this.attemptFormattingPreservationRename(sql,position,newName,originalName,renamerType);if(formatPreservedResult.success)return formatPreservedResult}catch(error){console.warn("Formatting preservation failed, falling back to standard rename:",error)}try{let newSql;if(renamerType==="cte")newSql=this.cteRenamer.renameCTEAtPosition(sql,position,newName);else if(renamerType==="alias"){let result=this.aliasRenamer.renameAlias(sql,position,newName);if(!result.success)return{success:!1,originalSql:sql,renamerType:"alias",originalName,newName,error:result.conflicts?.join(", ")||"Alias rename failed",formattingPreserved:!1,formattingMethod:"smart-renamer-only"};newSql=result.newSql}else return this.createErrorResult(sql,newName,"unknown",originalName,`Cannot determine if '${originalName}' is a CTE name or table alias`);return{success:!0,originalSql:sql,newSql,renamerType,originalName,newName,formattingPreserved:!1,formattingMethod:"smart-renamer-only"}}catch(error){return this.createErrorResult(sql,newName,renamerType,originalName,`${renamerType.toUpperCase()} rename failed: ${error instanceof Error?error.message:String(error)}`)}}catch(error){return this.createErrorResult(sql,newName,"unknown","",`Unexpected error: ${error instanceof Error?error.message:String(error)}`)}}detectRenamerType(sql,identifierName){try{let query=SelectQueryParser.parse(sql);return this.isCTEName(query,identifierName)?"cte":"alias"}catch{return"unknown"}}isCTEName(query,name){return query instanceof SimpleSelectQuery&&query.withClause?query.withClause.tables.some(cte=>cte.aliasExpression&&cte.aliasExpression.table&&cte.aliasExpression.table.name===name):query instanceof BinarySelectQuery?this.isCTEName(query.left,name)||this.isCTEName(query.right,name):!1}attemptFormattingPreservationRename(sql,position,newName,originalName,renamerType){let standardResult=this.performStandardRename(sql,position,newName,originalName,renamerType);if(!standardResult.success)return{...standardResult,formattingPreserved:!1,formattingMethod:"smart-renamer-only"};let renameMap=new Map([[originalName,newName]]);try{let formattedSql=this.identifierRenamer.renameIdentifiers(sql,renameMap);if(this.validateRenameResult(sql,formattedSql,originalName,newName))return{success:!0,originalSql:sql,newSql:formattedSql,renamerType,originalName,newName,formattingPreserved:!0,formattingMethod:"sql-identifier-renamer"};throw new Error("Validation failed: rename may not have been applied correctly")}catch{return{...standardResult,formattingPreserved:!1,formattingMethod:"smart-renamer-only"}}}performStandardRename(sql,position,newName,originalName,renamerType){try{let newSql;if(renamerType==="cte")newSql=this.cteRenamer.renameCTEAtPosition(sql,position,newName);else if(renamerType==="alias"){let result=this.aliasRenamer.renameAlias(sql,position,newName);if(!result.success)return{success:!1,originalSql:sql,renamerType:"alias",originalName,newName,error:result.conflicts?.join(", ")||"Alias rename failed"};newSql=result.newSql}else return{success:!1,originalSql:sql,renamerType:"unknown",originalName,newName,error:`Cannot determine if '${originalName}' is a CTE name or table alias`};return{success:!0,originalSql:sql,newSql,renamerType,originalName,newName}}catch(error){return{success:!1,originalSql:sql,renamerType,originalName,newName,error:`${renamerType.toUpperCase()} rename failed: ${error instanceof Error?error.message:String(error)}`}}}validateRenameResult(originalSql,newSql,oldName,newName){if(originalSql===newSql||!newSql.includes(newName))return!1;let originalOccurrences=this.countWordOccurrences(originalSql,oldName);return this.countWordOccurrences(newSql,oldName)<originalOccurrences}countWordOccurrences(sql,name){let regex=new RegExp(`\\b${name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\b`,"gi"),matches=sql.match(regex);return matches?matches.length:0}createErrorResult(sql,newName,renamerType,originalName,error){return{success:!1,originalSql:sql,renamerType,originalName,newName,error,formattingPreserved:!1,formattingMethod:"smart-renamer-only"}}batchRename(sql,renames,options){if(options?.preserveFormatting??!1)try{let renameMap=new Map(Object.entries(renames)),formattedSql=this.identifierRenamer.renameIdentifiers(sql,renameMap),originalNames=Object.keys(renames),newNames=Object.values(renames);return{success:!0,originalSql:sql,newSql:formattedSql,renamerType:"alias",originalName:originalNames.join(", "),newName:newNames.join(", "),formattingPreserved:!0,formattingMethod:"sql-identifier-renamer"}}catch(error){return{success:!1,originalSql:sql,renamerType:"unknown",originalName:Object.keys(renames).join(", "),newName:Object.values(renames).join(", "),error:`Batch rename failed: ${error instanceof Error?error.message:String(error)}`,formattingPreserved:!1,formattingMethod:"smart-renamer-only"}}else return{success:!1,originalSql:sql,renamerType:"unknown",originalName:Object.keys(renames).join(", "),newName:Object.values(renames).join(", "),error:"Batch rename without formatting preservation not implemented. Use individual renames or enable formatting preservation.",formattingPreserved:!1,formattingMethod:"smart-renamer-only"}}};var OriginalFormatRestorer=class{restore(lexemes){if(lexemes.length===0)return"";let result="";for(let lexeme of lexemes)result+=lexeme.value,lexeme.followingWhitespace&&(result+=lexeme.followingWhitespace);return result}restoreWithComments(lexemes,includeComments=!0){if(lexemes.length===0)return"";let result="";for(let lexeme of lexemes){if(result+=lexeme.value,includeComments&&lexeme.inlineComments&&lexeme.inlineComments.length>0)for(let comment of lexeme.inlineComments)comment.trim().length>0&&(result+=` -- ${comment}`);lexeme.followingWhitespace&&(result+=lexeme.followingWhitespace)}return result}analyzeFormatting(lexemes){let totalWhitespace=0,totalComments=0,spaceCount=0,tabCount=0,indentLines=0,totalIndentSize=0;for(let lexeme of lexemes){if(lexeme.followingWhitespace){totalWhitespace+=lexeme.followingWhitespace.length;let lines=lexeme.followingWhitespace.split(`
49
- `);for(let i=1;i<lines.length;i++){let line=lines[i],leadingSpaces=line.match(/^ */)?.[0].length||0,leadingTabs=line.match(/^\t*/)?.[0].length||0;(leadingSpaces>0||leadingTabs>0)&&(indentLines++,totalIndentSize+=leadingSpaces+leadingTabs*4,spaceCount+=leadingSpaces,tabCount+=leadingTabs)}}lexeme.inlineComments&&(totalComments+=lexeme.inlineComments.length)}let indentationStyle="none";return spaceCount>0&&tabCount>0?indentationStyle="mixed":spaceCount>0?indentationStyle="spaces":tabCount>0&&(indentationStyle="tabs"),{totalWhitespace,totalComments,indentationStyle,averageIndentSize:indentLines>0?totalIndentSize/indentLines:0}}validateFormattingLexemes(lexemes){let issues=[];for(let i=0;i<lexemes.length;i++){let lexeme=lexemes[i];lexeme.position||issues.push(`Lexeme ${i} missing position information`),lexeme.followingWhitespace===void 0&&issues.push(`Lexeme ${i} missing followingWhitespace property`),lexeme.inlineComments===void 0&&issues.push(`Lexeme ${i} missing inlineComments property`),lexeme.position&&lexeme.position.startPosition>=lexeme.position.endPosition&&issues.push(`Lexeme ${i} has invalid position range`)}return{isValid:issues.length===0,issues}}};var ClauseScopedColumnReferenceCollector=class{collect(query){if(!(query instanceof SimpleSelectQuery))throw new Error("ClauseScopedColumnReferenceCollector requires a SimpleSelectQuery.");let result=this.createEmptyResult();return this.collectFromSelectClause(query.selectClause,result),this.collectFromJoinClauses(query,result),query.whereClause&&this.collectFromWhereClause(query.whereClause,result),query.groupByClause&&this.collectFromGroupByClause(query.groupByClause,result),query.havingClause&&this.collectFromHavingClause(query.havingClause,result),query.orderByClause&&this.collectFromOrderByClause(query.orderByClause,"orderBy",result),query.windowClause&&this.collectFromWindowsClause(query.windowClause,result),query.limitClause&&this.collectFromLimitClause(query.limitClause,result),query.offsetClause&&this.collectFromOffsetClause(query.offsetClause,result),query.fetchClause&&this.collectFromFetchClause(query.fetchClause,result),result}createEmptyResult(){return{select:[],where:[],joinOn:[],groupBy:[],having:[],orderBy:[],window:[],limitOffset:[]}}collectFromSelectClause(clause,result){clause.distinct instanceof DistinctOn&&this.collectFromValueComponent(clause.distinct.value,"select",result);for(let item of clause.items)this.collectFromValueComponent(item.value,"select",result)}collectFromJoinClauses(query,result){if(query.fromClause?.joins)for(let join of query.fromClause.joins)(join.condition instanceof JoinOnClause||join.condition instanceof JoinUsingClause)&&this.collectFromValueComponent(join.condition.condition,"joinOn",result)}collectFromWhereClause(clause,result){this.collectFromValueComponent(clause.condition,"where",result)}collectFromGroupByClause(clause,result){for(let item of clause.grouping)this.collectFromValueComponent(item,"groupBy",result)}collectFromHavingClause(clause,result){this.collectFromValueComponent(clause.condition,"having",result)}collectFromOrderByClause(clause,target,result){for(let item of clause.order)item instanceof OrderByItem?this.collectFromValueComponent(item.value,target,result):this.collectFromValueComponent(item,target,result)}collectFromLimitClause(clause,result){this.collectFromValueComponent(clause.value,"limitOffset",result)}collectFromOffsetClause(clause,result){this.collectFromValueComponent(clause.value,"limitOffset",result)}collectFromFetchClause(clause,result){this.collectFromValueComponent(clause.expression.count,"limitOffset",result)}collectFromWindowsClause(clause,result){for(let window of clause.windows)this.collectFromWindowFrameExpression(window.expression,"window",result)}collectFromValueComponent(value,target,result,expression=value){if(value instanceof ColumnReference){result[target].push(this.createInfo(value,target,expression));return}if(value instanceof BinaryExpression)this.collectFromValueComponent(value.left,target,result,value),this.collectFromValueComponent(value.right,target,result,value);else if(value instanceof UnaryExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof FunctionCall)this.collectFromFunctionCall(value,target,result);else if(value instanceof CaseExpression){value.condition&&this.collectFromValueComponent(value.condition,target,result,value);for(let pair of value.switchCase.cases)this.collectFromValueComponent(pair.key,target,result,value),this.collectFromValueComponent(pair.value,target,result,value);value.switchCase.elseValue&&this.collectFromValueComponent(value.switchCase.elseValue,target,result,value)}else if(value instanceof ParenExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof CastExpression)this.collectFromValueComponent(value.input,target,result,value);else if(value instanceof BetweenExpression)this.collectFromValueComponent(value.expression,target,result,value),this.collectFromValueComponent(value.lower,target,result,value),this.collectFromValueComponent(value.upper,target,result,value);else if(value instanceof JsonPredicateExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof ArrayExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof ArraySliceExpression)this.collectFromValueComponent(value.array,target,result,value),value.startIndex&&this.collectFromValueComponent(value.startIndex,target,result,value),value.endIndex&&this.collectFromValueComponent(value.endIndex,target,result,value);else if(value instanceof ArrayIndexExpression)this.collectFromValueComponent(value.array,target,result,value),this.collectFromValueComponent(value.index,target,result,value);else if(value instanceof ValueList)for(let item of value.values)this.collectFromValueComponent(item,target,result,value);else if(value instanceof TupleExpression)for(let item of value.values)this.collectFromValueComponent(item,target,result,value);else if(value instanceof TypeValue&&value.argument)this.collectFromValueComponent(value.argument,target,result,value);else if(value instanceof InlineQuery||value instanceof ArrayQueryExpression)return}collectFromFunctionCall(value,target,result){value.argument&&this.collectFromValueComponent(value.argument,target,result,value),value.filterCondition&&this.collectFromValueComponent(value.filterCondition,target,result,value),value.withinGroup&&this.collectFromOrderByClause(value.withinGroup,target,result),value.internalOrderBy&&this.collectFromOrderByClause(value.internalOrderBy,target,result),value.over instanceof WindowFrameExpression&&this.collectFromWindowFrameExpression(value.over,target,result)}collectFromWindowFrameExpression(value,target,result){value.partition&&this.collectFromValueComponent(value.partition.value,target,result),value.order&&this.collectFromOrderByClause(value.order,target,result),value.frameSpec&&(value.frameSpec.startBound instanceof WindowFrameBoundaryValue&&this.collectFromValueComponent(value.frameSpec.startBound.value,target,result),value.frameSpec.endBound instanceof WindowFrameBoundaryValue&&this.collectFromValueComponent(value.frameSpec.endBound.value,target,result))}createInfo(reference,clause,expression){let namespaces=reference.namespaces?.map(namespace=>namespace.name)??[],columnName=this.getNameText(reference.qualifiedName.name);return{clause,reference,qualifiedName:reference.qualifiedName.toString(),namespaces,namespace:namespaces.length>0?namespaces.join("."):null,column:columnName,expression}}getNameText(name){return name instanceof IdentifierString?name.name:name.value}};var SelectResultSelectConverter=class{static toSelectQuery(query,options){let fixtureTables=options?.fixtureTables??[];if(fixtureTables.length===0)return query;let sources=new TableSourceCollector(!1).collect(query),referencedTables=new Set;sources.forEach(s=>referencedTables.add(s.getSourceName().toLowerCase()));let neededFixtures=fixtureTables.filter(f=>referencedTables.has(f.tableName.toLowerCase()));if(neededFixtures.length===0)return query;let fixtureCtes=FixtureCteBuilder.buildFixtures(neededFixtures);return query instanceof SimpleSelectQuery&&(query.withClause?query.withClause.tables=[...fixtureCtes,...query.withClause.tables]:query.appendWith(fixtureCtes)),query}};var SimulatedSelectConverter=class{static convert(ast,options){if(ast instanceof InsertQuery)return InsertResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof UpdateQuery)return UpdateResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof DeleteQuery)return DeleteResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof MergeQuery)return MergeResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof SimpleSelectQuery||ast instanceof BinarySelectQuery||ast instanceof ValuesQuery)return SelectResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof CreateTableQuery){if(ast.isTemporary&&ast.asSelectQuery){let processedSelect=SelectResultSelectConverter.toSelectQuery(ast.asSelectQuery,options);return ast.asSelectQuery=processedSelect,ast}return null}return null}};var DDLGeneralizer=class{static generalize(ast){let result=[];for(let component of ast)if(component instanceof CreateTableQuery){let{createTable,alterTables}=this.splitCreateTable(component);result.push(createTable),result.push(...alterTables)}else result.push(component);return result}static splitCreateTable(query){let newColumns=[],alterTables=[],tableQualifiedName=new QualifiedName(query.namespaces||[],query.tableName.name);for(let col of query.columns){let newConstraints=[];for(let constraint of col.constraints)if(["primary-key","unique","references","check"].includes(constraint.kind)){let tableConstraint=this.columnToTableConstraint(col.name,constraint);alterTables.push(new AlterTableStatement({table:tableQualifiedName,actions:[new AlterTableAddConstraint({constraint:tableConstraint})]}))}else newConstraints.push(constraint);newColumns.push(new TableColumnDefinition({name:col.name,dataType:col.dataType,constraints:newConstraints}))}if(query.tableConstraints)for(let constraint of query.tableConstraints)alterTables.push(new AlterTableStatement({table:tableQualifiedName,actions:[new AlterTableAddConstraint({constraint})]}));return{createTable:new CreateTableQuery({tableName:query.tableName.name,namespaces:query.namespaces,columns:newColumns,ifNotExists:query.ifNotExists,isTemporary:query.isTemporary,tableOptions:query.tableOptions,asSelectQuery:query.asSelectQuery,withDataOption:query.withDataOption,tableConstraints:[]}),alterTables}}static columnToTableConstraint(columnName,constraint){let baseParams={constraintName:constraint.constraintName,deferrable:constraint.reference?.deferrable,initially:constraint.reference?.initially};switch(constraint.kind){case"primary-key":return new TableConstraintDefinition({kind:"primary-key",columns:[columnName],...baseParams});case"unique":return new TableConstraintDefinition({kind:"unique",columns:[columnName],...baseParams});case"references":return new TableConstraintDefinition({kind:"foreign-key",columns:[columnName],reference:constraint.reference,...baseParams});case"check":return new TableConstraintDefinition({kind:"check",checkExpression:constraint.checkExpression,...baseParams});default:throw new Error(`Unsupported constraint kind for generalization: ${constraint.kind}`)}}};var DDLDiffGenerator=class{static generateDiff(currentSql,expectedSql,options={}){let currentAst=this.parseAndGeneralize(currentSql),expectedAst=this.parseAndGeneralize(expectedSql),currentSchema=this.buildSchema(currentAst),expectedSchema=this.buildSchema(expectedAst),diffAsts=[];for(let[tableName,expectedTable]of expectedSchema.tables){let currentTable=currentSchema.tables.get(tableName);if(currentTable)this.compareColumns(currentTable,expectedTable,diffAsts,options),this.compareConstraints(currentTable,expectedTable,diffAsts,options),this.compareIndexes(currentTable,expectedTable,diffAsts,options);else{let columns=Array.from(expectedTable.columns.values()).map(c=>c.definition),tableNameStr=expectedTable.qualifiedName.name instanceof RawString?expectedTable.qualifiedName.name.value:expectedTable.qualifiedName.name.name,namespaces=expectedTable.qualifiedName.namespaces?expectedTable.qualifiedName.namespaces.map(ns=>ns.name):null,createTable=new CreateTableQuery({tableName:tableNameStr,namespaces,columns});diffAsts.push(createTable);for(let constraint of expectedTable.constraints)diffAsts.push(new AlterTableStatement({table:expectedTable.qualifiedName,actions:[new AlterTableAddConstraint({constraint:constraint.definition})]}));for(let index of expectedTable.indexes)diffAsts.push(index.definition)}}if(options.dropTables)for(let[tableName,currentTable]of currentSchema.tables)expectedSchema.tables.has(tableName)||diffAsts.push(new DropTableStatement({tables:[currentTable.qualifiedName],ifExists:!1}));let formatter2=new SqlFormatter(options.formatOptions||{keywordCase:"upper"});return diffAsts.map(ast=>formatter2.format(ast).formattedSql+";")}static parseAndGeneralize(sql){let split=MultiQuerySplitter.split(sql),asts=[];for(let q of split.queries)if(!q.isEmpty)try{let ast=SqlParser.parse(q.sql);asts.push(ast)}catch(e){console.warn("Failed to parse SQL for diff:",q.sql,e)}return DDLGeneralizer.generalize(asts)}static buildSchema(asts){let tables=new Map,formatter2=new SqlFormatter({keywordCase:"none"});for(let ast of asts)if(ast instanceof CreateTableQuery){let qName=new QualifiedName(ast.namespaces||[],ast.tableName),key=this.getQualifiedNameKey(qName),tableModel={name:key,qualifiedName:qName,columns:new Map,constraints:[],indexes:[]};for(let col of ast.columns)tableModel.columns.set(col.name.name,{name:col.name.name,definition:col});tables.set(key,tableModel)}else if(ast instanceof AlterTableStatement){let key=this.getQualifiedNameKey(ast.table),tableModel=tables.get(key);if(tableModel)for(let action of ast.actions)if(action instanceof AlterTableAddConstraint){let formatted=formatter2.format(action.constraint).formattedSql;tableModel.constraints.push({name:action.constraint.constraintName?.name,kind:action.constraint.kind,definition:action.constraint,formatted})}else action instanceof AlterTableAddColumn&&tableModel.columns.set(action.column.name.name,{name:action.column.name.name,definition:action.column})}else if(ast instanceof CreateIndexStatement){let key=this.getQualifiedNameKey(ast.tableName),tableModel=tables.get(key);if(tableModel){let formatted=formatter2.format(ast).formattedSql;tableModel.indexes.push({name:ast.indexName.toString(),definition:ast,formatted})}}return{tables}}static compareColumns(current,expected,diffs,options){for(let[name,col]of expected.columns)current.columns.has(name)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableAddColumn({column:col.definition})]}));if(options.dropColumns)for(let[name,col]of current.columns)expected.columns.has(name)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableDropColumn({columnName:col.definition.name})]}))}static compareConstraints(current,expected,diffs,options){let formatter2=new SqlFormatter({keywordCase:"none"}),getConstraintSignature=c=>options.checkConstraintNames?c.kind==="primary-key"?c.formatted.replace(/^constraint\s+("[^"]+"|[^\s]+)\s+/i,"").trim():c.name||c.formatted:c.formatted.replace(/^constraint\s+("[^"]+"|[^\s]+)\s+/i,"").trim(),currentSignatures=new Set(current.constraints.map(getConstraintSignature));for(let expectedC of expected.constraints){let sig=getConstraintSignature(expectedC);currentSignatures.has(sig)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableAddConstraint({constraint:expectedC.definition})]}))}if(options.dropConstraints){let expectedSignatures=new Set(expected.constraints.map(getConstraintSignature));for(let currentC of current.constraints){let sig=getConstraintSignature(currentC);expectedSignatures.has(sig)||(currentC.name?diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableDropConstraint({constraintName:new IdentifierString(currentC.name)})]})):console.warn("Cannot drop unnamed constraint:",currentC.formatted))}}}static compareIndexes(current,expected,diffs,options){let getIndexSignature=idx=>{if(options.checkConstraintNames)return idx.name;let def=idx.definition,parts=[];parts.push(def.tableName.toString()),def.unique&&parts.push("UNIQUE"),def.usingMethod&&parts.push(`USING:${def.usingMethod.toString()}`);let columnSigs=def.columns.map(col=>{let expr=col.expression.toString(),sort=col.sortOrder||"",nulls=col.nullsOrder||"";return`${expr}${sort}${nulls}`});return parts.push(`COLS:${columnSigs.join(",")}`),def.include&&def.include.length>0&&parts.push(`INCLUDE:${def.include.map(i=>i.toString()).join(",")}`),def.where&&parts.push(`WHERE:${def.where.toString()}`),parts.join("|")},currentSignatures=new Set(current.indexes.map(getIndexSignature));for(let expectedIdx of expected.indexes){let sig=getIndexSignature(expectedIdx);currentSignatures.has(sig)||diffs.push(expectedIdx.definition)}if(options.checkConstraintNames||options.dropIndexes){let expectedSignatures=new Set(expected.indexes.map(getIndexSignature));for(let currentIdx of current.indexes){let sig=getIndexSignature(currentIdx);expectedSignatures.has(sig)||diffs.push(new DropIndexStatement({indexNames:[currentIdx.definition.indexName],ifExists:!1}))}}}static getQualifiedNameKey(qName){return qName.toString()}};var SelectBodyExtractor=class{static extract(input){return typeof input=="string"?this.extractFromSql(input):this.extractFromStatement(input)}static extractFromSql(sql){let lexemes=new SqlTokenizer(sql).readLexemes();return this.isCreateViewStatement(lexemes)?this.extractCreateViewFromLexemes(lexemes):this.extractFromStatement(SqlParser.parse(sql))}static extractFromStatement(statement){if(statement instanceof CreateTableQuery){let targetName=this.createTableTargetName(statement);return statement.asSelectQuery?{supported:!0,kind:"create-table-as",targetName,selectQuery:statement.asSelectQuery}:this.unsupported(targetName)}if(statement instanceof InsertQuery){let targetName=this.insertTargetName(statement);return!statement.selectQuery||statement.selectQuery instanceof ValuesQuery?this.unsupported(targetName):{supported:!0,kind:"insert-select",targetName,selectQuery:statement.selectQuery}}return{supported:!1,kind:null,targetName:null,selectQuery:null,reason:"Statement type is not supported."}}static extractCreateViewFromLexemes(lexemes){let idx=0;idx++;let materialized=lexemes[idx]?.value.toLowerCase()==="materialized";if(materialized&&idx++,lexemes[idx]?.value.toLowerCase()!=="view")return this.unsupported(null,"Statement type is not supported.");idx++,lexemes[idx]?.value.toLowerCase()==="if not exists"&&idx++;let targetResult=FullNameParser.parseFromLexeme(lexemes,idx);idx=targetResult.newIndex;let targetName=[...targetResult.namespaces??[],targetResult.name.name].join(".");if(lexemes[idx]?.type===4&&(idx=this.consumeBalancedParentheses(lexemes,idx)),lexemes[idx]?.value.toLowerCase()!=="as")return this.unsupported(targetName);idx++;let selectResult=SelectQueryParser.parseFromLexeme(lexemes,idx);return{supported:!0,kind:materialized?"create-materialized-view":"create-view",targetName,selectQuery:selectResult.value}}static isCreateViewStatement(lexemes){if(lexemes[0]?.value.toLowerCase()!=="create")return!1;let second=lexemes[1]?.value.toLowerCase(),third=lexemes[2]?.value.toLowerCase();return second==="view"||second==="materialized"&&third==="view"}static consumeBalancedParentheses(lexemes,index){let idx=index,depth=0;for(;idx<lexemes.length;){if(lexemes[idx].type===4)depth++;else if(lexemes[idx].type===8&&(depth--,depth===0))return idx+1;idx++}return idx}static createTableTargetName(query){return[...query.namespaces??[],query.tableName.name].join(".")}static insertTargetName(query){let source=query.insertClause.source;return source.datasource instanceof TableSource?source.datasource.getSourceName():source.getAliasName()}static unsupported(targetName,reason="No embedded SELECT body found."){return{supported:!1,kind:null,targetName,selectQuery:null,reason}}};var SelectOutputCollector=class _SelectOutputCollector{constructor(tableColumnResolver=null,initialCommonTables=null){this.tableColumnResolver=tableColumnResolver;this.commonTableCollector=new CTECollector;this.commonTables=initialCommonTables??[]}collect(arg){return this.collectRaw(arg).map((item,outputIndex)=>({...item,outputIndex}))}collectRaw(arg){return arg instanceof SimpleSelectQuery?this.collectSimpleSelectQuery(arg):arg instanceof SourceExpression?this.collectSourceExpression(arg.getAliasName(),arg):arg instanceof FromClause?this.collectFromClause(arg,!0):[]}collectSimpleSelectQuery(query){let previousCommonTables=this.commonTables;this.commonTables.length===0&&(this.commonTables=this.commonTableCollector.collect(query));try{let outputs=[];for(let item of query.selectClause.items)outputs.push(...this.collectSelectItem(item,query.fromClause));return outputs}finally{this.commonTables=previousCommonTables}}collectSelectItem(item,fromClause){if(item.identifier)return[this.createExplicitOutput(item.identifier.name,item.value,fromClause)];if(!(item.value instanceof ColumnReference))return[];let columnName=item.value.column.name;return columnName==="*"?this.expandWildcard(item.value,fromClause):[this.createExplicitOutput(columnName,item.value,fromClause)]}expandWildcard(value,fromClause){if(!fromClause)return[];if(value.namespaces===null)return this.collectFromClause(fromClause,!0);let sourceName=value.getNamespace();if(fromClause.getSourceAliasName()===sourceName)return this.collectFromClause(fromClause,!1);let join=fromClause.joins?.find(item=>this.getJoinSourceName(item)===sourceName);return join?this.collectJoinClause(join):[]}collectFromClause(clause,joinCascade){let outputs=this.collectSourceExpression(clause.getSourceAliasName(),clause.source);if(clause.joins&&joinCascade)for(let join of clause.joins)outputs.push(...this.collectJoinClause(join));return outputs}collectJoinClause(clause){return this.collectSourceExpression(this.getJoinSourceName(clause),clause.source)}getJoinSourceName(clause){return clause.source.getAliasName()}collectSourceExpression(sourceName,source){if(source.aliasExpression?.columns)return source.aliasExpression.columns.map(column=>({name:column.name,value:new ColumnReference(sourceName?[sourceName]:null,column.name),sourceAlias:sourceName,sourceName:null,sourceColumnName:column.name}));let cte=this.findCommonTable(source);if(cte){let innerCommonTables=this.commonTables.filter(item=>item.getSourceAliasName()!==cte.getSourceAliasName()),innerOutputs=this.collectCteQuery(cte.query,innerCommonTables);return this.qualifyOutputs(innerOutputs,sourceName,cte.getSourceAliasName())}if(source.datasource instanceof TableSource)return this.collectTableSource(sourceName,source.datasource);if(source.datasource instanceof SubQuerySource){let innerOutputs=this.collectNestedSelectQuery(source.datasource.query);return this.qualifyOutputs(innerOutputs,sourceName,null)}return source.datasource instanceof ParenSource?[]:[]}findCommonTable(source){if(!(source.datasource instanceof TableSource))return null;let tableName=source.datasource.getSourceName();return this.commonTables.find(item=>item.getSourceAliasName()===tableName)??null}collectTableSource(sourceName,source){if(!this.tableColumnResolver)return[];let tableName=source.getSourceName(),qualifier=sourceName??tableName;return this.tableColumnResolver(tableName).map(column=>({name:column,value:new ColumnReference([qualifier],column),sourceAlias:sourceName,sourceName:tableName,sourceColumnName:column}))}collectNestedSelectQuery(query){return new _SelectOutputCollector(this.tableColumnResolver,this.commonTables).collect(query).map(({name,value,sourceAlias,sourceName,sourceColumnName})=>({name,value,sourceAlias,sourceName,sourceColumnName}))}collectCteQuery(query,commonTables){return this.isSelectQuery(query)?new _SelectOutputCollector(this.tableColumnResolver,commonTables).collect(query).map(({name,value,sourceAlias,sourceName,sourceColumnName})=>({name,value,sourceAlias,sourceName,sourceColumnName})):this.collectReturningOutputs(query)}collectReturningOutputs(query){return query instanceof InsertQuery||query instanceof UpdateQuery||query instanceof DeleteQuery||query instanceof MergeQuery?query.returningClause?this.extractReturningOutputs(query.returningClause):[]:[]}extractReturningOutputs(clause){let outputs=[];for(let item of clause.items){let name=item.identifier?.name??this.extractSelectItemName(item);name&&outputs.push(this.createExplicitOutput(name,item.value))}return outputs}extractSelectItemName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}qualifyOutputs(outputs,sourceAlias,sourceName){return outputs.map(item=>({name:item.name,value:new ColumnReference(sourceAlias?[sourceAlias]:null,item.name),sourceAlias,sourceName,sourceColumnName:item.name}))}createExplicitOutput(name,value,fromClause=null){if(value instanceof ColumnReference&&value.column.name!=="*"){let sourceMetadata=this.resolveColumnSourceMetadata(value,fromClause);if(sourceMetadata)return{name,value,...sourceMetadata}}return{name,value,sourceAlias:null,sourceName:null,sourceColumnName:null}}resolveColumnSourceMetadata(value,fromClause){if(!fromClause||value.namespaces===null)return null;let namespace=value.getNamespace(),matches=fromClause.getSources().filter(source2=>this.getSourceMatchNames(source2).includes(namespace));if(matches.length!==1)return null;let source=matches[0];return{sourceAlias:this.getColumnReferenceSourceAlias(source,namespace),sourceName:this.getColumnReferenceSourceName(source),sourceColumnName:value.column.name}}getSourceMatchNames(source){let names=new Set;if(source.aliasExpression)return names.add(source.aliasExpression.table.name),[...names];let aliasName=source.getAliasName();return aliasName&&names.add(aliasName),source.datasource instanceof TableSource&&(names.add(source.datasource.table.name),names.add(source.datasource.getSourceName())),[...names]}getColumnReferenceSourceAlias(source,namespace){return source.aliasExpression?source.aliasExpression.table.name:namespace}getColumnReferenceSourceName(source){let cte=this.findCommonTable(source);return cte?cte.getSourceAliasName():source.aliasExpression?.columns?null:source.datasource instanceof TableSource?source.datasource.getSourceName():null}isSelectQuery(query){return"__selectQueryType"in query&&query.__selectQueryType==="SelectQuery"}};var clauseOrder=["select","where","joinOn","groupBy","having","orderBy","window","limitOffset"],WildcardColumnInferenceCollector=class{constructor(){this.clauseCollector=new ClauseScopedColumnReferenceCollector;this.requirements=new Map;this.visitedQueries=new Set;this.nextObjectId=0;this.objectIds=new WeakMap}collect(query){return this.requirements.clear(),this.visitedQueries.clear(),this.nextObjectId=0,this.objectIds=new WeakMap,this.collectFromSelectQuery(query,[]),[...this.requirements.values()].map(item=>this.inferTarget(item))}collectFromSelectQuery(query,commonTables){if(this.visitedQueries.has(query))return;if(this.visitedQueries.add(query),query instanceof BinarySelectQuery){let rightCommonTables=this.mergeCommonTables(commonTables,this.collectLeadingCommonTables(query.left));this.collectFromSelectQuery(query.left,commonTables),this.collectFromSelectQuery(query.right,rightCommonTables);return}if(!(query instanceof SimpleSelectQuery))return;let scopedCommonTables=this.mergeCommonTables(commonTables,query.withClause?.tables??[]);this.collectConsumerRequirements(query,scopedCommonTables),this.collectNestedSources(query.fromClause,scopedCommonTables);for(let commonTable of query.withClause?.tables??[])this.collectCteQuery(commonTable.query,scopedCommonTables)}collectCteQuery(query,commonTables){this.isSelectQuery(query)&&this.collectFromSelectQuery(query,commonTables)}collectConsumerRequirements(query,commonTables){if(!query.fromClause)return;let targets=this.collectConsumerTargets(query.fromClause,commonTables);if(targets.length===0)return;let targetByMatchName=new Map;for(let target of targets)for(let name of this.getTargetMatchNames(target)){let existing=targetByMatchName.get(name)??[];existing.push(target),targetByMatchName.set(name,existing)}let singleUnqualifiedTarget=query.fromClause.getSources().length===1&&targets.length===1?targets[0]:null;for(let reference of this.flattenReferences(this.clauseCollector.collect(query))){if(reference.column==="*")continue;let matchedTarget=reference.namespace?this.getUniqueTarget(targetByMatchName.get(reference.namespace)??[]):singleUnqualifiedTarget;matchedTarget&&this.addRequirement(matchedTarget,reference.column,this.createRequiredBy(reference))}}collectConsumerTargets(fromClause,commonTables){let targets=[];for(let source of fromClause.getSources()){let cteTarget=this.createCteTarget(source,commonTables);if(cteTarget){targets.push(cteTarget);continue}let derivedTarget=this.createDerivedTableTarget(source);derivedTarget&&targets.push(derivedTarget)}return targets}createCteTarget(source,commonTables){if(!(source.datasource instanceof TableSource))return null;let tableName=source.datasource.getSourceName(),commonTable=commonTables.find(item=>item.getSourceAliasName()===tableName);return!commonTable||!this.isSelectQuery(commonTable.query)?null:{key:`cte:${this.getObjectId(commonTable)}`,targetKind:"cte",targetName:commonTable.getSourceAliasName(),targetAlias:source.aliasExpression?source.getAliasName():commonTable.getSourceAliasName(),query:commonTable.query}}createDerivedTableTarget(source){return source.datasource instanceof SubQuerySource?{key:`derived:${this.getObjectId(source.datasource.query)}`,targetKind:"derivedTable",targetName:null,targetAlias:source.getAliasName(),query:source.datasource.query}:null}collectNestedSources(fromClause,commonTables){if(fromClause)for(let source of fromClause.getSources())source.datasource instanceof SubQuerySource&&this.collectFromSelectQuery(source.datasource.query,commonTables)}addRequirement(target,column,requiredBy){let requirement=this.requirements.get(target.key);requirement||(requirement={descriptor:target,requiredByColumn:new Map},this.requirements.set(target.key,requirement));let existing=requirement.requiredByColumn.get(column)??[];existing.push(requiredBy),requirement.requiredByColumn.set(column,existing)}inferTarget(requirement){let descriptor=requirement.descriptor,baseResult={targetKind:descriptor.targetKind,targetName:descriptor.targetName,targetAlias:descriptor.targetAlias,wildcards:[],explicitColumns:[],requiredColumns:[],unresolvedColumns:[]};if(!(descriptor.query instanceof SimpleSelectQuery)){for(let[outputName,requiredBy]of requirement.requiredByColumn)baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"unsupportedQueryShape",[],requiredBy));return baseResult}let outputMetadata=this.collectTargetOutputMetadata(descriptor.query);baseResult.wildcards=outputMetadata.wildcards,baseResult.explicitColumns=outputMetadata.explicitColumns;for(let[outputName,requiredBy]of requirement.requiredByColumn){let explicitMatches=outputMetadata.explicitColumns.filter(item=>item.outputName===outputName),candidateWildcards=outputMetadata.wildcards;if(explicitMatches.length>0&&candidateWildcards.length>0){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"duplicateOutputOwnership",candidateWildcards,requiredBy));continue}if(explicitMatches.length>0)continue;if(outputMetadata.unqualifiedWildcardWithMultipleSources){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"unqualifiedWildcardMultipleSources",candidateWildcards,requiredBy));continue}if(candidateWildcards.length===0){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"noWildcardSupplier",[],requiredBy));continue}if(candidateWildcards.length>1){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"multipleWildcardSuppliers",candidateWildcards,requiredBy));continue}let wildcard=candidateWildcards[0];baseResult.requiredColumns.push({outputName,sourceAlias:wildcard.sourceAlias,sourceName:wildcard.sourceName,sourceColumnName:outputName,wildcard,requiredByClause:this.collectRequiredByClauses(requiredBy),requiredBy})}return baseResult}collectTargetOutputMetadata(query){let wildcards=[],unqualifiedWildcardWithMultipleSources=!1;query.selectClause.items.forEach((item,outputIndex)=>{let wildcard=this.collectWildcardMetadata(item,outputIndex,query.fromClause);if(wildcard==="unqualifiedWildcardMultipleSources"){unqualifiedWildcardWithMultipleSources=!0,wildcards.push({kind:"unqualified",outputIndex,sourceAlias:null,sourceName:null});return}wildcard&&wildcards.push(wildcard)});let explicitColumns=new SelectOutputCollector().collect(query).filter(item=>!(item.value instanceof ColumnReference&&item.value.column.name==="*")).map(item=>({outputName:item.name,sourceAlias:item.sourceAlias,sourceName:item.sourceName,sourceColumnName:item.sourceColumnName}));return{wildcards,explicitColumns,unqualifiedWildcardWithMultipleSources}}collectWildcardMetadata(item,outputIndex,fromClause){if(!(item.value instanceof ColumnReference)||item.value.column.name!=="*"||!fromClause)return null;if(item.value.namespaces===null){let sources=fromClause.getSources();return sources.length!==1?"unqualifiedWildcardMultipleSources":{kind:"unqualified",outputIndex,sourceAlias:sources[0].getAliasName(),sourceName:this.getSourceName(sources[0])}}let namespace=item.value.getNamespace(),source=this.getUniqueSource(fromClause.getSources().filter(candidate=>this.getSourceMatchNames(candidate).includes(namespace)));return{kind:"qualified",outputIndex,sourceAlias:namespace,sourceName:source?this.getSourceName(source):null}}createUnresolved(outputName,reason,candidateWildcards,requiredBy){return{outputName,reason,candidateWildcards,requiredByClause:this.collectRequiredByClauses(requiredBy),requiredBy}}flattenReferences(references){return clauseOrder.flatMap(clause=>references[clause])}createRequiredBy(reference){return{clause:reference.clause,qualifiedName:reference.qualifiedName,namespace:reference.namespace,column:reference.column}}collectRequiredByClauses(requiredBy){let clauses=new Set(requiredBy.map(item=>item.clause));return clauseOrder.filter(clause=>clauses.has(clause))}getTargetMatchNames(target){return target.targetAlias?[target.targetAlias]:target.targetName?[target.targetName]:[]}getUniqueTarget(targets){return targets.length===1?targets[0]:null}getUniqueSource(sources){return sources.length===1?sources[0]:null}getSourceMatchNames(source){let names=new Set,aliasName=source.getAliasName();return aliasName&&names.add(aliasName),source.datasource instanceof TableSource&&(names.add(source.datasource.table.name),names.add(source.datasource.getSourceName())),[...names]}getSourceName(source){return source.datasource instanceof TableSource?source.datasource.getSourceName():null}collectLeadingCommonTables(query){return query instanceof SimpleSelectQuery?query.withClause?.tables??[]:query instanceof BinarySelectQuery?this.collectLeadingCommonTables(query.left):[]}mergeCommonTables(left,right){let merged=[...left];for(let table of right){let existingIndex=merged.findIndex(item=>item.getSourceAliasName()===table.getSourceAliasName());existingIndex===-1?merged.push(table):merged[existingIndex]=table}return merged}getObjectId(value){let existing=this.objectIds.get(value);if(existing!==void 0)return existing;let id=this.nextObjectId++;return this.objectIds.set(value,id),id}isSelectQuery(query){return!!query&&typeof query=="object"&&"__selectQueryType"in query&&query.__selectQueryType==="SelectQuery"}};var ParameterDetector=class{static extractParameterNames(query){return ParameterCollector.collect(query).map(p=>p.name.value)}static hasParameter(query,parameterName){return this.extractParameterNames(query).includes(parameterName)}static separateFilters(query,filter){let hardcodedParamNames=this.extractParameterNames(query),hardcodedParams={},dynamicFilters={};for(let[key,value]of Object.entries(filter))hardcodedParamNames.includes(key)?hardcodedParams[key]=value:dynamicFilters[key]=value;return{hardcodedParams,dynamicFilters}}};var FilterableItem=class{constructor(name,type,tableName){this.name=name;this.type=type;this.tableName=tableName}},FilterableItemCollector=class{constructor(tableColumnResolver,options){this.tableColumnResolver=tableColumnResolver,this.options={qualified:!1,upstream:!0,...options}}collect(query){let items=[],columnItems=this.collectColumns(query);items.push(...columnItems);let parameterItems=this.collectParameters(query);return items.push(...parameterItems),this.removeDuplicates(items)}collectColumns(query){let items=[];try{let columns=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:this.options.upstream}).collect(query);for(let column of columns){let tableName,realTableName;if(column.value&&typeof column.value.getNamespace=="function"){let namespace=column.value.getNamespace();namespace&&namespace.trim()!==""&&(tableName=namespace,this.options.qualified&&(realTableName=this.getRealTableName(query,namespace)))}tableName||(tableName=this.inferTableNameFromQuery(query),tableName&&this.options.qualified&&(realTableName=tableName));let columnName=column.name;this.options.qualified&&(realTableName||tableName)&&(columnName=`${realTableName||tableName}.${column.name}`),items.push(new FilterableItem(columnName,"column",tableName))}}catch(error){console.warn("Failed to collect columns with SelectableColumnCollector, using fallback:",error);try{let schemas=new SchemaCollector(this.tableColumnResolver,!0).collect(query);for(let schema of schemas)for(let columnName of schema.columns){let finalColumnName=columnName;this.options.qualified&&(finalColumnName=`${schema.name}.${columnName}`),items.push(new FilterableItem(finalColumnName,"column",schema.name))}}catch(fallbackError){console.warn("Failed to collect columns with both approaches:",error,fallbackError)}}return items}inferTableNameFromQuery(query){if(query instanceof SimpleSelectQuery&&query.fromClause&&query.fromClause.source){let datasource=query.fromClause.source.datasource;if(datasource&&typeof datasource.table=="object"){let table=datasource.table;if(table&&typeof table.name=="string")return table.name}}}getRealTableName(query,aliasOrName){try{let simpleQuery=query.type==="WITH"?query.toSimpleQuery():query;if(simpleQuery instanceof SimpleSelectQuery&&simpleQuery.fromClause){if(simpleQuery.fromClause.source?.datasource){let mainSource=simpleQuery.fromClause.source,realName=this.extractRealTableName(mainSource,aliasOrName);if(realName)return realName}let fromClause=simpleQuery.fromClause;if(fromClause.joinClauses&&Array.isArray(fromClause.joinClauses)){for(let joinClause of fromClause.joinClauses)if(joinClause.source?.datasource){let realName=this.extractRealTableName(joinClause.source,aliasOrName);if(realName)return realName}}}}catch(error){console.warn("Error resolving real table name:",error)}return aliasOrName}extractRealTableName(source,aliasOrName){try{let datasource=source.datasource;if(!datasource)return;let alias=source.alias||source.aliasExpression?.table?.name,realTableName=datasource.table?.name;if(alias===aliasOrName&&realTableName||!alias&&realTableName===aliasOrName)return realTableName}catch{}}collectParameters(query){let items=[];try{let parameterNames=ParameterDetector.extractParameterNames(query);for(let paramName of parameterNames)items.push(new FilterableItem(paramName,"parameter"))}catch(error){console.warn("Failed to collect parameters:",error)}return items}removeDuplicates(items){let seen=new Set,result=[];for(let item of items){let key=`${item.type}:${item.name}:${item.tableName||"none"}`;seen.has(key)||(seen.add(key),result.push(item))}return result.sort((a,b)=>{if(a.type!==b.type)return a.type==="column"?-1:1;if(a.type==="column"){let tableA=a.tableName||"",tableB=b.tableName||"";if(tableA!==tableB)return tableA.localeCompare(tableB)}return a.name.localeCompare(b.name)})}};var SqlSortInjector=class{constructor(tableColumnResolver){this.tableColumnResolver=tableColumnResolver}static removeOrderBy(query){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for ORDER BY removal");return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:null,windowClause:query.windowClause,limitClause:query.limitClause,offsetClause:query.offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}inject(query,sortConditions){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for sorting");let availableColumns=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query);for(let columnName of Object.keys(sortConditions))if(!availableColumns.find(item=>item.name===columnName))throw new Error(`Column or alias '${columnName}' not found in current query`);let newOrderByItems=[];for(let[columnName,condition]of Object.entries(sortConditions)){let columnEntry=availableColumns.find(item=>item.name===columnName);if(!columnEntry)continue;let columnRef=columnEntry.value;this.validateSortCondition(columnName,condition);let sortDirection;condition.desc?sortDirection="desc":sortDirection="asc";let nullsPosition=null;condition.nullsFirst?nullsPosition="first":condition.nullsLast&&(nullsPosition="last");let orderByItem=new OrderByItem(columnRef,sortDirection,nullsPosition);newOrderByItems.push(orderByItem)}let finalOrderByItems=[];query.orderByClause?finalOrderByItems=[...query.orderByClause.order,...newOrderByItems]:finalOrderByItems=newOrderByItems;let newOrderByClause=finalOrderByItems.length>0?new OrderByClause(finalOrderByItems):null;return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:newOrderByClause,windowClause:query.windowClause,limitClause:query.limitClause,offsetClause:query.offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}validateSortCondition(columnName,condition){if(condition.asc&&condition.desc)throw new Error(`Conflicting sort directions for column '${columnName}': both asc and desc specified`);if(condition.nullsFirst&&condition.nullsLast)throw new Error(`Conflicting nulls positions for column '${columnName}': both nullsFirst and nullsLast specified`);if(!condition.asc&&!condition.desc&&!condition.nullsFirst&&!condition.nullsLast)throw new Error(`Empty sort condition for column '${columnName}': at least one sort option must be specified`)}};var SqlPaginationInjector=class{inject(query,pagination){if(this.validatePaginationOptions(pagination),typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for pagination");if(query.limitClause||query.offsetClause)throw new Error("Query already contains LIMIT or OFFSET clause. Use removePagination() first if you want to override existing pagination.");let offset=(pagination.page-1)*pagination.pageSize,limitClause=new LimitClause(new ParameterExpression("paging_limit",pagination.pageSize)),offsetClause=new OffsetClause(new ParameterExpression("paging_offset",offset));return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:query.orderByClause,windowClause:query.windowClause,limitClause,offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}static removePagination(query){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for pagination removal");return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:query.orderByClause,windowClause:query.windowClause,limitClause:null,offsetClause:null,fetchClause:query.fetchClause,forClause:query.forClause})}validatePaginationOptions(pagination){if(!pagination)throw new Error("Pagination options are required");if(typeof pagination.page!="number"||pagination.page<1)throw new Error("Page number must be a positive integer (1 or greater)");if(typeof pagination.pageSize!="number"||pagination.pageSize<1)throw new Error("Page size must be a positive integer (1 or greater)");if(pagination.pageSize>1e3)throw new Error("Page size cannot exceed 1000 items")}};var SqlParameterBinder=class{constructor(options={}){this.options={requireAllParameters:!0,...options}}bind(query,parameterValues){let modifiedQuery=query,existingParams=ParameterDetector.extractParameterNames(modifiedQuery);if(this.options.requireAllParameters){let missingParams=existingParams.filter(paramName=>!(paramName in parameterValues)||parameterValues[paramName]===void 0);if(missingParams.length>0)throw new Error(`Missing values for required parameters: ${missingParams.join(", ")}`)}for(let[paramName,value]of Object.entries(parameterValues))if(existingParams.includes(paramName))try{ParameterHelper.set(modifiedQuery,paramName,value)}catch(error){throw new Error(`Failed to bind parameter '${paramName}': ${error instanceof Error?error.message:"Unknown error"}`)}return modifiedQuery}bindToSimpleQuery(query,parameterValues){return this.bind(query,parameterValues)}};var NAMESPACE_SEPARATOR="|",normalizeIdentifier=input=>{let value=input?.trim()??"";return value===""?"":value.toLowerCase()},normalizeColumnSetKey=columns=>columns.map(column=>normalizeIdentifier(column)).filter(Boolean).sort().join(NAMESPACE_SEPARATOR),buildSchemaMap=schemaInfo=>{let map=new Map;for(let table of schemaInfo){let normalizedName=normalizeIdentifier(table.name);if(!normalizedName)continue;let columnSet=new Set(table.columns.map(normalizeIdentifier).filter(Boolean)),uniqueSetKeys=new Set;for(let uniqueKey of table.uniqueKeys){let normalizedKey=normalizeColumnSetKey(uniqueKey);normalizedKey&&uniqueSetKeys.add(normalizedKey)}columnSet.size===0&&uniqueSetKeys.size===0||map.set(normalizedName,{columnSet,uniqueSetKeys})}return map},collectReferenceMetadata=query=>{let collector=new ColumnReferenceCollector,namespaceCounts=new Map,unqualifiedColumns=new Set;for(let ref of collector.collect(query)){let namespace=normalizeIdentifier(ref.getNamespace());if(namespace)namespaceCounts.set(namespace,(namespaceCounts.get(namespace)??0)+1);else{let column=normalizeIdentifier(ref.column.name);column&&unqualifiedColumns.add(column)}}let joinConditionCounts=new Map;if(query.fromClause?.joins)for(let join of query.fromClause.joins){let counts=new Map;if(join.condition&&join.condition instanceof JoinOnClause){let joinCollector=new ColumnReferenceCollector;for(let ref of joinCollector.collect(join.condition.condition)){let namespace=normalizeIdentifier(ref.getNamespace());namespace&&counts.set(namespace,(counts.get(namespace)??0)+1)}}joinConditionCounts.set(join,counts)}return{namespaceCounts,unqualifiedColumns,joinConditionCounts}},isLeftJoin=join=>join.joinType.value.toLowerCase().includes("left"),getJoinIdentifiers=join=>{let identifiers=new Set,alias=normalizeIdentifier(join.source.getAliasName());if(alias&&identifiers.add(alias),join.source.datasource instanceof TableSource){let rawName=join.source.datasource.getSourceName();rawName&&identifiers.add(normalizeIdentifier(rawName));let shortName=normalizeIdentifier(join.source.datasource.table.name);shortName&&identifiers.add(shortName)}return[...identifiers]},hasExternalReferences=(identifiers,metadata,join)=>{let local=metadata.joinConditionCounts.get(join)??new Map;for(let identifier of identifiers){let total=metadata.namespaceCounts.get(identifier)??0,localCount=local.get(identifier)??0;if(total-localCount>0)return!0}return!1},getJoinColumnInfo=(join,identifiers)=>{if(!(join.condition instanceof JoinOnClause))return null;let expression=join.condition.condition;if(!(expression instanceof BinaryExpression)||expression.operator.value.trim().toLowerCase()!=="=")return null;let resolveColumn=component=>component instanceof ColumnReference?component:null,leftRef=resolveColumn(expression.left),rightRef=resolveColumn(expression.right);if(!leftRef||!rightRef)return null;let normalizedLeftNamespace=normalizeIdentifier(leftRef.getNamespace()),normalizedRightNamespace=normalizeIdentifier(rightRef.getNamespace());return identifiers.has(normalizedLeftNamespace)?normalizeIdentifier(leftRef.column.name):identifiers.has(normalizedRightNamespace)?normalizeIdentifier(rightRef.column.name):null},shouldRemoveJoin=(join,schemaMap,metadata)=>{if(!isLeftJoin(join)||join.lateral||!(join.source.datasource instanceof TableSource))return!1;let candidates=[normalizeIdentifier(join.source.datasource.getSourceName()),normalizeIdentifier(join.source.datasource.table.name)].filter(Boolean),tableInfo;for(let candidate of candidates){let info=schemaMap.get(candidate);if(info){tableInfo=info;break}}if(!tableInfo)return!1;let identifiers=new Set(getJoinIdentifiers(join));if(identifiers.size===0||hasExternalReferences([...identifiers],metadata,join))return!1;let joinColumn=getJoinColumnInfo(join,identifiers);if(!joinColumn||metadata.unqualifiedColumns.has(joinColumn)||tableInfo.columnSet.size>0&&!tableInfo.columnSet.has(joinColumn))return!1;let uniqueKey=normalizeColumnSetKey([joinColumn]);return!!tableInfo.uniqueSetKeys.has(uniqueKey)},optimizeSimpleQuery=(query,schemaMap)=>{if(!query.fromClause?.joins?.length)return!1;let metadata=collectReferenceMetadata(query),retainedJoins=[],removed=!1;for(let join of query.fromClause.joins){if(shouldRemoveJoin(join,schemaMap,metadata)){removed=!0;continue}retainedJoins.push(join)}return query.fromClause.joins=retainedJoins.length>0?retainedJoins:null,removed},traverseSelectQuery=(query,schemaMap)=>{if(query instanceof SimpleSelectQuery)return optimizeSimpleQuery(query,schemaMap);if(query instanceof BinarySelectQuery){let leftChanged=traverseSelectQuery(query.left,schemaMap),rightChanged=traverseSelectQuery(query.right,schemaMap);return leftChanged||rightChanged}return!1},optimizeUnusedLeftJoinsOnce=(query,schemaMap)=>schemaMap.size===0?!1:traverseSelectQuery(query,schemaMap),optimizeUnusedLeftJoins=(query,schemaInfo)=>(optimizeUnusedLeftJoinsOnce(query,buildSchemaMap(schemaInfo)),query),optimizeUnusedLeftJoinsToFixedPoint=(query,schemaInfo)=>{let schemaMap=buildSchemaMap(schemaInfo),changed=!0;for(;changed;)changed=optimizeUnusedLeftJoinsOnce(query,schemaMap);return query},collectTableSourceNames=component=>{let collector=new CTETableReferenceCollector,names=new Set;for(let source of collector.collect(component)){let normalizedName=normalizeIdentifier(source.table.name);normalizedName&&names.add(normalizedName)}return names},isReferencedByOthers=(cteName,mainReferences,cteReferenceMap)=>{if(mainReferences.has(cteName))return!0;for(let[otherName,references]of cteReferenceMap)if(otherName!==cteName&&references.has(cteName))return!0;return!1},optimizeSimpleQueryCtes=query=>{let withClause=query.withClause;if(!withClause||withClause.recursive||withClause.tables.length===0)return!1;let mainReferences=collectTableSourceNames(query),cteReferenceMap=new Map;for(let table of withClause.tables){let normalizedName=normalizeIdentifier(table.aliasExpression.table.name);normalizedName&&cteReferenceMap.set(normalizedName,collectTableSourceNames(table.query))}let removableNames=[];for(let table of withClause.tables){let normalizedName=normalizeIdentifier(table.aliasExpression.table.name);if(!normalizedName)continue;let body=table.query;!(body instanceof SimpleSelectQuery)&&!(body instanceof BinarySelectQuery)||isReferencedByOthers(normalizedName,mainReferences,cteReferenceMap)||removableNames.push(normalizedName)}if(removableNames.length===0)return!1;for(let name of removableNames)query.removeCTE(name);return!0},optimizeCtesInSelectQuery=query=>{if(query instanceof SimpleSelectQuery)return optimizeSimpleQueryCtes(query);if(query instanceof BinarySelectQuery){let leftChanged=optimizeCtesInSelectQuery(query.left),rightChanged=optimizeCtesInSelectQuery(query.right);return leftChanged||rightChanged}return!1},optimizeUnusedCtesOnce=query=>optimizeCtesInSelectQuery(query),optimizeUnusedCtes=query=>(optimizeUnusedCtesOnce(query),query),optimizeUnusedCtesToFixedPoint=query=>{let changed=!0;for(;changed;)changed=optimizeUnusedCtesOnce(query);return query};var isBinaryOperator=(expression,operator)=>expression instanceof BinaryExpression&&expression.operator.value.trim().toLowerCase()===operator,unwrapSingleOuterParen=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},unwrapOptionalGuardParameter=expression=>{let candidate=unwrapSingleOuterParen(expression);for(;candidate instanceof CastExpression;)candidate=unwrapSingleOuterParen(candidate.input);if(candidate instanceof FunctionCall&&getFunctionCallName(candidate)==="cast"&&candidate.argument){let argument=unwrapSingleOuterParen(candidate.argument);if(isBinaryOperator(argument,"as"))return unwrapOptionalGuardParameter(argument.left)}return candidate},getFunctionCallName=expression=>{let name=expression.qualifiedName.name;return"value"in name?name.value.toLowerCase():name.name.toLowerCase()},collectTopLevelAndTerms=expression=>{let candidate=unwrapSingleOuterParen(expression);return isBinaryOperator(candidate,"and")?[...collectTopLevelAndTerms(candidate.left),...collectTopLevelAndTerms(candidate.right)]:[expression]},collectTopLevelOrTerms=expression=>{let candidate=unwrapSingleOuterParen(expression);return isBinaryOperator(candidate,"or")?[...collectTopLevelOrTerms(candidate.left),...collectTopLevelOrTerms(candidate.right)]:[expression]},isNullLiteral=expression=>expression instanceof LiteralValue&&expression.value===null||expression instanceof RawString&&expression.value.trim().toLowerCase()==="null",isTrueSentinel=expression=>{let candidate=unwrapSingleOuterParen(expression);return candidate instanceof LiteralValue?candidate.value===!0:isBinaryOperator(candidate,"=")?candidate.left instanceof LiteralValue&&candidate.right instanceof LiteralValue&&candidate.left.value===1&&candidate.right.value===1:!1},getGuardedParameterName=expression=>{let candidate=unwrapSingleOuterParen(expression);if(!isBinaryOperator(candidate,"is"))return null;let left=unwrapOptionalGuardParameter(candidate.left);return!(left instanceof ParameterExpression)||!isNullLiteral(candidate.right)?null:left.name.value},getUniqueParameterNames=expression=>new Set(ParameterCollector.collect(expression).map(parameter=>parameter.name.value)),isSupportedMeaningfulBranch=(expression,parameterName)=>{let candidate=unwrapSingleOuterParen(expression);if(candidate instanceof ParameterExpression)return!1;let parameterNames=getUniqueParameterNames(candidate);return parameterNames.size!==1||!parameterNames.has(parameterName)?!1:!(candidate instanceof LiteralValue||candidate instanceof RawString)},isExplicitPruningTarget=(pruningParameters,parameterName)=>Object.prototype.hasOwnProperty.call(pruningParameters,parameterName),isKnownAbsentTarget=(pruningParameters,parameterName)=>{if(!isExplicitPruningTarget(pruningParameters,parameterName))return!1;let parameterValue=pruningParameters[parameterName];return parameterValue==null},shouldPruneOptionalBranch=(expression,pruningParameters)=>{let branch=getSupportedOptionalConditionBranch(expression);return branch!==null&&isKnownAbsentTarget(pruningParameters,branch.parameterName)},rebuildAndCondition=terms=>{if(terms.length===0)return null;let condition=terms[0];for(let index=1;index<terms.length;index+=1)condition=new BinaryExpression(condition,"and",terms[index]);return condition},pruneSimpleQueryWhereClause=(query,pruningParameters)=>{if(!query.whereClause)return!1;let topLevelTerms=collectTopLevelAndTerms(query.whereClause.condition),retainedTerms=[],prunedAnyBranch=!1;for(let term of topLevelTerms){if(shouldPruneOptionalBranch(term,pruningParameters)){prunedAnyBranch=!0;continue}retainedTerms.push(term)}if(!prunedAnyBranch)return!1;let cleanedTerms=retainedTerms.filter(term=>!isTrueSentinel(term)),rebuiltCondition=rebuildAndCondition(cleanedTerms);return query.whereClause=rebuiltCondition?new WhereClause(rebuiltCondition):null,!0},isSelectQueryNode=value=>value instanceof SimpleSelectQuery||value instanceof BinarySelectQuery,traverseNestedSelectQueries=(root,pruningParameters)=>{let changed=!1,visited=new WeakSet,walk=value=>{if(!(!value||typeof value!="object")&&!visited.has(value)){if(visited.add(value),value!==root&&isSelectQueryNode(value)){changed=traverseSelectQuery2(value,pruningParameters)||changed;return}if(Array.isArray(value)){value.forEach(walk);return}for(let child of Object.values(value))walk(child)}};return walk(root),changed},traverseSelectQuery2=(query,pruningParameters)=>{if(query instanceof SimpleSelectQuery){let selfChanged=pruneSimpleQueryWhereClause(query,pruningParameters),nestedChanged=traverseNestedSelectQueries(query,pruningParameters);return selfChanged||nestedChanged}if(query instanceof BinarySelectQuery){let leftChanged=traverseSelectQuery2(query.left,pruningParameters),rightChanged=traverseSelectQuery2(query.right,pruningParameters);return leftChanged||rightChanged}return!1},getSupportedOptionalConditionBranch=expression=>{let orTerms=collectTopLevelOrTerms(expression);if(orTerms.length<2)return null;let guardTerms=orTerms.map(term=>({term,parameterName:getGuardedParameterName(term)})).filter(candidate=>candidate.parameterName!==null);if(guardTerms.length!==1)return null;let[{term:guardTerm,parameterName}]=guardTerms,meaningfulTerms=orTerms.filter(term=>term!==guardTerm);return meaningfulTerms.length===0||!meaningfulTerms.every(term=>isSupportedMeaningfulBranch(term,parameterName))?null:{parameterName,kind:"expression"}},collectSupportedBranchesFromSimpleQuery=(query,branches)=>{if(!query.whereClause)return;let topLevelTerms=collectTopLevelAndTerms(query.whereClause.condition);for(let term of topLevelTerms){let branch=getSupportedOptionalConditionBranch(term);branch&&branches.push({query,parameterName:branch.parameterName,expression:term,kind:branch.kind})}},collectSupportedBranchesFromSelectQuery=(query,branches)=>{if(query instanceof SimpleSelectQuery){collectSupportedBranchesFromSimpleQuery(query,branches),traverseNestedSelectQueriesForCollection(query,branches);return}query instanceof BinarySelectQuery&&(collectSupportedBranchesFromSelectQuery(query.left,branches),collectSupportedBranchesFromSelectQuery(query.right,branches))},traverseNestedSelectQueriesForCollection=(root,branches)=>{let visited=new WeakSet,walk=value=>{if(!(!value||typeof value!="object")&&!visited.has(value)){if(visited.add(value),value!==root&&isSelectQueryNode(value)){collectSupportedBranchesFromSelectQuery(value,branches);return}if(Array.isArray(value)){value.forEach(walk);return}for(let child of Object.values(value))walk(child)}};walk(root)},pruneOptionalConditionBranches=(query,pruningParameters)=>(Object.keys(pruningParameters).length===0||traverseSelectQuery2(query,pruningParameters),query),collectSupportedOptionalConditionBranches=query=>{let branches=[];return collectSupportedBranchesFromSelectQuery(query,branches),branches},collectSupportedOptionalConditionBranchSpans=sql=>{let parsed=SelectQueryParser.parse(sql),supportedBranches=collectSupportedOptionalConditionBranches(parsed);if(supportedBranches.length===0)return[];let candidates=collectOptionalConditionSpanCandidates(sql),remainingSupportedCounts=countSupportedBranchesByKey(supportedBranches);assertUnambiguousCandidateCounts(candidates,remainingSupportedCounts);let spans=[];for(let candidate of candidates){let key=getSupportedBranchKey(candidate),remainingCount=remainingSupportedCounts.get(key)??0;remainingCount<=0||(spans.push(candidate),remainingSupportedCounts.set(key,remainingCount-1))}return assertNoMissingSupportedBranches(remainingSupportedCounts),spans},getSupportedBranchKey=branch=>`${branch.kind}:${branch.parameterName}`,countSupportedBranchesByKey=branches=>{let counts=new Map;for(let branch of branches){let key=getSupportedBranchKey(branch);counts.set(key,(counts.get(key)??0)+1)}return counts},assertUnambiguousCandidateCounts=(candidates,supportedCounts)=>{let candidateCounts=countSupportedBranchesByKey(candidates);for(let[key,supportedCount]of supportedCounts){let candidateCount=candidateCounts.get(key)??0;if(candidateCount<supportedCount)throw new Error(`Could not locate source range for supported optional condition branch '${key}'.`);if(candidateCount>supportedCount)throw new Error(`Ambiguous source ranges for supported optional condition branch '${key}'.`)}},assertNoMissingSupportedBranches=supportedCounts=>{let missingKeys=[...supportedCounts.entries()].filter(([,count])=>count>0).map(([key])=>key);if(missingKeys.length>0)throw new Error(`Could not locate source ranges for supported optional condition branches: ${missingKeys.join(", ")}.`)},collectOptionalConditionSpanCandidates=sql=>{let lexemes=new SqlTokenizer(sql).readLexemes(),candidates=[],stack=[];for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];if(isOpenParen(lexeme)){stack.push(index);continue}if(!isCloseParen(lexeme))continue;let openParenIndex=stack.pop();if(openParenIndex===void 0)continue;let candidate=buildOptionalConditionSpanCandidate(sql,lexemes,openParenIndex,index);candidate&&candidates.push(candidate)}return candidates.sort((left,right)=>left.sourceRange.start-right.sourceRange.start)},buildOptionalConditionSpanCandidate=(sql,lexemes,openParenIndex,closeParenIndex)=>{let inside=lexemes.slice(openParenIndex+1,closeParenIndex),orTermRanges=splitTopLevelTermsByKeyword(inside,"or");if(orTermRanges.length<2)return null;let guardTerms=orTermRanges.map(range=>({range,parameterName:getGuardedParameterNameFromLexemes(inside.slice(range.start,range.end))})).filter(candidate=>candidate.parameterName!==null);if(guardTerms.length!==1)return null;let[{range:guardRange,parameterName}]=guardTerms,meaningfulTerms=orTermRanges.filter(range=>range!==guardRange);if(meaningfulTerms.length===0||!meaningfulTerms.every(range=>isSupportedMeaningfulBranchFromLexemes(inside.slice(range.start,range.end),parameterName)))return null;let expandedRange=expandWrappingParenRange(lexemes,openParenIndex,closeParenIndex),sourceStart=requiredPosition(lexemes[expandedRange.openParenIndex]).startPosition,sourceEnd=requiredPosition(lexemes[expandedRange.closeParenIndex]).endPosition,removalRange=getRemovalRange(sql,lexemes,expandedRange.openParenIndex,expandedRange.closeParenIndex);return{parameterName,kind:"expression",sourceRange:{start:sourceStart,end:sourceEnd,text:sql.slice(sourceStart,sourceEnd)},removalRange,openParenIndex:expandedRange.openParenIndex,closeParenIndex:expandedRange.closeParenIndex}},expandWrappingParenRange=(lexemes,openParenIndex,closeParenIndex)=>{let expandedOpenParenIndex=openParenIndex,expandedCloseParenIndex=closeParenIndex;for(;isOpenParen(lexemes[expandedOpenParenIndex-1])&&isCloseParen(lexemes[expandedCloseParenIndex+1]);)expandedOpenParenIndex-=1,expandedCloseParenIndex+=1;return{openParenIndex:expandedOpenParenIndex,closeParenIndex:expandedCloseParenIndex}},splitTopLevelTermsByKeyword=(lexemes,keyword)=>{let ranges=[],depth=0,start=0;for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];if(isOpenParen(lexeme)){depth+=1;continue}if(isCloseParen(lexeme)){depth-=1;continue}depth===0&&isKeyword(lexeme,keyword)&&(ranges.push({start,end:index}),start=index+1)}return ranges.push({start,end:lexemes.length}),ranges},getGuardedParameterNameFromLexemes=lexemes=>{let compact=lexemes.filter(lexeme=>!isWrappingParen(lexeme)),isIndexKeyword=(index,keyword)=>{let lexeme=compact[index];return lexeme!==void 0&&isKeyword(lexeme,keyword)};if(compact.length===3)return!isParameter(compact[0])||!isIndexKeyword(1,"is")||!isIndexKeyword(2,"null")?null:normalizeParameterName(compact[0].value);if(compact.length===5&&isParameter(compact[0])&&compact[1]?.value==="::"&&isIndexKeyword(3,"is")&&isIndexKeyword(4,"null"))return normalizeParameterName(compact[0].value);if(compact.length>=6&&isIndexKeyword(0,"cast")&&isParameter(compact[1])&&isIndexKeyword(2,"as")){let isIndex=compact.findIndex((lexeme,index)=>index>2&&isKeyword(lexeme,"is"));if(isIndex>=0&&isIndexKeyword(isIndex+1,"null"))return normalizeParameterName(compact[1].value)}return null},isSupportedMeaningfulBranchFromLexemes=(lexemes,parameterName)=>{try{let parsed=ValueParser.parseFromLexeme(lexemes,0);return parsed.newIndex!==lexemes.length?!1:isSupportedMeaningfulBranch(parsed.value,parameterName)}catch{return!1}},getRemovalRange=(sql,lexemes,openParenIndex,closeParenIndex)=>{let previous=lexemes[openParenIndex-1],next=lexemes[closeParenIndex+1],start=requiredPosition(lexemes[openParenIndex]).startPosition,end=requiredPosition(lexemes[closeParenIndex]).endPosition;return previous&&isKeyword(previous,"and")?start=requiredPosition(previous).startPosition:next&&isKeyword(next,"and")?end=requiredPosition(next).endPosition:previous&&isKeyword(previous,"where")&&(start=requiredPosition(previous).startPosition),{start,end,text:sql.slice(start,end)}},isParameter=lexeme=>(lexeme.type&256)!==0,isOpenParen=lexeme=>(lexeme.type&4)!==0,isCloseParen=lexeme=>(lexeme.type&8)!==0,isKeyword=(lexeme,keyword)=>lexeme.value.toLowerCase()===keyword,isWrappingParen=lexeme=>isOpenParen(lexeme)||isCloseParen(lexeme),normalizeParameterName=value=>value.startsWith("${")&&value.endsWith("}")?value.slice(2,-1):value.replace(/^[:@$]/,""),requiredPosition=lexeme=>{if(!lexeme.position)throw new Error(`Lexeme '${lexeme.value}' is missing source position metadata.`);return lexeme.position};var DynamicQueryBuilder=class{constructor(resolverOrOptions){typeof resolverOrOptions=="function"?this.tableColumnResolver=resolverOrOptions:resolverOrOptions&&(this.tableColumnResolver=resolverOrOptions.tableColumnResolver,this.defaultSchemaInfo=resolverOrOptions.schemaInfo)}buildQuery(sqlContent,options={}){let removedOptions=options;if("serialize"in removedOptions||"jsonb"in removedOptions)throw new Error("DynamicQueryBuilder SQL-result JSON shaping has been removed. Keep SQL results as rows and use generated AOT mappers so the executed SQL remains debuggable.");let parsedQuery;try{parsedQuery=SelectQueryParser.parse(sqlContent)}catch(error){throw new Error(`Failed to parse SQL: ${error instanceof Error?error.message:"Unknown error"}`)}let modifiedQuery=parsedQuery;if(options.filter&&Object.keys(options.filter).length>0){let{hardcodedParams,dynamicFilters}=ParameterDetector.separateFilters(modifiedQuery,options.filter);if(Object.keys(hardcodedParams).length>0&&(modifiedQuery=new SqlParameterBinder({requireAllParameters:!1}).bind(modifiedQuery,hardcodedParams)),Object.keys(dynamicFilters).length>0)throw new Error("DynamicQueryBuilder no longer injects runtime filter predicates. Use `ashiba query optional add` to author optional filters, `ashiba query optional refresh` to refresh them, and `optionalConditionParameters` at runtime for pruning only.")}if(options.sort&&Object.keys(options.sort).length>0){let sortInjector=new SqlSortInjector(this.tableColumnResolver),simpleQuery=QueryBuilder.buildSimpleQuery(modifiedQuery);modifiedQuery=sortInjector.inject(simpleQuery,options.sort)}if(options.paging){let{page=1,pageSize}=options.paging;if(pageSize!==void 0){let paginationInjector=new SqlPaginationInjector,paginationOptions={page,pageSize},simpleQuery=QueryBuilder.buildSimpleQuery(modifiedQuery);modifiedQuery=paginationInjector.inject(simpleQuery,paginationOptions)}}modifiedQuery=this.applyColumnFilters(modifiedQuery,options);let optionalConditionParameters=this.resolveOptionalConditionPruningParameters(options);Object.keys(optionalConditionParameters).length>0&&(modifiedQuery=pruneOptionalConditionBranches(modifiedQuery,optionalConditionParameters));let effectiveSchemaInfo=options.schemaInfo??this.defaultSchemaInfo;return options.removeUnusedLeftJoins&&effectiveSchemaInfo?.length&&(modifiedQuery=optimizeUnusedLeftJoinsToFixedPoint(modifiedQuery,effectiveSchemaInfo)),options.removeUnusedCtes&&(modifiedQuery=optimizeUnusedCtesToFixedPoint(modifiedQuery)),modifiedQuery}resolveOptionalConditionPruningParameters(options){if(options.optionalConditionParameters)return options.optionalConditionParameters;if(!options.optionalConditionParameterStates)return{};let legacyParameters={};for(let[parameterName,state]of Object.entries(options.optionalConditionParameterStates))legacyParameters[parameterName]=state==="absent"?null:"__RAWSQL_OPTIONAL_CONDITION_PRESENT__";return legacyParameters}applyColumnFilters(query,options){let hasIncludeFilters=Array.isArray(options.includeColumns)&&options.includeColumns.length>0,hasExcludeFilters=Array.isArray(options.excludeColumns)&&options.excludeColumns.length>0;if(!hasIncludeFilters&&!hasExcludeFilters)return query;if(hasIncludeFilters&&hasExcludeFilters)throw new Error("includeColumns and excludeColumns cannot be used together.");let simpleQuery=QueryBuilder.buildSimpleQuery(query),metadata=simpleQuery.selectClause.items.map(item=>{let name=this.getSelectItemName(item);return{item,normalized:name?this.normalizeColumnIdentifier(name):null}}),availableColumns=new Set(metadata.map(entry=>entry.normalized).filter(name=>name!==null)),includeFilters=hasIncludeFilters?this.normalizeColumnList(options.includeColumns):null,excludeFilters=hasExcludeFilters?this.normalizeColumnList(options.excludeColumns):null,includeSet=includeFilters?new Set(includeFilters.map(entry=>entry.normalized)):null,excludeSet=excludeFilters?new Set(excludeFilters.map(entry=>entry.normalized)):null;if(includeFilters){let missing=includeFilters.filter(entry=>!availableColumns.has(entry.normalized));if(missing.length>0)throw new Error(`Column${missing.length===1?"":"s"} not found in SELECT clause: ${missing.map(entry=>`'${entry.original}'`).join(", ")}.`)}if(excludeFilters){let missing=excludeFilters.filter(entry=>!availableColumns.has(entry.normalized));if(missing.length>0)throw new Error(`Column${missing.length===1?"":"s"} not found in SELECT clause: ${missing.map(entry=>`'${entry.original}'`).join(", ")}.`)}let filteredItems=metadata.filter(entry=>entry.normalized?includeSet?includeSet.has(entry.normalized):excludeSet?!excludeSet.has(entry.normalized):!0:!0).map(entry=>entry.item);if(filteredItems.length===0)throw new Error("Column filtering removed every SELECT item.");return simpleQuery.selectClause.items=filteredItems,simpleQuery}normalizeColumnList(columns){return columns.map(column=>{if(typeof column!="string")throw new Error("Column filters must be strings.");let trimmed=column.trim();if(trimmed==="")throw new Error("Column filters must not be empty.");return{normalized:this.normalizeColumnIdentifier(trimmed),original:trimmed}})}normalizeColumnIdentifier(value){return value.trim().toLowerCase()}getSelectItemName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}buildFilteredQuery(sqlContent,filter){return this.buildQuery(sqlContent,{filter})}buildSortedQuery(sqlContent,sort){return this.buildQuery(sqlContent,{sort})}buildPaginatedQuery(sqlContent,paging){return this.buildQuery(sqlContent,{paging})}validateSql(sqlContent){try{return SelectQueryParser.parse(sqlContent),!0}catch(error){throw new Error(`Invalid SQL: ${error instanceof Error?error.message:"Unknown error"}`)}}};var formatter=null,formatSqlComponent=component=>(formatter??=new SqlFormatter({exportComment:!0}),formatter.format(component).formattedSql);var SUPPORTED_SCALAR_OPERATORS=new Set(["=","<>","<","<=",">",">=","like","ilike"]),normalizeIdentifier2=value=>value.trim().toLowerCase(),normalizeSql=value=>value.replace(/\s+/g," ").trim().toLowerCase(),normalizeRewriteTokenType=lexeme=>(lexeme.type&128)!==0?128:(lexeme.type&64)!==0?64:lexeme.type,normalizeRewriteTokenValue=lexeme=>(lexeme.type&128)!==0?lexeme.value.toLowerCase():lexeme.value,tokenizeForRewritePlan=sql=>new SqlTokenizer(sql).tokenize().map(lexeme=>({type:normalizeRewriteTokenType(lexeme),value:normalizeRewriteTokenValue(lexeme)})),tokenSequencesEqual=(left,right)=>left.length!==right.length?!1:left.every((token,index)=>{let other=right[index];return other!==void 0&&token.type===other.type&&token.value===other.value}),collectCommentFragments=sql=>new SqlTokenizer(sql).tokenize().flatMap(lexeme=>lexeme.positionedComments?lexeme.positionedComments.flatMap(positioned=>positioned.comments):lexeme.comments?[...lexeme.comments]:[]),commentsPreservedInOrder=(before,after)=>{let cursor=0;for(let comment of before){let foundAt=after.indexOf(comment,cursor);if(foundAt<0)return!1;cursor=foundAt+1}return!0},countCommandToken=(tokens,value)=>tokens.filter(token=>token.type===128&&token.value===value).length,applyRewriteEdits=(sql,edits)=>[...edits].sort((left,right)=>right.start-left.start).reduce((current,edit)=>current.slice(0,edit.start)+edit.after+current.slice(edit.end),sql),getStatementEndPosition=sql=>{let end=sql.length;for(;end>0&&/\s/.test(sql[end-1]);)end--;if(end>0&&sql[end-1]===";")for(end--;end>0&&/\s/.test(sql[end-1]);)end--;return end},clauseBoundaryCommands=new Set(["group by","having","order by","limit","offset","fetch","for"]),isClauseBoundary=lexeme=>(lexeme.type&128)!==0&&clauseBoundaryCommands.has(lexeme.value.toLowerCase()),findMinimalWhereInsertPosition=sql=>{let lexemes=new SqlTokenizer(sql).tokenize(),statementEnd=getStatementEndPosition(sql),topLevelLexemes=[],depth=0;for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];(lexeme.type&8)!==0&&(depth=Math.max(0,depth-1)),depth===0&&topLevelLexemes.push({lexeme,index}),(lexeme.type&4)!==0&&(depth+=1)}let where=topLevelLexemes.find(entry=>(entry.lexeme.type&128)!==0&&entry.lexeme.value.toLowerCase()==="where");return where?{position:topLevelLexemes.filter(entry=>entry.index>where.index).map(entry=>entry.lexeme).find(isClauseBoundary)?.position?.startPosition??statementEnd,hasWhere:!0}:{position:topLevelLexemes.map(entry=>entry.lexeme).find(isClauseBoundary)?.position?.startPosition??statementEnd,hasWhere:!1}},findMatchingParenEnd=(sql,start)=>{let depth=0,quote=null;for(let index=start;index<sql.length;index++){let char=sql[index];if(quote){if(char===quote){if(quote==="'"&&sql[index+1]==="'"){index++;continue}quote=null}continue}if(char==="'"||char==='"'){quote=char;continue}if(char==="("&&depth++,char===")"&&(depth--,depth===0))return index+1}return-1},findOptionalBranchSpans=(sql,parameterName)=>{let spans=[],parameterNeedle=`:${parameterName.toLowerCase()}`,lowerSql=sql.toLowerCase();for(let index=0;index<sql.length;index++){if(sql[index]!=="(")continue;let end=findMatchingParenEnd(sql,index);if(end<0)break;let text=sql.slice(index,end),normalized=lowerSql.slice(index,end);normalized.includes(parameterNeedle)&&normalized.includes(" is null")&&normalized.includes(" or ")&&spans.push({start:index,end,text}),index=end-1}return spans},findBooleanOperatorBefore=(sql,start)=>{let prefix=sql.slice(0,start),match=/(\s+)(and|or)(\s*)$/i.exec(prefix);return!match||match.index===void 0?null:{start:match.index,end:start,value:match[2].toLowerCase()}},findBooleanOperatorAfter=(sql,end)=>{let suffix=sql.slice(end),match=/^(\s*)(and|or)(\s+)/i.exec(suffix);return match?{start:end,end:end+match[0].length,value:match[2].toLowerCase()}:null},findWhereBefore=(sql,position)=>{let lexemes=new SqlTokenizer(sql).tokenize(),found=null;for(let lexeme of lexemes){if((lexeme.position?.startPosition??0)>=position)break;(lexeme.type&128)!==0&&lexeme.value.toLowerCase()==="where"&&(found=lexeme)}return found?.position?{start:found.position.startPosition,end:found.position.endPosition}:null},findSourceColumnReferenceText=(sql,reference)=>{let namespace=normalizeIdentifier2(reference.getNamespace()),column=normalizeIdentifier2(reference.column.name),lexemes=new SqlTokenizer(sql).tokenize();for(let index=0;index<lexemes.length-2;index++){let first=lexemes[index],dot=lexemes[index+1],last=lexemes[index+2];if(!((first.type&64)===0||dot.value!=="."||(last.type&64)===0)&&!(normalizeIdentifier2(first.value)!==namespace||normalizeIdentifier2(last.value)!==column)&&!(!first.position||!last.position))return sql.slice(first.position.startPosition,last.position.endPosition)}return normalizeColumnReferenceText(reference)},normalizeColumnReferenceKey=reference=>`${normalizeIdentifier2(reference.getNamespace())}.${normalizeIdentifier2(reference.column.name)}`,normalizeColumnReferenceText=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},normalizeScalarOperator=value=>{if(!value)return"=";let normalized=value.trim().toLowerCase();if(normalized==="!=")return"<>";if(SUPPORTED_SCALAR_OPERATORS.has(normalized))return normalized;throw new Error(`Unsupported SSSQL operator '${value}'.`)},isExplicitEqualityScaffoldValue=value=>{if(value==null)return!0;if(Array.isArray(value))return!1;if(typeof value!="object")return!0;let entries=Object.entries(value).filter(([,entry])=>entry!==void 0);return entries.length===1&&entries[0]?.[0]==="="},parseQualifiedFilterName=filterName=>{let segments=filterName.split(".");if(segments.length!==2)return null;let[table,column]=segments.map(segment=>segment.trim());return!table||!column?null:{table,column}},makeParameterName=filterName=>filterName.trim().replace(/\./g,"_").replace(/[^a-zA-Z0-9_]/g,"_"),unwrapParens=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator2=(expression,operator)=>expression instanceof BinaryExpression&&expression.operator.value.trim().toLowerCase()===operator,collectTopLevelAndTerms2=expression=>{let candidate=unwrapParens(expression);return isBinaryOperator2(candidate,"and")?[...collectTopLevelAndTerms2(candidate.left),...collectTopLevelAndTerms2(candidate.right)]:[expression]},collectTopLevelOrTerms2=expression=>{let candidate=unwrapParens(expression);return isBinaryOperator2(candidate,"or")?[...collectTopLevelOrTerms2(candidate.left),...collectTopLevelOrTerms2(candidate.right)]:[expression]},getGuardedParameterName2=expression=>{let candidate=unwrapParens(expression);if(!isBinaryOperator2(candidate,"is"))return null;let left=unwrapOptionalGuardParameter2(candidate.left);if(!(left instanceof ParameterExpression))return null;let right=unwrapParens(candidate.right);return right instanceof LiteralValue&&right.value===null||right instanceof RawString&&right.value.trim().toLowerCase()==="null"?left.name.value:null},unwrapOptionalGuardParameter2=expression=>{let candidate=unwrapParens(expression);for(;candidate instanceof CastExpression;)candidate=unwrapParens(candidate.input);if(candidate instanceof FunctionCall&&getFunctionCallName2(candidate)==="cast"&&candidate.argument){let argument=unwrapParens(candidate.argument);if(isBinaryOperator2(argument,"as"))return unwrapOptionalGuardParameter2(argument.left)}return candidate},getFunctionCallName2=expression=>{let name=expression.qualifiedName.name;return"value"in name?name.value.toLowerCase():name.name.toLowerCase()},buildOptionalScalarBranch=(column,parameterName,operator)=>{let guard=new BinaryExpression(new ParameterExpression(parameterName),"is",new LiteralValue(null)),predicate=new BinaryExpression(new ColumnReference(column.getNamespace()||null,column.column.name),operator,new ParameterExpression(parameterName));return new ParenExpression(new BinaryExpression(guard,"or",predicate))},buildOptionalExistsBranch=(parameterName,subquery,kind)=>{let guard=new BinaryExpression(new ParameterExpression(parameterName),"is",new LiteralValue(null)),existsExpression=new UnaryExpression("exists",new InlineQuery(subquery)),predicate=kind==="exists"?existsExpression:new UnaryExpression("not",existsExpression);return new ParenExpression(new BinaryExpression(guard,"or",predicate))},rebuildWhereWithoutTerm=(query,termToRemove)=>{if(!query.whereClause)return;let terms=collectTopLevelAndTerms2(query.whereClause.condition).filter(term=>term!==termToRemove);if(terms.length===0){query.whereClause=null;return}let rebuilt=terms[0];for(let index=1;index<terms.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",terms[index]);query.whereClause=new WhereClause(rebuilt)},enforceSubqueryConstraints=sql=>{if(!sql.trim())throw new Error("SSSQL EXISTS/NOT EXISTS scaffold query must not be empty.");if(sql.includes(";"))throw new Error("SSSQL EXISTS/NOT EXISTS scaffold query must not contain semicolons or multiple statements.");if(/\blateral\b/i.test(sql))throw new Error("LATERAL is not supported in SSSQL EXISTS/NOT EXISTS scaffold.")},substituteAnchorPlaceholders=(sql,formattedColumns)=>{let usedIndexes=new Set,replaced=sql.replace(/\$c(\d+)/g,(_,indexDigits)=>{let index=Number(indexDigits);if(!Number.isInteger(index))throw new Error(`Invalid placeholder '$c${indexDigits}' in SSSQL scaffold query.`);if(index<0||index>=formattedColumns.length)throw new Error(`Placeholder '$c${index}' references a missing SSSQL scaffold anchor column.`);return usedIndexes.add(index),formattedColumns[index]});if(formattedColumns.length===0)return replaced;for(let index=0;index<formattedColumns.length;index+=1)if(!usedIndexes.has(index))throw new Error(`Missing placeholder '$c${index}' for SSSQL scaffold anchor column.`);return replaced},getScalarBranchDetails=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]);if(!(predicate instanceof BinaryExpression))return null;let left=unwrapParens(predicate.left),right=unwrapParens(predicate.right);if(left instanceof ColumnReference&&right instanceof ParameterExpression&&right.name.value===parameterName)try{return{operator:normalizeScalarOperator(predicate.operator.value),target:normalizeColumnReferenceText(left),column:left}}catch{return null}if(right instanceof ColumnReference&&left instanceof ParameterExpression&&left.name.value===parameterName)try{return{operator:normalizeScalarOperator(predicate.operator.value),target:normalizeColumnReferenceText(right),column:right}}catch{return null}return null},hasSelectQuery=value=>typeof value=="object"&&value!==null&&"selectQuery"in value,collectColumnReferencesDeep=value=>{let references=[],visited=new WeakSet,walk=candidate=>{if(!(!candidate||typeof candidate!="object")){if(candidate instanceof ColumnReference){references.push(candidate);return}if(!visited.has(candidate)){if(visited.add(candidate),Array.isArray(candidate)){for(let item of candidate)walk(item);return}for(let child of Object.values(candidate))walk(child)}}};return walk(value),references},getExistsBranchKind=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]),isInlineQueryValue=value=>value instanceof InlineQuery||hasSelectQuery(value);if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="exists")return isInlineQueryValue(unwrapParens(predicate.expression))?"exists":null;if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not exists")return isInlineQueryValue(unwrapParens(predicate.expression))?"not-exists":null;if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not"&&unwrapParens(predicate.expression)instanceof UnaryExpression){let nested=unwrapParens(predicate.expression);if(nested.operator.value.trim().toLowerCase()==="exists"&&isInlineQueryValue(unwrapParens(nested.expression)))return"not-exists"}return null},getExistsPredicateDetails=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]),isInlineQueryValue=value=>value instanceof InlineQuery||hasSelectQuery(value);if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="exists"){let candidate=unwrapParens(predicate.expression);return isInlineQueryValue(candidate)?{kind:"exists",subquery:candidate.selectQuery}:null}if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not exists"){let candidate=unwrapParens(predicate.expression);return isInlineQueryValue(candidate)?{kind:"not-exists",subquery:candidate.selectQuery}:null}if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not"&&unwrapParens(predicate.expression)instanceof UnaryExpression){let nested=unwrapParens(predicate.expression),candidate=unwrapParens(nested.expression);if(nested.operator.value.trim().toLowerCase()==="exists"&&isInlineQueryValue(candidate))return{kind:"not-exists",subquery:candidate.selectQuery}}return null},getBranchInfo=branch=>{let scalar=getScalarBranchDetails(branch.expression,branch.parameterName);if(scalar)return{parameterName:branch.parameterName,kind:"scalar",operator:scalar.operator,target:scalar.target,query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)};let existsKind=getExistsBranchKind(branch.expression,branch.parameterName);return existsKind?{parameterName:branch.parameterName,kind:existsKind,query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)}:{parameterName:branch.parameterName,kind:"expression",query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)}},isEquivalentScalarBranch=(branch,query,parameterName,operator,targetColumnText)=>branch.query===query&&branch.kind==="scalar"&&branch.parameterName===parameterName&&branch.operator===operator&&branch.target!==void 0&&normalizeIdentifier2(branch.target)===normalizeIdentifier2(targetColumnText),SSSQLFilterBuilder=class{constructor(tableColumnResolver){this.tableColumnResolver=tableColumnResolver;this.finder=new UpstreamSelectQueryFinder(this.tableColumnResolver)}list(query){let parsed=this.parseQuery(query);return collectSupportedOptionalConditionBranches(parsed).map(getBranchInfo)}planScaffold(query,filters){if(typeof query=="string"){let entries=Object.entries(filters);if(entries.length===1){let[filterName,filterValue]=entries[0];if(isExplicitEqualityScaffoldValue(filterValue))try{return this.planScalarInsert(query,{target:filterName,parameterName:makeParameterName(filterName),operator:"="})}catch{}}}return this.planRewrite(query,parsed=>this.scaffold(parsed,filters))}dryRunScaffold(query,filters){return this.planScaffold(query,filters)}planScaffoldBranch(query,spec){if(typeof query=="string"&&(spec.kind==="exists"||spec.kind==="not-exists"))try{return this.planExistsInsert(query,spec)}catch{}if(typeof query=="string"&&spec.kind!=="exists"&&spec.kind!=="not-exists")try{return this.planScalarInsert(query,spec)}catch{}return this.planRewrite(query,parsed=>this.scaffoldBranch(parsed,spec))}dryRunScaffoldBranch(query,spec){return this.planScaffoldBranch(query,spec)}planRefresh(query,filters){if(typeof query=="string")try{let parsed=SelectQueryParser.parse(query);if(!this.refreshParsed(parsed,filters).changed)return this.buildPlanFromEdits(query,[],[],[])}catch{}return this.planRewrite(query,parsed=>this.refresh(parsed,filters))}dryRunRefresh(query,filters){return this.planRefresh(query,filters)}planRemove(query,spec){if(typeof query=="string")try{return this.planBranchRemoval(query,spec)}catch{}return this.planRewrite(query,parsed=>this.remove(parsed,spec))}dryRunRemove(query,spec){return this.planRemove(query,spec)}planRemoveAll(query){return this.planRewrite(query,parsed=>this.removeAll(parsed))}dryRunRemoveAll(query){return this.planRemoveAll(query)}scaffold(query,filters){let parsed=this.parseQuery(query);for(let[filterName,filterValue]of Object.entries(filters)){if(!isExplicitEqualityScaffoldValue(filterValue))throw new Error(`SSSQL scaffold only supports equality filters in v1. Use structured scaffold or refresh for pre-authored branches: '${filterName}'.`);this.scaffoldBranch(parsed,{target:filterName,parameterName:makeParameterName(filterName),operator:"="})}return parsed}scaffoldBranch(query,spec){let parsed=this.parseQuery(query);return spec.kind==="exists"||spec.kind==="not-exists"?(this.scaffoldExistsBranch(parsed,spec),parsed):(this.scaffoldScalarBranch(parsed,spec),parsed)}refresh(query,filters){let parsed=this.parseQuery(query);return this.refreshParsed(parsed,filters),parsed}refreshParsed(parsed,filters){let changed=!1;for(let[filterName,filterValue]of Object.entries(filters)){let parameterName=filterName,target=null,matches=collectSupportedOptionalConditionBranches(parsed).filter(branch=>branch.parameterName===parameterName);if(matches.length===0&&(target=this.resolveTarget(parsed,filterName),parameterName=target.parameterName,matches=collectSupportedOptionalConditionBranches(parsed).filter(branch=>branch.parameterName===parameterName)),matches.length===0){if(target||(target=this.resolveTarget(parsed,filterName),parameterName=target.parameterName),!isExplicitEqualityScaffoldValue(filterValue))throw new Error(`No existing SSSQL branch was found for '${filterName}', and v1 scaffold only supports equality filters.`);this.scaffoldScalarBranch(parsed,{target:filterName,parameterName:target.parameterName,operator:"="}),changed=!0;continue}if(matches.length>1)throw new Error(`Multiple SSSQL branches matched parameter ':${parameterName}'. Refresh is ambiguous.`);let[match]=matches;if(!match)continue;let scalarDetails=getScalarBranchDetails(match.expression,match.parameterName);if(scalarDetails&&this.isNullableBranchColumn(match.query,scalarDetails.column))continue;let correlatedPlan=this.buildCorrelatedRefreshPlan(parsed,match);if(correlatedPlan){if(correlatedPlan.target.query===match.query)continue;this.rebaseMovedBranchByAlias(match.expression,correlatedPlan.sourceAlias,correlatedPlan.target.column),rebuildWhereWithoutTerm(match.query,match.expression),correlatedPlan.target.query.appendWhere(match.expression),changed=!0;continue}let scalarPlan=scalarDetails?this.buildScalarRefreshPlan(parsed,match,scalarDetails):null;if(scalarPlan){if(scalarPlan.query===match.query)continue;this.rebaseMovedBranch(match.expression,match.query,scalarPlan.column),rebuildWhereWithoutTerm(match.query,match.expression),scalarPlan.query.appendWhere(match.expression),changed=!0;continue}!target&&(target=this.tryResolveTarget(parsed,filterName),!target)||match.query!==target.query&&(this.rebaseMovedBranch(match.expression,match.query,target.column),rebuildWhereWithoutTerm(match.query,match.expression),target.query.appendWhere(match.expression),changed=!0)}return{query:parsed,changed}}remove(query,spec){let parsed=this.parseQuery(query),matches=this.findMatchingBranchInfos(parsed,spec);if(matches.length===0)return parsed;if(matches.length>1)throw new Error(`Multiple SSSQL branches matched parameter ':${spec.parameterName}'. Remove is ambiguous.`);let[match]=matches;return match&&rebuildWhereWithoutTerm(match.query,match.expression),parsed}removeAll(query){let parsed=this.parseQuery(query),matches=this.list(parsed);for(let match of matches)rebuildWhereWithoutTerm(match.query,match.expression);return parsed}parseQuery(query){return typeof query=="string"?SelectQueryParser.parse(query):query}planScalarInsert(sourceSql,spec){let parsed=SelectQueryParser.parse(sourceSql),target=this.resolveTarget(parsed,spec.target);if(target.query!==parsed)return this.planRewrite(sourceSql,query=>this.scaffoldBranch(query,spec));let parameterName=spec.parameterName?.trim()||target.parameterName,operator=normalizeScalarOperator(spec.operator),targetColumnText=findSourceColumnReferenceText(sourceSql,target.column),branchSql=`(:${parameterName} is null or ${targetColumnText} ${operator} :${parameterName})`,normalizedBranch=normalizeSql(branchSql);return this.list(parsed).find(existing=>existing.query===target.query&&normalizeSql(existing.sql)===normalizedBranch||isEquivalentScalarBranch(existing,target.query,parameterName,operator,targetColumnText))?this.buildPlanFromEdits(sourceSql,[],[],[]):this.buildMinimalInsertPlan(sourceSql,branchSql,{branchKind:"scalar",parameterName,column:targetColumnText})}planExistsInsert(sourceSql,spec){let parameterName=spec.parameterName.trim();if(!parameterName)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires parameterName.");if(spec.anchorColumns.length===0)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires at least one anchorColumn.");let parsed=SelectQueryParser.parse(sourceSql),anchorTargets=spec.anchorColumns.map(anchorColumn=>this.resolveTarget(parsed,anchorColumn)),targetQueries=[...new Set(anchorTargets.map(target=>target.query))];if(targetQueries.length!==1)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold anchor columns must resolve within one query scope.");let targetQuery=targetQueries[0];if(targetQuery!==parsed)return this.planRewrite(sourceSql,query=>this.scaffoldBranch(query,spec));let sourceColumns=anchorTargets.map(target=>findSourceColumnReferenceText(sourceSql,target.column)),substitutedSql=substituteAnchorPlaceholders(spec.query,sourceColumns).trim();enforceSubqueryConstraints(substitutedSql);let subquery=SelectQueryParser.parse(substitutedSql),parameterNames=new Set(ParameterCollector.collect(subquery).map(parameter=>parameter.name.value));if(parameterNames.size!==1||!parameterNames.has(parameterName))throw new Error(`SSSQL ${spec.kind.toUpperCase()} scaffold query must reference only parameter ':${parameterName}'.`);let branchSql=`(:${parameterName} is null or ${spec.kind==="not-exists"?"not exists":"exists"} (${substitutedSql}))`;return this.list(parsed).find(existing=>existing.query===targetQuery&&normalizeSql(existing.sql)===normalizeSql(branchSql))?this.buildPlanFromEdits(sourceSql,[],[],[]):this.buildMinimalInsertPlan(sourceSql,branchSql,{branchKind:spec.kind,parameterName,column:sourceColumns.join(", ")})}buildMinimalInsertPlan(sourceSql,branchSql,target){let insertPosition=findMinimalWhereInsertPosition(sourceSql),prefix=`${insertPosition.position===0||!/\s/.test(sourceSql[insertPosition.position-1])?" ":""}${insertPosition.hasWhere?"and":"where"} `,suffix=insertPosition.position<getStatementEndPosition(sourceSql)?" ":"",branchLabel=target.branchKind==="scalar"?"scalar":target.branchKind,edit={start:insertPosition.position,end:insertPosition.position,before:"",after:`${prefix}${branchSql}${suffix}`,kind:"insert",reason:insertPosition.hasWhere?`Append SSSQL ${branchLabel} branch to the existing WHERE clause.`:`Create a WHERE clause for the SSSQL ${branchLabel} branch.`,target},changedRegions=[{kind:"target-branch",start:edit.start+prefix.length,end:edit.start+edit.after.length-suffix.length,message:`Inserted SSSQL ${branchLabel} optional branch.`}];return insertPosition.hasWhere?changedRegions.unshift({kind:"boolean-operator",start:edit.start,end:edit.start+prefix.length,message:`Inserted AND before the SSSQL ${branchLabel} branch.`}):changedRegions.unshift({kind:"where-keyword",start:edit.start,end:edit.start+prefix.length,message:`Inserted WHERE before the SSSQL ${branchLabel} branch.`}),this.buildPlanFromEdits(sourceSql,[edit],changedRegions,[])}planBranchRemoval(sourceSql,spec){let parsed=SelectQueryParser.parse(sourceSql),matches=this.findMatchingBranchInfos(parsed,spec);if(matches.length>1)return this.buildPlanFromEdits(sourceSql,[],[],[],[{code:"REWRITE_FAILED",message:"SSSQL remove planning found multiple matching branches.",detail:`Multiple SSSQL branches matched parameter ':${spec.parameterName}'. Remove is ambiguous.`}]);if(matches.length===0)return this.buildPlanFromEdits(sourceSql,[],[],[]);let branchSpans=findOptionalBranchSpans(sourceSql,spec.parameterName);if(branchSpans.length>1)return this.planRewrite(sourceSql,query=>this.remove(query,spec));let span=branchSpans[0];if(!span)return this.planRewrite(sourceSql,query=>this.remove(query,spec));let beforeOperator=findBooleanOperatorBefore(sourceSql,span.start),afterOperator=findBooleanOperatorAfter(sourceSql,span.end),where=findWhereBefore(sourceSql,span.start),start=span.start,end=span.end,changedRegions=[{kind:"target-branch",start:span.start,end:span.end,message:"Removed SSSQL optional branch."}];if(beforeOperator)start=beforeOperator.start,changedRegions.unshift({kind:"boolean-operator",start:beforeOperator.start,end:beforeOperator.end,message:`Removed adjacent ${beforeOperator.value.toUpperCase()} before the SSSQL branch.`});else if(afterOperator)end=afterOperator.end,changedRegions.push({kind:"boolean-operator",start:afterOperator.start,end:afterOperator.end,message:`Removed adjacent ${afterOperator.value.toUpperCase()} after the SSSQL branch.`});else if(where){for(start=where.start;end<sourceSql.length&&/\s/.test(sourceSql[end]);)end++;changedRegions.unshift({kind:"where-keyword",start:where.start,end:where.end,message:"Removed WHERE because the SSSQL branch was the only condition."})}let edit={start,end,before:sourceSql.slice(start,end),after:"",kind:"delete",reason:"Remove the targeted SSSQL optional branch from the source SQL.",target:{branchKind:matches[0].kind,parameterName:matches[0].parameterName,column:matches[0].target}};return this.buildPlanFromEdits(sourceSql,[edit],changedRegions,[])}buildPlanFromEdits(sourceSql,edits,changedRegions,warnings,errors=[]){let plannedSql=errors.length===0?applyRewriteEdits(sourceSql,edits):void 0,beforeTokens=tokenizeForRewritePlan(sourceSql),beforeComments=collectCommentFragments(sourceSql),afterTokens=plannedSql!==void 0?tokenizeForRewritePlan(plannedSql):[],afterComments=plannedSql!==void 0?collectCommentFragments(plannedSql):[],commentsPreserved=plannedSql!==void 0?commentsPreservedInOrder(beforeComments,afterComments):!1,changedOnlyTargetBranches=errors.length===0&&changedRegions.every(region=>region.kind==="target-branch"||region.kind==="where-keyword"||region.kind==="boolean-operator"||region.kind==="parentheses")&&commentsPreserved,planWarnings=[...warnings];if(plannedSql!==void 0&&applyRewriteEdits(sourceSql,edits)!==plannedSql&&(errors=[...errors,{code:"APPLY_PLAN_MISMATCH",message:"Applying SSSQL rewrite plan edits did not reproduce the planned SQL."}]),plannedSql!==void 0)try{SelectQueryParser.parse(plannedSql)}catch(error){errors=[...errors,{code:"PARSE_AFTER_FAILED",message:"The SQL produced by SSSQL rewrite planning could not be parsed.",detail:error instanceof Error?error.message:error}]}return plannedSql!==void 0&&!commentsPreserved&&planWarnings.push({code:"COMMENTS_NOT_PRESERVED",message:"One or more input SQL comments are missing or reordered after the SSSQL rewrite."}),{ok:errors.length===0,requiresFullReformat:!1,edits,sql:plannedSql,safety:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length,tokenSequencePreserved:plannedSql!==void 0?tokenSequencesEqual(beforeTokens,afterTokens):!1,commentsPreserved,changedOnlyTargetBranches,changedRegions},warnings:planWarnings,errors}}planRewrite(query,rewrite){let warnings=[],errors=[],sourceSql=typeof query=="string"?query:formatSqlComponent(query);typeof query!="string"&&warnings.push({code:"SOURCE_SQL_UNAVAILABLE",message:"SSSQL rewrite planning received an AST, so the source SQL had to be formatter-generated before analysis."});let beforeTokens=[],beforeComments=[];try{beforeTokens=tokenizeForRewritePlan(sourceSql),beforeComments=collectCommentFragments(sourceSql)}catch(error){errors.push({code:"TOKENIZE_BEFORE_FAILED",message:"Could not tokenize the input SQL before SSSQL rewrite planning.",detail:error instanceof Error?error.message:error})}let plannedSql,afterTokens=[],afterComments=[];if(errors.length===0)try{let parsed=SelectQueryParser.parse(sourceSql),rewritten=rewrite(parsed);plannedSql=formatSqlComponent(rewritten)}catch(error){errors.push({code:"REWRITE_FAILED",message:"SSSQL rewrite planning could not produce a rewritten query.",detail:error instanceof Error?error.message:error})}if(plannedSql!==void 0){try{SelectQueryParser.parse(plannedSql)}catch(error){errors.push({code:"PARSE_AFTER_FAILED",message:"The SQL produced by SSSQL rewrite planning could not be parsed.",detail:error instanceof Error?error.message:error})}try{afterTokens=tokenizeForRewritePlan(plannedSql),afterComments=collectCommentFragments(plannedSql)}catch(error){errors.push({code:"TOKENIZE_AFTER_FAILED",message:"Could not tokenize the SQL produced by SSSQL rewrite planning.",detail:error instanceof Error?error.message:error})}}let edits=plannedSql!==void 0&&plannedSql!==sourceSql?[{start:0,end:sourceSql.length,before:sourceSql,after:plannedSql,kind:"replace",reason:"Current SSSQL rewrite planning is backed by AST rewrite plus formatter output."}]:[],changedRegions=edits.length>0?[{kind:"formatter-rewrite",start:0,end:sourceSql.length,message:"The conservative SSSQL rewrite plan requires replacing formatter output for the full SQL text."}]:[],requiresFullReformat=edits.length>0,tokenSequencePreserved=plannedSql!==void 0?tokenSequencesEqual(beforeTokens,afterTokens):!1,commentsPreserved=plannedSql!==void 0?commentsPreservedInOrder(beforeComments,afterComments):!1,changedOnlyTargetBranches=edits.length===0;return requiresFullReformat&&warnings.push({code:"FULL_REFORMAT_REQUIRED",message:"The current SSSQL rewrite plan can only represent the change as a full SQL replacement."}),plannedSql!==void 0&&!tokenSequencePreserved&&warnings.push({code:"TOKEN_SEQUENCE_CHANGED",message:"The SQL token sequence changes after the SSSQL rewrite. The conservative planner cannot prove that only target branches changed.",detail:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length}}),plannedSql!==void 0&&!commentsPreserved&&warnings.push({code:"COMMENTS_NOT_PRESERVED",message:"One or more input SQL comments are missing or reordered after the SSSQL rewrite."}),plannedSql!==void 0&&countCommandToken(afterTokens,"as")>countCommandToken(beforeTokens,"as")&&warnings.push({code:"OPTIONAL_ALIAS_AS_ADDED",message:"The rewrite output contains more AS tokens than the input, which may indicate formatter-added aliases."}),plannedSql!==void 0&&!sourceSql.includes('"')&&plannedSql.includes('"')&&warnings.push({code:"IDENTIFIER_QUOTES_ADDED",message:"The rewrite output contains double-quoted identifiers that were not present in the input SQL."}),{ok:errors.length===0,requiresFullReformat,edits,sql:plannedSql,safety:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length,tokenSequencePreserved,commentsPreserved,changedOnlyTargetBranches,changedRegions},warnings,errors}}findMatchingBranchInfos(root,spec){let normalizedOperator=spec.operator?normalizeScalarOperator(spec.operator):void 0,normalizedTarget=spec.target?normalizeIdentifier2(spec.target):void 0;return this.list(root).filter(branch=>!(branch.parameterName!==spec.parameterName||spec.kind&&branch.kind!==spec.kind||normalizedOperator&&branch.operator!==normalizedOperator||normalizedTarget&&(!branch.target||normalizeIdentifier2(branch.target)!==normalizedTarget)))}scaffoldScalarBranch(root,spec){let target=this.resolveTarget(root,spec.target),parameterName=spec.parameterName?.trim()||target.parameterName,operator=normalizeScalarOperator(spec.operator),branch=buildOptionalScalarBranch(target.column,parameterName,operator),branchSql=normalizeSql(formatSqlComponent(branch));this.list(root).find(existing=>existing.query===target.query&&normalizeSql(existing.sql)===branchSql)||target.query.appendWhere(branch)}scaffoldExistsBranch(root,spec){let parameterName=spec.parameterName.trim();if(!parameterName)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires parameterName.");if(spec.anchorColumns.length===0)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires at least one anchorColumn.");let anchorTargets=spec.anchorColumns.map(anchorColumn=>this.resolveTarget(root,anchorColumn)),targetQueries=[...new Set(anchorTargets.map(target=>target.query))];if(targetQueries.length!==1)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold anchor columns must resolve within one query scope.");let targetQuery=targetQueries[0],formattedColumns=anchorTargets.map(target=>formatSqlComponent(target.column)),substitutedSql=substituteAnchorPlaceholders(spec.query,formattedColumns).trim();enforceSubqueryConstraints(substitutedSql);let subquery=SelectQueryParser.parse(substitutedSql),parameterNames=new Set(ParameterCollector.collect(subquery).map(parameter=>parameter.name.value));if(parameterNames.size!==1||!parameterNames.has(parameterName))throw new Error(`SSSQL ${spec.kind.toUpperCase()} scaffold query must reference only parameter ':${parameterName}'.`);let branch=buildOptionalExistsBranch(parameterName,subquery,spec.kind),branchSql=normalizeSql(formatSqlComponent(branch));this.list(root).find(existing=>existing.query===targetQuery&&normalizeSql(existing.sql)===branchSql)||targetQuery.appendWhere(branch)}resolveTarget(root,filterName){let qualified=parseQualifiedFilterName(filterName),lookupColumn=qualified?.column??filterName.trim(),matches=[...new Set(this.finder.find(root,lookupColumn))].map(query=>this.resolveTargetInQuery(query,filterName,qualified)).filter(target=>target!==null);if(matches.length===0)throw new Error(`Could not resolve SSSQL filter target '${filterName}' in the current query graph.`);if(matches.length>1)throw new Error(`SSSQL filter target '${filterName}' is ambiguous across multiple query scopes.`);return matches[0]}resolveTargetInQuery(query,filterName,qualified){return qualified?this.resolveQualifiedTarget(query,qualified):this.resolveUnqualifiedTarget(query,filterName)}resolveQualifiedTarget(query,filterName){let alias=this.findAliasForTable(query,filterName.table);if(!alias)return null;let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeColumnReferenceKey(entry.value)===`${normalizeIdentifier2(alias)}.${normalizeIdentifier2(filterName.column)}`);if(matches.length===0)return null;if(matches.length>1)throw new Error(`SSSQL scaffold target '${filterName.table}.${filterName.column}' resolved to multiple columns.`);return{query,column:matches[0].value,parameterName:makeParameterName(`${filterName.table}.${filterName.column}`)}}resolveUnqualifiedTarget(query,filterName){let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===normalizeIdentifier2(filterName));if(matches.length===0)return null;if(matches.length>1)throw new Error(`SSSQL scaffold target '${filterName}' is ambiguous. Use a qualified table.column reference.`);return{query,column:matches[0].value,parameterName:makeParameterName(filterName)}}tryResolveTarget(root,filterName){try{return this.resolveTarget(root,filterName)}catch{return null}}findAliasForTable(query,tableName){let normalizedTable=normalizeIdentifier2(tableName),matchingAliases=(query.fromClause?.getSources()??[]).map(source=>this.resolveAliasForSource(source,normalizedTable)).filter(alias=>alias!==null);if(matchingAliases.length===0)return null;if(matchingAliases.length>1)throw new Error(`SSSQL scaffold target table '${tableName}' is ambiguous in the selected query scope.`);return matchingAliases[0]}resolveAliasForSource(source,normalizedTable){if(!(source.datasource instanceof TableSource))return null;let sourceName=normalizeIdentifier2(source.datasource.getSourceName()),shortName=normalizeIdentifier2(source.datasource.table.name);return sourceName!==normalizedTable&&shortName!==normalizedTable?null:source.getAliasName()??source.datasource.table.name}buildCorrelatedRefreshPlan(root,branch){let details=getExistsPredicateDetails(branch.expression,branch.parameterName);if(!details)return null;let sourceAliases=this.collectSourceAliases(branch.query),candidatesByKey=new Map;for(let reference of new ColumnReferenceCollector().collect(details.subquery)){let namespace=normalizeIdentifier2(reference.getNamespace());if(!namespace||!sourceAliases.has(namespace))continue;let column=normalizeIdentifier2(reference.column.name),key=`${namespace}.${column}`;candidatesByKey.has(key)||candidatesByKey.set(key,{namespace,column})}let candidates=[...candidatesByKey.values()];if(candidates.length===0)throw new Error(`SSSQL refresh could not infer a correlated anchor for ':${branch.parameterName}'.`);if(candidates.length>1){let listed=candidates.map(candidate=>`${candidate.namespace}.${candidate.column}`).join(", ");throw new Error(`SSSQL refresh found multiple correlated anchor candidates for ':${branch.parameterName}' (${listed}).`)}let[anchor]=candidates;if(!anchor)throw new Error(`SSSQL refresh could not infer a correlated anchor for ':${branch.parameterName}'.`);return{target:this.resolveCorrelatedAnchorTarget(root,branch.query,anchor,branch.parameterName),sourceAlias:anchor.namespace}}collectSourceAliases(query){let aliases=new Set;for(let source of query.fromClause?.getSources()??[]){let sourceAlias=this.getSourceAlias(source);sourceAlias&&aliases.add(sourceAlias)}return aliases}resolveCorrelatedAnchorTarget(root,sourceQuery,anchor,parameterName){let sourceExpression=this.findSourceExpressionByAlias(sourceQuery,anchor.namespace,parameterName),upstreamQuery=this.resolveSourceExpressionToUpstreamQuery(root,sourceExpression,parameterName);return upstreamQuery?this.resolveAnchorTargetInQuery(upstreamQuery,anchor,parameterName):{query:sourceQuery,column:new ColumnReference(anchor.namespace,anchor.column),parameterName}}findSourceExpressionByAlias(query,alias,parameterName){let matches=(query.fromClause?.getSources()??[]).filter(source=>this.getSourceAlias(source)===alias);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve correlated alias '${alias}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple correlated sources for alias '${alias}' and ':${parameterName}'.`);return matches[0]}resolveSourceExpressionToUpstreamQuery(root,source,parameterName){if(source.datasource instanceof SubQuerySource){if(source.datasource.query instanceof SimpleSelectQuery)return source.datasource.query;throw new Error(`SSSQL refresh requires a simple query anchor for ':${parameterName}'.`)}if(!(source.datasource instanceof TableSource))return null;let cteName=normalizeIdentifier2(source.datasource.table.name),cteMatches=new CTECollector().collect(root).filter(cte2=>normalizeIdentifier2(cte2.getSourceAliasName())===cteName);if(cteMatches.length===0)return null;if(cteMatches.length>1)throw new Error(`SSSQL refresh found multiple CTE anchors for ':${parameterName}' (${source.datasource.table.name}).`);let[cte]=cteMatches;if(!cte)return null;let cteQuery=cte.query;if(!(cteQuery instanceof SimpleSelectQuery))throw new Error(`SSSQL refresh requires a simple CTE anchor for ':${parameterName}'.`);return cteQuery}resolveAnchorTargetInQuery(query,anchor,parameterName){let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===anchor.column);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve correlated anchor column '${anchor.column}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple correlated anchor columns '${anchor.column}' for ':${parameterName}'.`);return{query,column:matches[0].value,parameterName}}getSourceAlias(source){let explicitAlias=source.getAliasName();return explicitAlias?normalizeIdentifier2(explicitAlias):source.datasource instanceof TableSource?normalizeIdentifier2(source.datasource.table.name):null}buildScalarRefreshPlan(root,branch,details){let sourceAlias=normalizeIdentifier2(details.column.getNamespace());if(!sourceAlias)return null;let sourceExpression=this.findSourceExpressionByAlias(branch.query,sourceAlias,branch.parameterName),upstreamQuery=this.resolveSourceExpressionToUpstreamQuery(root,sourceExpression,branch.parameterName);return upstreamQuery?this.resolveScalarTargetInQuery(upstreamQuery,details.column,branch.parameterName):null}resolveScalarTargetInQuery(query,sourceColumn,parameterName){let outputColumnName=normalizeIdentifier2(sourceColumn.column.name),matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===outputColumnName);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve scalar branch column '${sourceColumn.column.name}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple scalar branch columns '${sourceColumn.column.name}' for ':${parameterName}'.`);return{query,column:matches[0].value,parameterName}}isNullableBranchColumn(query,column){let alias=normalizeIdentifier2(column.getNamespace());if(!alias||!query.fromClause)return!1;let joins=query.fromClause.joins??[];if(this.getSourceAlias(query.fromClause.source)===alias)return this.hasLaterJoinThatNullsPriorSources(joins,-1);let joinIndex=joins.findIndex(join=>this.getSourceAlias(join.source)===alias);if(joinIndex<0)return!1;let introducingJoin=joins[joinIndex];return this.isJoinedSourceNullable(introducingJoin)||this.hasLaterJoinThatNullsPriorSources(joins,joinIndex)}hasLaterJoinThatNullsPriorSources(joins,sourceJoinIndex){return joins.slice(sourceJoinIndex+1).some(join=>this.isPriorSourcesNullableJoin(join))}isPriorSourcesNullableJoin(join){let joinType=join.joinType.value.toLowerCase();return joinType.includes("right")||joinType.includes("full")}isJoinedSourceNullable(join){let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("full")}rebaseMovedBranch(expression,sourceQuery,targetColumn){let targetNamespace=targetColumn.qualifiedName.namespaces?targetColumn.qualifiedName.namespaces.map(namespace=>namespace.name):null,targetColumnName=normalizeIdentifier2(targetColumn.column.name),sourceAliases=new Set(collectColumnReferencesDeep(expression).filter(reference=>normalizeIdentifier2(reference.column.name)===targetColumnName).map(reference=>normalizeIdentifier2(reference.getNamespace())).filter(namespace=>namespace.length>0));if(sourceAliases.size===0)return;if(sourceAliases.size>1){let aliases=[...sourceAliases].join(", ");throw new Error(`SSSQL refresh cannot safely rebase '${targetColumn.column.name}' across multiple aliases (${aliases}).`)}let[sourceAlias]=[...sourceAliases];if(new Set((sourceQuery.fromClause?.getSources()??[]).map(source=>source.getAliasName()).filter(alias=>typeof alias=="string").map(alias=>normalizeIdentifier2(alias))).has(sourceAlias))for(let reference of collectColumnReferencesDeep(expression))normalizeIdentifier2(reference.getNamespace())===sourceAlias&&(reference.qualifiedName.namespaces=targetNamespace?.map(namespace=>new IdentifierString(namespace))??null)}rebaseMovedBranchByAlias(expression,sourceAlias,targetColumn){let normalizedSourceAlias=normalizeIdentifier2(sourceAlias);if(!normalizedSourceAlias)return;let targetNamespace=targetColumn.qualifiedName.namespaces?targetColumn.qualifiedName.namespaces.map(namespace=>namespace.name):null;for(let reference of collectColumnReferencesDeep(expression))normalizeIdentifier2(reference.getNamespace())===normalizedSourceAlias&&(reference.qualifiedName.namespaces=targetNamespace?.map(namespace=>new IdentifierString(namespace))??null)}},scaffoldSssqlQuery=(sqlContent,filters)=>({query:new SSSQLFilterBuilder().scaffold(sqlContent,filters)}),refreshSssqlQuery=(sqlContent,filters)=>({query:new SSSQLFilterBuilder().refresh(sqlContent,filters)});var SUPPORTED_OPERATORS=new Set(["=","<>","!=","<","<=",">",">=","like","ilike","in"]),VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON="Condition contains a function call; volatile and expression predicates are not moved in the safe-only implementation.",normalizeIdentifier3=value=>value.trim().toLowerCase(),unwrapParens2=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator3=(expression,operator)=>{let candidate=unwrapParens2(expression);return candidate instanceof BinaryExpression&&candidate.operator.value.trim().toLowerCase()===operator},collectTopLevelAndTerms3=expression=>{let candidate=unwrapParens2(expression);return isBinaryOperator3(candidate,"and")?[...collectTopLevelAndTerms3(candidate.left),...collectTopLevelAndTerms3(candidate.right)]:[expression]},rebuildWhereWithoutTerms=(query,termsToRemove)=>{if(!query.whereClause||termsToRemove.size===0)return;let remaining=collectTopLevelAndTerms3(query.whereClause.condition).filter(term=>!termsToRemove.has(term));if(remaining.length===0){query.whereClause=null;return}let rebuilt=remaining[0];for(let index=1;index<remaining.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",remaining[index]);query.whereClause=new WhereClause(rebuilt)},cloneValueComponent=expression=>ValueParser.parse(formatSqlComponent(expression)),cloneColumnReference=reference=>{let namespaces=reference.namespaces?.map(namespace=>namespace.name)??null;return new ColumnReference(namespaces,reference.column.name)},columnReferenceText=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},sameColumnReference=(left,right)=>normalizeIdentifier3(left.column.name)===normalizeIdentifier3(right.column.name)&&normalizeIdentifier3(left.getNamespace())===normalizeIdentifier3(right.getNamespace()),appendUnique=(items,value)=>{items.includes(value)||items.push(value)},ParameterConditionPlacementOptimizer=class{plan(input,options={}){let parsed=this.parseInput(input),warnings=[...parsed.warnings],errors=[...parsed.errors];if(!parsed.query)return this.buildResult({sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});if(!(parsed.query instanceof SimpleSelectQuery))return warnings.push({code:"UNSUPPORTED_ROOT_QUERY",message:"Parameter condition placement currently supports only SimpleSelectQuery roots."}),this.buildResult({sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});let query=parsed.query,applied=[],skipped=[],movedTerms=[];for(let term of query.whereClause?collectTopLevelAndTerms3(query.whereClause.condition):[]){let candidate=this.analyzeCandidate(term);if(!candidate)continue;if("code"in candidate){skipped.push(this.makeSkipped(term,candidate));continue}let target=this.resolveTarget(query,candidate);if("code"in target){skipped.push(this.makeSkipped(term,target));continue}let targetColumn=this.resolveTargetColumn(target.query,target.outputColumnName);if("code"in targetColumn){skipped.push(this.makeSkipped(term,targetColumn));continue}let movedCondition=this.rebaseCondition(candidate.expression,candidate.column,targetColumn.column);target.query.appendWhere(movedCondition),movedTerms.push(term),applied.push({kind:"move_condition",conditionSql:candidate.conditionSql,fromScopeId:"scope:root",toScopeId:target.scopeId,reason:"All referenced columns resolve to a single direct upstream output before unsafe query boundaries.",parameterNames:candidate.parameterNames,columnReferences:[columnReferenceText(candidate.column)]})}rebuildWhereWithoutTerms(query,new Set(movedTerms));let sql=applied.length>0?formatSqlComponent(query):parsed.sql;return this.buildResult({sql,applied,skipped,warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource})}optimize(input,options={}){return this.plan(input,{...options,dryRun:options.dryRun??!1})}parseInput(input){let warnings=[],errors=[];try{let sourceSql=typeof input=="string"?input:formatSqlComponent(input);return typeof input!="string"&&warnings.push({code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."}),{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource:typeof input!="string",warnings,errors}}catch(error){let detail=error instanceof Error?error.message:String(error);return errors.push({code:"PARSE_FAILED",message:"Parameter condition optimization could not parse the input SQL.",detail}),{query:null,sql:typeof input=="string"?input:"",formatterGeneratedSource:typeof input!="string",warnings,errors}}}analyzeCandidate(expression){let parameterNames=this.collectParameterNames(expression);if(parameterNames.length===0)return null;let unsupported=this.findUnsupportedExpression(expression);if(unsupported)return unsupported;let candidate=unwrapParens2(expression);if(!(candidate instanceof BinaryExpression))return{code:"UNSUPPORTED_PARAMETER_CONDITION",reason:"Only simple binary parameter predicates are moved in the safe-only implementation."};let operator=candidate.operator.value.trim().toLowerCase();if(!SUPPORTED_OPERATORS.has(operator))return{code:"UNSUPPORTED_OPERATOR",reason:`Operator '${candidate.operator.value}' is not supported for safe-only parameter condition placement.`};let columnReferences=this.collectColumnReferences(expression);return columnReferences.length!==1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:columnReferences.length===0?"Parameter condition has no column reference to anchor the move.":"Parameter condition references multiple columns; moving it may change semantics."}:operator==="in"&&!this.isSupportedInPredicate(candidate)?{code:"UNSUPPORTED_IN_PREDICATE",reason:"Only simple column IN (:parameter) predicates are moved in the safe-only implementation."}:{expression,conditionSql:formatSqlComponent(expression),parameterNames,column:columnReferences[0]}}findUnsupportedExpression(expression){let found=null,visit=value=>{if(found)return;let candidate=unwrapParens2(value);if(candidate instanceof BinaryExpression){if(candidate.operator.value.trim().toLowerCase()==="or"){found={code:"OR_PREDICATE_UNSUPPORTED",reason:"Condition contains OR predicates, which are not moved in the first safe-only implementation."};return}visit(candidate.left),visit(candidate.right);return}if(candidate instanceof FunctionCall){found={code:"FUNCTION_PREDICATE_UNSUPPORTED",reason:VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON};return}if(candidate instanceof CaseExpression){found={code:"CASE_PREDICATE_UNSUPPORTED",reason:"CASE predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof InlineQuery||candidate instanceof ArrayQueryExpression){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Subquery predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof BetweenExpression){found={code:"BETWEEN_PREDICATE_UNSUPPORTED",reason:"BETWEEN predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),found}isSupportedInPredicate(expression){let left=unwrapParens2(expression.left),right=unwrapParens2(expression.right);return left instanceof ColumnReference?right instanceof ParameterExpression?!0:right instanceof ValueList?right.values.length>0&&right.values.every(value=>unwrapParens2(value)instanceof ParameterExpression):!1:!1}resolveTarget(root,candidate){let boundary=this.findCurrentQueryBoundary(root);if(boundary)return boundary;if(!root.fromClause)return{code:"NO_FROM_CLAUSE",reason:"Condition has no FROM source that can receive the predicate safely."};let bindingResult=this.resolveSourceBinding(root,candidate.column);if("code"in bindingResult)return bindingResult;let nullableSide=this.findNullableSideBoundary(root.fromClause,bindingResult);if(nullableSide)return nullableSide;let upstream=this.resolveUpstreamQuery(root,bindingResult,candidate.column.column.name);if("code"in upstream)return upstream;let targetBoundary=this.findTargetQueryBoundary(upstream.query);return targetBoundary||upstream}findCurrentQueryBoundary(query){return query.selectClause.distinct?{code:"DISTINCT_BOUNDARY",reason:"Condition crosses DISTINCT boundary; moving it may change semantics."}:query.groupByClause||query.havingClause?{code:"GROUP_BY_BOUNDARY",reason:"Condition crosses GROUP BY boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Condition crosses WINDOW boundary; moving it may change semantics."}:null}findTargetQueryBoundary(query){let commonBoundary=this.findCurrentQueryBoundary(query);return commonBoundary||(query.limitClause||query.offsetClause||query.fetchClause?{code:"ROW_LIMIT_BOUNDARY",reason:"Condition crosses LIMIT/OFFSET/FETCH boundary; moving it may change row selection semantics."}:query.fromClause&&this.hasOuterJoin(query.fromClause)?{code:"OUTER_JOIN_BOUNDARY",reason:"Target query contains an OUTER JOIN boundary that is not moved across in the safe-only implementation."}:null)}resolveSourceBinding(root,column){let fromClause=root.fromClause;if(!fromClause)return{code:"NO_FROM_CLAUSE",reason:"Condition has no FROM source that can receive the predicate safely."};let bindings=this.getSourceBindings(fromClause),namespace=normalizeIdentifier3(column.getNamespace()),columnName=column.column.name;if(namespace){let matches2=bindings.filter(binding=>normalizeIdentifier3(binding.alias)===namespace);if(matches2.length!==1)return{code:"AMBIGUOUS_COLUMN_SOURCE",reason:`Column source alias '${column.getNamespace()}' is not uniquely resolvable.`};if(this.resolveSourceQueryForColumns(root,matches2[0].source)instanceof BinarySelectQuery)return matches2[0];let matchCount=this.getOutputColumnMatchCount(root,matches2[0],columnName);return matchCount===0?{code:"COLUMN_NOT_AVAILABLE_UPSTREAM",reason:`Column '${columnReferenceText(column)}' is not a direct output of the referenced source.`}:matchCount>1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnReferenceText(column)}' resolves to multiple outputs in the referenced source.`}:matches2[0]}let matches=[],unionSource=null;for(let binding of bindings){if(this.resolveSourceQueryForColumns(root,binding.source)instanceof BinarySelectQuery){unionSource??=binding;continue}let matchCount=this.getOutputColumnMatchCount(root,binding,columnName);if(matchCount>1)return{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnName}' resolves to multiple outputs in source '${binding.alias}'.`};matchCount===1&&matches.push(binding)}return matches.length===0&&unionSource?{code:"UNION_BOUNDARY",reason:"Condition would need distribution into a UNION branch, which is unsupported."}:matches.length!==1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:matches.length===0?`Column '${columnName}' is not uniquely resolvable to a safe upstream source.`:`Column '${columnName}' is ambiguous across source query blocks.`}:matches[0]}resolveUpstreamQuery(root,binding,outputColumnName){let source=binding.source.datasource;if(source instanceof SubQuerySource)return source.query instanceof SimpleSelectQuery?{query:source.query,scopeId:`subquery:${binding.alias}`,outputColumnName,sourceBinding:binding}:{code:"UNION_BOUNDARY",reason:"Condition would need distribution into a UNION or non-simple subquery, which is unsupported."};if(!(source instanceof TableSource))return{code:"UNSUPPORTED_SOURCE",reason:"Only CTE and simple derived-table sources can receive moved parameter conditions."};let cteName=source.table.name,commonTable=this.findCte(root,cteName);if(!commonTable)return{code:"NO_SAFE_UPSTREAM_QUERY",reason:"The referenced source is a base table, so there is no upstream query block to move into."};let referenceCount=this.countTableSourceReferences(root,cteName);return referenceCount!==1?{code:"CTE_REUSE_UNSUPPORTED",reason:`CTE '${cteName}' is referenced ${referenceCount} times; moving a predicate into it may affect other consumers.`}:commonTable.query instanceof BinarySelectQuery?{code:"UNION_BOUNDARY",reason:"Condition would need distribution into a UNION branch, which is unsupported."}:commonTable.query instanceof SimpleSelectQuery?{query:commonTable.query,scopeId:`cte:${commonTable.getSourceAliasName()}`,outputColumnName,sourceBinding:binding,cteName:commonTable.getSourceAliasName()}:{code:"UNSUPPORTED_CTE_QUERY",reason:"Writable or non-select CTE bodies are not moved into by parameter condition placement."}}resolveTargetColumn(query,outputColumnName){let matches=query.selectClause.items.filter(item=>normalizeIdentifier3(this.getSelectItemOutputName(item)??"")===normalizeIdentifier3(outputColumnName));if(matches.length!==1)return{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`Target query does not expose '${outputColumnName}' as a direct output column.`:`Target query exposes multiple '${outputColumnName}' columns.`};let value=matches[0].value;if(!(value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`Target output '${outputColumnName}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,value);return sourceResolution||{column:value}}verifyColumnResolvableInQuery(query,column){if(!query.fromClause)return{code:"NO_TARGET_FROM_CLAUSE",reason:"Target query has no FROM clause where the moved column can be resolved."};let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier3(column.getNamespace());return namespace?bindings.filter(binding=>normalizeIdentifier3(binding.alias)===namespace).length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Target column '${columnReferenceText(column)}' is not uniquely resolvable in the destination query.`}:bindings.length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Unqualified target column '${column.column.name}' is ambiguous in a multi-source destination query.`}}rebaseCondition(expression,sourceColumn,targetColumn){let cloned=cloneValueComponent(expression);for(let reference of this.collectColumnReferences(cloned))sameColumnReference(reference,sourceColumn)&&(reference.qualifiedName=cloneColumnReference(targetColumn).qualifiedName);return cloned}getSourceBindings(fromClause){let bindings=[{source:fromClause.source,alias:fromClause.source.getAliasName()??"",join:null,isPrimary:!0}];for(let join of fromClause.joins??[])bindings.push({source:join.source,alias:join.source.getAliasName()??"",join,isPrimary:!1});return bindings}findNullableSideBoundary(fromClause,binding){if(!binding.join)return(fromClause.joins??[]).some(join=>{let joinType2=join.joinType.value.toLowerCase();return joinType2.includes("right")||joinType2.includes("full")})?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses OUTER JOIN nullable side; moving it may change semantics."}:null;let joinType=binding.join.joinType.value.toLowerCase();return joinType.includes("left")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses LEFT JOIN nullable side; moving it may change semantics."}:joinType.includes("full")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses FULL JOIN nullable side; moving it may change semantics."}:null}hasOuterJoin(fromClause){return(fromClause.joins??[]).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("right")||joinType.includes("full")||joinType.includes("outer")})}getOutputColumnMatchCount(root,binding,columnName){let target=this.resolveSourceQueryForColumns(root,binding.source);return!target||!(target instanceof SimpleSelectQuery)?0:target.selectClause.items.filter(item=>normalizeIdentifier3(this.getSelectItemOutputName(item)??"")===normalizeIdentifier3(columnName)).length}resolveSourceQueryForColumns(root,source){if(source.datasource instanceof SubQuerySource)return source.datasource.query;if(source.datasource instanceof TableSource){let cteQuery=this.findCte(root,source.datasource.table.name)?.query;return cteQuery instanceof SimpleSelectQuery||cteQuery instanceof BinarySelectQuery?cteQuery:null}return null}getSelectItemOutputName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}findCte(root,name){let normalized=normalizeIdentifier3(name),matches=(root.withClause?.tables??[]).filter(table=>normalizeIdentifier3(table.getSourceAliasName())===normalized);return matches.length===1?matches[0]:null}countTableSourceReferences(query,tableName){let normalized=normalizeIdentifier3(tableName),count=0,visitSelect=select=>{if(select instanceof BinarySelectQuery){visitSelect(select.left),visitSelect(select.right);return}if(select instanceof SimpleSelectQuery){if(select.fromClause)for(let binding of this.getSourceBindings(select.fromClause)){let source=binding.source.datasource;source instanceof TableSource&&normalizeIdentifier3(source.table.name)===normalized&&(count+=1),source instanceof SubQuerySource&&visitSelect(source.query)}for(let cte of select.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}};return visitSelect(query),count}hasWindowUsage(query){if(query.windowClause)return!0;let found=!1,visit=value=>{if(found)return;let candidate=unwrapParens2(value);if(candidate instanceof FunctionCall){if(candidate.over){found=!0;return}candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}candidate instanceof ValueList&&candidate.values.forEach(visit)};return query.selectClause.items.forEach(item=>visit(item.value)),found}collectColumnReferences(expression){let references=[],visit=value=>{let candidate=unwrapParens2(value);if(candidate instanceof ColumnReference){references.some(existing=>sameColumnReference(existing,candidate))||references.push(candidate);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),references}collectParameterNames(expression){let names=[],visit=value=>{let candidate=unwrapParens2(value);if(candidate instanceof ParameterExpression){appendUnique(names,candidate.name.value);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(!(candidate instanceof ArrayQueryExpression||candidate instanceof InlineQuery)){if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)}};return visit(expression),names}makeSkipped(expression,draft){return{conditionSql:formatSqlComponent(expression),scopeId:"scope:root",...draft}}buildResult(params){return{ok:params.errors.length===0,sql:params.sql,applied:params.applied,skipped:params.skipped,warnings:params.warnings,errors:params.errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun:params.dryRun,formatterGeneratedSource:params.formatterGeneratedSource},conditionMoves:params.applied}}},planParameterConditionOptimization=(input,options={})=>new ParameterConditionPlacementOptimizer().plan(input,options),optimizeParameterConditionPlacement=(input,options={})=>new ParameterConditionPlacementOptimizer().optimize(input,options);var VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON2="Predicate contains a function call; volatile and expression predicates are not moved in the safe-only implementation.",normalizeIdentifier4=value=>value.trim().toLowerCase(),unwrapParens3=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator4=(expression,operator)=>{let candidate=unwrapParens3(expression);return candidate instanceof BinaryExpression&&candidate.operator.value.trim().toLowerCase()===operator},collectTopLevelAndTerms4=expression=>{let candidate=unwrapParens3(expression);return isBinaryOperator4(candidate,"and")?[...collectTopLevelAndTerms4(candidate.left),...collectTopLevelAndTerms4(candidate.right)]:[expression]},rebuildWhereWithoutTerms2=(query,termsToRemove)=>{if(!query.whereClause||termsToRemove.size===0)return;let remaining=collectTopLevelAndTerms4(query.whereClause.condition).filter(term=>!termsToRemove.has(term));if(remaining.length===0){query.whereClause=null;return}let rebuilt=remaining[0];for(let index=1;index<remaining.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",remaining[index]);query.whereClause=new WhereClause(rebuilt)},cloneValueComponent2=expression=>ValueParser.parse(formatSqlComponent(expression)),cloneColumnReference2=reference=>{let namespaces=reference.namespaces?.map(namespace=>namespace.name)??null;return new ColumnReference(namespaces,reference.column.name)},columnReferenceText2=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},sameColumnReference2=(left,right)=>normalizeIdentifier4(left.column.name)===normalizeIdentifier4(right.column.name)&&normalizeIdentifier4(left.getNamespace())===normalizeIdentifier4(right.getNamespace()),appendUnique2=(items,value)=>{items.includes(value)||items.push(value)},StaticPredicatePlacementOptimizer=class{plan(input,options={}){let parsed=this.parseInput(input),warnings=[...parsed.warnings],errors=[...parsed.errors];if(!parsed.query)return this.buildResult({sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});if(!(parsed.query instanceof SimpleSelectQuery))return warnings.push({code:"UNSUPPORTED_ROOT_QUERY",message:"Static predicate placement currently supports only SimpleSelectQuery roots."}),this.buildResult({sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});let query=parsed.query,applied=[],skipped=[],movedTerms=[];for(let term of query.whereClause?collectTopLevelAndTerms4(query.whereClause.condition):[]){let candidate=this.analyzeCandidate(query,term);if(!candidate)continue;if("code"in candidate){skipped.push(this.makeSkipped(term,candidate));continue}let target=this.resolveTarget(query,candidate);if("code"in target){skipped.push(this.makeSkipped(term,target));continue}let targetColumns=this.resolveTargetColumns(target.query,candidate.references);if("code"in targetColumns){skipped.push(this.makeSkipped(term,targetColumns));continue}let movedPredicate=this.rebasePredicate(candidate.expression,targetColumns);target.query.appendWhere(movedPredicate),movedTerms.push(term),applied.push({kind:"move_static_predicate",predicateSql:candidate.predicateSql,fromScopeId:"scope:root",toScopeId:target.scopeId,reason:"All outer references resolve to direct upstream outputs before unsafe query boundaries.",columnReferences:candidate.references.map(columnReferenceText2)})}rebuildWhereWithoutTerms2(query,new Set(movedTerms));let sql=applied.length>0?formatSqlComponent(query):parsed.sql;return this.buildResult({sql,applied,skipped,warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource})}optimize(input,options={}){return this.plan(input,{...options,dryRun:options.dryRun??!1})}parseInput(input){let warnings=[],errors=[];try{let sourceSql=typeof input=="string"?input:formatSqlComponent(input);return typeof input!="string"&&warnings.push({code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."}),{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource:typeof input!="string",warnings,errors}}catch(error){let detail=error instanceof Error?error.message:String(error);return errors.push({code:"PARSE_FAILED",message:"Static predicate placement could not parse the input SQL.",detail}),{query:null,sql:typeof input=="string"?input:"",formatterGeneratedSource:typeof input!="string",warnings,errors}}}analyzeCandidate(root,expression){if(this.collectParameterNames(expression).length>0)return null;let unsupported=this.findUnsupportedExpression(expression,this.isExistsPredicate(expression));if(unsupported)return unsupported;let references=this.collectRootColumnReferences(root,expression);return references.length===0?{code:"NO_COLUMN_REFERENCE",reason:"Static predicate has no outer column reference to anchor the move."}:{expression,predicateSql:formatSqlComponent(expression),references}}isExistsPredicate(expression){let candidate=unwrapParens3(expression);return candidate instanceof UnaryExpression?candidate.operator.value.trim().toLowerCase()==="exists"&&unwrapParens3(candidate.expression)instanceof InlineQuery:!1}findUnsupportedExpression(expression,allowExistsSubquery){let found=null,visitSelect=query=>{if(!found){if(query instanceof BinarySelectQuery){found={code:"UNION_BOUNDARY",reason:"Static predicate would need distribution into a UNION branch, which is unsupported."};return}if(!(query instanceof SimpleSelectQuery)){found={code:"UNSUPPORTED_SUBQUERY",reason:"Static predicate contains a non-simple subquery, which is unsupported."};return}query.selectClause.items.forEach(item=>visit(item.value));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query)}query.whereClause&&visit(query.whereClause.condition),query.havingClause&&visit(query.havingClause.condition);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}},visit=value=>{if(found)return;let candidate=unwrapParens3(value);if(candidate instanceof BinaryExpression){if(candidate.operator.value.trim().toLowerCase()==="or"){found={code:"OR_PREDICATE_UNSUPPORTED",reason:"Predicate contains OR predicates, which are not moved in the first safe-only implementation."};return}visit(candidate.left),visit(candidate.right);return}if(candidate instanceof FunctionCall){found={code:"FUNCTION_PREDICATE_UNSUPPORTED",reason:VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON2};return}if(candidate instanceof CaseExpression){found={code:"CASE_PREDICATE_UNSUPPORTED",reason:"CASE predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof InlineQuery){if(!allowExistsSubquery){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Subquery predicates are only moved when they are simple EXISTS predicates."};return}visitSelect(candidate.selectQuery);return}if(candidate instanceof ArrayQueryExpression){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Array subquery predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof BetweenExpression){found={code:"BETWEEN_PREDICATE_UNSUPPORTED",reason:"BETWEEN predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),found}resolveTarget(root,candidate){let boundary=this.findCurrentQueryBoundary(root);if(boundary)return boundary;if(!root.fromClause)return{code:"NO_FROM_CLAUSE",reason:"Predicate has no FROM source that can receive it safely."};let bindings=[];for(let reference of candidate.references){let binding2=this.resolveSourceBinding(root,reference);if("code"in binding2)return binding2;bindings.some(item=>item.source===binding2.source)||bindings.push(binding2)}if(bindings.length!==1)return{code:"MULTIPLE_SOURCE_REFERENCES",reason:"Static predicate references multiple source query blocks; moving it may change semantics."};let binding=bindings[0],nullableSide=this.findNullableSideBoundary(root.fromClause,binding);if(nullableSide)return nullableSide;let upstream=this.resolveUpstreamQuery(root,binding);if("code"in upstream)return upstream;let targetBoundary=this.findTargetQueryBoundary(upstream.query);return targetBoundary||upstream}findCurrentQueryBoundary(query){return query.selectClause.distinct?{code:"DISTINCT_BOUNDARY",reason:"Predicate crosses DISTINCT boundary; moving it may change semantics."}:query.groupByClause||query.havingClause?{code:"GROUP_BY_BOUNDARY",reason:"Predicate crosses GROUP BY boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Predicate crosses WINDOW boundary; moving it may change semantics."}:null}findTargetQueryBoundary(query){let commonBoundary=this.findCurrentQueryBoundary(query);return commonBoundary||(query.limitClause||query.offsetClause||query.fetchClause?{code:"ROW_LIMIT_BOUNDARY",reason:"Predicate crosses LIMIT/OFFSET/FETCH boundary; moving it may change row selection semantics."}:query.fromClause&&this.hasOuterJoin(query.fromClause)?{code:"OUTER_JOIN_BOUNDARY",reason:"Target query contains an OUTER JOIN boundary that is not moved across in the safe-only implementation."}:null)}resolveSourceBinding(root,column){let fromClause=root.fromClause;if(!fromClause)return{code:"NO_FROM_CLAUSE",reason:"Predicate has no FROM source that can receive it safely."};let bindings=this.getSourceBindings(fromClause),namespace=normalizeIdentifier4(column.getNamespace()),columnName=column.column.name;if(namespace){let matches2=bindings.filter(binding=>normalizeIdentifier4(binding.alias)===namespace);if(matches2.length!==1)return{code:"AMBIGUOUS_COLUMN_SOURCE",reason:`Column source alias '${column.getNamespace()}' is not uniquely resolvable.`};if(this.resolveSourceQueryForColumns(root,matches2[0].source)instanceof BinarySelectQuery)return matches2[0];let matchCount=this.getOutputColumnMatchCount(root,matches2[0],columnName);return matchCount===0?{code:"COLUMN_NOT_AVAILABLE_UPSTREAM",reason:`Column '${columnReferenceText2(column)}' is not a direct output of the referenced source.`}:matchCount>1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnReferenceText2(column)}' resolves to multiple outputs in the referenced source.`}:matches2[0]}let matches=[],unionSource=null;for(let binding of bindings){if(this.resolveSourceQueryForColumns(root,binding.source)instanceof BinarySelectQuery){unionSource??=binding;continue}let matchCount=this.getOutputColumnMatchCount(root,binding,columnName);if(matchCount>1)return{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnName}' resolves to multiple outputs in source '${binding.alias}'.`};matchCount===1&&matches.push(binding)}return matches.length===0&&unionSource?{code:"UNION_BOUNDARY",reason:"Predicate would need distribution into a UNION branch, which is unsupported."}:matches.length!==1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:matches.length===0?`Column '${columnName}' is not uniquely resolvable to a safe upstream source.`:`Column '${columnName}' is ambiguous across source query blocks.`}:matches[0]}resolveUpstreamQuery(root,binding){let source=binding.source.datasource;if(source instanceof SubQuerySource)return source.query instanceof SimpleSelectQuery?{query:source.query,scopeId:`subquery:${binding.alias}`,sourceBinding:binding}:{code:"UNION_BOUNDARY",reason:"Predicate would need distribution into a UNION or non-simple subquery, which is unsupported."};if(!(source instanceof TableSource))return{code:"UNSUPPORTED_SOURCE",reason:"Only CTE and simple derived-table sources can receive moved static predicates."};let cteName=source.table.name,commonTable=this.findCte(root,cteName);if(!commonTable)return{code:"NO_SAFE_UPSTREAM_QUERY",reason:"The referenced source is a base table, so there is no upstream query block to move into."};let referenceCount=this.countTableSourceReferences(root,cteName);return referenceCount!==1?{code:"CTE_REUSE_UNSUPPORTED",reason:`CTE '${cteName}' is referenced ${referenceCount} times; moving a predicate into it may affect other consumers.`}:commonTable.query instanceof BinarySelectQuery?{code:"UNION_BOUNDARY",reason:"Predicate would need distribution into a UNION branch, which is unsupported."}:commonTable.query instanceof SimpleSelectQuery?{query:commonTable.query,scopeId:`cte:${commonTable.getSourceAliasName()}`,sourceBinding:binding,cteName:commonTable.getSourceAliasName()}:{code:"UNSUPPORTED_CTE_QUERY",reason:"Writable or non-select CTE bodies are not moved into by static predicate placement."}}resolveTargetColumns(query,references){let resolved=[];for(let reference of references){let matches=query.selectClause.items.filter(item=>normalizeIdentifier4(this.getSelectItemOutputName(item)??"")===normalizeIdentifier4(reference.column.name));if(matches.length!==1)return{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`Target query does not expose '${reference.column.name}' as a direct output column.`:`Target query exposes multiple '${reference.column.name}' columns.`};let value=matches[0].value;if(!(value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`Target output '${reference.column.name}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,value);if(sourceResolution)return sourceResolution;resolved.push({sourceColumn:reference,targetColumn:value})}return resolved}verifyColumnResolvableInQuery(query,column){if(!query.fromClause)return{code:"NO_TARGET_FROM_CLAUSE",reason:"Target query has no FROM clause where the moved column can be resolved."};let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier4(column.getNamespace());return namespace?bindings.filter(binding=>normalizeIdentifier4(binding.alias)===namespace).length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Target column '${columnReferenceText2(column)}' is not uniquely resolvable in the destination query.`}:bindings.length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Unqualified target column '${column.column.name}' is ambiguous in a multi-source destination query.`}}rebasePredicate(expression,targetColumns){let cloned=cloneValueComponent2(expression),visitSelect=(query,inheritedLocalAliases)=>{if(!(query instanceof SimpleSelectQuery))return;let localAliases=new Set(inheritedLocalAliases);for(let alias of this.collectSourceAliases(query))localAliases.add(alias);query.selectClause.items.forEach(item=>visit(item.value,localAliases));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition,localAliases);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query,localAliases)}query.whereClause&&visit(query.whereClause.condition,localAliases),query.havingClause&&visit(query.havingClause.condition,localAliases);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query,localAliases)},visit=(value,localAliases)=>{let candidate=unwrapParens3(value);if(candidate instanceof ColumnReference){let namespace=normalizeIdentifier4(candidate.getNamespace());if(namespace&&localAliases.has(namespace))return;let target=targetColumns.find(item=>sameColumnReference2(candidate,item.sourceColumn));target&&(candidate.qualifiedName=cloneColumnReference2(target.targetColumn).qualifiedName);return}if(candidate instanceof BinaryExpression){visit(candidate.left,localAliases),visit(candidate.right,localAliases);return}if(candidate instanceof UnaryExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery,localAliases);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument,localAliases),candidate.filterCondition&&visit(candidate.filterCondition,localAliases);return}if(candidate instanceof CastExpression){visit(candidate.input,localAliases);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition,localAliases);for(let pair of candidate.switchCase.cases)visit(pair.key,localAliases),visit(pair.value,localAliases);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue,localAliases);return}if(candidate instanceof BetweenExpression){visit(candidate.expression,localAliases),visit(candidate.lower,localAliases),visit(candidate.upper,localAliases);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ValueList){candidate.values.forEach(item=>visit(item,localAliases));return}if(candidate instanceof TupleExpression){candidate.values.forEach(item=>visit(item,localAliases));return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument,localAliases)};return visit(cloned,new Set),cloned}getSourceBindings(fromClause){let bindings=[{source:fromClause.source,alias:fromClause.source.getAliasName()??"",join:null,joinIndex:-1,isPrimary:!0}];for(let index=0;index<(fromClause.joins??[]).length;index+=1){let join=fromClause.joins[index];bindings.push({source:join.source,alias:join.source.getAliasName()??"",join,joinIndex:index,isPrimary:!1})}return bindings}findNullableSideBoundary(fromClause,binding){let joins=fromClause.joins??[];if(binding.isPrimary)return this.hasLaterJoinThatNullsPriorSources(joins,-1)?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses OUTER JOIN nullable side; moving it may change semantics."}:null;let join=binding.join;if(!join)return null;let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses LEFT JOIN nullable side; moving it may change semantics."}:joinType.includes("full")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses FULL JOIN nullable side; moving it may change semantics."}:this.hasLaterJoinThatNullsPriorSources(joins,binding.joinIndex)?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses later RIGHT/FULL JOIN nullable side; moving it may change semantics."}:null}hasLaterJoinThatNullsPriorSources(joins,sourceJoinIndex){return joins.slice(sourceJoinIndex+1).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("right")||joinType.includes("full")})}hasOuterJoin(fromClause){return(fromClause.joins??[]).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("right")||joinType.includes("full")||joinType.includes("outer")})}getOutputColumnMatchCount(root,binding,columnName){let target=this.resolveSourceQueryForColumns(root,binding.source);return!target||!(target instanceof SimpleSelectQuery)?0:target.selectClause.items.filter(item=>normalizeIdentifier4(this.getSelectItemOutputName(item)??"")===normalizeIdentifier4(columnName)).length}resolveSourceQueryForColumns(root,source){if(source.datasource instanceof SubQuerySource)return source.datasource.query;if(source.datasource instanceof TableSource){let cteQuery=this.findCte(root,source.datasource.table.name)?.query;return cteQuery instanceof SimpleSelectQuery||cteQuery instanceof BinarySelectQuery?cteQuery:null}return null}getSelectItemOutputName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}findCte(root,name){let normalized=normalizeIdentifier4(name),matches=(root.withClause?.tables??[]).filter(table=>normalizeIdentifier4(table.getSourceAliasName())===normalized);return matches.length===1?matches[0]:null}countTableSourceReferences(query,tableName){let normalized=normalizeIdentifier4(tableName),count=0,visitSelect=select=>{if(select instanceof BinarySelectQuery){visitSelect(select.left),visitSelect(select.right);return}if(select instanceof SimpleSelectQuery){if(select.fromClause)for(let binding of this.getSourceBindings(select.fromClause)){let source=binding.source.datasource;source instanceof TableSource&&normalizeIdentifier4(source.table.name)===normalized&&(count+=1),source instanceof SubQuerySource&&visitSelect(source.query)}for(let cte of select.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}};return visitSelect(query),count}collectSourceAliases(query){let aliases=new Set;for(let source of query.fromClause?.getSources()??[]){let alias=source.getAliasName();alias&&aliases.add(normalizeIdentifier4(alias))}return aliases}collectRootColumnReferences(root,expression){let references=[],rootAliases=this.collectSourceAliases(root),visitSelect=(query,inheritedLocalAliases)=>{if(!(query instanceof SimpleSelectQuery))return;let localAliases=new Set(inheritedLocalAliases);for(let alias of this.collectSourceAliases(query))localAliases.add(alias);query.selectClause.items.forEach(item=>visit(item.value,localAliases));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition,localAliases);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query,localAliases)}query.whereClause&&visit(query.whereClause.condition,localAliases),query.havingClause&&visit(query.havingClause.condition,localAliases);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query,localAliases)},collect=reference=>{references.some(existing=>sameColumnReference2(existing,reference))||references.push(reference)},visit=(value,localAliases)=>{let candidate=unwrapParens3(value);if(candidate instanceof ColumnReference){let namespace=normalizeIdentifier4(candidate.getNamespace());if(namespace){rootAliases.has(namespace)&&!localAliases.has(namespace)&&collect(candidate);return}localAliases.size===0&&collect(candidate);return}if(candidate instanceof BinaryExpression){visit(candidate.left,localAliases),visit(candidate.right,localAliases);return}if(candidate instanceof UnaryExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery,localAliases);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument,localAliases),candidate.filterCondition&&visit(candidate.filterCondition,localAliases);return}if(candidate instanceof CastExpression){visit(candidate.input,localAliases);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition,localAliases);for(let pair of candidate.switchCase.cases)visit(pair.key,localAliases),visit(pair.value,localAliases);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue,localAliases);return}if(candidate instanceof BetweenExpression){visit(candidate.expression,localAliases),visit(candidate.lower,localAliases),visit(candidate.upper,localAliases);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayQueryExpression){visitSelect(candidate.query,localAliases);return}if(candidate instanceof ValueList){candidate.values.forEach(item=>visit(item,localAliases));return}if(candidate instanceof TupleExpression){candidate.values.forEach(item=>visit(item,localAliases));return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument,localAliases)};return visit(expression,new Set),references}hasWindowUsage(query){if(query.windowClause)return!0;let found=!1,visit=value=>{if(found)return;let candidate=unwrapParens3(value);if(candidate instanceof FunctionCall){if(candidate.over){found=!0;return}candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}candidate instanceof ValueList&&candidate.values.forEach(visit)};return query.selectClause.items.forEach(item=>visit(item.value)),found}collectParameterNames(expression){let names=[],visitSelect=query=>{if(query instanceof BinarySelectQuery){visitSelect(query.left),visitSelect(query.right);return}if(query instanceof SimpleSelectQuery){query.selectClause.items.forEach(item=>visit(item.value));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query)}query.whereClause&&visit(query.whereClause.condition),query.havingClause&&visit(query.havingClause.condition);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}},visit=value=>{let candidate=unwrapParens3(value);if(candidate instanceof ParameterExpression){appendUnique2(names,candidate.name.value);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery);return}if(candidate instanceof ArrayQueryExpression){visitSelect(candidate.query);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),names}makeSkipped(expression,draft){return{predicateSql:formatSqlComponent(expression),scopeId:"scope:root",...draft}}buildResult(params){return{ok:params.errors.length===0,sql:params.sql,applied:params.applied,skipped:params.skipped,warnings:params.warnings,errors:params.errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun:params.dryRun,formatterGeneratedSource:params.formatterGeneratedSource},staticPredicateMoves:params.applied}}},planStaticPredicatePlacement=(input,options={})=>new StaticPredicatePlacementOptimizer().plan(input,options),optimizeStaticPredicatePlacement=(input,options={})=>new StaticPredicatePlacementOptimizer().optimize(input,options);var hasOwnParameter=(parameters,parameterName)=>Object.prototype.hasOwnProperty.call(parameters,parameterName),isAbsentOptionalValue=(parameters,parameterName)=>parameters[parameterName]===null||parameters[parameterName]===void 0,parseConditionOptimizationInput=input=>{let warnings=[],errors=[],sourceSql=typeof input=="string"?input:formatSqlComponent(input),formatterGeneratedSource=typeof input!="string";formatterGeneratedSource&&warnings.push({phaseKind:"sssql_optional_condition",code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."});try{return{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource,warnings,errors}}catch(error){return errors.push({phaseKind:"sssql_optional_condition",code:"PARSE_FAILED",message:"SSSQL optional condition optimization could not parse the input SQL.",detail:error instanceof Error?error.message:String(error)}),{query:null,sql:sourceSql,formatterGeneratedSource,warnings,errors}}},buildSssqlApplied=branch=>({phaseKind:"sssql_optional_condition",kind:"prune_optional_branch",conditionSql:formatSqlComponent(branch.expression),parameterName:branch.parameterName,reason:"The optional branch parameter is explicitly absent, so the safe-only SSSQL phase pruned the branch."}),buildSssqlRefreshApplied=(branch,previousConditionSql)=>({phaseKind:"sssql_optional_condition",kind:"refresh_optional_branch",conditionSql:formatSqlComponent(branch.expression),previousConditionSql,parameterName:branch.parameterName,reason:"The safe-only SSSQL phase refreshed the optional branch placement before ordinary parameter placement."}),buildSssqlSkipped=(branch,parameters)=>{let parameterProvided=hasOwnParameter(parameters,branch.parameterName);return{phaseKind:"sssql_optional_condition",kind:"optional_branch_skipped",conditionSql:formatSqlComponent(branch.expression),parameterName:branch.parameterName,code:parameterProvided?"SSSQL_OPTIONAL_PARAMETER_PRESENT":"SSSQL_OPTIONAL_PARAMETER_NOT_PROVIDED",reason:parameterProvided?"The optional branch parameter is present, so the branch remains active.":"No optional branch parameter value was provided, so the branch remains unchanged."}},buildSssqlRefreshSkipped=(branch,code,reason)=>({phaseKind:"sssql_optional_condition",kind:"optional_branch_skipped",conditionSql:formatSqlComponent(branch.expression),parameterName:branch.parameterName,code,reason}),buildSssqlRefreshFilters=(branches,parameters)=>{let filters={};for(let branch of branches)filters[branch.parameterName]=hasOwnParameter(parameters,branch.parameterName)?parameters[branch.parameterName]:null;return filters},refreshRemainingSssqlBranches=(sql,parameters)=>{let parsed=parseConditionOptimizationInput(sql),applied=[],skipped=[];if(!parsed.query)return{sql:parsed.sql,applied,skipped,warnings:parsed.warnings,errors:parsed.errors,formatterGeneratedSource:parsed.formatterGeneratedSource};let beforeBranches=collectSupportedOptionalConditionBranches(parsed.query);if(beforeBranches.length===0)return{sql:parsed.sql,applied,skipped,warnings:parsed.warnings,errors:parsed.errors,formatterGeneratedSource:parsed.formatterGeneratedSource};let beforeBranchSql=new WeakMap,beforeBranchQuery=new WeakMap;for(let branch of beforeBranches)beforeBranchSql.set(branch.expression,formatSqlComponent(branch.expression)),beforeBranchQuery.set(branch.expression,branch.query);try{new SSSQLFilterBuilder().refresh(parsed.query,buildSssqlRefreshFilters(beforeBranches,parameters))}catch(error){let detail=error instanceof Error?error.message:String(error);return{sql,applied,skipped:beforeBranches.map(branch=>buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_UNSUPPORTED",`SSSQL optional branch refresh was skipped because safe refresh could not be proven: ${detail}`)),warnings:parsed.warnings,errors:parsed.errors,formatterGeneratedSource:parsed.formatterGeneratedSource}}let afterBranches=collectSupportedOptionalConditionBranches(parsed.query);for(let branch of afterBranches){let previousSql=beforeBranchSql.get(branch.expression),previousQuery=beforeBranchQuery.get(branch.expression);if(!previousSql||!previousQuery){skipped.push(buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_UNSUPPORTED","SSSQL optional branch refresh left an untracked branch unchanged."));continue}let refreshedSql=formatSqlComponent(branch.expression);if(previousQuery!==branch.query||previousSql!==refreshedSql){applied.push(buildSssqlRefreshApplied(branch,previousSql));continue}skipped.push(buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_NOOP","SSSQL optional branch refresh found no safe placement change to apply."))}return{sql:applied.length>0?formatSqlComponent(parsed.query):sql,applied,skipped,warnings:parsed.warnings,errors:parsed.errors,formatterGeneratedSource:parsed.formatterGeneratedSource}},runSssqlOptionalConditionPhase=(input,options)=>{let parsed=parseConditionOptimizationInput(input),warnings=[...parsed.warnings],errors=[...parsed.errors],applied=[],skipped=[],optionalConditionParameters=options.optionalConditionParameters??{};if(!parsed.query)return{sql:parsed.sql,applied,skipped,warnings,errors,formatterGeneratedSource:parsed.formatterGeneratedSource};let currentSql=parsed.sql,branches=collectSupportedOptionalConditionBranches(parsed.query),pruneBranches=branches.filter(branch=>hasOwnParameter(optionalConditionParameters,branch.parameterName)&&isAbsentOptionalValue(optionalConditionParameters,branch.parameterName));if(pruneBranches.length>0)try{pruneOptionalConditionBranches(parsed.query,optionalConditionParameters),currentSql=formatSqlComponent(parsed.query),applied.push(...pruneBranches.map(buildSssqlApplied))}catch(error){errors=[...errors,{phaseKind:"sssql_optional_condition",code:"SSSQL_PRUNE_FAILED",message:"SSSQL optional condition optimization could not prune optional branches.",detail:error instanceof Error?error.message:String(error)}]}if(errors.length===0){let refreshPhase=refreshRemainingSssqlBranches(currentSql,optionalConditionParameters);applied.push(...refreshPhase.applied),skipped.push(...refreshPhase.skipped),warnings.push(...refreshPhase.warnings),errors.push(...refreshPhase.errors),currentSql=refreshPhase.sql}else for(let branch of branches)pruneBranches.includes(branch)||skipped.push(buildSssqlSkipped(branch,optionalConditionParameters));return{sql:errors.length===0?currentSql:parsed.sql,applied,skipped,warnings,errors,formatterGeneratedSource:parsed.formatterGeneratedSource}},mapParameterWarnings=warnings=>warnings.map(warning=>({phaseKind:"parameter_condition_placement",...warning})),mapParameterErrors=errors=>errors.map(error=>({phaseKind:"parameter_condition_placement",...error})),mapParameterApplied=applied=>applied.map(item=>({phaseKind:"parameter_condition_placement",...item})),mapParameterSkipped=skipped=>skipped.map(item=>({phaseKind:"parameter_condition_placement",...item})),mapStaticWarnings=warnings=>warnings.map(warning=>({phaseKind:"static_predicate_placement",...warning})),mapStaticErrors=errors=>errors.map(error=>({phaseKind:"static_predicate_placement",...error})),mapStaticApplied=applied=>applied.map(item=>({phaseKind:"static_predicate_placement",...item})),mapStaticSkipped=skipped=>skipped.map(item=>({phaseKind:"static_predicate_placement",...item})),makePhaseSummary=(kind,counts)=>({kind,appliedCount:counts.appliedCount,skippedCount:counts.skippedCount,warningCount:counts.warningCount,errorCount:counts.errorCount}),runConditionOptimization=(input,options,defaultDryRun)=>{let dryRun=options.dryRun??defaultDryRun,sssqlPhase=runSssqlOptionalConditionPhase(input,{...options,dryRun}),parameterPhase=dryRun?planParameterConditionOptimization(sssqlPhase.sql,{dryRun}):optimizeParameterConditionPlacement(sssqlPhase.sql,{dryRun}),parameterWarnings=mapParameterWarnings(parameterPhase.warnings),parameterErrors=mapParameterErrors(parameterPhase.errors),parameterApplied=mapParameterApplied(parameterPhase.applied),parameterSkipped=mapParameterSkipped(parameterPhase.skipped),staticPhase=dryRun?planStaticPredicatePlacement(parameterPhase.sql,{dryRun}):optimizeStaticPredicatePlacement(parameterPhase.sql,{dryRun}),staticWarnings=mapStaticWarnings(staticPhase.warnings),staticErrors=mapStaticErrors(staticPhase.errors),staticApplied=mapStaticApplied(staticPhase.applied),staticSkipped=mapStaticSkipped(staticPhase.skipped),warnings=[...sssqlPhase.warnings,...parameterWarnings,...staticWarnings],errors=[...sssqlPhase.errors,...parameterErrors,...staticErrors];return{ok:errors.length===0,sql:staticPhase.sql,phases:[makePhaseSummary("sssql_optional_condition",{appliedCount:sssqlPhase.applied.length,skippedCount:sssqlPhase.skipped.length,warningCount:sssqlPhase.warnings.length,errorCount:sssqlPhase.errors.length}),makePhaseSummary("parameter_condition_placement",{appliedCount:parameterApplied.length,skippedCount:parameterSkipped.length,warningCount:parameterWarnings.length,errorCount:parameterErrors.length}),makePhaseSummary("static_predicate_placement",{appliedCount:staticApplied.length,skippedCount:staticSkipped.length,warningCount:staticWarnings.length,errorCount:staticErrors.length})],applied:[...sssqlPhase.applied,...parameterApplied,...staticApplied],skipped:[...sssqlPhase.skipped,...parameterSkipped,...staticSkipped],warnings,errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun,formatterGeneratedSource:sssqlPhase.formatterGeneratedSource||parameterPhase.safety.formatterGeneratedSource||staticPhase.safety.formatterGeneratedSource}}},planConditionOptimization=(input,options={})=>runConditionOptimization(input,options,!0),optimizeConditions=(input,options={})=>runConditionOptimization(input,options,!1);var BaseDataFlowNode=class{constructor(id,label,type,shape,details){this.id=id;this.label=label;this.type=type;this.shape=shape;this.details=details}},DataSourceNode=class _DataSourceNode extends BaseDataFlowNode{constructor(id,label,type){super(id,label,type,type==="subquery"?"hexagon":"cylinder");this.annotations=new Set}addAnnotation(annotation){this.annotations.add(annotation)}hasAnnotation(annotation){return this.annotations.has(annotation)}getMermaidRepresentation(){return this.shape==="hexagon"?`${this.id}{{${this.label}}}`:`${this.id}[(${this.label})]`}static createTable(tableName){return new _DataSourceNode(`table_${tableName}`,tableName,"table")}static createCTE(cteName){return new _DataSourceNode(`cte_${cteName}`,`CTE:${cteName}`,"cte")}static createSubquery(alias){return new _DataSourceNode(`subquery_${alias}`,`SubQuery:${alias}`,"subquery")}},ProcessNode=class _ProcessNode extends BaseDataFlowNode{constructor(id,operation,context=""){let nodeId=context?`${context}_${operation.toLowerCase().replace(/\s+/g,"_")}`:operation.toLowerCase().replace(/\s+/g,"_");super(nodeId,operation,"process","hexagon")}getMermaidRepresentation(){return`${this.id}{{${this.label}}}`}static createWhere(context){return new _ProcessNode(`${context}_where`,"WHERE",context)}static createGroupBy(context){return new _ProcessNode(`${context}_group_by`,"GROUP BY",context)}static createHaving(context){return new _ProcessNode(`${context}_having`,"HAVING",context)}static createSelect(context){return new _ProcessNode(`${context}_select`,"SELECT",context)}static createOrderBy(context){return new _ProcessNode(`${context}_order_by`,"ORDER BY",context)}static createLimit(context,hasOffset=!1){let label=hasOffset?"LIMIT/OFFSET":"LIMIT";return new _ProcessNode(`${context}_limit`,label,context)}},OperationNode=class _OperationNode extends BaseDataFlowNode{constructor(id,operation,shape="diamond"){super(id,operation,"operation",shape)}getMermaidRepresentation(){switch(this.shape){case"rounded":return`${this.id}(${this.label})`;case"rectangle":return`${this.id}[${this.label}]`;case"hexagon":return`${this.id}{{${this.label}}}`;case"stadium":return`${this.id}([${this.label}])`;default:return`${this.id}{${this.label}}`}}static createJoin(joinId,joinType){let label,normalizedType=joinType.trim().toLowerCase();return normalizedType==="join"?label="INNER JOIN":normalizedType.endsWith(" join")?label=normalizedType.toUpperCase():label=normalizedType.toUpperCase()+" JOIN",new _OperationNode(`join_${joinId}`,label,"rectangle")}static createUnion(unionId,unionType="UNION ALL"){return new _OperationNode(`${unionType.toLowerCase().replace(/\s+/g,"_")}_${unionId}`,unionType.toUpperCase(),"rectangle")}static createSetOperation(operationId,operation){let normalizedOp=operation.toUpperCase(),id=`${normalizedOp.toLowerCase().replace(/\s+/g,"_")}_${operationId}`;return new _OperationNode(id,normalizedOp,"rectangle")}},OutputNode=class extends BaseDataFlowNode{constructor(context="main"){let label=context==="main"?"Final Result":`${context} Result`;super(`${context}_output`,label,"output","stadium")}getMermaidRepresentation(){return`${this.id}([${this.label}])`}};var DataFlowConnection=class _DataFlowConnection{constructor(from,to,label){this.from=from;this.to=to;this.label=label}getMermaidRepresentation(){let arrow=this.label?` -->|${this.label}| `:" --> ";return`${this.from}${arrow}${this.to}`}static create(from,to,label){return new _DataFlowConnection(from,to,label)}static createWithNullability(from,to,isNullable){let label=isNullable?"NULLABLE":"NOT NULL";return new _DataFlowConnection(from,to,label)}},DataFlowEdgeCollection=class{constructor(){this.edges=[];this.connectionSet=new Set}add(edge){let key=`${edge.from}->${edge.to}`;this.connectionSet.has(key)||(this.edges.push(edge),this.connectionSet.add(key))}addConnection(from,to,label){this.add(DataFlowConnection.create(from,to,label))}addJoinConnection(from,to,isNullable){this.add(DataFlowConnection.createWithNullability(from,to,isNullable))}hasConnection(from,to){return this.connectionSet.has(`${from}->${to}`)}getAll(){return[...this.edges]}getMermaidRepresentation(){return this.edges.map(edge=>edge.getMermaidRepresentation()).join(`
49
+ `);for(let i=1;i<lines.length;i++){let line=lines[i],leadingSpaces=line.match(/^ */)?.[0].length||0,leadingTabs=line.match(/^\t*/)?.[0].length||0;(leadingSpaces>0||leadingTabs>0)&&(indentLines++,totalIndentSize+=leadingSpaces+leadingTabs*4,spaceCount+=leadingSpaces,tabCount+=leadingTabs)}}lexeme.inlineComments&&(totalComments+=lexeme.inlineComments.length)}let indentationStyle="none";return spaceCount>0&&tabCount>0?indentationStyle="mixed":spaceCount>0?indentationStyle="spaces":tabCount>0&&(indentationStyle="tabs"),{totalWhitespace,totalComments,indentationStyle,averageIndentSize:indentLines>0?totalIndentSize/indentLines:0}}validateFormattingLexemes(lexemes){let issues=[];for(let i=0;i<lexemes.length;i++){let lexeme=lexemes[i];lexeme.position||issues.push(`Lexeme ${i} missing position information`),lexeme.followingWhitespace===void 0&&issues.push(`Lexeme ${i} missing followingWhitespace property`),lexeme.inlineComments===void 0&&issues.push(`Lexeme ${i} missing inlineComments property`),lexeme.position&&lexeme.position.startPosition>=lexeme.position.endPosition&&issues.push(`Lexeme ${i} has invalid position range`)}return{isValid:issues.length===0,issues}}};var ClauseScopedColumnReferenceCollector=class{collect(query){if(!(query instanceof SimpleSelectQuery))throw new Error("ClauseScopedColumnReferenceCollector requires a SimpleSelectQuery.");let result=this.createEmptyResult();return this.collectFromSelectClause(query.selectClause,result),this.collectFromJoinClauses(query,result),query.whereClause&&this.collectFromWhereClause(query.whereClause,result),query.groupByClause&&this.collectFromGroupByClause(query.groupByClause,result),query.havingClause&&this.collectFromHavingClause(query.havingClause,result),query.orderByClause&&this.collectFromOrderByClause(query.orderByClause,"orderBy",result),query.windowClause&&this.collectFromWindowsClause(query.windowClause,result),query.limitClause&&this.collectFromLimitClause(query.limitClause,result),query.offsetClause&&this.collectFromOffsetClause(query.offsetClause,result),query.fetchClause&&this.collectFromFetchClause(query.fetchClause,result),result}createEmptyResult(){return{select:[],where:[],joinOn:[],groupBy:[],having:[],orderBy:[],window:[],limitOffset:[]}}collectFromSelectClause(clause,result){clause.distinct instanceof DistinctOn&&this.collectFromValueComponent(clause.distinct.value,"select",result);for(let item of clause.items)this.collectFromValueComponent(item.value,"select",result)}collectFromJoinClauses(query,result){if(query.fromClause?.joins)for(let join of query.fromClause.joins)(join.condition instanceof JoinOnClause||join.condition instanceof JoinUsingClause)&&this.collectFromValueComponent(join.condition.condition,"joinOn",result)}collectFromWhereClause(clause,result){this.collectFromValueComponent(clause.condition,"where",result)}collectFromGroupByClause(clause,result){for(let item of clause.grouping)this.collectFromValueComponent(item,"groupBy",result)}collectFromHavingClause(clause,result){this.collectFromValueComponent(clause.condition,"having",result)}collectFromOrderByClause(clause,target,result){for(let item of clause.order)item instanceof OrderByItem?this.collectFromValueComponent(item.value,target,result):this.collectFromValueComponent(item,target,result)}collectFromLimitClause(clause,result){this.collectFromValueComponent(clause.value,"limitOffset",result)}collectFromOffsetClause(clause,result){this.collectFromValueComponent(clause.value,"limitOffset",result)}collectFromFetchClause(clause,result){this.collectFromValueComponent(clause.expression.count,"limitOffset",result)}collectFromWindowsClause(clause,result){for(let window of clause.windows)this.collectFromWindowFrameExpression(window.expression,"window",result)}collectFromValueComponent(value,target,result,expression=value){if(value instanceof ColumnReference){result[target].push(this.createInfo(value,target,expression));return}if(value instanceof BinaryExpression)this.collectFromValueComponent(value.left,target,result,value),this.collectFromValueComponent(value.right,target,result,value);else if(value instanceof UnaryExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof FunctionCall)this.collectFromFunctionCall(value,target,result);else if(value instanceof CaseExpression){value.condition&&this.collectFromValueComponent(value.condition,target,result,value);for(let pair of value.switchCase.cases)this.collectFromValueComponent(pair.key,target,result,value),this.collectFromValueComponent(pair.value,target,result,value);value.switchCase.elseValue&&this.collectFromValueComponent(value.switchCase.elseValue,target,result,value)}else if(value instanceof ParenExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof CastExpression)this.collectFromValueComponent(value.input,target,result,value);else if(value instanceof BetweenExpression)this.collectFromValueComponent(value.expression,target,result,value),this.collectFromValueComponent(value.lower,target,result,value),this.collectFromValueComponent(value.upper,target,result,value);else if(value instanceof JsonPredicateExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof ArrayExpression)this.collectFromValueComponent(value.expression,target,result,value);else if(value instanceof ArraySliceExpression)this.collectFromValueComponent(value.array,target,result,value),value.startIndex&&this.collectFromValueComponent(value.startIndex,target,result,value),value.endIndex&&this.collectFromValueComponent(value.endIndex,target,result,value);else if(value instanceof ArrayIndexExpression)this.collectFromValueComponent(value.array,target,result,value),this.collectFromValueComponent(value.index,target,result,value);else if(value instanceof ValueList)for(let item of value.values)this.collectFromValueComponent(item,target,result,value);else if(value instanceof TupleExpression)for(let item of value.values)this.collectFromValueComponent(item,target,result,value);else if(value instanceof TypeValue&&value.argument)this.collectFromValueComponent(value.argument,target,result,value);else if(value instanceof InlineQuery||value instanceof ArrayQueryExpression)return}collectFromFunctionCall(value,target,result){value.argument&&this.collectFromValueComponent(value.argument,target,result,value),value.filterCondition&&this.collectFromValueComponent(value.filterCondition,target,result,value),value.withinGroup&&this.collectFromOrderByClause(value.withinGroup,target,result),value.internalOrderBy&&this.collectFromOrderByClause(value.internalOrderBy,target,result),value.over instanceof WindowFrameExpression&&this.collectFromWindowFrameExpression(value.over,target,result)}collectFromWindowFrameExpression(value,target,result){value.partition&&this.collectFromValueComponent(value.partition.value,target,result),value.order&&this.collectFromOrderByClause(value.order,target,result),value.frameSpec&&(value.frameSpec.startBound instanceof WindowFrameBoundaryValue&&this.collectFromValueComponent(value.frameSpec.startBound.value,target,result),value.frameSpec.endBound instanceof WindowFrameBoundaryValue&&this.collectFromValueComponent(value.frameSpec.endBound.value,target,result))}createInfo(reference,clause,expression){let namespaces=reference.namespaces?.map(namespace=>namespace.name)??[],columnName=this.getNameText(reference.qualifiedName.name);return{clause,reference,qualifiedName:reference.qualifiedName.toString(),namespaces,namespace:namespaces.length>0?namespaces.join("."):null,column:columnName,expression}}getNameText(name){return name instanceof IdentifierString?name.name:name.value}};var SelectResultSelectConverter=class{static toSelectQuery(query,options){let fixtureTables=options?.fixtureTables??[];if(fixtureTables.length===0)return query;let sources=new TableSourceCollector(!1).collect(query),referencedTables=new Set;sources.forEach(s=>referencedTables.add(s.getSourceName().toLowerCase()));let neededFixtures=fixtureTables.filter(f=>referencedTables.has(f.tableName.toLowerCase()));if(neededFixtures.length===0)return query;let fixtureCtes=FixtureCteBuilder.buildFixtures(neededFixtures);return query instanceof SimpleSelectQuery&&(query.withClause?query.withClause.tables=[...fixtureCtes,...query.withClause.tables]:query.appendWith(fixtureCtes)),query}};var SimulatedSelectConverter=class{static convert(ast,options){if(ast instanceof InsertQuery)return InsertResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof UpdateQuery)return UpdateResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof DeleteQuery)return DeleteResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof MergeQuery)return MergeResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof SimpleSelectQuery||ast instanceof BinarySelectQuery||ast instanceof ValuesQuery)return SelectResultSelectConverter.toSelectQuery(ast,options);if(ast instanceof CreateTableQuery){if(ast.isTemporary&&ast.asSelectQuery){let processedSelect=SelectResultSelectConverter.toSelectQuery(ast.asSelectQuery,options);return ast.asSelectQuery=processedSelect,ast}return null}return null}};var DDLGeneralizer=class{static generalize(ast){let result=[];for(let component of ast)if(component instanceof CreateTableQuery){let{createTable,alterTables}=this.splitCreateTable(component);result.push(createTable),result.push(...alterTables)}else result.push(component);return result}static splitCreateTable(query){let newColumns=[],alterTables=[],tableQualifiedName=new QualifiedName(query.namespaces||[],query.tableName.name);for(let col of query.columns){let newConstraints=[];for(let constraint of col.constraints)if(["primary-key","unique","references","check"].includes(constraint.kind)){let tableConstraint=this.columnToTableConstraint(col.name,constraint);alterTables.push(new AlterTableStatement({table:tableQualifiedName,actions:[new AlterTableAddConstraint({constraint:tableConstraint})]}))}else newConstraints.push(constraint);newColumns.push(new TableColumnDefinition({name:col.name,dataType:col.dataType,constraints:newConstraints}))}if(query.tableConstraints)for(let constraint of query.tableConstraints)alterTables.push(new AlterTableStatement({table:tableQualifiedName,actions:[new AlterTableAddConstraint({constraint})]}));return{createTable:new CreateTableQuery({tableName:query.tableName.name,namespaces:query.namespaces,columns:newColumns,ifNotExists:query.ifNotExists,isTemporary:query.isTemporary,tableOptions:query.tableOptions,asSelectQuery:query.asSelectQuery,withDataOption:query.withDataOption,tableConstraints:[]}),alterTables}}static columnToTableConstraint(columnName,constraint){let baseParams={constraintName:constraint.constraintName,deferrable:constraint.reference?.deferrable,initially:constraint.reference?.initially};switch(constraint.kind){case"primary-key":return new TableConstraintDefinition({kind:"primary-key",columns:[columnName],...baseParams});case"unique":return new TableConstraintDefinition({kind:"unique",columns:[columnName],...baseParams});case"references":return new TableConstraintDefinition({kind:"foreign-key",columns:[columnName],reference:constraint.reference,...baseParams});case"check":return new TableConstraintDefinition({kind:"check",checkExpression:constraint.checkExpression,...baseParams});default:throw new Error(`Unsupported constraint kind for generalization: ${constraint.kind}`)}}};var DDLDiffGenerator=class{static generateDiff(currentSql,expectedSql,options={}){let currentAst=this.parseAndGeneralize(currentSql),expectedAst=this.parseAndGeneralize(expectedSql),currentSchema=this.buildSchema(currentAst),expectedSchema=this.buildSchema(expectedAst),diffAsts=[];for(let[tableName,expectedTable]of expectedSchema.tables){let currentTable=currentSchema.tables.get(tableName);if(currentTable)this.compareColumns(currentTable,expectedTable,diffAsts,options),this.compareConstraints(currentTable,expectedTable,diffAsts,options),this.compareIndexes(currentTable,expectedTable,diffAsts,options);else{let columns=Array.from(expectedTable.columns.values()).map(c=>c.definition),tableNameStr=expectedTable.qualifiedName.name instanceof RawString?expectedTable.qualifiedName.name.value:expectedTable.qualifiedName.name.name,namespaces=expectedTable.qualifiedName.namespaces?expectedTable.qualifiedName.namespaces.map(ns=>ns.name):null,createTable=new CreateTableQuery({tableName:tableNameStr,namespaces,columns});diffAsts.push(createTable);for(let constraint of expectedTable.constraints)diffAsts.push(new AlterTableStatement({table:expectedTable.qualifiedName,actions:[new AlterTableAddConstraint({constraint:constraint.definition})]}));for(let index of expectedTable.indexes)diffAsts.push(index.definition)}}if(options.dropTables)for(let[tableName,currentTable]of currentSchema.tables)expectedSchema.tables.has(tableName)||diffAsts.push(new DropTableStatement({tables:[currentTable.qualifiedName],ifExists:!1}));let formatter2=new SqlFormatter(options.formatOptions||{keywordCase:"upper"});return diffAsts.map(ast=>formatter2.format(ast).formattedSql+";")}static parseAndGeneralize(sql){let split=MultiQuerySplitter.split(sql),asts=[];for(let q of split.queries)if(!q.isEmpty)try{let ast=SqlParser.parse(q.sql);asts.push(ast)}catch(e){console.warn("Failed to parse SQL for diff:",q.sql,e)}return DDLGeneralizer.generalize(asts)}static buildSchema(asts){let tables=new Map,formatter2=new SqlFormatter({keywordCase:"none"});for(let ast of asts)if(ast instanceof CreateTableQuery){let qName=new QualifiedName(ast.namespaces||[],ast.tableName),key=this.getQualifiedNameKey(qName),tableModel={name:key,qualifiedName:qName,columns:new Map,constraints:[],indexes:[]};for(let col of ast.columns)tableModel.columns.set(col.name.name,{name:col.name.name,definition:col});tables.set(key,tableModel)}else if(ast instanceof AlterTableStatement){let key=this.getQualifiedNameKey(ast.table),tableModel=tables.get(key);if(tableModel)for(let action of ast.actions)if(action instanceof AlterTableAddConstraint){let formatted=formatter2.format(action.constraint).formattedSql;tableModel.constraints.push({name:action.constraint.constraintName?.name,kind:action.constraint.kind,definition:action.constraint,formatted})}else action instanceof AlterTableAddColumn&&tableModel.columns.set(action.column.name.name,{name:action.column.name.name,definition:action.column})}else if(ast instanceof CreateIndexStatement){let key=this.getQualifiedNameKey(ast.tableName),tableModel=tables.get(key);if(tableModel){let formatted=formatter2.format(ast).formattedSql;tableModel.indexes.push({name:ast.indexName.toString(),definition:ast,formatted})}}return{tables}}static compareColumns(current,expected,diffs,options){for(let[name,col]of expected.columns)current.columns.has(name)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableAddColumn({column:col.definition})]}));if(options.dropColumns)for(let[name,col]of current.columns)expected.columns.has(name)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableDropColumn({columnName:col.definition.name})]}))}static compareConstraints(current,expected,diffs,options){let formatter2=new SqlFormatter({keywordCase:"none"}),getConstraintSignature=c=>options.checkConstraintNames?c.kind==="primary-key"?c.formatted.replace(/^constraint\s+("[^"]+"|[^\s]+)\s+/i,"").trim():c.name||c.formatted:c.formatted.replace(/^constraint\s+("[^"]+"|[^\s]+)\s+/i,"").trim(),currentSignatures=new Set(current.constraints.map(getConstraintSignature));for(let expectedC of expected.constraints){let sig=getConstraintSignature(expectedC);currentSignatures.has(sig)||diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableAddConstraint({constraint:expectedC.definition})]}))}if(options.dropConstraints){let expectedSignatures=new Set(expected.constraints.map(getConstraintSignature));for(let currentC of current.constraints){let sig=getConstraintSignature(currentC);expectedSignatures.has(sig)||(currentC.name?diffs.push(new AlterTableStatement({table:expected.qualifiedName,actions:[new AlterTableDropConstraint({constraintName:new IdentifierString(currentC.name)})]})):console.warn("Cannot drop unnamed constraint:",currentC.formatted))}}}static compareIndexes(current,expected,diffs,options){let getIndexSignature=idx=>{if(options.checkConstraintNames)return idx.name;let def=idx.definition,parts=[];parts.push(def.tableName.toString()),def.unique&&parts.push("UNIQUE"),def.usingMethod&&parts.push(`USING:${def.usingMethod.toString()}`);let columnSigs=def.columns.map(col=>{let expr=col.expression.toString(),sort=col.sortOrder||"",nulls=col.nullsOrder||"";return`${expr}${sort}${nulls}`});return parts.push(`COLS:${columnSigs.join(",")}`),def.include&&def.include.length>0&&parts.push(`INCLUDE:${def.include.map(i=>i.toString()).join(",")}`),def.where&&parts.push(`WHERE:${def.where.toString()}`),parts.join("|")},currentSignatures=new Set(current.indexes.map(getIndexSignature));for(let expectedIdx of expected.indexes){let sig=getIndexSignature(expectedIdx);currentSignatures.has(sig)||diffs.push(expectedIdx.definition)}if(options.checkConstraintNames||options.dropIndexes){let expectedSignatures=new Set(expected.indexes.map(getIndexSignature));for(let currentIdx of current.indexes){let sig=getIndexSignature(currentIdx);expectedSignatures.has(sig)||diffs.push(new DropIndexStatement({indexNames:[currentIdx.definition.indexName],ifExists:!1}))}}}static getQualifiedNameKey(qName){return qName.toString()}};var SelectBodyExtractor=class{static extract(input){return typeof input=="string"?this.extractFromSql(input):this.extractFromStatement(input)}static extractFromSql(sql){let lexemes=new SqlTokenizer(sql).readLexemes();return this.isCreateViewStatement(lexemes)?this.extractCreateViewFromLexemes(lexemes):this.extractFromStatement(SqlParser.parse(sql))}static extractFromStatement(statement){if(statement instanceof CreateTableQuery){let targetName=this.createTableTargetName(statement);return statement.asSelectQuery?{supported:!0,kind:"create-table-as",targetName,selectQuery:statement.asSelectQuery}:this.unsupported(targetName)}if(statement instanceof InsertQuery){let targetName=this.insertTargetName(statement);return!statement.selectQuery||statement.selectQuery instanceof ValuesQuery?this.unsupported(targetName):{supported:!0,kind:"insert-select",targetName,selectQuery:statement.selectQuery}}return{supported:!1,kind:null,targetName:null,selectQuery:null,reason:"Statement type is not supported."}}static extractCreateViewFromLexemes(lexemes){let idx=0;idx++;let materialized=lexemes[idx]?.value.toLowerCase()==="materialized";if(materialized&&idx++,lexemes[idx]?.value.toLowerCase()!=="view")return this.unsupported(null,"Statement type is not supported.");idx++,lexemes[idx]?.value.toLowerCase()==="if not exists"&&idx++;let targetResult=FullNameParser.parseFromLexeme(lexemes,idx);idx=targetResult.newIndex;let targetName=[...targetResult.namespaces??[],targetResult.name.name].join(".");if(lexemes[idx]?.type===4&&(idx=this.consumeBalancedParentheses(lexemes,idx)),lexemes[idx]?.value.toLowerCase()!=="as")return this.unsupported(targetName);idx++;let selectResult=SelectQueryParser.parseFromLexeme(lexemes,idx);return{supported:!0,kind:materialized?"create-materialized-view":"create-view",targetName,selectQuery:selectResult.value}}static isCreateViewStatement(lexemes){if(lexemes[0]?.value.toLowerCase()!=="create")return!1;let second=lexemes[1]?.value.toLowerCase(),third=lexemes[2]?.value.toLowerCase();return second==="view"||second==="materialized"&&third==="view"}static consumeBalancedParentheses(lexemes,index){let idx=index,depth=0;for(;idx<lexemes.length;){if(lexemes[idx].type===4)depth++;else if(lexemes[idx].type===8&&(depth--,depth===0))return idx+1;idx++}return idx}static createTableTargetName(query){return[...query.namespaces??[],query.tableName.name].join(".")}static insertTargetName(query){let source=query.insertClause.source;return source.datasource instanceof TableSource?source.datasource.getSourceName():source.getAliasName()}static unsupported(targetName,reason="No embedded SELECT body found."){return{supported:!1,kind:null,targetName,selectQuery:null,reason}}};var SelectOutputCollector=class _SelectOutputCollector{constructor(tableColumnResolver=null,initialCommonTables=null){this.tableColumnResolver=tableColumnResolver;this.commonTableCollector=new CTECollector;this.commonTables=initialCommonTables??[]}collect(arg){return this.collectRaw(arg).map((item,outputIndex)=>({...item,outputIndex}))}collectRaw(arg){return arg instanceof SimpleSelectQuery?this.collectSimpleSelectQuery(arg):arg instanceof SourceExpression?this.collectSourceExpression(arg.getAliasName(),arg):arg instanceof FromClause?this.collectFromClause(arg,!0):[]}collectSimpleSelectQuery(query){let previousCommonTables=this.commonTables;this.commonTables.length===0&&(this.commonTables=this.commonTableCollector.collect(query));try{let outputs=[];for(let item of query.selectClause.items)outputs.push(...this.collectSelectItem(item,query.fromClause));return outputs}finally{this.commonTables=previousCommonTables}}collectSelectItem(item,fromClause){if(item.identifier)return[this.createExplicitOutput(item.identifier.name,item.value,fromClause)];if(!(item.value instanceof ColumnReference))return[];let columnName=item.value.column.name;return columnName==="*"?this.expandWildcard(item.value,fromClause):[this.createExplicitOutput(columnName,item.value,fromClause)]}expandWildcard(value,fromClause){if(!fromClause)return[];if(value.namespaces===null)return this.collectFromClause(fromClause,!0);let sourceName=value.getNamespace();if(fromClause.getSourceAliasName()===sourceName)return this.collectFromClause(fromClause,!1);let join=fromClause.joins?.find(item=>this.getJoinSourceName(item)===sourceName);return join?this.collectJoinClause(join):[]}collectFromClause(clause,joinCascade){let outputs=this.collectSourceExpression(clause.getSourceAliasName(),clause.source);if(clause.joins&&joinCascade)for(let join of clause.joins)outputs.push(...this.collectJoinClause(join));return outputs}collectJoinClause(clause){return this.collectSourceExpression(this.getJoinSourceName(clause),clause.source)}getJoinSourceName(clause){return clause.source.getAliasName()}collectSourceExpression(sourceName,source){if(source.aliasExpression?.columns)return source.aliasExpression.columns.map(column=>({name:column.name,value:new ColumnReference(sourceName?[sourceName]:null,column.name),sourceAlias:sourceName,sourceName:null,sourceColumnName:column.name}));let cte=this.findCommonTable(source);if(cte){let innerCommonTables=this.commonTables.filter(item=>item.getSourceAliasName()!==cte.getSourceAliasName()),innerOutputs=this.collectCteQuery(cte.query,innerCommonTables);return this.qualifyOutputs(innerOutputs,sourceName,cte.getSourceAliasName())}if(source.datasource instanceof TableSource)return this.collectTableSource(sourceName,source.datasource);if(source.datasource instanceof SubQuerySource){let innerOutputs=this.collectNestedSelectQuery(source.datasource.query);return this.qualifyOutputs(innerOutputs,sourceName,null)}return source.datasource instanceof ParenSource?[]:[]}findCommonTable(source){if(!(source.datasource instanceof TableSource))return null;let tableName=source.datasource.getSourceName();return this.commonTables.find(item=>item.getSourceAliasName()===tableName)??null}collectTableSource(sourceName,source){if(!this.tableColumnResolver)return[];let tableName=source.getSourceName(),qualifier=sourceName??tableName;return this.tableColumnResolver(tableName).map(column=>({name:column,value:new ColumnReference([qualifier],column),sourceAlias:sourceName,sourceName:tableName,sourceColumnName:column}))}collectNestedSelectQuery(query){return new _SelectOutputCollector(this.tableColumnResolver,this.commonTables).collect(query).map(({name,value,sourceAlias,sourceName,sourceColumnName})=>({name,value,sourceAlias,sourceName,sourceColumnName}))}collectCteQuery(query,commonTables){return this.isSelectQuery(query)?new _SelectOutputCollector(this.tableColumnResolver,commonTables).collect(query).map(({name,value,sourceAlias,sourceName,sourceColumnName})=>({name,value,sourceAlias,sourceName,sourceColumnName})):this.collectReturningOutputs(query)}collectReturningOutputs(query){return query instanceof InsertQuery||query instanceof UpdateQuery||query instanceof DeleteQuery||query instanceof MergeQuery?query.returningClause?this.extractReturningOutputs(query.returningClause):[]:[]}extractReturningOutputs(clause){let outputs=[];for(let item of clause.items){let name=item.identifier?.name??this.extractSelectItemName(item);name&&outputs.push(this.createExplicitOutput(name,item.value))}return outputs}extractSelectItemName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}qualifyOutputs(outputs,sourceAlias,sourceName){return outputs.map(item=>({name:item.name,value:new ColumnReference(sourceAlias?[sourceAlias]:null,item.name),sourceAlias,sourceName,sourceColumnName:item.name}))}createExplicitOutput(name,value,fromClause=null){if(value instanceof ColumnReference&&value.column.name!=="*"){let sourceMetadata=this.resolveColumnSourceMetadata(value,fromClause);if(sourceMetadata)return{name,value,...sourceMetadata}}return{name,value,sourceAlias:null,sourceName:null,sourceColumnName:null}}resolveColumnSourceMetadata(value,fromClause){if(!fromClause||value.namespaces===null)return null;let namespace=value.getNamespace(),matches=fromClause.getSources().filter(source2=>this.getSourceMatchNames(source2).includes(namespace));if(matches.length!==1)return null;let source=matches[0];return{sourceAlias:this.getColumnReferenceSourceAlias(source,namespace),sourceName:this.getColumnReferenceSourceName(source),sourceColumnName:value.column.name}}getSourceMatchNames(source){let names=new Set;if(source.aliasExpression)return names.add(source.aliasExpression.table.name),[...names];let aliasName=source.getAliasName();return aliasName&&names.add(aliasName),source.datasource instanceof TableSource&&(names.add(source.datasource.table.name),names.add(source.datasource.getSourceName())),[...names]}getColumnReferenceSourceAlias(source,namespace){return source.aliasExpression?source.aliasExpression.table.name:namespace}getColumnReferenceSourceName(source){let cte=this.findCommonTable(source);return cte?cte.getSourceAliasName():source.aliasExpression?.columns?null:source.datasource instanceof TableSource?source.datasource.getSourceName():null}isSelectQuery(query){return"__selectQueryType"in query&&query.__selectQueryType==="SelectQuery"}};var clauseOrder=["select","where","joinOn","groupBy","having","orderBy","window","limitOffset"],WildcardColumnInferenceCollector=class{constructor(){this.clauseCollector=new ClauseScopedColumnReferenceCollector;this.requirements=new Map;this.visitedQueries=new Set;this.nextObjectId=0;this.objectIds=new WeakMap}collect(query){return this.requirements.clear(),this.visitedQueries.clear(),this.nextObjectId=0,this.objectIds=new WeakMap,this.collectFromSelectQuery(query,[]),[...this.requirements.values()].map(item=>this.inferTarget(item))}collectFromSelectQuery(query,commonTables){if(this.visitedQueries.has(query))return;if(this.visitedQueries.add(query),query instanceof BinarySelectQuery){let rightCommonTables=this.mergeCommonTables(commonTables,this.collectLeadingCommonTables(query.left));this.collectFromSelectQuery(query.left,commonTables),this.collectFromSelectQuery(query.right,rightCommonTables);return}if(!(query instanceof SimpleSelectQuery))return;let scopedCommonTables=this.mergeCommonTables(commonTables,query.withClause?.tables??[]);this.collectConsumerRequirements(query,scopedCommonTables),this.collectNestedSources(query.fromClause,scopedCommonTables);for(let commonTable of query.withClause?.tables??[])this.collectCteQuery(commonTable.query,scopedCommonTables)}collectCteQuery(query,commonTables){this.isSelectQuery(query)&&this.collectFromSelectQuery(query,commonTables)}collectConsumerRequirements(query,commonTables){if(!query.fromClause)return;let targets=this.collectConsumerTargets(query.fromClause,commonTables);if(targets.length===0)return;let targetByMatchName=new Map;for(let target of targets)for(let name of this.getTargetMatchNames(target)){let existing=targetByMatchName.get(name)??[];existing.push(target),targetByMatchName.set(name,existing)}let singleUnqualifiedTarget=query.fromClause.getSources().length===1&&targets.length===1?targets[0]:null;for(let reference of this.flattenReferences(this.clauseCollector.collect(query))){if(reference.column==="*")continue;let matchedTarget=reference.namespace?this.getUniqueTarget(targetByMatchName.get(reference.namespace)??[]):singleUnqualifiedTarget;matchedTarget&&this.addRequirement(matchedTarget,reference.column,this.createRequiredBy(reference))}}collectConsumerTargets(fromClause,commonTables){let targets=[];for(let source of fromClause.getSources()){let cteTarget=this.createCteTarget(source,commonTables);if(cteTarget){targets.push(cteTarget);continue}let derivedTarget=this.createDerivedTableTarget(source);derivedTarget&&targets.push(derivedTarget)}return targets}createCteTarget(source,commonTables){if(!(source.datasource instanceof TableSource))return null;let tableName=source.datasource.getSourceName(),commonTable=commonTables.find(item=>item.getSourceAliasName()===tableName);return!commonTable||!this.isSelectQuery(commonTable.query)?null:{key:`cte:${this.getObjectId(commonTable)}`,targetKind:"cte",targetName:commonTable.getSourceAliasName(),targetAlias:source.aliasExpression?source.getAliasName():commonTable.getSourceAliasName(),query:commonTable.query}}createDerivedTableTarget(source){return source.datasource instanceof SubQuerySource?{key:`derived:${this.getObjectId(source.datasource.query)}`,targetKind:"derivedTable",targetName:null,targetAlias:source.getAliasName(),query:source.datasource.query}:null}collectNestedSources(fromClause,commonTables){if(fromClause)for(let source of fromClause.getSources())source.datasource instanceof SubQuerySource&&this.collectFromSelectQuery(source.datasource.query,commonTables)}addRequirement(target,column,requiredBy){let requirement=this.requirements.get(target.key);requirement||(requirement={descriptor:target,requiredByColumn:new Map},this.requirements.set(target.key,requirement));let existing=requirement.requiredByColumn.get(column)??[];existing.push(requiredBy),requirement.requiredByColumn.set(column,existing)}inferTarget(requirement){let descriptor=requirement.descriptor,baseResult={targetKind:descriptor.targetKind,targetName:descriptor.targetName,targetAlias:descriptor.targetAlias,wildcards:[],explicitColumns:[],requiredColumns:[],unresolvedColumns:[]};if(!(descriptor.query instanceof SimpleSelectQuery)){for(let[outputName,requiredBy]of requirement.requiredByColumn)baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"unsupportedQueryShape",[],requiredBy));return baseResult}let outputMetadata=this.collectTargetOutputMetadata(descriptor.query);baseResult.wildcards=outputMetadata.wildcards,baseResult.explicitColumns=outputMetadata.explicitColumns;for(let[outputName,requiredBy]of requirement.requiredByColumn){let explicitMatches=outputMetadata.explicitColumns.filter(item=>item.outputName===outputName),candidateWildcards=outputMetadata.wildcards;if(explicitMatches.length>0&&candidateWildcards.length>0){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"duplicateOutputOwnership",candidateWildcards,requiredBy));continue}if(explicitMatches.length>0)continue;if(outputMetadata.unqualifiedWildcardWithMultipleSources){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"unqualifiedWildcardMultipleSources",candidateWildcards,requiredBy));continue}if(candidateWildcards.length===0){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"noWildcardSupplier",[],requiredBy));continue}if(candidateWildcards.length>1){baseResult.unresolvedColumns.push(this.createUnresolved(outputName,"multipleWildcardSuppliers",candidateWildcards,requiredBy));continue}let wildcard=candidateWildcards[0];baseResult.requiredColumns.push({outputName,sourceAlias:wildcard.sourceAlias,sourceName:wildcard.sourceName,sourceColumnName:outputName,wildcard,requiredByClause:this.collectRequiredByClauses(requiredBy),requiredBy})}return baseResult}collectTargetOutputMetadata(query){let wildcards=[],unqualifiedWildcardWithMultipleSources=!1;query.selectClause.items.forEach((item,outputIndex)=>{let wildcard=this.collectWildcardMetadata(item,outputIndex,query.fromClause);if(wildcard==="unqualifiedWildcardMultipleSources"){unqualifiedWildcardWithMultipleSources=!0,wildcards.push({kind:"unqualified",outputIndex,sourceAlias:null,sourceName:null});return}wildcard&&wildcards.push(wildcard)});let explicitColumns=new SelectOutputCollector().collect(query).filter(item=>!(item.value instanceof ColumnReference&&item.value.column.name==="*")).map(item=>({outputName:item.name,sourceAlias:item.sourceAlias,sourceName:item.sourceName,sourceColumnName:item.sourceColumnName}));return{wildcards,explicitColumns,unqualifiedWildcardWithMultipleSources}}collectWildcardMetadata(item,outputIndex,fromClause){if(!(item.value instanceof ColumnReference)||item.value.column.name!=="*"||!fromClause)return null;if(item.value.namespaces===null){let sources=fromClause.getSources();return sources.length!==1?"unqualifiedWildcardMultipleSources":{kind:"unqualified",outputIndex,sourceAlias:sources[0].getAliasName(),sourceName:this.getSourceName(sources[0])}}let namespace=item.value.getNamespace(),source=this.getUniqueSource(fromClause.getSources().filter(candidate=>this.getSourceMatchNames(candidate).includes(namespace)));return{kind:"qualified",outputIndex,sourceAlias:namespace,sourceName:source?this.getSourceName(source):null}}createUnresolved(outputName,reason,candidateWildcards,requiredBy){return{outputName,reason,candidateWildcards,requiredByClause:this.collectRequiredByClauses(requiredBy),requiredBy}}flattenReferences(references){return clauseOrder.flatMap(clause=>references[clause])}createRequiredBy(reference){return{clause:reference.clause,qualifiedName:reference.qualifiedName,namespace:reference.namespace,column:reference.column}}collectRequiredByClauses(requiredBy){let clauses=new Set(requiredBy.map(item=>item.clause));return clauseOrder.filter(clause=>clauses.has(clause))}getTargetMatchNames(target){return target.targetAlias?[target.targetAlias]:target.targetName?[target.targetName]:[]}getUniqueTarget(targets){return targets.length===1?targets[0]:null}getUniqueSource(sources){return sources.length===1?sources[0]:null}getSourceMatchNames(source){let names=new Set,aliasName=source.getAliasName();return aliasName&&names.add(aliasName),source.datasource instanceof TableSource&&(names.add(source.datasource.table.name),names.add(source.datasource.getSourceName())),[...names]}getSourceName(source){return source.datasource instanceof TableSource?source.datasource.getSourceName():null}collectLeadingCommonTables(query){return query instanceof SimpleSelectQuery?query.withClause?.tables??[]:query instanceof BinarySelectQuery?this.collectLeadingCommonTables(query.left):[]}mergeCommonTables(left,right){let merged=[...left];for(let table of right){let existingIndex=merged.findIndex(item=>item.getSourceAliasName()===table.getSourceAliasName());existingIndex===-1?merged.push(table):merged[existingIndex]=table}return merged}getObjectId(value){let existing=this.objectIds.get(value);if(existing!==void 0)return existing;let id=this.nextObjectId++;return this.objectIds.set(value,id),id}isSelectQuery(query){return!!query&&typeof query=="object"&&"__selectQueryType"in query&&query.__selectQueryType==="SelectQuery"}};var ParameterDetector=class{static extractParameterNames(query){return ParameterCollector.collect(query).map(p=>p.name.value)}static hasParameter(query,parameterName){return this.extractParameterNames(query).includes(parameterName)}static separateFilters(query,filter){let hardcodedParamNames=this.extractParameterNames(query),hardcodedParams={},dynamicFilters={};for(let[key,value]of Object.entries(filter))hardcodedParamNames.includes(key)?hardcodedParams[key]=value:dynamicFilters[key]=value;return{hardcodedParams,dynamicFilters}}};var FilterableItem=class{constructor(name,type,tableName){this.name=name;this.type=type;this.tableName=tableName}},FilterableItemCollector=class{constructor(tableColumnResolver,options){this.tableColumnResolver=tableColumnResolver,this.options={qualified:!1,upstream:!0,...options}}collect(query){let items=[],columnItems=this.collectColumns(query);items.push(...columnItems);let parameterItems=this.collectParameters(query);return items.push(...parameterItems),this.removeDuplicates(items)}collectColumns(query){let items=[];try{let columns=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:this.options.upstream}).collect(query);for(let column of columns){let tableName,realTableName;if(column.value&&typeof column.value.getNamespace=="function"){let namespace=column.value.getNamespace();namespace&&namespace.trim()!==""&&(tableName=namespace,this.options.qualified&&(realTableName=this.getRealTableName(query,namespace)))}tableName||(tableName=this.inferTableNameFromQuery(query),tableName&&this.options.qualified&&(realTableName=tableName));let columnName=column.name;this.options.qualified&&(realTableName||tableName)&&(columnName=`${realTableName||tableName}.${column.name}`),items.push(new FilterableItem(columnName,"column",tableName))}}catch(error){console.warn("Failed to collect columns with SelectableColumnCollector, using fallback:",error);try{let schemas=new SchemaCollector(this.tableColumnResolver,!0).collect(query);for(let schema of schemas)for(let columnName of schema.columns){let finalColumnName=columnName;this.options.qualified&&(finalColumnName=`${schema.name}.${columnName}`),items.push(new FilterableItem(finalColumnName,"column",schema.name))}}catch(fallbackError){console.warn("Failed to collect columns with both approaches:",error,fallbackError)}}return items}inferTableNameFromQuery(query){if(query instanceof SimpleSelectQuery&&query.fromClause&&query.fromClause.source){let datasource=query.fromClause.source.datasource;if(datasource&&typeof datasource.table=="object"){let table=datasource.table;if(table&&typeof table.name=="string")return table.name}}}getRealTableName(query,aliasOrName){try{let simpleQuery=query.type==="WITH"?query.toSimpleQuery():query;if(simpleQuery instanceof SimpleSelectQuery&&simpleQuery.fromClause){if(simpleQuery.fromClause.source?.datasource){let mainSource=simpleQuery.fromClause.source,realName=this.extractRealTableName(mainSource,aliasOrName);if(realName)return realName}let fromClause=simpleQuery.fromClause;if(fromClause.joinClauses&&Array.isArray(fromClause.joinClauses)){for(let joinClause of fromClause.joinClauses)if(joinClause.source?.datasource){let realName=this.extractRealTableName(joinClause.source,aliasOrName);if(realName)return realName}}}}catch(error){console.warn("Error resolving real table name:",error)}return aliasOrName}extractRealTableName(source,aliasOrName){try{let datasource=source.datasource;if(!datasource)return;let alias=source.alias||source.aliasExpression?.table?.name,realTableName=datasource.table?.name;if(alias===aliasOrName&&realTableName||!alias&&realTableName===aliasOrName)return realTableName}catch{}}collectParameters(query){let items=[];try{let parameterNames=ParameterDetector.extractParameterNames(query);for(let paramName of parameterNames)items.push(new FilterableItem(paramName,"parameter"))}catch(error){console.warn("Failed to collect parameters:",error)}return items}removeDuplicates(items){let seen=new Set,result=[];for(let item of items){let key=`${item.type}:${item.name}:${item.tableName||"none"}`;seen.has(key)||(seen.add(key),result.push(item))}return result.sort((a,b)=>{if(a.type!==b.type)return a.type==="column"?-1:1;if(a.type==="column"){let tableA=a.tableName||"",tableB=b.tableName||"";if(tableA!==tableB)return tableA.localeCompare(tableB)}return a.name.localeCompare(b.name)})}};var SqlSortInjector=class{constructor(tableColumnResolver){this.tableColumnResolver=tableColumnResolver}static removeOrderBy(query){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for ORDER BY removal");return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:null,windowClause:query.windowClause,limitClause:query.limitClause,offsetClause:query.offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}inject(query,sortConditions){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for sorting");let availableColumns=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query);for(let columnName of Object.keys(sortConditions))if(!availableColumns.find(item=>item.name===columnName))throw new Error(`Column or alias '${columnName}' not found in current query`);let newOrderByItems=[];for(let[columnName,condition]of Object.entries(sortConditions)){let columnEntry=availableColumns.find(item=>item.name===columnName);if(!columnEntry)continue;let columnRef=columnEntry.value;this.validateSortCondition(columnName,condition);let sortDirection;condition.desc?sortDirection="desc":sortDirection="asc";let nullsPosition=null;condition.nullsFirst?nullsPosition="first":condition.nullsLast&&(nullsPosition="last");let orderByItem=new OrderByItem(columnRef,sortDirection,nullsPosition);newOrderByItems.push(orderByItem)}let finalOrderByItems=[];query.orderByClause?finalOrderByItems=[...query.orderByClause.order,...newOrderByItems]:finalOrderByItems=newOrderByItems;let newOrderByClause=finalOrderByItems.length>0?new OrderByClause(finalOrderByItems):null;return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:newOrderByClause,windowClause:query.windowClause,limitClause:query.limitClause,offsetClause:query.offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}validateSortCondition(columnName,condition){if(condition.asc&&condition.desc)throw new Error(`Conflicting sort directions for column '${columnName}': both asc and desc specified`);if(condition.nullsFirst&&condition.nullsLast)throw new Error(`Conflicting nulls positions for column '${columnName}': both nullsFirst and nullsLast specified`);if(!condition.asc&&!condition.desc&&!condition.nullsFirst&&!condition.nullsLast)throw new Error(`Empty sort condition for column '${columnName}': at least one sort option must be specified`)}};var SqlPaginationInjector=class{inject(query,pagination){if(this.validatePaginationOptions(pagination),typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for pagination");if(query.limitClause||query.offsetClause)throw new Error("Query already contains LIMIT or OFFSET clause. Use removePagination() first if you want to override existing pagination.");let offset=(pagination.page-1)*pagination.pageSize,limitClause=new LimitClause(new ParameterExpression("paging_limit",pagination.pageSize)),offsetClause=new OffsetClause(new ParameterExpression("paging_offset",offset));return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:query.orderByClause,windowClause:query.windowClause,limitClause,offsetClause,fetchClause:query.fetchClause,forClause:query.forClause})}static removePagination(query){if(typeof query=="string"&&(query=SelectQueryParser.parse(query)),!(query instanceof SimpleSelectQuery))throw new Error("Complex queries are not supported for pagination removal");return new SimpleSelectQuery({withClause:query.withClause,selectClause:query.selectClause,fromClause:query.fromClause,whereClause:query.whereClause,groupByClause:query.groupByClause,havingClause:query.havingClause,orderByClause:query.orderByClause,windowClause:query.windowClause,limitClause:null,offsetClause:null,fetchClause:query.fetchClause,forClause:query.forClause})}validatePaginationOptions(pagination){if(!pagination)throw new Error("Pagination options are required");if(typeof pagination.page!="number"||pagination.page<1)throw new Error("Page number must be a positive integer (1 or greater)");if(typeof pagination.pageSize!="number"||pagination.pageSize<1)throw new Error("Page size must be a positive integer (1 or greater)");if(pagination.pageSize>1e3)throw new Error("Page size cannot exceed 1000 items")}};var SqlParameterBinder=class{constructor(options={}){this.options={requireAllParameters:!0,...options}}bind(query,parameterValues){let modifiedQuery=query,existingParams=ParameterDetector.extractParameterNames(modifiedQuery);if(this.options.requireAllParameters){let missingParams=existingParams.filter(paramName=>!(paramName in parameterValues)||parameterValues[paramName]===void 0);if(missingParams.length>0)throw new Error(`Missing values for required parameters: ${missingParams.join(", ")}`)}for(let[paramName,value]of Object.entries(parameterValues))if(existingParams.includes(paramName))try{ParameterHelper.set(modifiedQuery,paramName,value)}catch(error){throw new Error(`Failed to bind parameter '${paramName}': ${error instanceof Error?error.message:"Unknown error"}`)}return modifiedQuery}bindToSimpleQuery(query,parameterValues){return this.bind(query,parameterValues)}};var NAMESPACE_SEPARATOR="|",normalizeIdentifier=input=>{let value=input?.trim()??"";return value===""?"":value.toLowerCase()},normalizeColumnSetKey=columns=>columns.map(column=>normalizeIdentifier(column)).filter(Boolean).sort().join(NAMESPACE_SEPARATOR),buildSchemaMap=schemaInfo=>{let map=new Map;for(let table of schemaInfo){let normalizedName=normalizeIdentifier(table.name);if(!normalizedName)continue;let columnSet=new Set(table.columns.map(normalizeIdentifier).filter(Boolean)),uniqueSetKeys=new Set;for(let uniqueKey of table.uniqueKeys){let normalizedKey=normalizeColumnSetKey(uniqueKey);normalizedKey&&uniqueSetKeys.add(normalizedKey)}columnSet.size===0&&uniqueSetKeys.size===0||map.set(normalizedName,{columnSet,uniqueSetKeys})}return map},collectReferenceMetadata=query=>{let collector=new ColumnReferenceCollector,namespaceCounts=new Map,unqualifiedColumns=new Set;for(let ref of collector.collect(query)){let namespace=normalizeIdentifier(ref.getNamespace());if(namespace)namespaceCounts.set(namespace,(namespaceCounts.get(namespace)??0)+1);else{let column=normalizeIdentifier(ref.column.name);column&&unqualifiedColumns.add(column)}}let joinConditionCounts=new Map;if(query.fromClause?.joins)for(let join of query.fromClause.joins){let counts=new Map;if(join.condition&&join.condition instanceof JoinOnClause){let joinCollector=new ColumnReferenceCollector;for(let ref of joinCollector.collect(join.condition.condition)){let namespace=normalizeIdentifier(ref.getNamespace());namespace&&counts.set(namespace,(counts.get(namespace)??0)+1)}}joinConditionCounts.set(join,counts)}return{namespaceCounts,unqualifiedColumns,joinConditionCounts}},isLeftJoin=join=>join.joinType.value.toLowerCase().includes("left"),getJoinIdentifiers=join=>{let identifiers=new Set,alias=normalizeIdentifier(join.source.getAliasName());if(alias&&identifiers.add(alias),join.source.datasource instanceof TableSource){let rawName=join.source.datasource.getSourceName();rawName&&identifiers.add(normalizeIdentifier(rawName));let shortName=normalizeIdentifier(join.source.datasource.table.name);shortName&&identifiers.add(shortName)}return[...identifiers]},hasExternalReferences=(identifiers,metadata,join)=>{let local=metadata.joinConditionCounts.get(join)??new Map;for(let identifier of identifiers){let total=metadata.namespaceCounts.get(identifier)??0,localCount=local.get(identifier)??0;if(total-localCount>0)return!0}return!1},getJoinColumnInfo=(join,identifiers)=>{if(!(join.condition instanceof JoinOnClause))return null;let expression=join.condition.condition;if(!(expression instanceof BinaryExpression)||expression.operator.value.trim().toLowerCase()!=="=")return null;let resolveColumn=component=>component instanceof ColumnReference?component:null,leftRef=resolveColumn(expression.left),rightRef=resolveColumn(expression.right);if(!leftRef||!rightRef)return null;let normalizedLeftNamespace=normalizeIdentifier(leftRef.getNamespace()),normalizedRightNamespace=normalizeIdentifier(rightRef.getNamespace());return identifiers.has(normalizedLeftNamespace)?normalizeIdentifier(leftRef.column.name):identifiers.has(normalizedRightNamespace)?normalizeIdentifier(rightRef.column.name):null},shouldRemoveJoin=(join,schemaMap,metadata)=>{if(!isLeftJoin(join)||join.lateral||!(join.source.datasource instanceof TableSource))return!1;let candidates=[normalizeIdentifier(join.source.datasource.getSourceName()),normalizeIdentifier(join.source.datasource.table.name)].filter(Boolean),tableInfo;for(let candidate of candidates){let info=schemaMap.get(candidate);if(info){tableInfo=info;break}}if(!tableInfo)return!1;let identifiers=new Set(getJoinIdentifiers(join));if(identifiers.size===0||hasExternalReferences([...identifiers],metadata,join))return!1;let joinColumn=getJoinColumnInfo(join,identifiers);if(!joinColumn||metadata.unqualifiedColumns.has(joinColumn)||tableInfo.columnSet.size>0&&!tableInfo.columnSet.has(joinColumn))return!1;let uniqueKey=normalizeColumnSetKey([joinColumn]);return!!tableInfo.uniqueSetKeys.has(uniqueKey)},optimizeSimpleQuery=(query,schemaMap)=>{if(!query.fromClause?.joins?.length)return!1;let metadata=collectReferenceMetadata(query),retainedJoins=[],removed=!1;for(let join of query.fromClause.joins){if(shouldRemoveJoin(join,schemaMap,metadata)){removed=!0;continue}retainedJoins.push(join)}return query.fromClause.joins=retainedJoins.length>0?retainedJoins:null,removed},traverseSelectQuery=(query,schemaMap)=>{if(query instanceof SimpleSelectQuery)return optimizeSimpleQuery(query,schemaMap);if(query instanceof BinarySelectQuery){let leftChanged=traverseSelectQuery(query.left,schemaMap),rightChanged=traverseSelectQuery(query.right,schemaMap);return leftChanged||rightChanged}return!1},optimizeUnusedLeftJoinsOnce=(query,schemaMap)=>schemaMap.size===0?!1:traverseSelectQuery(query,schemaMap),optimizeUnusedLeftJoins=(query,schemaInfo)=>(optimizeUnusedLeftJoinsOnce(query,buildSchemaMap(schemaInfo)),query),optimizeUnusedLeftJoinsToFixedPoint=(query,schemaInfo)=>{let schemaMap=buildSchemaMap(schemaInfo),changed=!0;for(;changed;)changed=optimizeUnusedLeftJoinsOnce(query,schemaMap);return query},collectTableSourceNames=component=>{let collector=new CTETableReferenceCollector,names=new Set;for(let source of collector.collect(component)){let normalizedName=normalizeIdentifier(source.table.name);normalizedName&&names.add(normalizedName)}return names},isReferencedByOthers=(cteName,mainReferences,cteReferenceMap)=>{if(mainReferences.has(cteName))return!0;for(let[otherName,references]of cteReferenceMap)if(otherName!==cteName&&references.has(cteName))return!0;return!1},optimizeSimpleQueryCtes=query=>{let withClause=query.withClause;if(!withClause||withClause.recursive||withClause.tables.length===0)return!1;let mainReferences=collectTableSourceNames(query),cteReferenceMap=new Map;for(let table of withClause.tables){let normalizedName=normalizeIdentifier(table.aliasExpression.table.name);normalizedName&&cteReferenceMap.set(normalizedName,collectTableSourceNames(table.query))}let removableNames=[];for(let table of withClause.tables){let normalizedName=normalizeIdentifier(table.aliasExpression.table.name);if(!normalizedName)continue;let body=table.query;!(body instanceof SimpleSelectQuery)&&!(body instanceof BinarySelectQuery)||isReferencedByOthers(normalizedName,mainReferences,cteReferenceMap)||removableNames.push(normalizedName)}if(removableNames.length===0)return!1;for(let name of removableNames)query.removeCTE(name);return!0},optimizeCtesInSelectQuery=query=>{if(query instanceof SimpleSelectQuery)return optimizeSimpleQueryCtes(query);if(query instanceof BinarySelectQuery){let leftChanged=optimizeCtesInSelectQuery(query.left),rightChanged=optimizeCtesInSelectQuery(query.right);return leftChanged||rightChanged}return!1},optimizeUnusedCtesOnce=query=>optimizeCtesInSelectQuery(query),optimizeUnusedCtes=query=>(optimizeUnusedCtesOnce(query),query),optimizeUnusedCtesToFixedPoint=query=>{let changed=!0;for(;changed;)changed=optimizeUnusedCtesOnce(query);return query};var isBinaryOperator=(expression,operator)=>expression instanceof BinaryExpression&&expression.operator.value.trim().toLowerCase()===operator,unwrapSingleOuterParen=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},unwrapOptionalGuardParameter=expression=>{let candidate=unwrapSingleOuterParen(expression);for(;candidate instanceof CastExpression;)candidate=unwrapSingleOuterParen(candidate.input);if(candidate instanceof FunctionCall&&getFunctionCallName(candidate)==="cast"&&candidate.argument){let argument=unwrapSingleOuterParen(candidate.argument);if(isBinaryOperator(argument,"as"))return unwrapOptionalGuardParameter(argument.left)}return candidate},getFunctionCallName=expression=>{let name=expression.qualifiedName.name;return"value"in name?name.value.toLowerCase():name.name.toLowerCase()},collectTopLevelAndTerms=expression=>{let candidate=unwrapSingleOuterParen(expression);return isBinaryOperator(candidate,"and")?[...collectTopLevelAndTerms(candidate.left),...collectTopLevelAndTerms(candidate.right)]:[expression]},collectTopLevelOrTerms=expression=>{let candidate=unwrapSingleOuterParen(expression);return isBinaryOperator(candidate,"or")?[...collectTopLevelOrTerms(candidate.left),...collectTopLevelOrTerms(candidate.right)]:[expression]},isNullLiteral=expression=>expression instanceof LiteralValue&&expression.value===null||expression instanceof RawString&&expression.value.trim().toLowerCase()==="null",isTrueSentinel=expression=>{let candidate=unwrapSingleOuterParen(expression);return candidate instanceof LiteralValue?candidate.value===!0:isBinaryOperator(candidate,"=")?candidate.left instanceof LiteralValue&&candidate.right instanceof LiteralValue&&candidate.left.value===1&&candidate.right.value===1:!1},getGuardedParameterName=expression=>{let candidate=unwrapSingleOuterParen(expression);if(!isBinaryOperator(candidate,"is"))return null;let left=unwrapOptionalGuardParameter(candidate.left);return!(left instanceof ParameterExpression)||!isNullLiteral(candidate.right)?null:left.name.value},getUniqueParameterNames=expression=>new Set(ParameterCollector.collect(expression).map(parameter=>parameter.name.value)),isSupportedMeaningfulBranch=(expression,parameterName)=>{let candidate=unwrapSingleOuterParen(expression);if(candidate instanceof ParameterExpression)return!1;let parameterNames=getUniqueParameterNames(candidate);return parameterNames.size!==1||!parameterNames.has(parameterName)?!1:!(candidate instanceof LiteralValue||candidate instanceof RawString)},isExplicitPruningTarget=(pruningParameters,parameterName)=>Object.prototype.hasOwnProperty.call(pruningParameters,parameterName),isKnownAbsentTarget=(pruningParameters,parameterName)=>{if(!isExplicitPruningTarget(pruningParameters,parameterName))return!1;let parameterValue=pruningParameters[parameterName];return parameterValue==null},shouldPruneOptionalBranch=(expression,pruningParameters)=>{let branch=getSupportedOptionalConditionBranch(expression);return branch!==null&&isKnownAbsentTarget(pruningParameters,branch.parameterName)},rebuildAndCondition=terms=>{if(terms.length===0)return null;let condition=terms[0];for(let index=1;index<terms.length;index+=1)condition=new BinaryExpression(condition,"and",terms[index]);return condition},pruneSimpleQueryWhereClause=(query,pruningParameters)=>{if(!query.whereClause)return!1;let topLevelTerms=collectTopLevelAndTerms(query.whereClause.condition),retainedTerms=[],prunedAnyBranch=!1;for(let term of topLevelTerms){if(shouldPruneOptionalBranch(term,pruningParameters)){prunedAnyBranch=!0;continue}retainedTerms.push(term)}if(!prunedAnyBranch)return!1;let cleanedTerms=retainedTerms.filter(term=>!isTrueSentinel(term)),rebuiltCondition=rebuildAndCondition(cleanedTerms);return query.whereClause=rebuiltCondition?new WhereClause(rebuiltCondition):null,!0},isSelectQueryNode=value=>value instanceof SimpleSelectQuery||value instanceof BinarySelectQuery,traverseNestedSelectQueries=(root,pruningParameters)=>{let changed=!1,visited=new WeakSet,walk=value=>{if(!(!value||typeof value!="object")&&!visited.has(value)){if(visited.add(value),value!==root&&isSelectQueryNode(value)){changed=traverseSelectQuery2(value,pruningParameters)||changed;return}if(Array.isArray(value)){value.forEach(walk);return}for(let child of Object.values(value))walk(child)}};return walk(root),changed},traverseSelectQuery2=(query,pruningParameters)=>{if(query instanceof SimpleSelectQuery){let selfChanged=pruneSimpleQueryWhereClause(query,pruningParameters),nestedChanged=traverseNestedSelectQueries(query,pruningParameters);return selfChanged||nestedChanged}if(query instanceof BinarySelectQuery){let leftChanged=traverseSelectQuery2(query.left,pruningParameters),rightChanged=traverseSelectQuery2(query.right,pruningParameters);return leftChanged||rightChanged}return!1},getSupportedOptionalConditionBranch=expression=>{let orTerms=collectTopLevelOrTerms(expression);if(orTerms.length<2)return null;let guardTerms=orTerms.map(term=>({term,parameterName:getGuardedParameterName(term)})).filter(candidate=>candidate.parameterName!==null);if(guardTerms.length!==1)return null;let[{term:guardTerm,parameterName}]=guardTerms,meaningfulTerms=orTerms.filter(term=>term!==guardTerm);return meaningfulTerms.length===0||!meaningfulTerms.every(term=>isSupportedMeaningfulBranch(term,parameterName))?null:{parameterName,kind:"expression"}},collectSupportedBranchesFromSimpleQuery=(query,branches)=>{if(!query.whereClause)return;let topLevelTerms=collectTopLevelAndTerms(query.whereClause.condition);for(let term of topLevelTerms){let branch=getSupportedOptionalConditionBranch(term);branch&&branches.push({query,parameterName:branch.parameterName,expression:term,kind:branch.kind})}},collectSupportedBranchesFromSelectQuery=(query,branches)=>{if(query instanceof SimpleSelectQuery){collectSupportedBranchesFromSimpleQuery(query,branches),traverseNestedSelectQueriesForCollection(query,branches);return}query instanceof BinarySelectQuery&&(collectSupportedBranchesFromSelectQuery(query.left,branches),collectSupportedBranchesFromSelectQuery(query.right,branches))},traverseNestedSelectQueriesForCollection=(root,branches)=>{let visited=new WeakSet,walk=value=>{if(!(!value||typeof value!="object")&&!visited.has(value)){if(visited.add(value),value!==root&&isSelectQueryNode(value)){collectSupportedBranchesFromSelectQuery(value,branches);return}if(Array.isArray(value)){value.forEach(walk);return}for(let child of Object.values(value))walk(child)}};walk(root)},pruneOptionalConditionBranches=(query,pruningParameters)=>(Object.keys(pruningParameters).length===0||traverseSelectQuery2(query,pruningParameters),query),collectSupportedOptionalConditionBranches=query=>{let branches=[];return collectSupportedBranchesFromSelectQuery(query,branches),branches},collectSupportedOptionalConditionBranchSpans=sql=>{let parsed=SelectQueryParser.parse(sql),supportedBranches=collectSupportedOptionalConditionBranches(parsed);if(supportedBranches.length===0)return[];let candidates=collectOptionalConditionSpanCandidates(sql),remainingSupportedCounts=countSupportedBranchesByKey(supportedBranches);assertUnambiguousCandidateCounts(candidates,remainingSupportedCounts);let spans=[];for(let candidate of candidates){let key=getSupportedBranchKey(candidate),remainingCount=remainingSupportedCounts.get(key)??0;remainingCount<=0||(spans.push(candidate),remainingSupportedCounts.set(key,remainingCount-1))}return assertNoMissingSupportedBranches(remainingSupportedCounts),spans},getSupportedBranchKey=branch=>`${branch.kind}:${branch.parameterName}`,countSupportedBranchesByKey=branches=>{let counts=new Map;for(let branch of branches){let key=getSupportedBranchKey(branch);counts.set(key,(counts.get(key)??0)+1)}return counts},assertUnambiguousCandidateCounts=(candidates,supportedCounts)=>{let candidateCounts=countSupportedBranchesByKey(candidates);for(let[key,supportedCount]of supportedCounts){let candidateCount=candidateCounts.get(key)??0;if(candidateCount<supportedCount)throw new Error(`Could not locate source range for supported optional condition branch '${key}'.`);if(candidateCount>supportedCount)throw new Error(`Ambiguous source ranges for supported optional condition branch '${key}'.`)}},assertNoMissingSupportedBranches=supportedCounts=>{let missingKeys=[...supportedCounts.entries()].filter(([,count])=>count>0).map(([key])=>key);if(missingKeys.length>0)throw new Error(`Could not locate source ranges for supported optional condition branches: ${missingKeys.join(", ")}.`)},collectOptionalConditionSpanCandidates=sql=>{let lexemes=new SqlTokenizer(sql).readLexemes(),candidates=[],stack=[];for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];if(isOpenParen(lexeme)){stack.push(index);continue}if(!isCloseParen(lexeme))continue;let openParenIndex=stack.pop();if(openParenIndex===void 0)continue;let candidate=buildOptionalConditionSpanCandidate(sql,lexemes,openParenIndex,index);candidate&&candidates.push(candidate)}return candidates.sort((left,right)=>left.sourceRange.start-right.sourceRange.start)},buildOptionalConditionSpanCandidate=(sql,lexemes,openParenIndex,closeParenIndex)=>{let inside=lexemes.slice(openParenIndex+1,closeParenIndex),orTermRanges=splitTopLevelTermsByKeyword(inside,"or");if(orTermRanges.length<2)return null;let guardTerms=orTermRanges.map(range=>({range,parameterName:getGuardedParameterNameFromLexemes(inside.slice(range.start,range.end))})).filter(candidate=>candidate.parameterName!==null);if(guardTerms.length!==1)return null;let[{range:guardRange,parameterName}]=guardTerms,meaningfulTerms=orTermRanges.filter(range=>range!==guardRange);if(meaningfulTerms.length===0||!meaningfulTerms.every(range=>isSupportedMeaningfulBranchFromLexemes(inside.slice(range.start,range.end),parameterName)))return null;let expandedRange=expandWrappingParenRange(lexemes,openParenIndex,closeParenIndex),sourceStart=requiredPosition(lexemes[expandedRange.openParenIndex]).startPosition,sourceEnd=requiredPosition(lexemes[expandedRange.closeParenIndex]).endPosition,removalRange=getRemovalRange(sql,lexemes,expandedRange.openParenIndex,expandedRange.closeParenIndex);return{parameterName,kind:"expression",sourceRange:{start:sourceStart,end:sourceEnd,text:sql.slice(sourceStart,sourceEnd)},removalRange,openParenIndex:expandedRange.openParenIndex,closeParenIndex:expandedRange.closeParenIndex}},expandWrappingParenRange=(lexemes,openParenIndex,closeParenIndex)=>{let expandedOpenParenIndex=openParenIndex,expandedCloseParenIndex=closeParenIndex;for(;isOpenParen(lexemes[expandedOpenParenIndex-1])&&isCloseParen(lexemes[expandedCloseParenIndex+1]);)expandedOpenParenIndex-=1,expandedCloseParenIndex+=1;return{openParenIndex:expandedOpenParenIndex,closeParenIndex:expandedCloseParenIndex}},splitTopLevelTermsByKeyword=(lexemes,keyword)=>{let ranges=[],depth=0,start=0;for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];if(isOpenParen(lexeme)){depth+=1;continue}if(isCloseParen(lexeme)){depth-=1;continue}depth===0&&isKeyword(lexeme,keyword)&&(ranges.push({start,end:index}),start=index+1)}return ranges.push({start,end:lexemes.length}),ranges},getGuardedParameterNameFromLexemes=lexemes=>{let compact=lexemes.filter(lexeme=>!isWrappingParen(lexeme)),isIndexKeyword=(index,keyword)=>{let lexeme=compact[index];return lexeme!==void 0&&isKeyword(lexeme,keyword)};if(compact.length===3)return!isParameter(compact[0])||!isIndexKeyword(1,"is")||!isIndexKeyword(2,"null")?null:normalizeParameterName(compact[0].value);if(compact.length===5&&isParameter(compact[0])&&compact[1]?.value==="::"&&isIndexKeyword(3,"is")&&isIndexKeyword(4,"null"))return normalizeParameterName(compact[0].value);if(compact.length>=6&&isIndexKeyword(0,"cast")&&isParameter(compact[1])&&isIndexKeyword(2,"as")){let isIndex=compact.findIndex((lexeme,index)=>index>2&&isKeyword(lexeme,"is"));if(isIndex>=0&&isIndexKeyword(isIndex+1,"null"))return normalizeParameterName(compact[1].value)}return null},isSupportedMeaningfulBranchFromLexemes=(lexemes,parameterName)=>{try{let parsed=ValueParser.parseFromLexeme(lexemes,0);return parsed.newIndex!==lexemes.length?!1:isSupportedMeaningfulBranch(parsed.value,parameterName)}catch{return!1}},getRemovalRange=(sql,lexemes,openParenIndex,closeParenIndex)=>{let previous=lexemes[openParenIndex-1],next=lexemes[closeParenIndex+1],start=requiredPosition(lexemes[openParenIndex]).startPosition,end=requiredPosition(lexemes[closeParenIndex]).endPosition;return previous&&isKeyword(previous,"and")?start=requiredPosition(previous).startPosition:next&&isKeyword(next,"and")?end=requiredPosition(next).endPosition:previous&&isKeyword(previous,"where")&&(start=requiredPosition(previous).startPosition),{start,end,text:sql.slice(start,end)}},isParameter=lexeme=>(lexeme.type&256)!==0,isOpenParen=lexeme=>(lexeme.type&4)!==0,isCloseParen=lexeme=>(lexeme.type&8)!==0,isKeyword=(lexeme,keyword)=>lexeme.value.toLowerCase()===keyword,isWrappingParen=lexeme=>isOpenParen(lexeme)||isCloseParen(lexeme),normalizeParameterName=value=>value.startsWith("${")&&value.endsWith("}")?value.slice(2,-1):value.replace(/^[:@$]/,""),requiredPosition=lexeme=>{if(!lexeme.position)throw new Error(`Lexeme '${lexeme.value}' is missing source position metadata.`);return lexeme.position};var DynamicQueryBuilder=class{constructor(resolverOrOptions){typeof resolverOrOptions=="function"?this.tableColumnResolver=resolverOrOptions:resolverOrOptions&&(this.tableColumnResolver=resolverOrOptions.tableColumnResolver,this.defaultSchemaInfo=resolverOrOptions.schemaInfo)}buildQuery(sqlContent,options={}){let removedOptions=options;if("serialize"in removedOptions||"jsonb"in removedOptions)throw new Error("DynamicQueryBuilder SQL-result JSON shaping has been removed. Keep SQL results as rows and use generated AOT mappers so the executed SQL remains debuggable.");let parsedQuery;try{parsedQuery=SelectQueryParser.parse(sqlContent)}catch(error){throw new Error(`Failed to parse SQL: ${error instanceof Error?error.message:"Unknown error"}`)}let modifiedQuery=parsedQuery;if(options.filter&&Object.keys(options.filter).length>0){let{hardcodedParams,dynamicFilters}=ParameterDetector.separateFilters(modifiedQuery,options.filter);if(Object.keys(hardcodedParams).length>0&&(modifiedQuery=new SqlParameterBinder({requireAllParameters:!1}).bind(modifiedQuery,hardcodedParams)),Object.keys(dynamicFilters).length>0)throw new Error("DynamicQueryBuilder no longer injects runtime filter predicates. Use `ashiba query optional add` to author optional filters, `ashiba query optional refresh` to refresh them, and `optionalConditionParameters` at runtime for pruning only.")}if(options.sort&&Object.keys(options.sort).length>0){let sortInjector=new SqlSortInjector(this.tableColumnResolver),simpleQuery=QueryBuilder.buildSimpleQuery(modifiedQuery);modifiedQuery=sortInjector.inject(simpleQuery,options.sort)}if(options.paging){let{page=1,pageSize}=options.paging;if(pageSize!==void 0){let paginationInjector=new SqlPaginationInjector,paginationOptions={page,pageSize},simpleQuery=QueryBuilder.buildSimpleQuery(modifiedQuery);modifiedQuery=paginationInjector.inject(simpleQuery,paginationOptions)}}modifiedQuery=this.applyColumnFilters(modifiedQuery,options);let optionalConditionParameters=this.resolveOptionalConditionPruningParameters(options);Object.keys(optionalConditionParameters).length>0&&(modifiedQuery=pruneOptionalConditionBranches(modifiedQuery,optionalConditionParameters));let effectiveSchemaInfo=options.schemaInfo??this.defaultSchemaInfo;return options.removeUnusedLeftJoins&&effectiveSchemaInfo?.length&&(modifiedQuery=optimizeUnusedLeftJoinsToFixedPoint(modifiedQuery,effectiveSchemaInfo)),options.removeUnusedCtes&&(modifiedQuery=optimizeUnusedCtesToFixedPoint(modifiedQuery)),modifiedQuery}resolveOptionalConditionPruningParameters(options){if(options.optionalConditionParameters)return options.optionalConditionParameters;if(!options.optionalConditionParameterStates)return{};let legacyParameters={};for(let[parameterName,state]of Object.entries(options.optionalConditionParameterStates))legacyParameters[parameterName]=state==="absent"?null:"__RAWSQL_OPTIONAL_CONDITION_PRESENT__";return legacyParameters}applyColumnFilters(query,options){let hasIncludeFilters=Array.isArray(options.includeColumns)&&options.includeColumns.length>0,hasExcludeFilters=Array.isArray(options.excludeColumns)&&options.excludeColumns.length>0;if(!hasIncludeFilters&&!hasExcludeFilters)return query;if(hasIncludeFilters&&hasExcludeFilters)throw new Error("includeColumns and excludeColumns cannot be used together.");let simpleQuery=QueryBuilder.buildSimpleQuery(query),metadata=simpleQuery.selectClause.items.map(item=>{let name=this.getSelectItemName(item);return{item,normalized:name?this.normalizeColumnIdentifier(name):null}}),availableColumns=new Set(metadata.map(entry=>entry.normalized).filter(name=>name!==null)),includeFilters=hasIncludeFilters?this.normalizeColumnList(options.includeColumns):null,excludeFilters=hasExcludeFilters?this.normalizeColumnList(options.excludeColumns):null,includeSet=includeFilters?new Set(includeFilters.map(entry=>entry.normalized)):null,excludeSet=excludeFilters?new Set(excludeFilters.map(entry=>entry.normalized)):null;if(includeFilters){let missing=includeFilters.filter(entry=>!availableColumns.has(entry.normalized));if(missing.length>0)throw new Error(`Column${missing.length===1?"":"s"} not found in SELECT clause: ${missing.map(entry=>`'${entry.original}'`).join(", ")}.`)}if(excludeFilters){let missing=excludeFilters.filter(entry=>!availableColumns.has(entry.normalized));if(missing.length>0)throw new Error(`Column${missing.length===1?"":"s"} not found in SELECT clause: ${missing.map(entry=>`'${entry.original}'`).join(", ")}.`)}let filteredItems=metadata.filter(entry=>entry.normalized?includeSet?includeSet.has(entry.normalized):excludeSet?!excludeSet.has(entry.normalized):!0:!0).map(entry=>entry.item);if(filteredItems.length===0)throw new Error("Column filtering removed every SELECT item.");return simpleQuery.selectClause.items=filteredItems,simpleQuery}normalizeColumnList(columns){return columns.map(column=>{if(typeof column!="string")throw new Error("Column filters must be strings.");let trimmed=column.trim();if(trimmed==="")throw new Error("Column filters must not be empty.");return{normalized:this.normalizeColumnIdentifier(trimmed),original:trimmed}})}normalizeColumnIdentifier(value){return value.trim().toLowerCase()}getSelectItemName(item){return item.identifier?item.identifier.name:item.value instanceof ColumnReference?item.value.column.name:null}buildFilteredQuery(sqlContent,filter){return this.buildQuery(sqlContent,{filter})}buildSortedQuery(sqlContent,sort){return this.buildQuery(sqlContent,{sort})}buildPaginatedQuery(sqlContent,paging){return this.buildQuery(sqlContent,{paging})}validateSql(sqlContent){try{return SelectQueryParser.parse(sqlContent),!0}catch(error){throw new Error(`Invalid SQL: ${error instanceof Error?error.message:"Unknown error"}`)}}};var formatter=null,formatSqlComponent=(component,options={})=>options.formatter?options.formatter(component):options.formatOptions?new SqlFormatter({exportComment:!0,...options.formatOptions}).format(component).formattedSql:(formatter??=new SqlFormatter({exportComment:!0}),formatter.format(component).formattedSql),hasSqlComponentFormatOverride=(options={})=>!!(options.formatter||options.formatOptions);var SUPPORTED_SCALAR_OPERATORS=new Set(["=","<>","<","<=",">",">=","like","ilike"]),normalizeIdentifier2=value=>value.trim().toLowerCase(),normalizeSql=value=>value.replace(/\s+/g," ").trim().toLowerCase(),normalizeRewriteTokenType=lexeme=>(lexeme.type&128)!==0?128:(lexeme.type&64)!==0?64:lexeme.type,normalizeRewriteTokenValue=lexeme=>(lexeme.type&128)!==0?lexeme.value.toLowerCase():lexeme.value,tokenizeForRewritePlan=sql=>new SqlTokenizer(sql).tokenize().map(lexeme=>({type:normalizeRewriteTokenType(lexeme),value:normalizeRewriteTokenValue(lexeme)})),tokenSequencesEqual=(left,right)=>left.length!==right.length?!1:left.every((token,index)=>{let other=right[index];return other!==void 0&&token.type===other.type&&token.value===other.value}),collectCommentFragments=sql=>new SqlTokenizer(sql).tokenize().flatMap(lexeme=>lexeme.positionedComments?lexeme.positionedComments.flatMap(positioned=>positioned.comments):lexeme.comments?[...lexeme.comments]:[]),commentsPreservedInOrder=(before,after)=>{let cursor=0;for(let comment of before){let foundAt=after.indexOf(comment,cursor);if(foundAt<0)return!1;cursor=foundAt+1}return!0},countCommandToken=(tokens,value)=>tokens.filter(token=>token.type===128&&token.value===value).length,applyRewriteEdits=(sql,edits)=>[...edits].sort((left,right)=>right.start-left.start).reduce((current,edit)=>current.slice(0,edit.start)+edit.after+current.slice(edit.end),sql),getStatementEndPosition=sql=>{let end=sql.length;for(;end>0&&/\s/.test(sql[end-1]);)end--;if(end>0&&sql[end-1]===";")for(end--;end>0&&/\s/.test(sql[end-1]);)end--;return end},clauseBoundaryCommands=new Set(["group by","having","order by","limit","offset","fetch","for"]),isClauseBoundary=lexeme=>(lexeme.type&128)!==0&&clauseBoundaryCommands.has(lexeme.value.toLowerCase()),findMinimalWhereInsertPosition=sql=>{let lexemes=new SqlTokenizer(sql).tokenize(),statementEnd=getStatementEndPosition(sql),topLevelLexemes=[],depth=0;for(let index=0;index<lexemes.length;index+=1){let lexeme=lexemes[index];(lexeme.type&8)!==0&&(depth=Math.max(0,depth-1)),depth===0&&topLevelLexemes.push({lexeme,index}),(lexeme.type&4)!==0&&(depth+=1)}let where=topLevelLexemes.find(entry=>(entry.lexeme.type&128)!==0&&entry.lexeme.value.toLowerCase()==="where");return where?{position:topLevelLexemes.filter(entry=>entry.index>where.index).map(entry=>entry.lexeme).find(isClauseBoundary)?.position?.startPosition??statementEnd,hasWhere:!0}:{position:topLevelLexemes.map(entry=>entry.lexeme).find(isClauseBoundary)?.position?.startPosition??statementEnd,hasWhere:!1}},findMatchingParenEnd=(sql,start)=>{let depth=0,quote=null;for(let index=start;index<sql.length;index++){let char=sql[index];if(quote){if(char===quote){if(quote==="'"&&sql[index+1]==="'"){index++;continue}quote=null}continue}if(char==="'"||char==='"'){quote=char;continue}if(char==="("&&depth++,char===")"&&(depth--,depth===0))return index+1}return-1},findOptionalBranchSpans=(sql,parameterName)=>{let spans=[],parameterNeedle=`:${parameterName.toLowerCase()}`,lowerSql=sql.toLowerCase();for(let index=0;index<sql.length;index++){if(sql[index]!=="(")continue;let end=findMatchingParenEnd(sql,index);if(end<0)break;let text=sql.slice(index,end),normalized=lowerSql.slice(index,end);normalized.includes(parameterNeedle)&&normalized.includes(" is null")&&normalized.includes(" or ")&&spans.push({start:index,end,text}),index=end-1}return spans},findBooleanOperatorBefore=(sql,start)=>{let prefix=sql.slice(0,start),match=/(\s+)(and|or)(\s*)$/i.exec(prefix);return!match||match.index===void 0?null:{start:match.index,end:start,value:match[2].toLowerCase()}},findBooleanOperatorAfter=(sql,end)=>{let suffix=sql.slice(end),match=/^(\s*)(and|or)(\s+)/i.exec(suffix);return match?{start:end,end:end+match[0].length,value:match[2].toLowerCase()}:null},findWhereBefore=(sql,position)=>{let lexemes=new SqlTokenizer(sql).tokenize(),found=null;for(let lexeme of lexemes){if((lexeme.position?.startPosition??0)>=position)break;(lexeme.type&128)!==0&&lexeme.value.toLowerCase()==="where"&&(found=lexeme)}return found?.position?{start:found.position.startPosition,end:found.position.endPosition}:null},findSourceColumnReferenceText=(sql,reference)=>{let namespace=normalizeIdentifier2(reference.getNamespace()),column=normalizeIdentifier2(reference.column.name),lexemes=new SqlTokenizer(sql).tokenize();for(let index=0;index<lexemes.length-2;index++){let first=lexemes[index],dot=lexemes[index+1],last=lexemes[index+2];if(!((first.type&64)===0||dot.value!=="."||(last.type&64)===0)&&!(normalizeIdentifier2(first.value)!==namespace||normalizeIdentifier2(last.value)!==column)&&!(!first.position||!last.position))return sql.slice(first.position.startPosition,last.position.endPosition)}return normalizeColumnReferenceText(reference)},normalizeColumnReferenceKey=reference=>`${normalizeIdentifier2(reference.getNamespace())}.${normalizeIdentifier2(reference.column.name)}`,normalizeColumnReferenceText=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},normalizeScalarOperator=value=>{if(!value)return"=";let normalized=value.trim().toLowerCase();if(normalized==="!=")return"<>";if(SUPPORTED_SCALAR_OPERATORS.has(normalized))return normalized;throw new Error(`Unsupported SSSQL operator '${value}'.`)},isExplicitEqualityScaffoldValue=value=>{if(value==null)return!0;if(Array.isArray(value))return!1;if(typeof value!="object")return!0;let entries=Object.entries(value).filter(([,entry])=>entry!==void 0);return entries.length===1&&entries[0]?.[0]==="="},parseQualifiedFilterName=filterName=>{let segments=filterName.split(".");if(segments.length!==2)return null;let[table,column]=segments.map(segment=>segment.trim());return!table||!column?null:{table,column}},makeParameterName=filterName=>filterName.trim().replace(/\./g,"_").replace(/[^a-zA-Z0-9_]/g,"_"),unwrapParens=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator2=(expression,operator)=>expression instanceof BinaryExpression&&expression.operator.value.trim().toLowerCase()===operator,collectTopLevelAndTerms2=expression=>{let candidate=unwrapParens(expression);return isBinaryOperator2(candidate,"and")?[...collectTopLevelAndTerms2(candidate.left),...collectTopLevelAndTerms2(candidate.right)]:[expression]},collectTopLevelOrTerms2=expression=>{let candidate=unwrapParens(expression);return isBinaryOperator2(candidate,"or")?[...collectTopLevelOrTerms2(candidate.left),...collectTopLevelOrTerms2(candidate.right)]:[expression]},getGuardedParameterName2=expression=>{let candidate=unwrapParens(expression);if(!isBinaryOperator2(candidate,"is"))return null;let left=unwrapOptionalGuardParameter2(candidate.left);if(!(left instanceof ParameterExpression))return null;let right=unwrapParens(candidate.right);return right instanceof LiteralValue&&right.value===null||right instanceof RawString&&right.value.trim().toLowerCase()==="null"?left.name.value:null},unwrapOptionalGuardParameter2=expression=>{let candidate=unwrapParens(expression);for(;candidate instanceof CastExpression;)candidate=unwrapParens(candidate.input);if(candidate instanceof FunctionCall&&getFunctionCallName2(candidate)==="cast"&&candidate.argument){let argument=unwrapParens(candidate.argument);if(isBinaryOperator2(argument,"as"))return unwrapOptionalGuardParameter2(argument.left)}return candidate},getFunctionCallName2=expression=>{let name=expression.qualifiedName.name;return"value"in name?name.value.toLowerCase():name.name.toLowerCase()},buildOptionalScalarBranch=(column,parameterName,operator)=>{let guard=new BinaryExpression(new ParameterExpression(parameterName),"is",new LiteralValue(null)),predicate=new BinaryExpression(new ColumnReference(column.getNamespace()||null,column.column.name),operator,new ParameterExpression(parameterName));return new ParenExpression(new BinaryExpression(guard,"or",predicate))},buildOptionalExistsBranch=(parameterName,subquery,kind)=>{let guard=new BinaryExpression(new ParameterExpression(parameterName),"is",new LiteralValue(null)),existsExpression=new UnaryExpression("exists",new InlineQuery(subquery)),predicate=kind==="exists"?existsExpression:new UnaryExpression("not",existsExpression);return new ParenExpression(new BinaryExpression(guard,"or",predicate))},rebuildWhereWithoutTerm=(query,termToRemove)=>{if(!query.whereClause)return;let terms=collectTopLevelAndTerms2(query.whereClause.condition).filter(term=>term!==termToRemove);if(terms.length===0){query.whereClause=null;return}let rebuilt=terms[0];for(let index=1;index<terms.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",terms[index]);query.whereClause=new WhereClause(rebuilt)},enforceSubqueryConstraints=sql=>{if(!sql.trim())throw new Error("SSSQL EXISTS/NOT EXISTS scaffold query must not be empty.");if(sql.includes(";"))throw new Error("SSSQL EXISTS/NOT EXISTS scaffold query must not contain semicolons or multiple statements.");if(/\blateral\b/i.test(sql))throw new Error("LATERAL is not supported in SSSQL EXISTS/NOT EXISTS scaffold.")},substituteAnchorPlaceholders=(sql,formattedColumns)=>{let usedIndexes=new Set,replaced=sql.replace(/\$c(\d+)/g,(_,indexDigits)=>{let index=Number(indexDigits);if(!Number.isInteger(index))throw new Error(`Invalid placeholder '$c${indexDigits}' in SSSQL scaffold query.`);if(index<0||index>=formattedColumns.length)throw new Error(`Placeholder '$c${index}' references a missing SSSQL scaffold anchor column.`);return usedIndexes.add(index),formattedColumns[index]});if(formattedColumns.length===0)return replaced;for(let index=0;index<formattedColumns.length;index+=1)if(!usedIndexes.has(index))throw new Error(`Missing placeholder '$c${index}' for SSSQL scaffold anchor column.`);return replaced},getScalarBranchDetails=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]);if(!(predicate instanceof BinaryExpression))return null;let left=unwrapParens(predicate.left),right=unwrapParens(predicate.right);if(left instanceof ColumnReference&&right instanceof ParameterExpression&&right.name.value===parameterName)try{return{operator:normalizeScalarOperator(predicate.operator.value),target:normalizeColumnReferenceText(left),column:left}}catch{return null}if(right instanceof ColumnReference&&left instanceof ParameterExpression&&left.name.value===parameterName)try{return{operator:normalizeScalarOperator(predicate.operator.value),target:normalizeColumnReferenceText(right),column:right}}catch{return null}return null},hasSelectQuery=value=>typeof value=="object"&&value!==null&&"selectQuery"in value,collectColumnReferencesDeep=value=>{let references=[],visited=new WeakSet,walk=candidate=>{if(!(!candidate||typeof candidate!="object")){if(candidate instanceof ColumnReference){references.push(candidate);return}if(!visited.has(candidate)){if(visited.add(candidate),Array.isArray(candidate)){for(let item of candidate)walk(item);return}for(let child of Object.values(candidate))walk(child)}}};return walk(value),references},getExistsBranchKind=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]),isInlineQueryValue=value=>value instanceof InlineQuery||hasSelectQuery(value);if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="exists")return isInlineQueryValue(unwrapParens(predicate.expression))?"exists":null;if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not exists")return isInlineQueryValue(unwrapParens(predicate.expression))?"not-exists":null;if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not"&&unwrapParens(predicate.expression)instanceof UnaryExpression){let nested=unwrapParens(predicate.expression);if(nested.operator.value.trim().toLowerCase()==="exists"&&isInlineQueryValue(unwrapParens(nested.expression)))return"not-exists"}return null},getExistsPredicateDetails=(expression,parameterName)=>{let meaningfulTerms=collectTopLevelOrTerms2(expression).filter(term=>getGuardedParameterName2(term)!==parameterName);if(meaningfulTerms.length!==1)return null;let predicate=unwrapParens(meaningfulTerms[0]),isInlineQueryValue=value=>value instanceof InlineQuery||hasSelectQuery(value);if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="exists"){let candidate=unwrapParens(predicate.expression);return isInlineQueryValue(candidate)?{kind:"exists",subquery:candidate.selectQuery}:null}if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not exists"){let candidate=unwrapParens(predicate.expression);return isInlineQueryValue(candidate)?{kind:"not-exists",subquery:candidate.selectQuery}:null}if(predicate instanceof UnaryExpression&&predicate.operator.value.trim().toLowerCase()==="not"&&unwrapParens(predicate.expression)instanceof UnaryExpression){let nested=unwrapParens(predicate.expression),candidate=unwrapParens(nested.expression);if(nested.operator.value.trim().toLowerCase()==="exists"&&isInlineQueryValue(candidate))return{kind:"not-exists",subquery:candidate.selectQuery}}return null},getBranchInfo=branch=>{let scalar=getScalarBranchDetails(branch.expression,branch.parameterName);if(scalar)return{parameterName:branch.parameterName,kind:"scalar",operator:scalar.operator,target:scalar.target,query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)};let existsKind=getExistsBranchKind(branch.expression,branch.parameterName);return existsKind?{parameterName:branch.parameterName,kind:existsKind,query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)}:{parameterName:branch.parameterName,kind:"expression",query:branch.query,expression:branch.expression,sql:formatSqlComponent(branch.expression)}},isEquivalentScalarBranch=(branch,query,parameterName,operator,targetColumnText)=>branch.query===query&&branch.kind==="scalar"&&branch.parameterName===parameterName&&branch.operator===operator&&branch.target!==void 0&&normalizeIdentifier2(branch.target)===normalizeIdentifier2(targetColumnText),SSSQLFilterBuilder=class{constructor(tableColumnResolver){this.tableColumnResolver=tableColumnResolver;this.finder=new UpstreamSelectQueryFinder(this.tableColumnResolver)}list(query){let parsed=this.parseQuery(query);return collectSupportedOptionalConditionBranches(parsed).map(getBranchInfo)}planScaffold(query,filters){if(typeof query=="string"){let entries=Object.entries(filters);if(entries.length===1){let[filterName,filterValue]=entries[0];if(isExplicitEqualityScaffoldValue(filterValue))try{return this.planScalarInsert(query,{target:filterName,parameterName:makeParameterName(filterName),operator:"="})}catch{}}}return this.planRewrite(query,parsed=>this.scaffold(parsed,filters))}dryRunScaffold(query,filters){return this.planScaffold(query,filters)}planScaffoldBranch(query,spec){if(typeof query=="string"&&(spec.kind==="exists"||spec.kind==="not-exists"))try{return this.planExistsInsert(query,spec)}catch{}if(typeof query=="string"&&spec.kind!=="exists"&&spec.kind!=="not-exists")try{return this.planScalarInsert(query,spec)}catch{}return this.planRewrite(query,parsed=>this.scaffoldBranch(parsed,spec))}dryRunScaffoldBranch(query,spec){return this.planScaffoldBranch(query,spec)}planRefresh(query,filters){if(typeof query=="string")try{let parsed=SelectQueryParser.parse(query);if(!this.refreshParsed(parsed,filters).changed)return this.buildPlanFromEdits(query,[],[],[])}catch{}return this.planRewrite(query,parsed=>this.refresh(parsed,filters))}dryRunRefresh(query,filters){return this.planRefresh(query,filters)}planRemove(query,spec){if(typeof query=="string")try{return this.planBranchRemoval(query,spec)}catch{}return this.planRewrite(query,parsed=>this.remove(parsed,spec))}dryRunRemove(query,spec){return this.planRemove(query,spec)}planRemoveAll(query){return this.planRewrite(query,parsed=>this.removeAll(parsed))}dryRunRemoveAll(query){return this.planRemoveAll(query)}scaffold(query,filters){let parsed=this.parseQuery(query);for(let[filterName,filterValue]of Object.entries(filters)){if(!isExplicitEqualityScaffoldValue(filterValue))throw new Error(`SSSQL scaffold only supports equality filters in v1. Use structured scaffold or refresh for pre-authored branches: '${filterName}'.`);this.scaffoldBranch(parsed,{target:filterName,parameterName:makeParameterName(filterName),operator:"="})}return parsed}scaffoldBranch(query,spec){let parsed=this.parseQuery(query);return spec.kind==="exists"||spec.kind==="not-exists"?(this.scaffoldExistsBranch(parsed,spec),parsed):(this.scaffoldScalarBranch(parsed,spec),parsed)}refresh(query,filters){let parsed=this.parseQuery(query);return this.refreshParsed(parsed,filters),parsed}refreshParsed(parsed,filters){let changed=!1;for(let[filterName,filterValue]of Object.entries(filters)){let parameterName=filterName,target=null,matches=collectSupportedOptionalConditionBranches(parsed).filter(branch=>branch.parameterName===parameterName);if(matches.length===0&&(target=this.resolveTarget(parsed,filterName),parameterName=target.parameterName,matches=collectSupportedOptionalConditionBranches(parsed).filter(branch=>branch.parameterName===parameterName)),matches.length===0){if(target||(target=this.resolveTarget(parsed,filterName),parameterName=target.parameterName),!isExplicitEqualityScaffoldValue(filterValue))throw new Error(`No existing SSSQL branch was found for '${filterName}', and v1 scaffold only supports equality filters.`);this.scaffoldScalarBranch(parsed,{target:filterName,parameterName:target.parameterName,operator:"="}),changed=!0;continue}if(matches.length>1)throw new Error(`Multiple SSSQL branches matched parameter ':${parameterName}'. Refresh is ambiguous.`);let[match]=matches;if(!match)continue;let scalarDetails=getScalarBranchDetails(match.expression,match.parameterName);if(scalarDetails&&this.isNullableBranchColumn(match.query,scalarDetails.column))continue;let correlatedPlan=this.buildCorrelatedRefreshPlan(parsed,match);if(correlatedPlan){if(correlatedPlan.target.query===match.query)continue;this.rebaseMovedBranchByAlias(match.expression,correlatedPlan.sourceAlias,correlatedPlan.target.column),rebuildWhereWithoutTerm(match.query,match.expression),correlatedPlan.target.query.appendWhere(match.expression),changed=!0;continue}let scalarPlan=scalarDetails?this.buildScalarRefreshPlan(parsed,match,scalarDetails):null;if(scalarPlan){if(scalarPlan.query===match.query)continue;this.rebaseMovedBranch(match.expression,match.query,scalarPlan.column),rebuildWhereWithoutTerm(match.query,match.expression),scalarPlan.query.appendWhere(match.expression),changed=!0;continue}!target&&(target=this.tryResolveTarget(parsed,filterName),!target)||match.query!==target.query&&(this.rebaseMovedBranch(match.expression,match.query,target.column),rebuildWhereWithoutTerm(match.query,match.expression),target.query.appendWhere(match.expression),changed=!0)}return{query:parsed,changed}}remove(query,spec){let parsed=this.parseQuery(query),matches=this.findMatchingBranchInfos(parsed,spec);if(matches.length===0)return parsed;if(matches.length>1)throw new Error(`Multiple SSSQL branches matched parameter ':${spec.parameterName}'. Remove is ambiguous.`);let[match]=matches;return match&&rebuildWhereWithoutTerm(match.query,match.expression),parsed}removeAll(query){let parsed=this.parseQuery(query),matches=this.list(parsed);for(let match of matches)rebuildWhereWithoutTerm(match.query,match.expression);return parsed}parseQuery(query){return typeof query=="string"?SelectQueryParser.parse(query):query}planScalarInsert(sourceSql,spec){let parsed=SelectQueryParser.parse(sourceSql),target=this.resolveTarget(parsed,spec.target);if(target.query!==parsed)return this.planRewrite(sourceSql,query=>this.scaffoldBranch(query,spec));let parameterName=spec.parameterName?.trim()||target.parameterName,operator=normalizeScalarOperator(spec.operator),targetColumnText=findSourceColumnReferenceText(sourceSql,target.column),branchSql=`(:${parameterName} is null or ${targetColumnText} ${operator} :${parameterName})`,normalizedBranch=normalizeSql(branchSql);return this.list(parsed).find(existing=>existing.query===target.query&&normalizeSql(existing.sql)===normalizedBranch||isEquivalentScalarBranch(existing,target.query,parameterName,operator,targetColumnText))?this.buildPlanFromEdits(sourceSql,[],[],[]):this.buildMinimalInsertPlan(sourceSql,branchSql,{branchKind:"scalar",parameterName,column:targetColumnText})}planExistsInsert(sourceSql,spec){let parameterName=spec.parameterName.trim();if(!parameterName)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires parameterName.");if(spec.anchorColumns.length===0)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires at least one anchorColumn.");let parsed=SelectQueryParser.parse(sourceSql),anchorTargets=spec.anchorColumns.map(anchorColumn=>this.resolveTarget(parsed,anchorColumn)),targetQueries=[...new Set(anchorTargets.map(target=>target.query))];if(targetQueries.length!==1)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold anchor columns must resolve within one query scope.");let targetQuery=targetQueries[0];if(targetQuery!==parsed)return this.planRewrite(sourceSql,query=>this.scaffoldBranch(query,spec));let sourceColumns=anchorTargets.map(target=>findSourceColumnReferenceText(sourceSql,target.column)),substitutedSql=substituteAnchorPlaceholders(spec.query,sourceColumns).trim();enforceSubqueryConstraints(substitutedSql);let subquery=SelectQueryParser.parse(substitutedSql),parameterNames=new Set(ParameterCollector.collect(subquery).map(parameter=>parameter.name.value));if(parameterNames.size!==1||!parameterNames.has(parameterName))throw new Error(`SSSQL ${spec.kind.toUpperCase()} scaffold query must reference only parameter ':${parameterName}'.`);let branchSql=`(:${parameterName} is null or ${spec.kind==="not-exists"?"not exists":"exists"} (${substitutedSql}))`;return this.list(parsed).find(existing=>existing.query===targetQuery&&normalizeSql(existing.sql)===normalizeSql(branchSql))?this.buildPlanFromEdits(sourceSql,[],[],[]):this.buildMinimalInsertPlan(sourceSql,branchSql,{branchKind:spec.kind,parameterName,column:sourceColumns.join(", ")})}buildMinimalInsertPlan(sourceSql,branchSql,target){let insertPosition=findMinimalWhereInsertPosition(sourceSql),prefix=`${insertPosition.position===0||!/\s/.test(sourceSql[insertPosition.position-1])?" ":""}${insertPosition.hasWhere?"and":"where"} `,suffix=insertPosition.position<getStatementEndPosition(sourceSql)?" ":"",branchLabel=target.branchKind==="scalar"?"scalar":target.branchKind,edit={start:insertPosition.position,end:insertPosition.position,before:"",after:`${prefix}${branchSql}${suffix}`,kind:"insert",reason:insertPosition.hasWhere?`Append SSSQL ${branchLabel} branch to the existing WHERE clause.`:`Create a WHERE clause for the SSSQL ${branchLabel} branch.`,target},changedRegions=[{kind:"target-branch",start:edit.start+prefix.length,end:edit.start+edit.after.length-suffix.length,message:`Inserted SSSQL ${branchLabel} optional branch.`}];return insertPosition.hasWhere?changedRegions.unshift({kind:"boolean-operator",start:edit.start,end:edit.start+prefix.length,message:`Inserted AND before the SSSQL ${branchLabel} branch.`}):changedRegions.unshift({kind:"where-keyword",start:edit.start,end:edit.start+prefix.length,message:`Inserted WHERE before the SSSQL ${branchLabel} branch.`}),this.buildPlanFromEdits(sourceSql,[edit],changedRegions,[])}planBranchRemoval(sourceSql,spec){let parsed=SelectQueryParser.parse(sourceSql),matches=this.findMatchingBranchInfos(parsed,spec);if(matches.length>1)return this.buildPlanFromEdits(sourceSql,[],[],[],[{code:"REWRITE_FAILED",message:"SSSQL remove planning found multiple matching branches.",detail:`Multiple SSSQL branches matched parameter ':${spec.parameterName}'. Remove is ambiguous.`}]);if(matches.length===0)return this.buildPlanFromEdits(sourceSql,[],[],[]);let branchSpans=findOptionalBranchSpans(sourceSql,spec.parameterName);if(branchSpans.length>1)return this.planRewrite(sourceSql,query=>this.remove(query,spec));let span=branchSpans[0];if(!span)return this.planRewrite(sourceSql,query=>this.remove(query,spec));let beforeOperator=findBooleanOperatorBefore(sourceSql,span.start),afterOperator=findBooleanOperatorAfter(sourceSql,span.end),where=findWhereBefore(sourceSql,span.start),start=span.start,end=span.end,changedRegions=[{kind:"target-branch",start:span.start,end:span.end,message:"Removed SSSQL optional branch."}];if(beforeOperator)start=beforeOperator.start,changedRegions.unshift({kind:"boolean-operator",start:beforeOperator.start,end:beforeOperator.end,message:`Removed adjacent ${beforeOperator.value.toUpperCase()} before the SSSQL branch.`});else if(afterOperator)end=afterOperator.end,changedRegions.push({kind:"boolean-operator",start:afterOperator.start,end:afterOperator.end,message:`Removed adjacent ${afterOperator.value.toUpperCase()} after the SSSQL branch.`});else if(where){for(start=where.start;end<sourceSql.length&&/\s/.test(sourceSql[end]);)end++;changedRegions.unshift({kind:"where-keyword",start:where.start,end:where.end,message:"Removed WHERE because the SSSQL branch was the only condition."})}let edit={start,end,before:sourceSql.slice(start,end),after:"",kind:"delete",reason:"Remove the targeted SSSQL optional branch from the source SQL.",target:{branchKind:matches[0].kind,parameterName:matches[0].parameterName,column:matches[0].target}};return this.buildPlanFromEdits(sourceSql,[edit],changedRegions,[])}buildPlanFromEdits(sourceSql,edits,changedRegions,warnings,errors=[]){let plannedSql=errors.length===0?applyRewriteEdits(sourceSql,edits):void 0,beforeTokens=tokenizeForRewritePlan(sourceSql),beforeComments=collectCommentFragments(sourceSql),afterTokens=plannedSql!==void 0?tokenizeForRewritePlan(plannedSql):[],afterComments=plannedSql!==void 0?collectCommentFragments(plannedSql):[],commentsPreserved=plannedSql!==void 0?commentsPreservedInOrder(beforeComments,afterComments):!1,changedOnlyTargetBranches=errors.length===0&&changedRegions.every(region=>region.kind==="target-branch"||region.kind==="where-keyword"||region.kind==="boolean-operator"||region.kind==="parentheses")&&commentsPreserved,planWarnings=[...warnings];if(plannedSql!==void 0&&applyRewriteEdits(sourceSql,edits)!==plannedSql&&(errors=[...errors,{code:"APPLY_PLAN_MISMATCH",message:"Applying SSSQL rewrite plan edits did not reproduce the planned SQL."}]),plannedSql!==void 0)try{SelectQueryParser.parse(plannedSql)}catch(error){errors=[...errors,{code:"PARSE_AFTER_FAILED",message:"The SQL produced by SSSQL rewrite planning could not be parsed.",detail:error instanceof Error?error.message:error}]}return plannedSql!==void 0&&!commentsPreserved&&planWarnings.push({code:"COMMENTS_NOT_PRESERVED",message:"One or more input SQL comments are missing or reordered after the SSSQL rewrite."}),{ok:errors.length===0,requiresFullReformat:!1,edits,sql:plannedSql,safety:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length,tokenSequencePreserved:plannedSql!==void 0?tokenSequencesEqual(beforeTokens,afterTokens):!1,commentsPreserved,changedOnlyTargetBranches,changedRegions},warnings:planWarnings,errors}}planRewrite(query,rewrite){let warnings=[],errors=[],sourceSql=typeof query=="string"?query:formatSqlComponent(query);typeof query!="string"&&warnings.push({code:"SOURCE_SQL_UNAVAILABLE",message:"SSSQL rewrite planning received an AST, so the source SQL had to be formatter-generated before analysis."});let beforeTokens=[],beforeComments=[];try{beforeTokens=tokenizeForRewritePlan(sourceSql),beforeComments=collectCommentFragments(sourceSql)}catch(error){errors.push({code:"TOKENIZE_BEFORE_FAILED",message:"Could not tokenize the input SQL before SSSQL rewrite planning.",detail:error instanceof Error?error.message:error})}let plannedSql,afterTokens=[],afterComments=[];if(errors.length===0)try{let parsed=SelectQueryParser.parse(sourceSql),rewritten=rewrite(parsed);plannedSql=formatSqlComponent(rewritten)}catch(error){errors.push({code:"REWRITE_FAILED",message:"SSSQL rewrite planning could not produce a rewritten query.",detail:error instanceof Error?error.message:error})}if(plannedSql!==void 0){try{SelectQueryParser.parse(plannedSql)}catch(error){errors.push({code:"PARSE_AFTER_FAILED",message:"The SQL produced by SSSQL rewrite planning could not be parsed.",detail:error instanceof Error?error.message:error})}try{afterTokens=tokenizeForRewritePlan(plannedSql),afterComments=collectCommentFragments(plannedSql)}catch(error){errors.push({code:"TOKENIZE_AFTER_FAILED",message:"Could not tokenize the SQL produced by SSSQL rewrite planning.",detail:error instanceof Error?error.message:error})}}let edits=plannedSql!==void 0&&plannedSql!==sourceSql?[{start:0,end:sourceSql.length,before:sourceSql,after:plannedSql,kind:"replace",reason:"Current SSSQL rewrite planning is backed by AST rewrite plus formatter output."}]:[],changedRegions=edits.length>0?[{kind:"formatter-rewrite",start:0,end:sourceSql.length,message:"The conservative SSSQL rewrite plan requires replacing formatter output for the full SQL text."}]:[],requiresFullReformat=edits.length>0,tokenSequencePreserved=plannedSql!==void 0?tokenSequencesEqual(beforeTokens,afterTokens):!1,commentsPreserved=plannedSql!==void 0?commentsPreservedInOrder(beforeComments,afterComments):!1,changedOnlyTargetBranches=edits.length===0;return requiresFullReformat&&warnings.push({code:"FULL_REFORMAT_REQUIRED",message:"The current SSSQL rewrite plan can only represent the change as a full SQL replacement."}),plannedSql!==void 0&&!tokenSequencePreserved&&warnings.push({code:"TOKEN_SEQUENCE_CHANGED",message:"The SQL token sequence changes after the SSSQL rewrite. The conservative planner cannot prove that only target branches changed.",detail:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length}}),plannedSql!==void 0&&!commentsPreserved&&warnings.push({code:"COMMENTS_NOT_PRESERVED",message:"One or more input SQL comments are missing or reordered after the SSSQL rewrite."}),plannedSql!==void 0&&countCommandToken(afterTokens,"as")>countCommandToken(beforeTokens,"as")&&warnings.push({code:"OPTIONAL_ALIAS_AS_ADDED",message:"The rewrite output contains more AS tokens than the input, which may indicate formatter-added aliases."}),plannedSql!==void 0&&!sourceSql.includes('"')&&plannedSql.includes('"')&&warnings.push({code:"IDENTIFIER_QUOTES_ADDED",message:"The rewrite output contains double-quoted identifiers that were not present in the input SQL."}),{ok:errors.length===0,requiresFullReformat,edits,sql:plannedSql,safety:{tokenCountBefore:beforeTokens.length,tokenCountAfter:afterTokens.length,tokenSequencePreserved,commentsPreserved,changedOnlyTargetBranches,changedRegions},warnings,errors}}findMatchingBranchInfos(root,spec){let normalizedOperator=spec.operator?normalizeScalarOperator(spec.operator):void 0,normalizedTarget=spec.target?normalizeIdentifier2(spec.target):void 0;return this.list(root).filter(branch=>!(branch.parameterName!==spec.parameterName||spec.kind&&branch.kind!==spec.kind||normalizedOperator&&branch.operator!==normalizedOperator||normalizedTarget&&(!branch.target||normalizeIdentifier2(branch.target)!==normalizedTarget)))}scaffoldScalarBranch(root,spec){let target=this.resolveTarget(root,spec.target),parameterName=spec.parameterName?.trim()||target.parameterName,operator=normalizeScalarOperator(spec.operator),branch=buildOptionalScalarBranch(target.column,parameterName,operator),branchSql=normalizeSql(formatSqlComponent(branch));this.list(root).find(existing=>existing.query===target.query&&normalizeSql(existing.sql)===branchSql)||target.query.appendWhere(branch)}scaffoldExistsBranch(root,spec){let parameterName=spec.parameterName.trim();if(!parameterName)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires parameterName.");if(spec.anchorColumns.length===0)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold requires at least one anchorColumn.");let anchorTargets=spec.anchorColumns.map(anchorColumn=>this.resolveTarget(root,anchorColumn)),targetQueries=[...new Set(anchorTargets.map(target=>target.query))];if(targetQueries.length!==1)throw new Error("SSSQL EXISTS/NOT EXISTS scaffold anchor columns must resolve within one query scope.");let targetQuery=targetQueries[0],formattedColumns=anchorTargets.map(target=>formatSqlComponent(target.column)),substitutedSql=substituteAnchorPlaceholders(spec.query,formattedColumns).trim();enforceSubqueryConstraints(substitutedSql);let subquery=SelectQueryParser.parse(substitutedSql),parameterNames=new Set(ParameterCollector.collect(subquery).map(parameter=>parameter.name.value));if(parameterNames.size!==1||!parameterNames.has(parameterName))throw new Error(`SSSQL ${spec.kind.toUpperCase()} scaffold query must reference only parameter ':${parameterName}'.`);let branch=buildOptionalExistsBranch(parameterName,subquery,spec.kind),branchSql=normalizeSql(formatSqlComponent(branch));this.list(root).find(existing=>existing.query===targetQuery&&normalizeSql(existing.sql)===branchSql)||targetQuery.appendWhere(branch)}resolveTarget(root,filterName){let qualified=parseQualifiedFilterName(filterName),lookupColumn=qualified?.column??filterName.trim(),matches=[...new Set(this.finder.find(root,lookupColumn))].map(query=>this.resolveTargetInQuery(query,filterName,qualified)).filter(target=>target!==null);if(matches.length===0)throw new Error(`Could not resolve SSSQL filter target '${filterName}' in the current query graph.`);if(matches.length>1)throw new Error(`SSSQL filter target '${filterName}' is ambiguous across multiple query scopes.`);return matches[0]}resolveTargetInQuery(query,filterName,qualified){return qualified?this.resolveQualifiedTarget(query,qualified):this.resolveUnqualifiedTarget(query,filterName)}resolveQualifiedTarget(query,filterName){let alias=this.findAliasForTable(query,filterName.table);if(!alias)return null;let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeColumnReferenceKey(entry.value)===`${normalizeIdentifier2(alias)}.${normalizeIdentifier2(filterName.column)}`);if(matches.length===0)return null;if(matches.length>1)throw new Error(`SSSQL scaffold target '${filterName.table}.${filterName.column}' resolved to multiple columns.`);return{query,column:matches[0].value,parameterName:makeParameterName(`${filterName.table}.${filterName.column}`)}}resolveUnqualifiedTarget(query,filterName){let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===normalizeIdentifier2(filterName));if(matches.length===0)return null;if(matches.length>1)throw new Error(`SSSQL scaffold target '${filterName}' is ambiguous. Use a qualified table.column reference.`);return{query,column:matches[0].value,parameterName:makeParameterName(filterName)}}tryResolveTarget(root,filterName){try{return this.resolveTarget(root,filterName)}catch{return null}}findAliasForTable(query,tableName){let normalizedTable=normalizeIdentifier2(tableName),matchingAliases=(query.fromClause?.getSources()??[]).map(source=>this.resolveAliasForSource(source,normalizedTable)).filter(alias=>alias!==null);if(matchingAliases.length===0)return null;if(matchingAliases.length>1)throw new Error(`SSSQL scaffold target table '${tableName}' is ambiguous in the selected query scope.`);return matchingAliases[0]}resolveAliasForSource(source,normalizedTable){if(!(source.datasource instanceof TableSource))return null;let sourceName=normalizeIdentifier2(source.datasource.getSourceName()),shortName=normalizeIdentifier2(source.datasource.table.name);return sourceName!==normalizedTable&&shortName!==normalizedTable?null:source.getAliasName()??source.datasource.table.name}buildCorrelatedRefreshPlan(root,branch){let details=getExistsPredicateDetails(branch.expression,branch.parameterName);if(!details)return null;let sourceAliases=this.collectSourceAliases(branch.query),candidatesByKey=new Map;for(let reference of new ColumnReferenceCollector().collect(details.subquery)){let namespace=normalizeIdentifier2(reference.getNamespace());if(!namespace||!sourceAliases.has(namespace))continue;let column=normalizeIdentifier2(reference.column.name),key=`${namespace}.${column}`;candidatesByKey.has(key)||candidatesByKey.set(key,{namespace,column})}let candidates=[...candidatesByKey.values()];if(candidates.length===0)throw new Error(`SSSQL refresh could not infer a correlated anchor for ':${branch.parameterName}'.`);if(candidates.length>1){let listed=candidates.map(candidate=>`${candidate.namespace}.${candidate.column}`).join(", ");throw new Error(`SSSQL refresh found multiple correlated anchor candidates for ':${branch.parameterName}' (${listed}).`)}let[anchor]=candidates;if(!anchor)throw new Error(`SSSQL refresh could not infer a correlated anchor for ':${branch.parameterName}'.`);return{target:this.resolveCorrelatedAnchorTarget(root,branch.query,anchor,branch.parameterName),sourceAlias:anchor.namespace}}collectSourceAliases(query){let aliases=new Set;for(let source of query.fromClause?.getSources()??[]){let sourceAlias=this.getSourceAlias(source);sourceAlias&&aliases.add(sourceAlias)}return aliases}resolveCorrelatedAnchorTarget(root,sourceQuery,anchor,parameterName){let sourceExpression=this.findSourceExpressionByAlias(sourceQuery,anchor.namespace,parameterName),upstreamQuery=this.resolveSourceExpressionToUpstreamQuery(root,sourceExpression,parameterName);return upstreamQuery?this.resolveAnchorTargetInQuery(upstreamQuery,anchor,parameterName):{query:sourceQuery,column:new ColumnReference(anchor.namespace,anchor.column),parameterName}}findSourceExpressionByAlias(query,alias,parameterName){let matches=(query.fromClause?.getSources()??[]).filter(source=>this.getSourceAlias(source)===alias);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve correlated alias '${alias}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple correlated sources for alias '${alias}' and ':${parameterName}'.`);return matches[0]}resolveSourceExpressionToUpstreamQuery(root,source,parameterName){if(source.datasource instanceof SubQuerySource){if(source.datasource.query instanceof SimpleSelectQuery)return source.datasource.query;throw new Error(`SSSQL refresh requires a simple query anchor for ':${parameterName}'.`)}if(!(source.datasource instanceof TableSource))return null;let cteName=normalizeIdentifier2(source.datasource.table.name),cteMatches=new CTECollector().collect(root).filter(cte2=>normalizeIdentifier2(cte2.getSourceAliasName())===cteName);if(cteMatches.length===0)return null;if(cteMatches.length>1)throw new Error(`SSSQL refresh found multiple CTE anchors for ':${parameterName}' (${source.datasource.table.name}).`);let[cte]=cteMatches;if(!cte)return null;let cteQuery=cte.query;if(!(cteQuery instanceof SimpleSelectQuery))throw new Error(`SSSQL refresh requires a simple CTE anchor for ':${parameterName}'.`);return cteQuery}resolveAnchorTargetInQuery(query,anchor,parameterName){let matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===anchor.column);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve correlated anchor column '${anchor.column}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple correlated anchor columns '${anchor.column}' for ':${parameterName}'.`);return{query,column:matches[0].value,parameterName}}getSourceAlias(source){let explicitAlias=source.getAliasName();return explicitAlias?normalizeIdentifier2(explicitAlias):source.datasource instanceof TableSource?normalizeIdentifier2(source.datasource.table.name):null}buildScalarRefreshPlan(root,branch,details){let sourceAlias=normalizeIdentifier2(details.column.getNamespace());if(!sourceAlias)return null;let sourceExpression=this.findSourceExpressionByAlias(branch.query,sourceAlias,branch.parameterName),upstreamQuery=this.resolveSourceExpressionToUpstreamQuery(root,sourceExpression,branch.parameterName);return upstreamQuery?this.resolveScalarTargetInQuery(upstreamQuery,details.column,branch.parameterName):null}resolveScalarTargetInQuery(query,sourceColumn,parameterName){let outputColumnName=normalizeIdentifier2(sourceColumn.column.name),matches=new SelectableColumnCollector(this.tableColumnResolver,!1,"fullName",{upstream:!0}).collect(query).filter(entry=>entry.value instanceof ColumnReference).filter(entry=>normalizeIdentifier2(entry.name)===outputColumnName);if(matches.length===0)throw new Error(`SSSQL refresh could not resolve scalar branch column '${sourceColumn.column.name}' for ':${parameterName}'.`);if(matches.length>1)throw new Error(`SSSQL refresh found multiple scalar branch columns '${sourceColumn.column.name}' for ':${parameterName}'.`);return{query,column:matches[0].value,parameterName}}isNullableBranchColumn(query,column){let alias=normalizeIdentifier2(column.getNamespace());if(!alias||!query.fromClause)return!1;let joins=query.fromClause.joins??[];if(this.getSourceAlias(query.fromClause.source)===alias)return this.hasLaterJoinThatNullsPriorSources(joins,-1);let joinIndex=joins.findIndex(join=>this.getSourceAlias(join.source)===alias);if(joinIndex<0)return!1;let introducingJoin=joins[joinIndex];return this.isJoinedSourceNullable(introducingJoin)||this.hasLaterJoinThatNullsPriorSources(joins,joinIndex)}hasLaterJoinThatNullsPriorSources(joins,sourceJoinIndex){return joins.slice(sourceJoinIndex+1).some(join=>this.isPriorSourcesNullableJoin(join))}isPriorSourcesNullableJoin(join){let joinType=join.joinType.value.toLowerCase();return joinType.includes("right")||joinType.includes("full")}isJoinedSourceNullable(join){let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("full")}rebaseMovedBranch(expression,sourceQuery,targetColumn){let targetNamespace=targetColumn.qualifiedName.namespaces?targetColumn.qualifiedName.namespaces.map(namespace=>namespace.name):null,targetColumnName=normalizeIdentifier2(targetColumn.column.name),sourceAliases=new Set(collectColumnReferencesDeep(expression).filter(reference=>normalizeIdentifier2(reference.column.name)===targetColumnName).map(reference=>normalizeIdentifier2(reference.getNamespace())).filter(namespace=>namespace.length>0));if(sourceAliases.size===0)return;if(sourceAliases.size>1){let aliases=[...sourceAliases].join(", ");throw new Error(`SSSQL refresh cannot safely rebase '${targetColumn.column.name}' across multiple aliases (${aliases}).`)}let[sourceAlias]=[...sourceAliases];if(new Set((sourceQuery.fromClause?.getSources()??[]).map(source=>source.getAliasName()).filter(alias=>typeof alias=="string").map(alias=>normalizeIdentifier2(alias))).has(sourceAlias))for(let reference of collectColumnReferencesDeep(expression))normalizeIdentifier2(reference.getNamespace())===sourceAlias&&(reference.qualifiedName.namespaces=targetNamespace?.map(namespace=>new IdentifierString(namespace))??null)}rebaseMovedBranchByAlias(expression,sourceAlias,targetColumn){let normalizedSourceAlias=normalizeIdentifier2(sourceAlias);if(!normalizedSourceAlias)return;let targetNamespace=targetColumn.qualifiedName.namespaces?targetColumn.qualifiedName.namespaces.map(namespace=>namespace.name):null;for(let reference of collectColumnReferencesDeep(expression))normalizeIdentifier2(reference.getNamespace())===normalizedSourceAlias&&(reference.qualifiedName.namespaces=targetNamespace?.map(namespace=>new IdentifierString(namespace))??null)}},scaffoldSssqlQuery=(sqlContent,filters)=>({query:new SSSQLFilterBuilder().scaffold(sqlContent,filters)}),refreshSssqlQuery=(sqlContent,filters)=>({query:new SSSQLFilterBuilder().refresh(sqlContent,filters)});var SUPPORTED_OPERATORS=new Set(["=","<>","!=","<","<=",">",">=","like","ilike","in"]),VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON="Condition contains a function call; volatile and expression predicates are not moved in the safe-only implementation.",normalizeIdentifier3=value=>value.trim().toLowerCase(),unwrapParens2=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator3=(expression,operator)=>{let candidate=unwrapParens2(expression);return candidate instanceof BinaryExpression&&candidate.operator.value.trim().toLowerCase()===operator},collectTopLevelAndTerms3=expression=>{let candidate=unwrapParens2(expression);return isBinaryOperator3(candidate,"and")?[...collectTopLevelAndTerms3(candidate.left),...collectTopLevelAndTerms3(candidate.right)]:[expression]},rebuildWhereWithoutTerms=(query,termsToRemove)=>{if(!query.whereClause||termsToRemove.size===0)return;let remaining=collectTopLevelAndTerms3(query.whereClause.condition).filter(term=>!termsToRemove.has(term));if(remaining.length===0){query.whereClause=null;return}let rebuilt=remaining[0];for(let index=1;index<remaining.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",remaining[index]);query.whereClause=new WhereClause(rebuilt)},cloneValueComponent=(expression,options)=>ValueParser.parse(formatSqlComponent(expression,options)),cloneColumnReference=reference=>{let namespaces=reference.namespaces?.map(namespace=>namespace.name)??null;return new ColumnReference(namespaces,reference.column.name)},columnReferenceText=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},sameColumnReference=(left,right)=>normalizeIdentifier3(left.column.name)===normalizeIdentifier3(right.column.name)&&normalizeIdentifier3(left.getNamespace())===normalizeIdentifier3(right.getNamespace()),appendUnique=(items,value)=>{items.includes(value)||items.push(value)},ParameterConditionPlacementOptimizer=class{plan(input,options={}){let parsed=this.parseInput(input,options),warnings=[...parsed.warnings],errors=[...parsed.errors];if(!parsed.query)return this.buildResult({query:null,sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});if(!(parsed.query instanceof SimpleSelectQuery))return warnings.push({code:"UNSUPPORTED_ROOT_QUERY",message:"Parameter condition placement currently supports only SimpleSelectQuery roots."}),this.buildResult({query:parsed.query,sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});let query=parsed.query,applied=[],skipped=[],movedTerms=[];for(let term of query.whereClause?collectTopLevelAndTerms3(query.whereClause.condition):[]){let candidate=this.analyzeCandidate(term,options);if(!candidate)continue;if("code"in candidate){skipped.push(this.makeSkipped(term,candidate,options));continue}let target=this.resolveTarget(query,candidate);if("code"in target){skipped.push(this.makeSkipped(term,target,options));continue}let appliedReason="";if(target.kind==="simple"){let targetColumns=this.resolveTargetColumns(query,target.query,candidate.references);if("code"in targetColumns){skipped.push(this.makeSkipped(term,targetColumns,options));continue}let placement=this.resolveTargetPlacement(target.query,targetColumns);if("code"in placement){skipped.push(this.makeSkipped(term,placement,options));continue}let movedCondition=this.rebaseCondition(candidate.expression,targetColumns,options);target.query.appendWhere(movedCondition),appliedReason=placement.reason}else{let placements=[],skip=null;for(let branch of target.branches){let placement=this.resolveTargetPlacement(branch.query,branch.targetColumns);if("code"in placement){skip=placement;break}placements.push(placement)}if(skip){skipped.push(this.makeSkipped(term,skip,options));continue}for(let branch of target.branches){let movedCondition=this.rebaseCondition(candidate.expression,branch.targetColumns,options);branch.query.appendWhere(movedCondition)}appliedReason=placements.some(item=>/group by/i.test(item.reason))?"Condition is distributed to every UNION branch by output column position; grouped branches only receive GROUP BY-key predicates.":"Condition is distributed to every UNION branch by output column position before unsafe query boundaries."}movedTerms.push(term),applied.push({kind:"move_condition",conditionSql:candidate.conditionSql,fromScopeId:"scope:root",toScopeId:target.scopeId,reason:appliedReason,parameterNames:candidate.parameterNames,columnReferences:candidate.references.map(columnReferenceText)})}rebuildWhereWithoutTerms(query,new Set(movedTerms));let sql=applied.length>0||hasSqlComponentFormatOverride(options)?formatSqlComponent(query,options):parsed.sql;return this.buildResult({query,sql,applied,skipped,warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource})}optimize(input,options={}){return this.plan(input,{...options,dryRun:options.dryRun??!1})}parseInput(input,options){let warnings=[],errors=[];try{let sourceSql=typeof input=="string"?input:formatSqlComponent(input,options);return typeof input!="string"&&options.cloneInput===!1?{query:input,sql:sourceSql,formatterGeneratedSource:!1,warnings,errors}:(typeof input!="string"&&warnings.push({code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."}),{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource:typeof input!="string",warnings,errors})}catch(error){let detail=error instanceof Error?error.message:String(error);return errors.push({code:"PARSE_FAILED",message:"Parameter condition optimization could not parse the input SQL.",detail}),{query:null,sql:typeof input=="string"?input:"",formatterGeneratedSource:typeof input!="string",warnings,errors}}}analyzeCandidate(expression,options){let parameterNames=this.collectParameterNames(expression);if(parameterNames.length===0)return null;let unsupported=this.findUnsupportedExpression(expression);if(unsupported)return unsupported;let columnReferences=this.collectColumnReferences(expression);if(columnReferences.length===0)return{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:"Parameter condition has no column reference to anchor the move."};let unsupportedShape=this.findUnsupportedParameterPredicateShape(expression);return unsupportedShape||{expression,conditionSql:formatSqlComponent(expression,options),parameterNames,references:columnReferences}}findUnsupportedExpression(expression){let found=null,visit=value=>{if(found)return;let candidate=unwrapParens2(value);if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof FunctionCall){found={code:"FUNCTION_PREDICATE_UNSUPPORTED",reason:VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON};return}if(candidate instanceof CaseExpression){found={code:"CASE_PREDICATE_UNSUPPORTED",reason:"CASE predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof InlineQuery||candidate instanceof ArrayQueryExpression){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Subquery predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),found}findUnsupportedParameterPredicateShape(expression){let visit=value=>{let candidate=unwrapParens2(value);if(candidate instanceof BetweenExpression)return null;if(candidate instanceof BinaryExpression){let operator=candidate.operator.value.trim().toLowerCase();return operator==="and"||operator==="or"?visit(candidate.left)??visit(candidate.right):SUPPORTED_OPERATORS.has(operator)?operator==="in"&&!this.isSupportedInPredicate(candidate)?{code:"UNSUPPORTED_IN_PREDICATE",reason:"Only simple column IN (:parameter) predicates are moved in the safe-only implementation."}:null:{code:"UNSUPPORTED_OPERATOR",reason:`Operator '${candidate.operator.value}' is not supported for safe-only parameter condition placement.`}}return{code:"UNSUPPORTED_PARAMETER_CONDITION",reason:"Only simple binary, BETWEEN, and whole OR/AND parameter predicates are moved in the safe-only implementation."}};return visit(expression)}isSupportedInPredicate(expression){let left=unwrapParens2(expression.left),right=unwrapParens2(expression.right);return left instanceof ColumnReference?right instanceof ParameterExpression?!0:right instanceof ValueList?right.values.length>0&&right.values.every(value=>unwrapParens2(value)instanceof ParameterExpression):!1:!1}resolveTarget(root,candidate){let boundary=this.findRootQueryBoundary(root);if(boundary)return boundary;if(!root.fromClause)return{code:"NO_FROM_CLAUSE",reason:"Condition has no FROM source that can receive the predicate safely."};let bindings=[];for(let reference of candidate.references){let binding2=this.resolveSourceBinding(root,root,reference);if("code"in binding2)return binding2;bindings.some(item=>item.source===binding2.source)||bindings.push(binding2)}if(bindings.length!==1)return{code:"MULTIPLE_SOURCE_REFERENCES",reason:"Parameter condition references multiple source query blocks; moving it may change semantics."};let binding=bindings[0],nullableSide=this.findNullableSideBoundary(root.fromClause,binding);if(nullableSide)return nullableSide;let upstream=this.resolveUpstreamQuery(root,binding,candidate.references);return"code"in upstream,upstream}findRootQueryBoundary(query){return this.hasDistinctOnBoundary(query)?{code:"DISTINCT_BOUNDARY",reason:"Condition crosses DISTINCT ON boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Condition crosses WINDOW boundary; moving it may change semantics."}:null}resolveTargetPlacement(query,targetColumns){let hasOrdinaryDistinct=this.hasOrdinaryDistinct(query);return this.hasDistinctOnBoundary(query)?{code:"DISTINCT_BOUNDARY",reason:"Condition crosses DISTINCT ON boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Condition crosses WINDOW boundary; moving it may change semantics."}:query.limitClause||query.offsetClause||query.fetchClause?{code:"ROW_LIMIT_BOUNDARY",reason:"Condition crosses LIMIT/OFFSET/FETCH boundary; moving it may change row selection semantics."}:query.fromClause&&this.hasOuterJoin(query.fromClause)?{code:"OUTER_JOIN_BOUNDARY",reason:"Target query contains an OUTER JOIN boundary that is not moved across in the safe-only implementation."}:query.groupByClause?targetColumns.every(item=>this.isGroupKeyColumn(query,item.targetColumn))?{reason:"Condition references only GROUP BY keys; it is moved into pre-aggregation WHERE."}:{code:"GROUP_BY_BOUNDARY",reason:"Condition references a target column that is not proven to be a GROUP BY key."}:query.havingClause?{code:"GROUP_BY_BOUNDARY",reason:"Condition crosses HAVING aggregation boundary; moving it may change semantics."}:hasOrdinaryDistinct?{reason:"Condition references a direct ordinary DISTINCT output column; it is moved into the DISTINCT input WHERE."}:{reason:"All referenced columns resolve to a single direct upstream output before unsafe query boundaries."}}resolveSourceBinding(contextRoot,query,column){let fromClause=query.fromClause;if(!fromClause)return{code:"NO_FROM_CLAUSE",reason:"Condition has no FROM source that can receive the predicate safely."};let bindings=this.getSourceBindings(fromClause),namespace=normalizeIdentifier3(column.getNamespace()),columnName=column.column.name;if(namespace){let matches2=bindings.filter(binding=>normalizeIdentifier3(binding.alias)===namespace);if(matches2.length!==1)return{code:"AMBIGUOUS_COLUMN_SOURCE",reason:`Column source alias '${column.getNamespace()}' is not uniquely resolvable.`};let matchCount=this.getOutputColumnMatchCount(contextRoot,matches2[0],columnName);return matchCount===0?{code:"COLUMN_NOT_AVAILABLE_UPSTREAM",reason:`Column '${columnReferenceText(column)}' is not a direct output of the referenced source.`}:matchCount>1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnReferenceText(column)}' resolves to multiple outputs in the referenced source.`}:matches2[0]}let matches=[];for(let binding of bindings){let matchCount=this.getOutputColumnMatchCount(contextRoot,binding,columnName);if(matchCount>1)return{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnName}' resolves to multiple outputs in source '${binding.alias}'.`};matchCount===1&&matches.push(binding)}return matches.length!==1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:matches.length===0?`Column '${columnName}' is not uniquely resolvable to a safe upstream source.`:`Column '${columnName}' is ambiguous across source query blocks.`}:matches[0]}resolveUpstreamQuery(root,binding,references){let source=binding.source.datasource;if(source instanceof SubQuerySource)return source.query instanceof SimpleSelectQuery?{kind:"simple",query:source.query,scopeId:`subquery:${binding.alias}`,sourceBinding:binding}:source.query instanceof BinarySelectQuery?this.resolveUnionTarget(root,source.query,`subquery:${binding.alias}`,references):{code:"UNION_BOUNDARY",reason:"Condition would need distribution into a UNION or non-simple subquery, which is unsupported."};if(!(source instanceof TableSource))return{code:"UNSUPPORTED_SOURCE",reason:"Only CTE and simple derived-table sources can receive moved parameter conditions."};let cteName=source.table.name,commonTable=this.findCte(root,cteName);if(!commonTable)return{code:"NO_SAFE_UPSTREAM_QUERY",reason:"The referenced source is a base table, so there is no upstream query block to move into."};let referenceCount=this.countTableSourceReferences(root,cteName);return referenceCount!==1?{code:"CTE_REUSE_UNSUPPORTED",reason:`CTE '${cteName}' is referenced ${referenceCount} times; moving a predicate into it may affect other consumers.`}:commonTable.query instanceof BinarySelectQuery?this.resolveUnionTarget(root,commonTable.query,`cte:${commonTable.getSourceAliasName()}`,references):commonTable.query instanceof SimpleSelectQuery?{kind:"simple",query:commonTable.query,scopeId:`cte:${commonTable.getSourceAliasName()}`,sourceBinding:binding,cteName:commonTable.getSourceAliasName()}:{code:"UNSUPPORTED_CTE_QUERY",reason:"Writable or non-select CTE bodies are not moved into by parameter condition placement."}}resolveUnionTarget(root,query,scopeId,references){let branches=this.collectUnionBranches(query);if("code"in branches)return branches;let outputIndexes=new Map;for(let reference of references){let outputIndex=this.resolveUnionOutputIndex(root,branches[0],reference.column.name);if("code"in outputIndex)return outputIndex;outputIndexes.set(reference,outputIndex.index)}let branchTargets=[];for(let branch of branches){let targetColumns=[];for(let[reference,outputIndex]of outputIndexes.entries()){let targetColumn=this.resolveTargetColumnByOutputIndex(root,branch,outputIndex,reference);if("code"in targetColumn)return targetColumn;targetColumns.push(targetColumn)}branchTargets.push(this.resolveDeepestBranchTarget(root,branch,targetColumns))}return{kind:"union",scopeId,branches:branchTargets}}resolveTargetColumns(root,query,references){let resolved=[];for(let reference of references){let matches=this.collectSelectOutputs(root,query).filter(item=>normalizeIdentifier3(item.name)===normalizeIdentifier3(reference.column.name));if(matches.length!==1)return{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`Target query does not expose '${reference.column.name}' as a direct output column.`:`Target query exposes multiple '${reference.column.name}' columns.`};let value=matches[0].value;if(!(value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`Target output '${reference.column.name}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,value);if(sourceResolution)return sourceResolution;resolved.push({sourceColumn:reference,targetColumn:value})}return resolved}resolveTargetColumnByOutputIndex(root,query,outputIndex,sourceColumn){let output=this.collectSelectOutputs(root,query)[outputIndex];if(!output)return{code:"UNION_COLUMN_MISMATCH",reason:`UNION branch does not expose column '${sourceColumn.column.name}' at output position ${outputIndex+1}.`};if(!(output.value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`UNION branch output at position ${outputIndex+1} for '${sourceColumn.column.name}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,output.value);return sourceResolution||{sourceColumn,targetColumn:output.value}}resolveDeepestBranchTarget(contextRoot,query,targetColumns,visited=new Set){if(visited.has(query)||targetColumns.length===0)return{query,targetColumns:[...targetColumns]};let nextVisited=new Set(visited);nextVisited.add(query);let bindings=[];for(let item of targetColumns){let binding2=this.resolveSourceBinding(contextRoot,query,item.targetColumn);if("code"in binding2)return{query,targetColumns:[...targetColumns]};bindings.some(existing=>existing.source===binding2.source)||bindings.push(binding2)}if(bindings.length!==1)return{query,targetColumns:[...targetColumns]};let binding=bindings[0];if(query.fromClause?this.findNullableSideBoundary(query.fromClause,binding):null)return{query,targetColumns:[...targetColumns]};let upstream=this.resolveUpstreamQuery(contextRoot,binding,targetColumns.map(item=>item.targetColumn));if("code"in upstream||upstream.kind==="union")return{query,targetColumns:[...targetColumns]};let upstreamColumns=this.resolveTargetColumns(contextRoot,upstream.query,targetColumns.map(item=>item.targetColumn));if("code"in upstreamColumns)return{query,targetColumns:[...targetColumns]};if("code"in this.resolveTargetPlacement(upstream.query,upstreamColumns))return{query,targetColumns:[...targetColumns]};let rebasedColumns=upstreamColumns.map((item,index)=>({sourceColumn:targetColumns[index].sourceColumn,targetColumn:item.targetColumn}));return this.resolveDeepestBranchTarget(contextRoot,upstream.query,rebasedColumns,nextVisited)}verifyColumnResolvableInQuery(query,column){if(!query.fromClause)return{code:"NO_TARGET_FROM_CLAUSE",reason:"Target query has no FROM clause where the moved column can be resolved."};let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier3(column.getNamespace());return namespace?bindings.filter(binding=>normalizeIdentifier3(binding.alias)===namespace).length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Target column '${columnReferenceText(column)}' is not uniquely resolvable in the destination query.`}:bindings.length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Unqualified target column '${column.column.name}' is ambiguous in a multi-source destination query.`}}isGroupKeyColumn(query,column){let groupBy=query.groupByClause;return!groupBy||groupBy.mode||groupBy.grouping.length===0?!1:groupBy.grouping.some(grouping=>{let candidate=unwrapParens2(grouping);return candidate instanceof ColumnReference&&this.sameResolvableColumnInQuery(query,candidate,column)})}sameResolvableColumnInQuery(query,left,right){if(sameColumnReference(left,right))return!0;if(normalizeIdentifier3(left.column.name)!==normalizeIdentifier3(right.column.name))return!1;let leftSource=this.resolveColumnSourceAlias(query,left),rightSource=this.resolveColumnSourceAlias(query,right);return leftSource!==null&&leftSource===rightSource}resolveColumnSourceAlias(query,column){if(!query.fromClause)return null;let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier3(column.getNamespace());if(namespace){let matches=bindings.filter(binding=>normalizeIdentifier3(binding.alias)===namespace);return matches.length===1?normalizeIdentifier3(matches[0].alias):null}return bindings.length===1?normalizeIdentifier3(bindings[0].alias):null}rebaseCondition(expression,targetColumns,options){let cloned=cloneValueComponent(expression,options);for(let reference of this.collectColumnReferences(cloned)){let target=targetColumns.find(item=>sameColumnReference(reference,item.sourceColumn));target&&(reference.qualifiedName=cloneColumnReference(target.targetColumn).qualifiedName)}return cloned}getSourceBindings(fromClause){let bindings=[{source:fromClause.source,alias:fromClause.source.getAliasName()??"",join:null,isPrimary:!0}];for(let join of fromClause.joins??[])bindings.push({source:join.source,alias:join.source.getAliasName()??"",join,isPrimary:!1});return bindings}findNullableSideBoundary(fromClause,binding){if(!binding.join)return(fromClause.joins??[]).some(join=>{let joinType2=join.joinType.value.toLowerCase();return joinType2.includes("right")||joinType2.includes("full")})?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses OUTER JOIN nullable side; moving it may change semantics."}:null;let joinType=binding.join.joinType.value.toLowerCase();return joinType.includes("left")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses LEFT JOIN nullable side; moving it may change semantics."}:joinType.includes("full")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Condition crosses FULL JOIN nullable side; moving it may change semantics."}:null}hasOuterJoin(fromClause){return(fromClause.joins??[]).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("right")||joinType.includes("full")||joinType.includes("outer")})}hasDistinctOnBoundary(query){return query.selectClause.distinct instanceof DistinctOn}hasOrdinaryDistinct(query){return query.selectClause.distinct!==null&&!this.hasDistinctOnBoundary(query)}getOutputColumnMatchCount(root,binding,columnName){let target=this.resolveSourceQueryForColumns(root,binding.source);if(!target)return 0;if(target instanceof BinarySelectQuery){let branches=this.collectUnionBranches(target);return"code"in branches?0:this.collectSelectOutputs(root,branches[0]).filter(item=>normalizeIdentifier3(item.name)===normalizeIdentifier3(columnName)).length}return target instanceof SimpleSelectQuery?this.collectSelectOutputs(root,target).filter(item=>normalizeIdentifier3(item.name)===normalizeIdentifier3(columnName)).length:0}collectUnionBranches(query){let branches=[],visit=select=>{if(select instanceof SimpleSelectQuery)return branches.push(select),null;if(!(select instanceof BinarySelectQuery))return{code:"UNION_BOUNDARY",reason:"Condition would need distribution into a non-simple UNION branch, which is unsupported."};let operator=select.operator.value.trim().toLowerCase();return operator!=="union"&&operator!=="union all"?{code:"UNION_BOUNDARY",reason:`Condition would need distribution through '${select.operator.value}', which is unsupported.`}:visit(select.left)??visit(select.right)};return visit(query)??branches}resolveUnionOutputIndex(root,firstBranch,outputColumnName){let matches=[];return this.collectSelectOutputs(root,firstBranch).forEach((item,index)=>{normalizeIdentifier3(item.name)===normalizeIdentifier3(outputColumnName)&&matches.push(index)}),matches.length!==1?{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`UNION output does not expose '${outputColumnName}' from its first branch.`:`UNION first branch exposes multiple '${outputColumnName}' columns.`}:{index:matches[0]}}collectSelectOutputs(root,query){let commonTables=[...query.withClause?.tables??[],...root.withClause?.tables??[]];return new SelectOutputCollector(null,commonTables.length>0?commonTables:null).collect(query)}resolveSourceQueryForColumns(root,source){if(source.datasource instanceof SubQuerySource)return source.datasource.query;if(source.datasource instanceof TableSource){let cteQuery=this.findCte(root,source.datasource.table.name)?.query;return cteQuery instanceof SimpleSelectQuery||cteQuery instanceof BinarySelectQuery?cteQuery:null}return null}findCte(root,name){let normalized=normalizeIdentifier3(name),matches=(root.withClause?.tables??[]).filter(table=>normalizeIdentifier3(table.getSourceAliasName())===normalized);return matches.length===1?matches[0]:null}countTableSourceReferences(query,tableName){let normalized=normalizeIdentifier3(tableName),count=0,visitSelect=select=>{if(select instanceof BinarySelectQuery){visitSelect(select.left),visitSelect(select.right);return}if(select instanceof SimpleSelectQuery){if(select.fromClause)for(let binding of this.getSourceBindings(select.fromClause)){let source=binding.source.datasource;source instanceof TableSource&&normalizeIdentifier3(source.table.name)===normalized&&(count+=1),source instanceof SubQuerySource&&visitSelect(source.query)}for(let cte of select.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}};return visitSelect(query),count}hasWindowUsage(query){if(query.windowClause)return!0;let found=!1,visit=value=>{if(found)return;let candidate=unwrapParens2(value);if(candidate instanceof FunctionCall){if(candidate.over){found=!0;return}candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}candidate instanceof ValueList&&candidate.values.forEach(visit)};return query.selectClause.items.forEach(item=>visit(item.value)),found}collectColumnReferences(expression){let references=[],visit=value=>{let candidate=unwrapParens2(value);if(candidate instanceof ColumnReference){references.some(existing=>sameColumnReference(existing,candidate))||references.push(candidate);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),references}collectParameterNames(expression){let names=[],visit=value=>{let candidate=unwrapParens2(value);if(candidate instanceof ParameterExpression){appendUnique(names,candidate.name.value);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(!(candidate instanceof ArrayQueryExpression||candidate instanceof InlineQuery)){if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)}};return visit(expression),names}makeSkipped(expression,draft,options){return{conditionSql:formatSqlComponent(expression,options),scopeId:"scope:root",...draft}}buildResult(params){return{ok:params.errors.length===0,sql:params.sql,query:params.query,applied:params.applied,skipped:params.skipped,warnings:params.warnings,errors:params.errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun:params.dryRun,formatterGeneratedSource:params.formatterGeneratedSource},conditionMoves:params.applied}}},planParameterConditionOptimization=(input,options={})=>new ParameterConditionPlacementOptimizer().plan(input,options),optimizeParameterConditionPlacement=(input,options={})=>new ParameterConditionPlacementOptimizer().optimize(input,options);var VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON2="Predicate contains a function call; volatile and expression predicates are not moved in the safe-only implementation.",normalizeIdentifier4=value=>value.trim().toLowerCase(),unwrapParens3=expression=>{let candidate=expression;for(;candidate instanceof ParenExpression;)candidate=candidate.expression;return candidate},isBinaryOperator4=(expression,operator)=>{let candidate=unwrapParens3(expression);return candidate instanceof BinaryExpression&&candidate.operator.value.trim().toLowerCase()===operator},collectTopLevelAndTerms4=expression=>{let candidate=unwrapParens3(expression);return isBinaryOperator4(candidate,"and")?[...collectTopLevelAndTerms4(candidate.left),...collectTopLevelAndTerms4(candidate.right)]:[expression]},rebuildWhereWithoutTerms2=(query,termsToRemove)=>{if(!query.whereClause||termsToRemove.size===0)return;let remaining=collectTopLevelAndTerms4(query.whereClause.condition).filter(term=>!termsToRemove.has(term));if(remaining.length===0){query.whereClause=null;return}let rebuilt=remaining[0];for(let index=1;index<remaining.length;index+=1)rebuilt=new BinaryExpression(rebuilt,"and",remaining[index]);query.whereClause=new WhereClause(rebuilt)},cloneValueComponent2=(expression,options)=>ValueParser.parse(formatSqlComponent(expression,options)),cloneColumnReference2=reference=>{let namespaces=reference.namespaces?.map(namespace=>namespace.name)??null;return new ColumnReference(namespaces,reference.column.name)},columnReferenceText2=reference=>{let namespace=reference.getNamespace();return namespace?`${namespace}.${reference.column.name}`:reference.column.name},sameColumnReference2=(left,right)=>normalizeIdentifier4(left.column.name)===normalizeIdentifier4(right.column.name)&&normalizeIdentifier4(left.getNamespace())===normalizeIdentifier4(right.getNamespace()),appendUnique2=(items,value)=>{items.includes(value)||items.push(value)},StaticPredicatePlacementOptimizer=class{plan(input,options={}){let parsed=this.parseInput(input,options),warnings=[...parsed.warnings],errors=[...parsed.errors];if(!parsed.query)return this.buildResult({query:null,sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});if(!(parsed.query instanceof SimpleSelectQuery))return warnings.push({code:"UNSUPPORTED_ROOT_QUERY",message:"Static predicate placement currently supports only SimpleSelectQuery roots."}),this.buildResult({query:parsed.query,sql:parsed.sql,applied:[],skipped:[],warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource});let query=parsed.query,applied=[],skipped=[],movedTerms=[];for(let term of query.whereClause?collectTopLevelAndTerms4(query.whereClause.condition):[]){let candidate=this.analyzeCandidate(query,term,options);if(!candidate)continue;if("code"in candidate){skipped.push(this.makeSkipped(term,candidate,options));continue}let target=this.resolveTarget(query,candidate);if("code"in target){skipped.push(this.makeSkipped(term,target,options));continue}let appliedReason="";if(target.kind==="simple"){let targetColumns=this.resolveTargetColumns(query,target.query,candidate.references);if("code"in targetColumns){skipped.push(this.makeSkipped(term,targetColumns,options));continue}let placement=this.resolveTargetPlacement(target.query,targetColumns);if("code"in placement){skipped.push(this.makeSkipped(term,placement,options));continue}let movedPredicate=this.rebasePredicate(candidate.expression,targetColumns,options);target.query.appendWhere(movedPredicate),appliedReason=placement.reason}else{let placements=[],skip=null;for(let branch of target.branches){let placement=this.resolveTargetPlacement(branch.query,branch.targetColumns);if("code"in placement){skip=placement;break}placements.push(placement)}if(skip){skipped.push(this.makeSkipped(term,skip,options));continue}for(let branch of target.branches){let movedPredicate=this.rebasePredicate(candidate.expression,branch.targetColumns,options);branch.query.appendWhere(movedPredicate)}appliedReason=placements.some(item=>/group by/i.test(item.reason))?"Predicate is distributed to every UNION branch by output column position; grouped branches only receive GROUP BY-key predicates.":"Predicate is distributed to every UNION branch by output column position before unsafe query boundaries."}movedTerms.push(term),applied.push({kind:"move_static_predicate",predicateSql:candidate.predicateSql,fromScopeId:"scope:root",toScopeId:target.scopeId,reason:appliedReason,columnReferences:candidate.references.map(columnReferenceText2)})}rebuildWhereWithoutTerms2(query,new Set(movedTerms));let sql=applied.length>0||hasSqlComponentFormatOverride(options)?formatSqlComponent(query,options):parsed.sql;return this.buildResult({query,sql,applied,skipped,warnings,errors,dryRun:options.dryRun??!0,formatterGeneratedSource:parsed.formatterGeneratedSource})}optimize(input,options={}){return this.plan(input,{...options,dryRun:options.dryRun??!1})}parseInput(input,options){let warnings=[],errors=[];try{let sourceSql=typeof input=="string"?input:formatSqlComponent(input,options);return typeof input!="string"&&options.cloneInput===!1?{query:input,sql:sourceSql,formatterGeneratedSource:!1,warnings,errors}:(typeof input!="string"&&warnings.push({code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."}),{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource:typeof input!="string",warnings,errors})}catch(error){let detail=error instanceof Error?error.message:String(error);return errors.push({code:"PARSE_FAILED",message:"Static predicate placement could not parse the input SQL.",detail}),{query:null,sql:typeof input=="string"?input:"",formatterGeneratedSource:typeof input!="string",warnings,errors}}}analyzeCandidate(root,expression,options){if(this.collectParameterNames(expression).length>0)return null;let unsupported=this.findUnsupportedExpression(expression,this.isExistsPredicate(expression));if(unsupported)return unsupported;let references=this.collectRootColumnReferences(root,expression);return references.length===0?{code:"NO_COLUMN_REFERENCE",reason:"Static predicate has no outer column reference to anchor the move."}:{expression,predicateSql:formatSqlComponent(expression,options),references}}isExistsPredicate(expression){let candidate=unwrapParens3(expression);return candidate instanceof UnaryExpression?candidate.operator.value.trim().toLowerCase()==="exists"&&unwrapParens3(candidate.expression)instanceof InlineQuery:!1}findUnsupportedExpression(expression,allowExistsSubquery){let found=null,visitSelect=query=>{if(!found){if(query instanceof BinarySelectQuery){found={code:"UNION_BOUNDARY",reason:"Static predicate would need distribution into a UNION branch, which is unsupported."};return}if(!(query instanceof SimpleSelectQuery)){found={code:"UNSUPPORTED_SUBQUERY",reason:"Static predicate contains a non-simple subquery, which is unsupported."};return}query.selectClause.items.forEach(item=>visit(item.value));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query)}query.whereClause&&visit(query.whereClause.condition),query.havingClause&&visit(query.havingClause.condition);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}},visit=value=>{if(found)return;let candidate=unwrapParens3(value);if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof FunctionCall){found={code:"FUNCTION_PREDICATE_UNSUPPORTED",reason:VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON2};return}if(candidate instanceof CaseExpression){found={code:"CASE_PREDICATE_UNSUPPORTED",reason:"CASE predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof InlineQuery){if(!allowExistsSubquery){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Subquery predicates are only moved when they are simple EXISTS predicates."};return}visitSelect(candidate.selectQuery);return}if(candidate instanceof ArrayQueryExpression){found={code:"SUBQUERY_PREDICATE_UNSUPPORTED",reason:"Array subquery predicates are not moved in the first safe-only implementation."};return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),found}resolveTarget(root,candidate){let boundary=this.findRootQueryBoundary(root);if(boundary)return boundary;if(!root.fromClause)return{code:"NO_FROM_CLAUSE",reason:"Predicate has no FROM source that can receive it safely."};let bindings=[];for(let reference of candidate.references){let binding2=this.resolveSourceBinding(root,root,reference);if("code"in binding2)return binding2;bindings.some(item=>item.source===binding2.source)||bindings.push(binding2)}if(bindings.length!==1)return{code:"MULTIPLE_SOURCE_REFERENCES",reason:"Static predicate references multiple source query blocks; moving it may change semantics."};let binding=bindings[0],nullableSide=this.findNullableSideBoundary(root.fromClause,binding);if(nullableSide)return nullableSide;let upstream=this.resolveUpstreamQuery(root,binding,candidate.references);return"code"in upstream,upstream}findRootQueryBoundary(query){return this.hasDistinctOnBoundary(query)?{code:"DISTINCT_BOUNDARY",reason:"Predicate crosses DISTINCT ON boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Predicate crosses WINDOW boundary; moving it may change semantics."}:null}resolveTargetPlacement(query,targetColumns){let hasOrdinaryDistinct=this.hasOrdinaryDistinct(query);return this.hasDistinctOnBoundary(query)?{code:"DISTINCT_BOUNDARY",reason:"Predicate crosses DISTINCT ON boundary; moving it may change semantics."}:this.hasWindowUsage(query)?{code:"WINDOW_BOUNDARY",reason:"Predicate crosses WINDOW boundary; moving it may change semantics."}:query.limitClause||query.offsetClause||query.fetchClause?{code:"ROW_LIMIT_BOUNDARY",reason:"Predicate crosses LIMIT/OFFSET/FETCH boundary; moving it may change row selection semantics."}:query.fromClause&&this.hasOuterJoin(query.fromClause)?{code:"OUTER_JOIN_BOUNDARY",reason:"Target query contains an OUTER JOIN boundary that is not moved across in the safe-only implementation."}:query.groupByClause?targetColumns.every(item=>this.isGroupKeyColumn(query,item.targetColumn))?{reason:"Predicate references only GROUP BY keys; it is moved into pre-aggregation WHERE."}:{code:"GROUP_BY_BOUNDARY",reason:"Predicate references a target column that is not proven to be a GROUP BY key."}:query.havingClause?{code:"GROUP_BY_BOUNDARY",reason:"Predicate crosses HAVING aggregation boundary; moving it may change semantics."}:hasOrdinaryDistinct?{reason:"Predicate references direct ordinary DISTINCT output columns; it is moved into the DISTINCT input WHERE."}:{reason:"All outer references resolve to direct upstream outputs before unsafe query boundaries."}}resolveSourceBinding(contextRoot,query,column){let fromClause=query.fromClause;if(!fromClause)return{code:"NO_FROM_CLAUSE",reason:"Predicate has no FROM source that can receive it safely."};let bindings=this.getSourceBindings(fromClause),namespace=normalizeIdentifier4(column.getNamespace()),columnName=column.column.name;if(namespace){let matches2=bindings.filter(binding=>normalizeIdentifier4(binding.alias)===namespace);if(matches2.length!==1)return{code:"AMBIGUOUS_COLUMN_SOURCE",reason:`Column source alias '${column.getNamespace()}' is not uniquely resolvable.`};let matchCount=this.getOutputColumnMatchCount(contextRoot,matches2[0],columnName);return matchCount===0?{code:"COLUMN_NOT_AVAILABLE_UPSTREAM",reason:`Column '${columnReferenceText2(column)}' is not a direct output of the referenced source.`}:matchCount>1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnReferenceText2(column)}' resolves to multiple outputs in the referenced source.`}:matches2[0]}let matches=[];for(let binding of bindings){let matchCount=this.getOutputColumnMatchCount(contextRoot,binding,columnName);if(matchCount>1)return{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:`Column '${columnName}' resolves to multiple outputs in source '${binding.alias}'.`};matchCount===1&&matches.push(binding)}return matches.length!==1?{code:"AMBIGUOUS_COLUMN_REFERENCE",reason:matches.length===0?`Column '${columnName}' is not uniquely resolvable to a safe upstream source.`:`Column '${columnName}' is ambiguous across source query blocks.`}:matches[0]}resolveUpstreamQuery(root,binding,references){let source=binding.source.datasource;if(source instanceof SubQuerySource)return source.query instanceof SimpleSelectQuery?{kind:"simple",query:source.query,scopeId:`subquery:${binding.alias}`,sourceBinding:binding}:source.query instanceof BinarySelectQuery?this.resolveUnionTarget(root,source.query,`subquery:${binding.alias}`,references):{code:"UNION_BOUNDARY",reason:"Predicate would need distribution into a UNION or non-simple subquery, which is unsupported."};if(!(source instanceof TableSource))return{code:"UNSUPPORTED_SOURCE",reason:"Only CTE and simple derived-table sources can receive moved static predicates."};let cteName=source.table.name,commonTable=this.findCte(root,cteName);if(!commonTable)return{code:"NO_SAFE_UPSTREAM_QUERY",reason:"The referenced source is a base table, so there is no upstream query block to move into."};let referenceCount=this.countTableSourceReferences(root,cteName);return referenceCount!==1?{code:"CTE_REUSE_UNSUPPORTED",reason:`CTE '${cteName}' is referenced ${referenceCount} times; moving a predicate into it may affect other consumers.`}:commonTable.query instanceof BinarySelectQuery?this.resolveUnionTarget(root,commonTable.query,`cte:${commonTable.getSourceAliasName()}`,references):commonTable.query instanceof SimpleSelectQuery?{kind:"simple",query:commonTable.query,scopeId:`cte:${commonTable.getSourceAliasName()}`,sourceBinding:binding,cteName:commonTable.getSourceAliasName()}:{code:"UNSUPPORTED_CTE_QUERY",reason:"Writable or non-select CTE bodies are not moved into by static predicate placement."}}resolveUnionTarget(root,query,scopeId,references){let branches=this.collectUnionBranches(query);if("code"in branches)return branches;let outputIndexes=new Map;for(let reference of references){let outputIndex=this.resolveUnionOutputIndex(root,branches[0],reference.column.name);if("code"in outputIndex)return outputIndex;outputIndexes.set(reference,outputIndex.index)}let branchTargets=[];for(let branch of branches){let targetColumns=[];for(let[reference,outputIndex]of outputIndexes.entries()){let targetColumn=this.resolveTargetColumnByOutputIndex(root,branch,outputIndex,reference);if("code"in targetColumn)return targetColumn;targetColumns.push(targetColumn)}branchTargets.push(this.resolveDeepestBranchTarget(root,branch,targetColumns))}return{kind:"union",scopeId,branches:branchTargets}}resolveTargetColumns(root,query,references){let resolved=[];for(let reference of references){let matches=this.collectSelectOutputs(root,query).filter(item=>normalizeIdentifier4(item.name)===normalizeIdentifier4(reference.column.name));if(matches.length!==1)return{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`Target query does not expose '${reference.column.name}' as a direct output column.`:`Target query exposes multiple '${reference.column.name}' columns.`};let value=matches[0].value;if(!(value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`Target output '${reference.column.name}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,value);if(sourceResolution)return sourceResolution;resolved.push({sourceColumn:reference,targetColumn:value})}return resolved}resolveDeepestBranchTarget(contextRoot,query,targetColumns,visited=new Set){if(visited.has(query)||targetColumns.length===0)return{query,targetColumns:[...targetColumns]};let nextVisited=new Set(visited);nextVisited.add(query);let bindings=[];for(let item of targetColumns){let binding2=this.resolveSourceBinding(contextRoot,query,item.targetColumn);if("code"in binding2)return{query,targetColumns:[...targetColumns]};bindings.some(existing=>existing.source===binding2.source)||bindings.push(binding2)}if(bindings.length!==1)return{query,targetColumns:[...targetColumns]};let binding=bindings[0];if(query.fromClause?this.findNullableSideBoundary(query.fromClause,binding):null)return{query,targetColumns:[...targetColumns]};let upstream=this.resolveUpstreamQuery(contextRoot,binding,targetColumns.map(item=>item.targetColumn));if("code"in upstream||upstream.kind==="union")return{query,targetColumns:[...targetColumns]};let upstreamColumns=this.resolveTargetColumns(contextRoot,upstream.query,targetColumns.map(item=>item.targetColumn));if("code"in upstreamColumns)return{query,targetColumns:[...targetColumns]};if("code"in this.resolveTargetPlacement(upstream.query,upstreamColumns))return{query,targetColumns:[...targetColumns]};let rebasedColumns=upstreamColumns.map((item,index)=>({sourceColumn:targetColumns[index].sourceColumn,targetColumn:item.targetColumn}));return this.resolveDeepestBranchTarget(contextRoot,upstream.query,rebasedColumns,nextVisited)}verifyColumnResolvableInQuery(query,column){if(!query.fromClause)return{code:"NO_TARGET_FROM_CLAUSE",reason:"Target query has no FROM clause where the moved column can be resolved."};let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier4(column.getNamespace());return namespace?bindings.filter(binding=>normalizeIdentifier4(binding.alias)===namespace).length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Target column '${columnReferenceText2(column)}' is not uniquely resolvable in the destination query.`}:bindings.length===1?null:{code:"AMBIGUOUS_TARGET_COLUMN",reason:`Unqualified target column '${column.column.name}' is ambiguous in a multi-source destination query.`}}isGroupKeyColumn(query,column){let groupBy=query.groupByClause;return!groupBy||groupBy.mode||groupBy.grouping.length===0?!1:groupBy.grouping.some(grouping=>{let candidate=unwrapParens3(grouping);return candidate instanceof ColumnReference&&this.sameResolvableColumnInQuery(query,candidate,column)})}sameResolvableColumnInQuery(query,left,right){if(sameColumnReference2(left,right))return!0;if(normalizeIdentifier4(left.column.name)!==normalizeIdentifier4(right.column.name))return!1;let leftSource=this.resolveColumnSourceAlias(query,left),rightSource=this.resolveColumnSourceAlias(query,right);return leftSource!==null&&leftSource===rightSource}resolveColumnSourceAlias(query,column){if(!query.fromClause)return null;let bindings=this.getSourceBindings(query.fromClause),namespace=normalizeIdentifier4(column.getNamespace());if(namespace){let matches=bindings.filter(binding=>normalizeIdentifier4(binding.alias)===namespace);return matches.length===1?normalizeIdentifier4(matches[0].alias):null}return bindings.length===1?normalizeIdentifier4(bindings[0].alias):null}rebasePredicate(expression,targetColumns,options){let cloned=cloneValueComponent2(expression,options),visitSelect=(query,inheritedLocalAliases)=>{if(!(query instanceof SimpleSelectQuery))return;let localAliases=new Set(inheritedLocalAliases);for(let alias of this.collectSourceAliases(query))localAliases.add(alias);query.selectClause.items.forEach(item=>visit(item.value,localAliases));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition,localAliases);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query,localAliases)}query.whereClause&&visit(query.whereClause.condition,localAliases),query.havingClause&&visit(query.havingClause.condition,localAliases);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query,localAliases)},visit=(value,localAliases)=>{let candidate=unwrapParens3(value);if(candidate instanceof ColumnReference){let namespace=normalizeIdentifier4(candidate.getNamespace());if(namespace&&localAliases.has(namespace))return;let target=targetColumns.find(item=>sameColumnReference2(candidate,item.sourceColumn));target&&(candidate.qualifiedName=cloneColumnReference2(target.targetColumn).qualifiedName);return}if(candidate instanceof BinaryExpression){visit(candidate.left,localAliases),visit(candidate.right,localAliases);return}if(candidate instanceof UnaryExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery,localAliases);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument,localAliases),candidate.filterCondition&&visit(candidate.filterCondition,localAliases);return}if(candidate instanceof CastExpression){visit(candidate.input,localAliases);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition,localAliases);for(let pair of candidate.switchCase.cases)visit(pair.key,localAliases),visit(pair.value,localAliases);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue,localAliases);return}if(candidate instanceof BetweenExpression){visit(candidate.expression,localAliases),visit(candidate.lower,localAliases),visit(candidate.upper,localAliases);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ValueList){candidate.values.forEach(item=>visit(item,localAliases));return}if(candidate instanceof TupleExpression){candidate.values.forEach(item=>visit(item,localAliases));return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument,localAliases)};return visit(cloned,new Set),cloned}getSourceBindings(fromClause){let bindings=[{source:fromClause.source,alias:fromClause.source.getAliasName()??"",join:null,joinIndex:-1,isPrimary:!0}];for(let index=0;index<(fromClause.joins??[]).length;index+=1){let join=fromClause.joins[index];bindings.push({source:join.source,alias:join.source.getAliasName()??"",join,joinIndex:index,isPrimary:!1})}return bindings}findNullableSideBoundary(fromClause,binding){let joins=fromClause.joins??[];if(binding.isPrimary)return this.hasLaterJoinThatNullsPriorSources(joins,-1)?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses OUTER JOIN nullable side; moving it may change semantics."}:null;let join=binding.join;if(!join)return null;let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses LEFT JOIN nullable side; moving it may change semantics."}:joinType.includes("full")?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses FULL JOIN nullable side; moving it may change semantics."}:this.hasLaterJoinThatNullsPriorSources(joins,binding.joinIndex)?{code:"OUTER_JOIN_NULLABLE_SIDE",reason:"Predicate crosses later RIGHT/FULL JOIN nullable side; moving it may change semantics."}:null}hasLaterJoinThatNullsPriorSources(joins,sourceJoinIndex){return joins.slice(sourceJoinIndex+1).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("right")||joinType.includes("full")})}hasOuterJoin(fromClause){return(fromClause.joins??[]).some(join=>{let joinType=join.joinType.value.toLowerCase();return joinType.includes("left")||joinType.includes("right")||joinType.includes("full")||joinType.includes("outer")})}hasDistinctOnBoundary(query){return query.selectClause.distinct instanceof DistinctOn}hasOrdinaryDistinct(query){return query.selectClause.distinct!==null&&!this.hasDistinctOnBoundary(query)}getOutputColumnMatchCount(root,binding,columnName){let target=this.resolveSourceQueryForColumns(root,binding.source);if(!target)return 0;if(target instanceof BinarySelectQuery){let branches=this.collectUnionBranches(target);return"code"in branches?0:this.collectSelectOutputs(root,branches[0]).filter(item=>normalizeIdentifier4(item.name)===normalizeIdentifier4(columnName)).length}return target instanceof SimpleSelectQuery?this.collectSelectOutputs(root,target).filter(item=>normalizeIdentifier4(item.name)===normalizeIdentifier4(columnName)).length:0}collectUnionBranches(query){let branches=[],visit=select=>{if(select instanceof SimpleSelectQuery)return branches.push(select),null;if(!(select instanceof BinarySelectQuery))return{code:"UNION_BOUNDARY",reason:"Predicate would need distribution into a non-simple UNION branch, which is unsupported."};let operator=select.operator.value.trim().toLowerCase();return operator!=="union"&&operator!=="union all"?{code:"UNION_BOUNDARY",reason:`Predicate would need distribution through '${select.operator.value}', which is unsupported.`}:visit(select.left)??visit(select.right)};return visit(query)??branches}resolveUnionOutputIndex(root,firstBranch,outputColumnName){let matches=[];return this.collectSelectOutputs(root,firstBranch).forEach((item,index)=>{normalizeIdentifier4(item.name)===normalizeIdentifier4(outputColumnName)&&matches.push(index)}),matches.length!==1?{code:"AMBIGUOUS_TARGET_COLUMN",reason:matches.length===0?`UNION output does not expose '${outputColumnName}' from its first branch.`:`UNION first branch exposes multiple '${outputColumnName}' columns.`}:{index:matches[0]}}resolveTargetColumnByOutputIndex(root,query,outputIndex,sourceColumn){let output=this.collectSelectOutputs(root,query)[outputIndex];if(!output)return{code:"UNION_COLUMN_MISMATCH",reason:`UNION branch does not expose column '${sourceColumn.column.name}' at output position ${outputIndex+1}.`};if(!(output.value instanceof ColumnReference))return{code:"EXPRESSION_OUTPUT_UNSUPPORTED",reason:`UNION branch output at position ${outputIndex+1} for '${sourceColumn.column.name}' is an expression, not a direct column reference.`};let sourceResolution=this.verifyColumnResolvableInQuery(query,output.value);return sourceResolution||{sourceColumn,targetColumn:output.value}}collectSelectOutputs(root,query){let commonTables=[...query.withClause?.tables??[],...root.withClause?.tables??[]];return new SelectOutputCollector(null,commonTables.length>0?commonTables:null).collect(query)}resolveSourceQueryForColumns(root,source){if(source.datasource instanceof SubQuerySource)return source.datasource.query;if(source.datasource instanceof TableSource){let cteQuery=this.findCte(root,source.datasource.table.name)?.query;return cteQuery instanceof SimpleSelectQuery||cteQuery instanceof BinarySelectQuery?cteQuery:null}return null}findCte(root,name){let normalized=normalizeIdentifier4(name),matches=(root.withClause?.tables??[]).filter(table=>normalizeIdentifier4(table.getSourceAliasName())===normalized);return matches.length===1?matches[0]:null}countTableSourceReferences(query,tableName){let normalized=normalizeIdentifier4(tableName),count=0,visitSelect=select=>{if(select instanceof BinarySelectQuery){visitSelect(select.left),visitSelect(select.right);return}if(select instanceof SimpleSelectQuery){if(select.fromClause)for(let binding of this.getSourceBindings(select.fromClause)){let source=binding.source.datasource;source instanceof TableSource&&normalizeIdentifier4(source.table.name)===normalized&&(count+=1),source instanceof SubQuerySource&&visitSelect(source.query)}for(let cte of select.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}};return visitSelect(query),count}collectSourceAliases(query){let aliases=new Set;for(let source of query.fromClause?.getSources()??[]){let alias=source.getAliasName();alias&&aliases.add(normalizeIdentifier4(alias))}return aliases}collectRootColumnReferences(root,expression){let references=[],rootAliases=this.collectSourceAliases(root),visitSelect=(query,inheritedLocalAliases)=>{if(!(query instanceof SimpleSelectQuery))return;let localAliases=new Set(inheritedLocalAliases);for(let alias of this.collectSourceAliases(query))localAliases.add(alias);query.selectClause.items.forEach(item=>visit(item.value,localAliases));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition,localAliases);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query,localAliases)}query.whereClause&&visit(query.whereClause.condition,localAliases),query.havingClause&&visit(query.havingClause.condition,localAliases);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query,localAliases)},collect=reference=>{references.some(existing=>sameColumnReference2(existing,reference))||references.push(reference)},visit=(value,localAliases)=>{let candidate=unwrapParens3(value);if(candidate instanceof ColumnReference){let namespace=normalizeIdentifier4(candidate.getNamespace());if(namespace){rootAliases.has(namespace)&&!localAliases.has(namespace)&&collect(candidate);return}localAliases.size===0&&collect(candidate);return}if(candidate instanceof BinaryExpression){visit(candidate.left,localAliases),visit(candidate.right,localAliases);return}if(candidate instanceof UnaryExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery,localAliases);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument,localAliases),candidate.filterCondition&&visit(candidate.filterCondition,localAliases);return}if(candidate instanceof CastExpression){visit(candidate.input,localAliases);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition,localAliases);for(let pair of candidate.switchCase.cases)visit(pair.key,localAliases),visit(pair.value,localAliases);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue,localAliases);return}if(candidate instanceof BetweenExpression){visit(candidate.expression,localAliases),visit(candidate.lower,localAliases),visit(candidate.upper,localAliases);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayExpression){visit(candidate.expression,localAliases);return}if(candidate instanceof ArrayQueryExpression){visitSelect(candidate.query,localAliases);return}if(candidate instanceof ValueList){candidate.values.forEach(item=>visit(item,localAliases));return}if(candidate instanceof TupleExpression){candidate.values.forEach(item=>visit(item,localAliases));return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument,localAliases)};return visit(expression,new Set),references}hasWindowUsage(query){if(query.windowClause)return!0;let found=!1,visit=value=>{if(found)return;let candidate=unwrapParens3(value);if(candidate instanceof FunctionCall){if(candidate.over){found=!0;return}candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}candidate instanceof ValueList&&candidate.values.forEach(visit)};return query.selectClause.items.forEach(item=>visit(item.value)),found}collectParameterNames(expression){let names=[],visitSelect=query=>{if(query instanceof BinarySelectQuery){visitSelect(query.left),visitSelect(query.right);return}if(query instanceof SimpleSelectQuery){query.selectClause.items.forEach(item=>visit(item.value));for(let join of query.fromClause?.joins??[]){join.condition&&visit(join.condition.condition);let source=join.source.datasource;source instanceof SubQuerySource&&visitSelect(source.query)}query.whereClause&&visit(query.whereClause.condition),query.havingClause&&visit(query.havingClause.condition);for(let cte of query.withClause?.tables??[])(cte.query instanceof SimpleSelectQuery||cte.query instanceof BinarySelectQuery)&&visitSelect(cte.query)}},visit=value=>{let candidate=unwrapParens3(value);if(candidate instanceof ParameterExpression){appendUnique2(names,candidate.name.value);return}if(candidate instanceof BinaryExpression){visit(candidate.left),visit(candidate.right);return}if(candidate instanceof UnaryExpression){visit(candidate.expression);return}if(candidate instanceof InlineQuery){visitSelect(candidate.selectQuery);return}if(candidate instanceof ArrayQueryExpression){visitSelect(candidate.query);return}if(candidate instanceof FunctionCall){candidate.argument&&visit(candidate.argument),candidate.filterCondition&&visit(candidate.filterCondition);return}if(candidate instanceof CastExpression){visit(candidate.input);return}if(candidate instanceof CaseExpression){candidate.condition&&visit(candidate.condition);for(let pair of candidate.switchCase.cases)visit(pair.key),visit(pair.value);candidate.switchCase.elseValue&&visit(candidate.switchCase.elseValue);return}if(candidate instanceof BetweenExpression){visit(candidate.expression),visit(candidate.lower),visit(candidate.upper);return}if(candidate instanceof JsonPredicateExpression){visit(candidate.expression);return}if(candidate instanceof ArrayExpression){visit(candidate.expression);return}if(candidate instanceof ValueList){candidate.values.forEach(visit);return}if(candidate instanceof TupleExpression){candidate.values.forEach(visit);return}candidate instanceof TypeValue&&candidate.argument&&visit(candidate.argument)};return visit(expression),names}makeSkipped(expression,draft,options){return{predicateSql:formatSqlComponent(expression,options),scopeId:"scope:root",...draft}}buildResult(params){return{ok:params.errors.length===0,sql:params.sql,query:params.query,applied:params.applied,skipped:params.skipped,warnings:params.warnings,errors:params.errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun:params.dryRun,formatterGeneratedSource:params.formatterGeneratedSource},staticPredicateMoves:params.applied}}},planStaticPredicatePlacement=(input,options={})=>new StaticPredicatePlacementOptimizer().plan(input,options),optimizeStaticPredicatePlacement=(input,options={})=>new StaticPredicatePlacementOptimizer().optimize(input,options);var hasOwnParameter=(parameters,parameterName)=>Object.prototype.hasOwnProperty.call(parameters,parameterName),isAbsentOptionalValue=(parameters,parameterName)=>parameters[parameterName]===null||parameters[parameterName]===void 0,parseConditionOptimizationInput=(input,options)=>{let warnings=[],errors=[],sourceSql=typeof input=="string"?input:formatSqlComponent(input,options),formatterGeneratedSource=typeof input!="string";if(typeof input!="string"&&options.cloneInput===!1)return{query:input,sql:sourceSql,formatterGeneratedSource:!1,warnings,errors};formatterGeneratedSource&&warnings.push({phaseKind:"sssql_optional_condition",code:"AST_INPUT_FORMATTED",message:"AST input is cloned through formatter output so the caller-owned query is not mutated."});try{return{query:SelectQueryParser.parse(sourceSql),sql:sourceSql,formatterGeneratedSource,warnings,errors}}catch(error){return errors.push({phaseKind:"sssql_optional_condition",code:"PARSE_FAILED",message:"SSSQL optional condition optimization could not parse the input SQL.",detail:error instanceof Error?error.message:String(error)}),{query:null,sql:sourceSql,formatterGeneratedSource,warnings,errors}}},buildSssqlApplied=(branch,options)=>({phaseKind:"sssql_optional_condition",kind:"prune_optional_branch",conditionSql:formatSqlComponent(branch.expression,options),parameterName:branch.parameterName,reason:"The optional branch parameter is explicitly absent, so the safe-only SSSQL phase pruned the branch."}),buildSssqlRefreshApplied=(branch,previousConditionSql,options)=>({phaseKind:"sssql_optional_condition",kind:"refresh_optional_branch",conditionSql:formatSqlComponent(branch.expression,options),previousConditionSql,parameterName:branch.parameterName,reason:"The safe-only SSSQL phase refreshed the optional branch placement before ordinary parameter placement."}),buildSssqlSkipped=(branch,parameters,options)=>{let parameterProvided=hasOwnParameter(parameters,branch.parameterName);return{phaseKind:"sssql_optional_condition",kind:"optional_branch_skipped",conditionSql:formatSqlComponent(branch.expression,options),parameterName:branch.parameterName,code:parameterProvided?"SSSQL_OPTIONAL_PARAMETER_PRESENT":"SSSQL_OPTIONAL_PARAMETER_NOT_PROVIDED",reason:parameterProvided?"The optional branch parameter is present, so the branch remains active.":"No optional branch parameter value was provided, so the branch remains unchanged."}},buildSssqlRefreshSkipped=(branch,code,reason,options)=>({phaseKind:"sssql_optional_condition",kind:"optional_branch_skipped",conditionSql:formatSqlComponent(branch.expression,options),parameterName:branch.parameterName,code,reason}),buildSssqlRefreshFilters=(branches,parameters)=>{let filters={};for(let branch of branches)filters[branch.parameterName]=hasOwnParameter(parameters,branch.parameterName)?parameters[branch.parameterName]:null;return filters},refreshRemainingSssqlBranches=(query,fallbackSql,parameters,options)=>{let applied=[],skipped=[],beforeBranches=collectSupportedOptionalConditionBranches(query);if(beforeBranches.length===0)return{query,sql:fallbackSql,applied,skipped,warnings:[],errors:[],formatterGeneratedSource:!1};let beforeBranchSql=new WeakMap,beforeBranchQuery=new WeakMap;for(let branch of beforeBranches)beforeBranchSql.set(branch.expression,formatSqlComponent(branch.expression,options)),beforeBranchQuery.set(branch.expression,branch.query);try{new SSSQLFilterBuilder().refresh(query,buildSssqlRefreshFilters(beforeBranches,parameters))}catch(error){let detail=error instanceof Error?error.message:String(error);return{query,sql:fallbackSql,applied,skipped:beforeBranches.map(branch=>buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_UNSUPPORTED",`SSSQL optional branch refresh was skipped because safe refresh could not be proven: ${detail}`,options)),warnings:[],errors:[],formatterGeneratedSource:!1}}let afterBranches=collectSupportedOptionalConditionBranches(query);for(let branch of afterBranches){let previousSql=beforeBranchSql.get(branch.expression),previousQuery=beforeBranchQuery.get(branch.expression);if(!previousSql||!previousQuery){skipped.push(buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_UNSUPPORTED","SSSQL optional branch refresh left an untracked branch unchanged.",options));continue}let refreshedSql=formatSqlComponent(branch.expression,options);if(previousQuery!==branch.query||previousSql!==refreshedSql){applied.push(buildSssqlRefreshApplied(branch,previousSql,options));continue}skipped.push(buildSssqlRefreshSkipped(branch,"SSSQL_OPTIONAL_REFRESH_NOOP","SSSQL optional branch refresh found no safe placement change to apply.",options))}return{query,sql:applied.length>0||hasSqlComponentFormatOverride(options)?formatSqlComponent(query,options):fallbackSql,applied,skipped,warnings:[],errors:[],formatterGeneratedSource:!1}},refreshRemainingSssqlBranchesFromSql=(sql,parameters,options)=>{let parsed=parseConditionOptimizationInput(sql,options);if(!parsed.query)return{query:null,sql:parsed.sql,applied:[],skipped:[],warnings:parsed.warnings,errors:parsed.errors,formatterGeneratedSource:parsed.formatterGeneratedSource};let refreshed=refreshRemainingSssqlBranches(parsed.query,sql,parameters,options);return{...refreshed,warnings:[...parsed.warnings,...refreshed.warnings],errors:[...parsed.errors,...refreshed.errors],formatterGeneratedSource:parsed.formatterGeneratedSource||refreshed.formatterGeneratedSource}},runSssqlOptionalConditionPhase=(input,options)=>{let reuseOwnedModel=options.cloneInput===!1&&typeof input!="string",parsed=parseConditionOptimizationInput(input,options),warnings=[...parsed.warnings],errors=[...parsed.errors],applied=[],skipped=[],optionalConditionParameters=options.optionalConditionParameters??{};if(!parsed.query)return{query:null,sql:parsed.sql,applied,skipped,warnings,errors,formatterGeneratedSource:parsed.formatterGeneratedSource};let currentSql=parsed.sql,currentQuery=parsed.query,formatterGeneratedSource=parsed.formatterGeneratedSource,branches=collectSupportedOptionalConditionBranches(parsed.query),pruneBranches=branches.filter(branch=>hasOwnParameter(optionalConditionParameters,branch.parameterName)&&isAbsentOptionalValue(optionalConditionParameters,branch.parameterName));if(pruneBranches.length>0)try{pruneOptionalConditionBranches(parsed.query,optionalConditionParameters),currentSql=formatSqlComponent(parsed.query,options),applied.push(...pruneBranches.map(branch=>buildSssqlApplied(branch,options)))}catch(error){errors=[...errors,{phaseKind:"sssql_optional_condition",code:"SSSQL_PRUNE_FAILED",message:"SSSQL optional condition optimization could not prune optional branches.",detail:error instanceof Error?error.message:String(error)}]}if(errors.length===0){let refreshPhase=reuseOwnedModel?refreshRemainingSssqlBranches(parsed.query,currentSql,optionalConditionParameters,options):refreshRemainingSssqlBranchesFromSql(currentSql,optionalConditionParameters,options);applied.push(...refreshPhase.applied),skipped.push(...refreshPhase.skipped),warnings.push(...refreshPhase.warnings),errors.push(...refreshPhase.errors),currentSql=refreshPhase.sql,currentQuery=refreshPhase.query,formatterGeneratedSource=formatterGeneratedSource||refreshPhase.formatterGeneratedSource}else for(let branch of branches)pruneBranches.includes(branch)||skipped.push(buildSssqlSkipped(branch,optionalConditionParameters,options));return{query:errors.length===0?currentQuery:null,sql:errors.length===0?currentSql:parsed.sql,applied,skipped,warnings,errors,formatterGeneratedSource}},mapParameterWarnings=warnings=>warnings.map(warning=>({phaseKind:"parameter_condition_placement",...warning})),mapParameterErrors=errors=>errors.map(error=>({phaseKind:"parameter_condition_placement",...error})),mapParameterApplied=applied=>applied.map(item=>({phaseKind:"parameter_condition_placement",...item})),mapParameterSkipped=skipped=>skipped.map(item=>({phaseKind:"parameter_condition_placement",...item})),mapStaticWarnings=warnings=>warnings.map(warning=>({phaseKind:"static_predicate_placement",...warning})),mapStaticErrors=errors=>errors.map(error=>({phaseKind:"static_predicate_placement",...error})),mapStaticApplied=applied=>applied.map(item=>({phaseKind:"static_predicate_placement",...item})),mapStaticSkipped=skipped=>skipped.map(item=>({phaseKind:"static_predicate_placement",...item})),makePhaseSummary=(kind,counts)=>({kind,appliedCount:counts.appliedCount,skippedCount:counts.skippedCount,warningCount:counts.warningCount,errorCount:counts.errorCount}),runConditionOptimization=(input,options,defaultDryRun)=>{let dryRun=options.dryRun??defaultDryRun,reuseOwnedModel=options.cloneInput===!1&&typeof input!="string",sssqlPhase=runSssqlOptionalConditionPhase(input,{...options,dryRun}),parameterOptimizer=new ParameterConditionPlacementOptimizer,parameterInput=reuseOwnedModel?sssqlPhase.query??sssqlPhase.sql:sssqlPhase.sql,parameterOptions={...options,dryRun,cloneInput:reuseOwnedModel&&sssqlPhase.query?!1:options.cloneInput},parameterPhase=dryRun?parameterOptimizer.plan(parameterInput,parameterOptions):parameterOptimizer.optimize(parameterInput,parameterOptions),parameterWarnings=mapParameterWarnings(parameterPhase.warnings),parameterErrors=mapParameterErrors(parameterPhase.errors),parameterApplied=mapParameterApplied(parameterPhase.applied),parameterSkipped=mapParameterSkipped(parameterPhase.skipped),staticOptimizer=new StaticPredicatePlacementOptimizer,staticInput=reuseOwnedModel?parameterPhase.query??parameterPhase.sql:parameterPhase.sql,staticOptions={...options,dryRun,cloneInput:reuseOwnedModel&&parameterPhase.query?!1:options.cloneInput},staticPhase=dryRun?staticOptimizer.plan(staticInput,staticOptions):staticOptimizer.optimize(staticInput,staticOptions),staticWarnings=mapStaticWarnings(staticPhase.warnings),staticErrors=mapStaticErrors(staticPhase.errors),staticApplied=mapStaticApplied(staticPhase.applied),staticSkipped=mapStaticSkipped(staticPhase.skipped),warnings=[...sssqlPhase.warnings,...parameterWarnings,...staticWarnings],errors=[...sssqlPhase.errors,...parameterErrors,...staticErrors];return{ok:errors.length===0,sql:staticPhase.sql,query:staticPhase.query,phases:[makePhaseSummary("sssql_optional_condition",{appliedCount:sssqlPhase.applied.length,skippedCount:sssqlPhase.skipped.length,warningCount:sssqlPhase.warnings.length,errorCount:sssqlPhase.errors.length}),makePhaseSummary("parameter_condition_placement",{appliedCount:parameterApplied.length,skippedCount:parameterSkipped.length,warningCount:parameterWarnings.length,errorCount:parameterErrors.length}),makePhaseSummary("static_predicate_placement",{appliedCount:staticApplied.length,skippedCount:staticSkipped.length,warningCount:staticWarnings.length,errorCount:staticErrors.length})],applied:[...sssqlPhase.applied,...parameterApplied,...staticApplied],skipped:[...sssqlPhase.skipped,...parameterSkipped,...staticSkipped],warnings,errors,safety:{mode:"safe_only",unsafeRewriteApplied:!1,dryRun,formatterGeneratedSource:sssqlPhase.formatterGeneratedSource||parameterPhase.safety.formatterGeneratedSource||staticPhase.safety.formatterGeneratedSource}}},planConditionOptimization=(input,options={})=>runConditionOptimization(input,options,!0),optimizeConditions=(input,options={})=>runConditionOptimization(input,options,!1);var BaseDataFlowNode=class{constructor(id,label,type,shape,details){this.id=id;this.label=label;this.type=type;this.shape=shape;this.details=details}},DataSourceNode=class _DataSourceNode extends BaseDataFlowNode{constructor(id,label,type){super(id,label,type,type==="subquery"?"hexagon":"cylinder");this.annotations=new Set}addAnnotation(annotation){this.annotations.add(annotation)}hasAnnotation(annotation){return this.annotations.has(annotation)}getMermaidRepresentation(){return this.shape==="hexagon"?`${this.id}{{${this.label}}}`:`${this.id}[(${this.label})]`}static createTable(tableName){return new _DataSourceNode(`table_${tableName}`,tableName,"table")}static createCTE(cteName){return new _DataSourceNode(`cte_${cteName}`,`CTE:${cteName}`,"cte")}static createSubquery(alias){return new _DataSourceNode(`subquery_${alias}`,`SubQuery:${alias}`,"subquery")}},ProcessNode=class _ProcessNode extends BaseDataFlowNode{constructor(id,operation,context=""){let nodeId=context?`${context}_${operation.toLowerCase().replace(/\s+/g,"_")}`:operation.toLowerCase().replace(/\s+/g,"_");super(nodeId,operation,"process","hexagon")}getMermaidRepresentation(){return`${this.id}{{${this.label}}}`}static createWhere(context){return new _ProcessNode(`${context}_where`,"WHERE",context)}static createGroupBy(context){return new _ProcessNode(`${context}_group_by`,"GROUP BY",context)}static createHaving(context){return new _ProcessNode(`${context}_having`,"HAVING",context)}static createSelect(context){return new _ProcessNode(`${context}_select`,"SELECT",context)}static createOrderBy(context){return new _ProcessNode(`${context}_order_by`,"ORDER BY",context)}static createLimit(context,hasOffset=!1){let label=hasOffset?"LIMIT/OFFSET":"LIMIT";return new _ProcessNode(`${context}_limit`,label,context)}},OperationNode=class _OperationNode extends BaseDataFlowNode{constructor(id,operation,shape="diamond"){super(id,operation,"operation",shape)}getMermaidRepresentation(){switch(this.shape){case"rounded":return`${this.id}(${this.label})`;case"rectangle":return`${this.id}[${this.label}]`;case"hexagon":return`${this.id}{{${this.label}}}`;case"stadium":return`${this.id}([${this.label}])`;default:return`${this.id}{${this.label}}`}}static createJoin(joinId,joinType){let label,normalizedType=joinType.trim().toLowerCase();return normalizedType==="join"?label="INNER JOIN":normalizedType.endsWith(" join")?label=normalizedType.toUpperCase():label=normalizedType.toUpperCase()+" JOIN",new _OperationNode(`join_${joinId}`,label,"rectangle")}static createUnion(unionId,unionType="UNION ALL"){return new _OperationNode(`${unionType.toLowerCase().replace(/\s+/g,"_")}_${unionId}`,unionType.toUpperCase(),"rectangle")}static createSetOperation(operationId,operation){let normalizedOp=operation.toUpperCase(),id=`${normalizedOp.toLowerCase().replace(/\s+/g,"_")}_${operationId}`;return new _OperationNode(id,normalizedOp,"rectangle")}},OutputNode=class extends BaseDataFlowNode{constructor(context="main"){let label=context==="main"?"Final Result":`${context} Result`;super(`${context}_output`,label,"output","stadium")}getMermaidRepresentation(){return`${this.id}([${this.label}])`}};var DataFlowConnection=class _DataFlowConnection{constructor(from,to,label){this.from=from;this.to=to;this.label=label}getMermaidRepresentation(){let arrow=this.label?` -->|${this.label}| `:" --> ";return`${this.from}${arrow}${this.to}`}static create(from,to,label){return new _DataFlowConnection(from,to,label)}static createWithNullability(from,to,isNullable){let label=isNullable?"NULLABLE":"NOT NULL";return new _DataFlowConnection(from,to,label)}},DataFlowEdgeCollection=class{constructor(){this.edges=[];this.connectionSet=new Set}add(edge){let key=`${edge.from}->${edge.to}`;this.connectionSet.has(key)||(this.edges.push(edge),this.connectionSet.add(key))}addConnection(from,to,label){this.add(DataFlowConnection.create(from,to,label))}addJoinConnection(from,to,isNullable){this.add(DataFlowConnection.createWithNullability(from,to,isNullable))}hasConnection(from,to){return this.connectionSet.has(`${from}->${to}`)}getAll(){return[...this.edges]}getMermaidRepresentation(){return this.edges.map(edge=>edge.getMermaidRepresentation()).join(`
50
50
  `)}};var DataFlowGraph=class{constructor(){this.nodes=new Map;this.edges=new DataFlowEdgeCollection}addNode(node){this.nodes.set(node.id,node)}addEdge(edge){this.edges.add(edge)}addConnection(from,to,label){this.edges.addConnection(from,to,label)}hasNode(nodeId){return this.nodes.has(nodeId)}hasConnection(from,to){return this.edges.hasConnection(from,to)}getNode(nodeId){return this.nodes.get(nodeId)}getAllNodes(){return Array.from(this.nodes.values())}getAllEdges(){return this.edges.getAll()}generateMermaid(direction="TD",title){let mermaid=`flowchart ${direction}
51
51
  `;title&&(mermaid+=` %% ${title}
52
52
  `);let nodeLines=Array.from(this.nodes.values()).map(node=>` ${node.getMermaidRepresentation()}`).join(`