rawsql-ts 0.10.3-beta → 0.10.4-beta

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/models/SqlComponent.ts", "../src/models/InsertQuery.ts", "../src/models/ValueComponent.ts", "../src/models/Clause.ts", "../src/models/Lexeme.ts", "../src/utils/charLookupTable.ts", "../src/utils/stringUtils.ts", "../src/tokenReaders/BaseTokenReader.ts", "../src/tokenReaders/IdentifierTokenReader.ts", "../src/parsers/KeywordParser.ts", "../src/models/KeywordTrie.ts", "../src/tokenReaders/LiteralTokenReader.ts", "../src/tokenReaders/ParameterTokenReader.ts", "../src/tokenReaders/SymbolTokenReader.ts", "../src/tokenReaders/TokenReaderManager.ts", "../src/tokenReaders/OperatorTokenReader.ts", "../src/tokenReaders/CommandTokenReader.ts", "../src/tokenReaders/StringSpecifierTokenReader.ts", "../src/tokenReaders/FunctionTokenReader.ts", "../src/tokenReaders/TypeTokenReader.ts", "../src/tokenReaders/EscapedIdentifierTokenReader.ts", "../src/parsers/SqlTokenizer.ts", "../src/parsers/FullNameParser.ts", "../src/parsers/IdentifierParser.ts", "../src/parsers/LiteralParser.ts", "../src/parsers/ParenExpressionParser.ts", "../src/parsers/UnaryExpressionParser.ts", "../src/parsers/ParameterExpressionParser.ts", "../src/parsers/StringSpecifierExpressionParser.ts", "../src/parsers/CommandExpressionParser.ts", "../src/parsers/OrderByClauseParser.ts", "../src/parsers/PartitionByParser.ts", "../src/parsers/WindowExpressionParser.ts", "../src/parsers/OverExpressionParser.ts", "../src/parsers/FunctionExpressionParser.ts", "../src/parsers/ParseError.ts", "../src/utils/OperatorPrecedence.ts", "../src/parsers/ValueParser.ts", "../src/transformers/CTECollector.ts", "../src/transformers/CTEDisabler.ts", "../src/transformers/TableSourceCollector.ts", "../src/models/SqlPrintToken.ts", "../src/transformers/ParameterCollector.ts", "../src/parsers/IdentifierDecorator.ts", "../src/parsers/ParameterDecorator.ts", "../src/models/UpdateQuery.ts", "../src/transformers/SelectValueCollector.ts", "../src/models/CreateTableQuery.ts", "../src/parsers/SqlPrintTokenParser.ts", "../src/transformers/LinePrinter.ts", "../src/transformers/SqlPrinter.ts", "../src/transformers/SqlFormatter.ts", "../src/transformers/Formatter.ts", "../src/transformers/CTEBuilder.ts", "../src/transformers/CTEInjector.ts", "../src/transformers/CTENormalizer.ts", "../src/transformers/SelectableColumnCollector.ts", "../src/parsers/SourceParser.ts", "../src/transformers/UpstreamSelectQueryFinder.ts", "../src/parsers/SourceAliasExpressionParser.ts", "../src/parsers/SourceExpressionParser.ts", "../src/transformers/QueryBuilder.ts", "../src/utils/ParameterHelper.ts", "../src/models/SimpleSelectQuery.ts", "../src/models/BinarySelectQuery.ts", "../src/models/ValuesQuery.ts", "../src/parsers/SelectClauseParser.ts", "../src/parsers/JoinOnClauseParser.ts", "../src/parsers/JoinUsingClauseParser.ts", "../src/parsers/JoinClauseParser.ts", "../src/parsers/FromClauseParser.ts", "../src/parsers/WhereClauseParser.ts", "../src/parsers/GroupByParser.ts", "../src/parsers/HavingParser.ts", "../src/parsers/WindowClauseParser.ts", "../src/parsers/LimitClauseParser.ts", "../src/parsers/ForClauseParser.ts", "../src/parsers/CommonTableParser.ts", "../src/parsers/WithClauseParser.ts", "../src/parsers/ValuesQueryParser.ts", "../src/parsers/FetchClauseParser.ts", "../src/parsers/OffsetClauseParser.ts", "../src/parsers/SelectQueryParser.ts", "../src/parsers/InsertQueryParser.ts", "../src/transformers/PostgresObjectEntityCteBuilder.ts", "../src/transformers/PostgresArrayEntityCteBuilder.ts", "../src/transformers/PostgresJsonQueryBuilder.ts", "../src/transformers/SchemaCollector.ts", "../src/transformers/SqlParamInjector.ts", "../src/utils/SqlSchemaValidator.ts", "../src/utils/SchemaManager.ts"],
4
- "sourcesContent": ["// Entry point for rawsql-ts package\r\nexport * from './parsers/SelectQueryParser';\r\nexport * from './parsers/InsertQueryParser';\r\n\r\nexport * from './models/BinarySelectQuery';\r\nexport * from './models/SelectQuery';\r\nexport * from './models/ValueComponent';\r\nexport * from './models/ValuesQuery';\r\n\r\nexport * from './transformers/CTECollector';\r\nexport * from './transformers/CTENormalizer';\r\nexport * from './transformers/Formatter';\r\nexport * from './transformers/SqlFormatter';\r\nexport * from './transformers/PostgresJsonQueryBuilder';\r\nexport * from './transformers/QueryBuilder'; // old name:QueryConverter\r\nexport * from './transformers/SelectValueCollector';\r\nexport * from './transformers/SelectableColumnCollector';\r\nexport * from './transformers/TableColumnResolver';\r\nexport * from './transformers/TableSourceCollector';\r\nexport * from './transformers/UpstreamSelectQueryFinder';\r\nexport * from './transformers/SchemaCollector';\r\nexport * from './transformers/SqlParamInjector';\r\n\r\nexport * from './utils/SqlSchemaValidator';\r\nexport * from './utils/SchemaManager';\r\n// Add more exports here if you want to expose additional public API\r\n", "\uFEFFexport abstract class SqlComponent {\r\n // `kind` is declared abstractly and defined concretely in a subclass.\r\n static kind: symbol;\r\n\r\n getKind(): symbol {\r\n return (this.constructor as typeof SqlComponent).kind;\r\n }\r\n\r\n accept<T>(visitor: SqlComponentVisitor<T>): T {\r\n return visitor.visit(this);\r\n }\r\n\r\n toSqlString(formatter: SqlComponentVisitor<string>): string {\r\n return this.accept(formatter);\r\n }\r\n\r\n comments: string[] | null = null;\r\n}\r\n\r\nexport interface SqlComponentVisitor<T> {\r\n visit(expr: SqlComponent): T;\r\n}\r\n\r\nexport class SqlDialectConfiguration {\r\n public parameterSymbol: string = \":\";\r\n public identifierEscape = { start: '\"', end: '\"' };\r\n public exportComment: boolean = true;\r\n}\r\n", "// Represents an INSERT query in SQL.\r\n// Supports single/multi-row VALUES and INSERT ... SELECT.\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { SelectQuery } from \"./SelectQuery\";\r\nimport { InsertClause } from \"./Clause\";\r\n\r\nexport class InsertQuery extends SqlComponent {\r\n static kind = Symbol(\"InsertQuery\");\r\n insertClause: InsertClause;\r\n selectQuery: SelectQuery | null;\r\n\r\n /**\r\n * @param params.insertClause InsertClause instance (target table and columns)\r\n * @param params.selectQuery SELECT/VALUES query (required)\r\n */\r\n constructor(params: {\r\n insertClause: InsertClause;\r\n selectQuery?: SelectQuery | null;\r\n }) {\r\n super();\r\n this.insertClause = params.insertClause;\r\n this.selectQuery = params.selectQuery ?? null;\r\n }\r\n}", "import { PartitionByClause, OrderByClause } from \"./Clause\";\r\nimport { SelectQuery, SimpleSelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\n\r\nexport type ValueComponent = ValueList |\r\n ColumnReference |\r\n FunctionCall |\r\n UnaryExpression |\r\n BinaryExpression |\r\n LiteralValue |\r\n ParameterExpression |\r\n SwitchCaseArgument |\r\n CaseKeyValuePair |\r\n RawString |\r\n IdentifierString |\r\n ParenExpression |\r\n CastExpression |\r\n CaseExpression |\r\n ArrayExpression |\r\n ArrayQueryExpression |\r\n BetweenExpression |\r\n InlineQuery |\r\n StringSpecifierExpression |\r\n TypeValue |\r\n TupleExpression;\r\n\r\nexport class InlineQuery extends SqlComponent {\r\n static kind = Symbol(\"InlineQuery\");\r\n selectQuery: SelectQuery;\r\n constructor(selectQuery: SelectQuery) {\r\n super();\r\n this.selectQuery = selectQuery;\r\n }\r\n}\r\n\r\nexport class ValueList extends SqlComponent {\r\n static kind = Symbol(\"ValueList\");\r\n values: ValueComponent[];\r\n constructor(values: ValueComponent[]) {\r\n super();\r\n this.values = values;\r\n }\r\n}\r\n\r\nexport class ColumnReference extends SqlComponent {\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the column name as IdentifierString (readonly)\r\n */\r\n get column(): IdentifierString {\r\n // If the name is RawString, convert to IdentifierString for compatibility\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n static kind = Symbol(\"ColumnReference\");\r\n qualifiedName: QualifiedName; constructor(namespaces: string | string[] | IdentifierString[] | null, column: string | IdentifierString) {\r\n super();\r\n const col = typeof column === \"string\" ? new IdentifierString(column) : column;\r\n this.qualifiedName = new QualifiedName(toIdentifierStringArray(namespaces), col);\r\n }\r\n\r\n public toString(): string {\r\n return this.qualifiedName.toString();\r\n }\r\n public getNamespace(): string {\r\n if (this.qualifiedName.namespaces) {\r\n return this.qualifiedName.namespaces.map((namespace) => namespace.name).join(\".\");\r\n } else {\r\n return '';\r\n }\r\n }\r\n}\r\n\r\nexport class FunctionCall extends SqlComponent {\r\n static kind = Symbol(\"FunctionCall\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n over: OverExpression | null; constructor(\r\n namespaces: string | string[] | IdentifierString[] | null,\r\n name: string | RawString | IdentifierString,\r\n argument: ValueComponent | null,\r\n over: OverExpression | null\r\n ) {\r\n super();\r\n this.qualifiedName = new QualifiedName(namespaces, name);\r\n this.argument = argument;\r\n this.over = over;\r\n }\r\n\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the function name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n}\r\n\r\nexport type OverExpression = WindowFrameExpression | IdentifierString;\r\n\r\nexport enum WindowFrameType {\r\n Rows = \"rows\",\r\n Range = \"range\",\r\n Groups = \"groups\",\r\n}\r\n\r\nexport enum WindowFrameBound {\r\n UnboundedPreceding = \"unbounded preceding\",\r\n UnboundedFollowing = \"unbounded following\",\r\n CurrentRow = \"current row\",\r\n}\r\n\r\nexport type FrameBoundaryComponent = WindowFrameBoundStatic | WindowFrameBoundaryValue;\r\n\r\nexport class WindowFrameBoundStatic extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameStaticBound\");\r\n bound: WindowFrameBound;\r\n constructor(bound: WindowFrameBound) {\r\n super();\r\n this.bound = bound;\r\n }\r\n}\r\n\r\nexport class WindowFrameBoundaryValue extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameBoundary\");\r\n value: ValueComponent;\r\n isFollowing: boolean; // true for \"FOLLOWING\", false for \"PRECEDING\"\r\n constructor(value: ValueComponent, isFollowing: boolean) {\r\n super();\r\n this.value = value;\r\n this.isFollowing = isFollowing;\r\n }\r\n}\r\n\r\nexport class WindowFrameSpec extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameSpec\");\r\n frameType: WindowFrameType;\r\n startBound: FrameBoundaryComponent;\r\n endBound: FrameBoundaryComponent | null; // null for single boundary specification\r\n constructor(frameType: WindowFrameType, startBound: FrameBoundaryComponent, endBound: FrameBoundaryComponent | null) {\r\n super();\r\n this.frameType = frameType;\r\n this.startBound = startBound;\r\n this.endBound = endBound;\r\n }\r\n}\r\n\r\nexport class WindowFrameExpression extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameExpression\");\r\n partition: PartitionByClause | null;\r\n order: OrderByClause | null;\r\n frameSpec: WindowFrameSpec | null;\r\n constructor(partition: PartitionByClause | null, order: OrderByClause | null, frameSpec: WindowFrameSpec | null = null) {\r\n super();\r\n this.partition = partition;\r\n this.order = order;\r\n this.frameSpec = frameSpec;\r\n }\r\n}\r\n\r\nexport class UnaryExpression extends SqlComponent {\r\n static kind = Symbol(\"UnaryExpression\");\r\n operator: RawString;\r\n expression: ValueComponent;\r\n constructor(operator: string, expression: ValueComponent) {\r\n super();\r\n this.operator = new RawString(operator);\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class BinaryExpression extends SqlComponent {\r\n static kind = Symbol(\"BinaryExpression\");\r\n left: ValueComponent;\r\n operator: RawString;\r\n right: ValueComponent;\r\n constructor(left: ValueComponent, operator: string, right: ValueComponent) {\r\n super();\r\n this.left = left;\r\n this.operator = new RawString(operator);\r\n this.right = right;\r\n }\r\n}\r\n\r\nexport class LiteralValue extends SqlComponent {\r\n static kind = Symbol(\"LiteralExpression\");\r\n // Use the string type instead of the RawString type because it has its own escaping process.\r\n value: string | number | boolean | null;\r\n constructor(value: string | number | boolean | null) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class ParameterExpression extends SqlComponent {\r\n static kind = Symbol(\"ParameterExpression\");\r\n name: RawString;\r\n value: any | null; // Holds the parameter value; can be provided via second argument.\r\n /**\r\n * The index assigned by the formatter when generating parameterized queries.\r\n * Used for naming parameters like $1, $2, etc.\r\n */\r\n index: number | null;\r\n constructor(name: string, value: any | null = null) {\r\n super();\r\n this.name = new RawString(name);\r\n this.value = value; // Value is now accepted as a second argument (optional)\r\n this.index = null;\r\n }\r\n}\r\n\r\nexport class SwitchCaseArgument extends SqlComponent {\r\n static kind = Symbol(\"SwitchCaseArgument\");\r\n cases: CaseKeyValuePair[];\r\n elseValue: ValueComponent | null;\r\n constructor(cases: CaseKeyValuePair[], elseValue: ValueComponent | null = null) {\r\n super();\r\n this.cases = cases;\r\n this.elseValue = elseValue;\r\n }\r\n}\r\n\r\nexport class CaseKeyValuePair extends SqlComponent {\r\n static kind = Symbol(\"CaseKeyValuePair\");\r\n key: ValueComponent;\r\n value: ValueComponent;\r\n constructor(key: ValueComponent, value: ValueComponent) {\r\n super();\r\n this.key = key;\r\n this.value = value;\r\n }\r\n}\r\n\r\n/*\r\n * Values \u200B\u200Bthat must be hard-coded, such as type names and function names.\r\n * A simple check is performed when decoding.\r\n */\r\nexport class RawString extends SqlComponent {\r\n static kind = Symbol(\"RawString\");\r\n value: string;\r\n constructor(value: string) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class IdentifierString extends SqlComponent {\r\n static kind = Symbol(\"IdentifierString\");\r\n name: string;\r\n constructor(alias: string) {\r\n super();\r\n this.name = alias;\r\n }\r\n}\r\n\r\nexport class ParenExpression extends SqlComponent {\r\n static kind = Symbol(\"ParenExpression\");\r\n expression: ValueComponent;\r\n constructor(expression: ValueComponent) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class CastExpression extends SqlComponent {\r\n static kind = Symbol(\"CastExpression\");\r\n input: ValueComponent;\r\n castType: TypeValue;\r\n constructor(input: ValueComponent, castType: TypeValue) {\r\n super();\r\n this.input = input;\r\n this.castType = castType;\r\n }\r\n}\r\n\r\nexport class CaseExpression extends SqlComponent {\r\n static kind = Symbol(\"CaseExpression\");\r\n condition: ValueComponent | null;\r\n switchCase: SwitchCaseArgument;\r\n\r\n constructor(condition: ValueComponent | null, switchCase: SwitchCaseArgument) {\r\n super();\r\n this.condition = condition;\r\n this.switchCase = switchCase;\r\n }\r\n}\r\n\r\nexport class ArrayExpression extends SqlComponent {\r\n static kind = Symbol(\"ArrayExpression\");\r\n expression: ValueComponent;\r\n constructor(expression: ValueComponent) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class ArrayQueryExpression extends SqlComponent {\r\n static kind = Symbol(\"ArrayQueryExpression\");\r\n query: SelectQuery;\r\n constructor(query: SelectQuery) {\r\n super();\r\n this.query = query;\r\n }\r\n}\r\n\r\nexport class BetweenExpression extends SqlComponent {\r\n static kind = Symbol(\"BetweenExpression\");\r\n expression: ValueComponent;\r\n lower: ValueComponent;\r\n upper: ValueComponent;\r\n negated: boolean;\r\n constructor(expression: ValueComponent, lower: ValueComponent, upper: ValueComponent, negated: boolean) {\r\n super();\r\n this.expression = expression;\r\n this.lower = lower;\r\n this.upper = upper;\r\n this.negated = negated;\r\n }\r\n}\r\n\r\nexport class StringSpecifierExpression extends SqlComponent {\r\n static kind = Symbol(\"StringSpecifierExpression\");\r\n // e.g. 'E', 'X', 'U&'\r\n specifier: RawString;\r\n value: LiteralValue;\r\n constructor(specifier: string, value: string) {\r\n super();\r\n this.specifier = new RawString(specifier);\r\n this.value = new LiteralValue(value);\r\n }\r\n}\r\n\r\n// other\r\n\r\nexport class TypeValue extends SqlComponent {\r\n static kind = Symbol(\"TypeValue\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n constructor(namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString, argument: ValueComponent | null = null) {\r\n super();\r\n this.qualifiedName = new QualifiedName(namespaces, name);\r\n this.argument = argument;\r\n }\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the type name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n public getTypeName(): string {\r\n const nameValue = this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name;\r\n if (this.qualifiedName.namespaces && this.qualifiedName.namespaces.length > 0) {\r\n return this.qualifiedName.namespaces.map(ns => ns.name).join(\".\") + \".\" + nameValue;\r\n } else {\r\n return nameValue;\r\n }\r\n }\r\n}\r\n\r\nexport class TupleExpression extends SqlComponent {\r\n static kind = Symbol(\"TupleExpression\");\r\n values: ValueComponent[];\r\n constructor(values: ValueComponent[]) {\r\n super();\r\n this.values = values;\r\n }\r\n}\r\n\r\nfunction toIdentifierStringArray(input: string | string[] | IdentifierString[] | null): IdentifierString[] | null {\r\n if (input == null) return null;\r\n\r\n if (typeof input === \"string\") {\r\n // Empty string should be treated as null\r\n return input.trim() === \"\" ? null : [new IdentifierString(input)];\r\n }\r\n\r\n if (Array.isArray(input)) {\r\n if (input.length === 0) return null;\r\n\r\n if (typeof input[0] === \"string\") {\r\n // Filter out empty strings from string array\r\n const filteredStrings = (input as string[]).filter(ns => ns.trim() !== \"\");\r\n return filteredStrings.length === 0 ? null : filteredStrings.map(ns => new IdentifierString(ns));\r\n } else {\r\n // Filter out empty IdentifierStrings from IdentifierString array\r\n const filteredIdentifiers = (input as IdentifierString[]).filter(ns => ns.name.trim() !== \"\");\r\n return filteredIdentifiers.length === 0 ? null : filteredIdentifiers;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Represents a qualified name with optional namespaces (e.g. schema.table, db.schema.function)\r\n */\r\nexport class QualifiedName extends SqlComponent {\r\n static kind = Symbol(\"QualifiedName\");\r\n\r\n /** List of namespaces (e.g. schema, database) */\r\n namespaces: IdentifierString[] | null;\r\n /** The actual name (e.g. table, function, type, column) */\r\n name: RawString | IdentifierString;\r\n\r\n constructor(namespaces: string | string[] | IdentifierString[] | null, name: string | RawString | IdentifierString) {\r\n super();\r\n this.namespaces = toIdentifierStringArray(namespaces);\r\n if (typeof name === \"string\") {\r\n this.name = new RawString(name);\r\n } else {\r\n this.name = name;\r\n }\r\n }\r\n\r\n /** Returns the full qualified name as a string (dot-separated) */\r\n toString(): string {\r\n const nameValue = this.name instanceof RawString ? this.name.value : this.name.name;\r\n if (this.namespaces && this.namespaces.length > 0) {\r\n return this.namespaces.map(ns => ns.name).join(\".\") + \".\" + nameValue;\r\n } else {\r\n return nameValue;\r\n }\r\n }\r\n}", "import { SelectQuery, SimpleSelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { IdentifierString, RawString, TupleExpression, ValueComponent, WindowFrameExpression, QualifiedName } from \"./ValueComponent\";\r\n\r\nexport class SelectItem extends SqlComponent {\r\n static kind = Symbol(\"SelectItem\");\r\n value: ValueComponent;\r\n identifier: IdentifierString | null;\r\n constructor(value: ValueComponent, name: string | null = null) {\r\n super();\r\n this.value = value;\r\n this.identifier = name ? new IdentifierString(name) : null;\r\n }\r\n}\r\n\r\nexport class SelectClause extends SqlComponent {\r\n static kind = Symbol(\"SelectClause\");\r\n items: SelectItem[];\r\n distinct: DistinctComponent | null;\r\n constructor(items: SelectItem[], distinct: DistinctComponent | null = null) {\r\n super();\r\n this.items = items;\r\n this.distinct = distinct;\r\n }\r\n}\r\n\r\nexport type DistinctComponent = Distinct | DistinctOn;\r\n\r\nexport class Distinct extends SqlComponent {\r\n static kind = Symbol(\"Distinct\");\r\n constructor() {\r\n super();\r\n }\r\n}\r\n\r\nexport class DistinctOn extends SqlComponent {\r\n static kind = Symbol(\"DistinctOn\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\n\r\nexport class WhereClause extends SqlComponent {\r\n static kind = Symbol(\"WhereClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class PartitionByClause extends SqlComponent {\r\n static kind = Symbol(\"PartitionByClause\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class WindowFrameClause extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameClause\");\r\n name: IdentifierString;\r\n expression: WindowFrameExpression;\r\n constructor(name: string, expression: WindowFrameExpression) {\r\n super();\r\n this.name = new IdentifierString(name);\r\n this.expression = expression;\r\n }\r\n}\r\n\r\n/**\r\n * Represents a collection of window definitions (WINDOW clause in SQL).\r\n * @param windows Array of WindowFrameClause\r\n */\r\nexport class WindowsClause extends SqlComponent {\r\n static kind = Symbol(\"WindowsClause\");\r\n windows: WindowFrameClause[];\r\n constructor(windows: WindowFrameClause[]) {\r\n super();\r\n this.windows = windows;\r\n }\r\n}\r\n\r\nexport enum SortDirection {\r\n Ascending = \"asc\",\r\n Descending = \"desc\",\r\n}\r\nexport enum NullsSortDirection {\r\n First = \"first\",\r\n Last = \"last\",\r\n}\r\n\r\nexport type OrderByComponent = OrderByItem | ValueComponent;\r\n\r\nexport class OrderByClause extends SqlComponent {\r\n static kind = Symbol(\"OrderByClause\");\r\n order: OrderByComponent[];\r\n constructor(items: OrderByComponent[]) {\r\n super();\r\n this.order = items;\r\n }\r\n}\r\n\r\nexport class OrderByItem extends SqlComponent {\r\n static kind = Symbol(\"OrderByItem\");\r\n value: ValueComponent;\r\n sortDirection: SortDirection;\r\n nullsPosition: NullsSortDirection | null;\r\n constructor(expression: ValueComponent, sortDirection: SortDirection | null, nullsPosition: NullsSortDirection | null) {\r\n super();\r\n this.value = expression;\r\n this.sortDirection = sortDirection === null ? SortDirection.Ascending : sortDirection;\r\n this.nullsPosition = nullsPosition;\r\n }\r\n}\r\n\r\nexport class GroupByClause extends SqlComponent {\r\n static kind = Symbol(\"GroupByClause\");\r\n grouping: ValueComponent[];\r\n constructor(expression: ValueComponent[]) {\r\n super();\r\n this.grouping = expression;\r\n }\r\n}\r\n\r\nexport class HavingClause extends SqlComponent {\r\n static kind = Symbol(\"HavingClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport type SourceComponent = TableSource |\r\n FunctionSource |\r\n SubQuerySource |\r\n ParenSource;\r\n\r\nexport class TableSource extends SqlComponent {\r\n static kind = Symbol(\"TableSource\");\r\n qualifiedName: QualifiedName;\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the table name as IdentifierString (readonly)\r\n */\r\n get table(): IdentifierString {\r\n // If the name is RawString, convert to IdentifierString for compatibility\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n /**\r\n * For backward compatibility: returns the table name as IdentifierString (readonly)\r\n */\r\n get identifier(): IdentifierString {\r\n return this.table;\r\n }\r\n constructor(namespaces: string[] | IdentifierString[] | null, table: string | IdentifierString) {\r\n super();\r\n // Convert the table name to an IdentifierString if it is provided as a string.\r\n const tbl = typeof table === \"string\" ? new IdentifierString(table) : table;\r\n // Wrap the namespaces and table name in a QualifiedName object.\r\n // This design choice ensures backward compatibility by allowing the namespaces\r\n // and table name to be accessed in a way consistent with the previous implementation.\r\n this.qualifiedName = new QualifiedName(namespaces, tbl);\r\n }\r\n public getSourceName(): string {\r\n if (this.qualifiedName.namespaces && this.qualifiedName.namespaces.length > 0) {\r\n return this.qualifiedName.namespaces.map((namespace) => namespace.name).join(\".\") + \".\" + (this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name);\r\n } else {\r\n return this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name;\r\n }\r\n }\r\n}\r\n\r\nexport class FunctionSource extends SqlComponent {\r\n static kind = Symbol(\"FunctionSource\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n constructor(\r\n name: string | IdentifierString | { namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString },\r\n argument: ValueComponent | null\r\n ) {\r\n super();\r\n if (typeof name === \"object\" && name !== null && \"name\" in name) {\r\n // Accepts { namespaces, name }\r\n const nameObj = name as { namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString };\r\n this.qualifiedName = new QualifiedName(nameObj.namespaces, nameObj.name);\r\n } else {\r\n this.qualifiedName = new QualifiedName(null, name as string | RawString | IdentifierString);\r\n }\r\n this.argument = argument;\r\n }\r\n\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the function name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n}\r\n\r\nexport class ParenSource extends SqlComponent {\r\n static kind = Symbol(\"ParenSource\");\r\n source: SourceComponent;\r\n constructor(source: SourceComponent) {\r\n super();\r\n this.source = source;\r\n }\r\n}\r\n\r\nexport class SubQuerySource extends SqlComponent {\r\n static kind = Symbol(\"SubQuerySource\");\r\n query: SelectQuery;\r\n constructor(query: SelectQuery) {\r\n super();\r\n this.query = query;\r\n }\r\n}\r\n\r\nexport class SourceExpression extends SqlComponent {\r\n static kind = Symbol(\"SourceExpression\");\r\n datasource: SourceComponent;\r\n aliasExpression: SourceAliasExpression | null;\r\n constructor(datasource: SourceComponent, aliasExpression: SourceAliasExpression | null) {\r\n super();\r\n this.datasource = datasource;\r\n this.aliasExpression = aliasExpression;\r\n }\r\n public getAliasName(): string | null {\r\n if (this.aliasExpression) {\r\n return this.aliasExpression.table.name;\r\n }\r\n else if (this.datasource instanceof TableSource) {\r\n return this.datasource.getSourceName();\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nexport type JoinConditionComponent = JoinOnClause | JoinUsingClause;\r\n\r\nexport class JoinOnClause extends SqlComponent {\r\n static kind = Symbol(\"JoinOnClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class JoinUsingClause extends SqlComponent {\r\n static kind = Symbol(\"JoinUsingClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class JoinClause extends SqlComponent {\r\n static kind = Symbol(\"JoinItem\");\r\n joinType: RawString;\r\n source: SourceExpression;\r\n condition: JoinConditionComponent | null;\r\n lateral: boolean;\r\n constructor(joinType: string, source: SourceExpression, condition: JoinConditionComponent | null, lateral: boolean) {\r\n super();\r\n this.joinType = new RawString(joinType);\r\n this.source = source;\r\n this.condition = condition;\r\n this.lateral = lateral;\r\n }\r\n public getSourceAliasName(): string | null {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source instanceof TableSource) {\r\n return this.source.table.name;\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nexport class FromClause extends SqlComponent {\r\n static kind = Symbol(\"FromClause\");\r\n source: SourceExpression;\r\n joins: JoinClause[] | null;\r\n constructor(source: SourceExpression, join: JoinClause[] | null) {\r\n super();\r\n this.source = source;\r\n this.joins = join;\r\n }\r\n public getSourceAliasName(): string | null {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source.datasource instanceof TableSource) {\r\n return this.source.datasource.table.name;\r\n }\r\n return null;\r\n }\r\n /**\r\n * Returns all SourceExpression objects in this FROM clause, including main source and all JOIN sources.\r\n */\r\n public getSources(): SourceExpression[] {\r\n const sources: SourceExpression[] = [this.source];\r\n if (this.joins) {\r\n for (const join of this.joins) {\r\n sources.push(join.source);\r\n }\r\n }\r\n return sources;\r\n }\r\n}\r\n\r\nexport class CommonTable extends SqlComponent {\r\n static kind = Symbol(\"CommonTable\");\r\n query: SelectQuery;\r\n materialized: boolean | null;\r\n aliasExpression: SourceAliasExpression;\r\n constructor(query: SelectQuery, aliasExpression: SourceAliasExpression | string, materialized: boolean | null) {\r\n super();\r\n this.query = query;\r\n this.materialized = materialized;\r\n if (typeof aliasExpression === \"string\") {\r\n this.aliasExpression = new SourceAliasExpression(aliasExpression, null);\r\n } else {\r\n this.aliasExpression = aliasExpression;\r\n }\r\n }\r\n public getSourceAliasName(): string {\r\n return this.aliasExpression.table.name;\r\n }\r\n}\r\n\r\nexport class WithClause extends SqlComponent {\r\n static kind = Symbol(\"WithClause\");\r\n recursive: boolean;\r\n tables: CommonTable[];\r\n constructor(recursive: boolean, tables: CommonTable[]) {\r\n super();\r\n this.recursive = recursive;\r\n this.tables = tables;\r\n }\r\n}\r\n\r\nexport class LimitClause extends SqlComponent {\r\n static kind = Symbol(\"LimitClause\");\r\n value: ValueComponent;\r\n constructor(limit: ValueComponent) {\r\n super();\r\n this.value = limit;\r\n }\r\n}\r\n\r\nexport enum FetchType {\r\n Next = \"next\",\r\n First = \"first\",\r\n}\r\n\r\nexport enum FetchUnit {\r\n RowsOnly = \"rows only\",\r\n Percent = \"percent\",\r\n PercentWithTies = \"percent with ties\",\r\n}\r\n\r\n\r\nexport class OffsetClause extends SqlComponent {\r\n static kind = Symbol(\"OffsetClause\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class FetchClause extends SqlComponent {\r\n static kind = Symbol(\"FetchClause\");\r\n expression: FetchExpression;\r\n constructor(expression: FetchExpression) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class FetchExpression extends SqlComponent {\r\n static kind = Symbol(\"FetchExpression\");\r\n // type count unit\r\n type: FetchType;\r\n count: ValueComponent;\r\n unit: FetchUnit | null;\r\n constructor(type: FetchType, count: ValueComponent, unit: FetchUnit | null) {\r\n super();\r\n this.type = type;\r\n this.count = count;\r\n this.unit = unit;\r\n }\r\n}\r\n\r\nexport enum LockMode {\r\n Update = \"update\",\r\n Share = \"share\",\r\n KeyShare = \"key share\",\r\n NokeyUpdate = \"no key update\",\r\n}\r\n\r\nexport class ForClause extends SqlComponent {\r\n static kind = Symbol(\"ForClause\");\r\n lockMode: LockMode;\r\n constructor(lockMode: LockMode) {\r\n super();\r\n this.lockMode = lockMode;\r\n }\r\n}\r\n\r\nexport class SourceAliasExpression extends SqlComponent {\r\n static kind = Symbol(\"SourceAliasExpression\");\r\n table: IdentifierString;\r\n columns: IdentifierString[] | null;\r\n constructor(alias: string, columnAlias: string[] | null) {\r\n super();\r\n this.table = new IdentifierString(alias);\r\n this.columns = columnAlias !== null ? columnAlias.map((alias) => new IdentifierString(alias)) : null;\r\n }\r\n}\r\n\r\nexport class ReturningClause extends SqlComponent {\r\n static kind = Symbol(\"ReturningClause\");\r\n columns: IdentifierString[];\r\n /**\r\n * Constructs a ReturningClause.\r\n * @param columns Array of IdentifierString or string representing column names.\r\n */\r\n constructor(columns: (IdentifierString | string)[]) {\r\n super();\r\n this.columns = columns.map(col => typeof col === \"string\" ? new IdentifierString(col) : col);\r\n }\r\n}\r\n\r\nexport class SetClause extends SqlComponent {\r\n static kind = Symbol(\"SetClause\");\r\n items: SetClauseItem[];\r\n constructor(items: (SetClauseItem | { column: string | IdentifierString, value: ValueComponent })[]) {\r\n super();\r\n this.items = items.map(item => item instanceof SetClauseItem ? item : new SetClauseItem(item.column, item.value));\r\n }\r\n}\r\n\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n */\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n * Now supports namespaces for fully qualified column names (e.g. schema.table.column).\r\n */\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n * Now supports namespaces for fully qualified column names (e.g. schema.table.column).\r\n * Refactored to use QualifiedName for unified name/namespace handling.\r\n */\r\nexport class SetClauseItem extends SqlComponent {\r\n static kind = Symbol(\"SetClauseItem\");\r\n qualifiedName: QualifiedName;\r\n value: ValueComponent;\r\n constructor(\r\n column: string | IdentifierString | { namespaces: string[] | IdentifierString[] | null, column: string | IdentifierString },\r\n value: ValueComponent\r\n ) {\r\n super();\r\n // Accepts { namespaces, column } or just column\r\n if (typeof column === \"object\" && column !== null && \"column\" in column) {\r\n const colObj = column as { namespaces: string[] | IdentifierString[] | null, column: string | IdentifierString };\r\n const col = typeof colObj.column === \"string\" ? new IdentifierString(colObj.column) : colObj.column;\r\n this.qualifiedName = new QualifiedName(colObj.namespaces, col);\r\n } else {\r\n const col = typeof column === \"string\" ? new IdentifierString(column) : column as IdentifierString;\r\n this.qualifiedName = new QualifiedName(null, col);\r\n }\r\n this.value = value;\r\n }\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the column name as IdentifierString (readonly)\r\n */\r\n get column(): IdentifierString {\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n /**\r\n * Returns the fully qualified column name as a string.\r\n */\r\n public getFullName(): string {\r\n return this.qualifiedName.toString();\r\n }\r\n}\r\n\r\nexport class UpdateClause extends SqlComponent {\r\n static kind = Symbol(\"UpdateClause\");\r\n source: SourceExpression;\r\n constructor(source: SourceExpression) {\r\n super();\r\n this.source = source;\r\n }\r\n public getSourceAliasName() {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source.datasource instanceof TableSource) {\r\n return this.source.datasource.table.name;\r\n }\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Represents the target table (with optional alias/schema) and columns for an INSERT statement.\r\n * @param source The target table as a SourceExpression (can include schema, alias, etc.)\r\n * @param columns Array of column names (as strings)\r\n */\r\nexport class InsertClause extends SqlComponent {\r\n source: SourceExpression;\r\n columns: IdentifierString[];\r\n\r\n constructor(source: SourceExpression, columns: string[]) {\r\n super();\r\n this.source = source;\r\n this.columns = columns.map((col) => new IdentifierString(col));\r\n }\r\n}", "\uFEFFexport enum TokenType {\r\n None = 0,\r\n Literal = 1 << 0,\r\n Operator = 1 << 1,\r\n OpenParen = 1 << 2,\r\n CloseParen = 1 << 3,\r\n Comma = 1 << 4,\r\n Dot = 1 << 5,\r\n Identifier = 1 << 6,\r\n Command = 1 << 7, // select, from, where as, on, array etc\r\n Parameter = 1 << 8,\r\n OpenBracket = 1 << 9,\r\n CloseBracket = 1 << 10,\r\n Function = 1 << 11, // next token is open paren\r\n StringSpecifier = 1 << 12, // next token is string literal\r\n Type = 1 << 13,\r\n}\r\n\r\n/**\r\n * Represents a lexical token in SQL parsing\r\n */\r\nexport interface Lexeme {\r\n type: number; // Bit flags for TokenType\r\n value: string;\r\n comments: string[] | null;\r\n}\r\n", "\uFEFF/**\r\n * Fast character classification utilities for SQL tokenization\r\n */\r\nexport class CharLookupTable {\r\n public static isWhitespace(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check for space(32), tab(9), line feed(10), carriage return(13)\r\n return code === 32 || code === 9 || code === 10 || code === 13;\r\n }\r\n\r\n public static isDigit(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check if within '0'(48) to '9'(57) range\r\n return code >= 48 && code <= 57;\r\n }\r\n\r\n public static isHexChar(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check if '0'(48) to '9'(57) or 'a'(97) to 'f'(102) or 'A'(65) to 'F'(70)\r\n return (code >= 48 && code <= 57) ||\r\n (code >= 97 && code <= 102) ||\r\n (code >= 65 && code <= 70);\r\n }\r\n\r\n public static isOperatorSymbol(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // Check for specific operator character codes\r\n // '+'=43, '-'=45, '*'=42, '/'=47, '%'=37, '~'=126, '@'=64, '#'=35, '^'=94, \r\n // '&'=38, ':'=58, '!'=33, '<'=60, '>'=62, '='=61, '|'=124\r\n return code === 43 || code === 45 || code === 42 || code === 47 ||\r\n code === 37 || code === 126 || code === 64 || code === 35 ||\r\n code === 94 || code === 38 || code === 58 || code === 33 ||\r\n code === 60 || code === 62 || code === 61 || code === 124;\r\n }\r\n\r\n public static isDelimiter(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // First check delimiters: '.'=46, ','=44, '('=40, ')'=41, '['=91, ']'=93, '{'=123, '}'=125, ';'=59\r\n if (code === 46 || code === 44 || code === 40 || code === 41 ||\r\n code === 91 || code === 93 || code === 123 || code === 125 || code === 59) {\r\n return true;\r\n }\r\n\r\n // Then check for whitespace: ' '=32, '\\t'=9, '\\n'=10, '\\r'=13\r\n if (code === 32 || code === 9 || code === 10 || code === 13) {\r\n return true;\r\n }\r\n\r\n // Finally check for operator symbols\r\n // '+'=43, '-'=45, '*'=42, '/'=47, '%'=37, '~'=126, '@'=64, '#'=35, '^'=94, \r\n // '&'=38, ':'=58, '!'=33, '<'=60, '>'=62, '='=61, '|'=124\r\n return code === 43 || code === 45 || code === 42 || code === 47 ||\r\n code === 37 || code === 126 || code === 64 || code === 35 ||\r\n code === 94 || code === 38 || code === 58 || code === 33 ||\r\n code === 60 || code === 62 || code === 61 || code === 124;\r\n }\r\n\r\n public static isNamedParameterPrefix(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // Check for parameter prefix characters: '@'=64, ':'=58, '$'=36\r\n return code === 64 || code === 58 || code === 36;\r\n }\r\n}\r\n", "\uFEFFimport { CharLookupTable } from \"./charLookupTable\";\r\n\r\n/**\r\n * Utilities for string operations during tokenization\r\n */\r\nexport class StringUtils {\r\n /**\r\n * Creates a visual representation of an error position in text\r\n * @param input The input text\r\n * @param errPosition The error position\r\n * @returns A string with a caret pointing to the error position\r\n */\r\n public static getDebugPositionInfo(input: string, errPosition: number): string {\r\n // Get 5 characters before and after the error\r\n // If the start and end points are out of the string range, keep them within the range\r\n // Display ^ at the error position on the next line\r\n const start = Math.max(0, errPosition - 5);\r\n const end = Math.min(input.length, errPosition + 5);\r\n const debugInfo = input.slice(start, end);\r\n const caret = ' '.repeat(errPosition - start) + '^';\r\n return `${debugInfo}\\n${caret}`;\r\n }\r\n\r\n /**\r\n * Skip white space characters.\r\n */\r\n private static skipWhiteSpace(input: string, position: number): number {\r\n const length = input.length;\r\n\r\n /*\r\n * Optimization: Try to skip 4 spaces at once (for 4-space indents).\r\n * This is effective when SQL is deeply nested and uses 4-space indentation.\r\n * In typical cases, charCodeAt in a loop is fastest, but for large/indented SQL,\r\n * this can reduce the number of iterations and improve stability (lower error/deviation in benchmarks).\r\n * If indentation is not 4 spaces, this check is skipped quickly, so overhead is minimal.\r\n *\r\n * Even for 2-space indents or mixed indents (2, 4, tab),\r\n * the remaining whitespace is handled by the following loop, so there is no performance loss.\r\n *\r\n * Benchmark results show that this optimization does not slow down short queries,\r\n * and can make long/indented queries more stable and slightly faster.\r\n */\r\n while (position + 4 <= length && input.slice(position, position + 4) === ' ') {\r\n position += 4;\r\n }\r\n\r\n // Then skip remaining whitespace one by one (space, tab, newline, carriage return)\r\n while (position < length) {\r\n const charCode = input.charCodeAt(position);\r\n // ' '=32, '\\t'=9, '\\n'=10, '\\r'=13\r\n if (charCode !== 32 && charCode !== 9 && charCode !== 10 && charCode !== 13) {\r\n break;\r\n }\r\n position++;\r\n }\r\n\r\n return position;\r\n }\r\n\r\n /**\r\n * Skip line comment.\r\n */\r\n private static readLineComment(input: string, position: number): { newPosition: number, comment: string | null } {\r\n if (position + 1 >= input.length) {\r\n return { newPosition: position, comment: null };\r\n }\r\n\r\n // '-'=45\r\n if (input.charCodeAt(position) === 45 && input.charCodeAt(position + 1) === 45) {\r\n const start = position;\r\n position += 2;\r\n\r\n // '\\n'=10\r\n while (position < input.length && input.charCodeAt(position) !== 10) {\r\n position++;\r\n }\r\n\r\n // Return the trimmed comment content (excluding -- tokens)\r\n const comment = input.slice(start + 2, position).trim();\r\n return { newPosition: position, comment };\r\n }\r\n return { newPosition: position, comment: null };\r\n }\r\n\r\n /**\r\n * Skip block comment.\r\n */\r\n private static readBlockComment(input: string, position: number): { newPosition: number, comments: string[] | null } {\r\n if (position + 3 >= input.length) {\r\n return { newPosition: position, comments: null };\r\n }\r\n\r\n // '/'=47, '*'=42, '+'=43\r\n if (input.charCodeAt(position) === 47 && input.charCodeAt(position + 1) === 42 && input.charCodeAt(position + 2) !== 43) {\r\n const start = position;\r\n position += 2;\r\n\r\n while (position + 1 < input.length) {\r\n // '*'=42, '/'=47\r\n if (input.charCodeAt(position) === 42 && input.charCodeAt(position + 1) === 47) {\r\n position += 2;\r\n\r\n // Process the comment content\r\n const lines = input.slice(start + 2, position - 2).replace(/\\r/g, '').split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n lines[i] = lines[i].trim();\r\n }\r\n\r\n // Remove empty lines, but only at the beginning and end\r\n while (lines.length > 0 && lines[0] === '') {\r\n lines.shift();\r\n }\r\n while (lines.length > 0 && lines[lines.length - 1] === '') {\r\n lines.pop();\r\n }\r\n\r\n return { newPosition: position, comments: lines };\r\n }\r\n position++;\r\n }\r\n throw new Error(`Block comment is not closed. position: ${position}`);\r\n }\r\n return { newPosition: position, comments: null };\r\n }\r\n\r\n /**\r\n * Skip white space characters and SQL comments.\r\n * @returns Object containing the new position and an array of skipped comments\r\n */\r\n public static readWhiteSpaceAndComment(input: string, position: number): { position: number, lines: string[] } {\r\n const lines: string[] = [];\r\n const length = input.length;\r\n\r\n while (position < length) {\r\n // Store current position\r\n const oldPosition = position;\r\n\r\n // Skip whitespace first\r\n position = StringUtils.skipWhiteSpace(input, position);\r\n if (position !== oldPosition) {\r\n continue;\r\n }\r\n\r\n // Fast character code check\r\n const charCode = input.charCodeAt(position);\r\n\r\n // '-'=45 (Line comment)\r\n if (charCode === 45) {\r\n const lineCommentResult = StringUtils.readLineComment(input, position);\r\n if (lineCommentResult.newPosition !== position) {\r\n position = lineCommentResult.newPosition;\r\n if (lineCommentResult.comment) {\r\n lines.push(lineCommentResult.comment.trim());\r\n }\r\n continue;\r\n }\r\n }\r\n // '/'=47 (Block comment)\r\n else if (charCode === 47) {\r\n const blockCommentResult = StringUtils.readBlockComment(input, position);\r\n if (blockCommentResult.newPosition !== position) {\r\n position = blockCommentResult.newPosition;\r\n if (blockCommentResult.comments) {\r\n lines.push(...blockCommentResult.comments);\r\n }\r\n continue;\r\n }\r\n }\r\n\r\n // No more whitespace or comments found\r\n break;\r\n }\r\n\r\n return { position, lines: lines };\r\n }\r\n\r\n /**\r\n * Read a regular identifier.\r\n */\r\n public static readRegularIdentifier(input: string, position: number): { identifier: string, newPosition: number } {\r\n const result = this.tryReadRegularIdentifier(input, position);\r\n\r\n if (!result) {\r\n throw new Error(`Unexpected character. position: ${position}\\n${StringUtils.getDebugPositionInfo(input, position)}`);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public static tryReadRegularIdentifier(input: string, position: number): { identifier: string, newPosition: number } | null {\r\n const start = position;\r\n\r\n while (position < input.length) {\r\n if (CharLookupTable.isDelimiter(input[position])) {\r\n break;\r\n }\r\n position++;\r\n }\r\n\r\n if (start === position) {\r\n return null;\r\n }\r\n\r\n // Check index range before checking for [] (array type)\r\n while (\r\n position + 1 < input.length &&\r\n input[position] === '[' &&\r\n input[position + 1] === ']'\r\n ) {\r\n position += 2; // Skip the []\r\n }\r\n\r\n return {\r\n identifier: input.slice(start, position),\r\n newPosition: position\r\n };\r\n }\r\n}\r\n", "\uFEFFimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Base class for token readers\r\n */\r\nexport abstract class BaseTokenReader {\r\n protected input: string;\r\n protected position: number;\r\n\r\n constructor(input: string, position: number = 0) {\r\n this.input = input;\r\n this.position = position;\r\n }\r\n\r\n /**\r\n * Get the current position in the input\r\n */\r\n public getPosition(): number {\r\n return this.position;\r\n }\r\n\r\n /**\r\n * Set the position in the input\r\n */\r\n public setPosition(position: number): void {\r\n this.position = position;\r\n }\r\n\r\n /**\r\n * Check if we've reached the end of input\r\n */\r\n protected isEndOfInput(shift: number = 0): boolean {\r\n return this.position + shift >= this.input.length;\r\n }\r\n\r\n /**\r\n * Check if we can read more characters\r\n */\r\n protected canRead(shift: number = 0): boolean {\r\n return !this.isEndOfInput(shift);\r\n }\r\n\r\n /**\r\n * Read an expected character\r\n */\r\n protected read(expectChar: string): string {\r\n if (this.isEndOfInput()) {\r\n throw new Error(`Unexpected character. expect: ${expectChar}, actual: EndOfInput, position: ${this.position}`);\r\n }\r\n\r\n const char = this.input[this.position];\r\n if (char !== expectChar) {\r\n throw new Error(`Unexpected character. expect: ${expectChar}, actual: ${char}, position: ${this.position}`);\r\n }\r\n\r\n this.position++;\r\n return char;\r\n }\r\n\r\n /**\r\n * Create a lexeme with the specified type and value\r\n */\r\n protected createLexeme(type: TokenType, value: string, comments: string[] | null = null): Lexeme {\r\n if (type === TokenType.Command || type === TokenType.Operator || type === TokenType.Function) {\r\n // Benchmark tests showed that directly calling toLowerCase() is ~5x faster\r\n // than first checking if the string is already lowercase.\r\n // See benchmarks/lowercase-benchmark.js for detailed performance analysis.\r\n return {\r\n type,\r\n value: value.toLowerCase(),\r\n comments: comments,\r\n };\r\n }\r\n return {\r\n type,\r\n value,\r\n comments: comments,\r\n };\r\n }\r\n\r\n /**\r\n * Get debug info for error reporting\r\n */\r\n protected getDebugPositionInfo(errPosition: number): string {\r\n return StringUtils.getDebugPositionInfo(this.input, errPosition);\r\n }\r\n\r\n /**\r\n * Try to read a token from the current position\r\n * @param previous The previous token, if available\r\n * @returns The read token or null if no token could be read\r\n */\r\n public abstract tryRead(previous: Lexeme | null): Lexeme | null;\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class IdentifierTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // wildcard identifier\r\n if (char === '*') {\r\n // Assume that the OperatorTokenReader is executed before the IdentifierTokenReader.\r\n // Since we have determined that the OperatorTokenReader is not an Operator,\r\n // we treat '*' here as a wildcard identifier.\r\n this.position++;\r\n return this.createLexeme(TokenType.Identifier, char);\r\n }\r\n\r\n // Regular identifier\r\n const result = StringUtils.readRegularIdentifier(this.input, this.position);\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Identifier, result.identifier);\r\n }\r\n}\r\n", "\uFEFFimport { KeywordTrie } from \"../models/KeywordTrie\";\r\nimport { StringUtils } from \"../utils/stringUtils\";\r\n\r\nexport enum KeywordMatchResult {\r\n NotAKeyword, // \"Not recognized as a keyword\"\r\n PartialOnly, // \"Partial match (this will not be the end)\"\r\n PartialOrFinal, // \"Partial or complete match (it can stop here)\"\r\n Final // \"Complete match (no longer keywords after this)\"\r\n}\r\n\r\nexport class KeywordParser {\r\n private trie: KeywordTrie;\r\n\r\n constructor(trie: KeywordTrie) {\r\n this.trie = trie;\r\n }\r\n\r\n private isEndOfInput(input: string, position: number, shift: number = 0): boolean {\r\n return position + shift >= input.length;\r\n }\r\n\r\n private canParse(input: string, position: number, shift: number = 0): boolean {\r\n return !this.isEndOfInput(input, position, shift);\r\n }\r\n\r\n public parse(input: string, position: number): { keyword: string, newPosition: number } | null {\r\n if (this.isEndOfInput(input, position)) {\r\n return null;\r\n }\r\n\r\n // reset trie node\r\n this.trie.reset();\r\n const result = StringUtils.tryReadRegularIdentifier(input, position);\r\n\r\n if (result === null) {\r\n return null;\r\n }\r\n\r\n let matchResult = this.trie.pushLexeme(result.identifier.toLowerCase());\r\n\r\n if (matchResult === KeywordMatchResult.NotAKeyword) {\r\n return null;\r\n }\r\n\r\n if (matchResult === KeywordMatchResult.Final) {\r\n return {\r\n keyword: result.identifier,\r\n newPosition: result.newPosition\r\n };\r\n }\r\n\r\n // multi-word keyword\r\n let lexeme = result.identifier;\r\n position = StringUtils.readWhiteSpaceAndComment(input, result.newPosition).position;\r\n\r\n // end of input\r\n if (this.isEndOfInput(input, position)) {\r\n if (matchResult === KeywordMatchResult.PartialOrFinal) {\r\n // if the last match was partial or final, it means that the keyword is finished\r\n return {\r\n keyword: lexeme,\r\n newPosition: position\r\n };\r\n } else {\r\n\r\n return null;\r\n }\r\n }\r\n\r\n while (this.canParse(input, position)) {\r\n const previousMatchResult = matchResult;\r\n\r\n const result = StringUtils.tryReadRegularIdentifier(input, position);\r\n\r\n if (result !== null) {\r\n matchResult = this.trie.pushLexeme(result.identifier.toLowerCase());\r\n\r\n if (matchResult === KeywordMatchResult.NotAKeyword) {\r\n if (previousMatchResult === KeywordMatchResult.PartialOrFinal) {\r\n break;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n lexeme += ' ' + result.identifier;\r\n position = StringUtils.readWhiteSpaceAndComment(input, result.newPosition).position;\r\n\r\n if (matchResult === KeywordMatchResult.Final) {\r\n break;\r\n }\r\n } else if (previousMatchResult === KeywordMatchResult.PartialOrFinal) {\r\n break;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n keyword: lexeme,\r\n newPosition: position\r\n };\r\n }\r\n}\r\n\r\n", "\uFEFFimport { KeywordMatchResult } from \"../parsers/KeywordParser\";\r\n\r\n// Note: An object-based trie (string-keyed object) was tested, but benchmark results showed no improvement and sometimes worse performance for long queries.\r\n// Therefore, the original Map-based implementation is retained for best stability and speed.\r\n\r\nexport class KeywordTrie {\r\n private root: Map<string, any> = new Map();\r\n private currentNode: Map<string, any>;\r\n\r\n // cache properties\r\n private hasEndProperty: boolean = false;\r\n private hasMoreProperties: boolean = false;\r\n\r\n constructor(keywords: string[][]) {\r\n // initialize root node\r\n for (const keyword of keywords) {\r\n this.addKeyword(keyword);\r\n }\r\n // set current node to root\r\n this.currentNode = this.root;\r\n }\r\n\r\n private addKeyword(keyword: string[]) {\r\n let node = this.root;\r\n for (const word of keyword) {\r\n if (!node.has(word)) {\r\n node.set(word, new Map());\r\n }\r\n node = node.get(word);\r\n }\r\n node.set(\"__end__\", true);\r\n }\r\n\r\n public reset(): void {\r\n this.currentNode = this.root;\r\n this.hasEndProperty = false;\r\n this.hasMoreProperties = false;\r\n }\r\n\r\n public pushLexeme(lexeme: string): KeywordMatchResult {\r\n if (!this.currentNode.has(lexeme)) {\r\n return KeywordMatchResult.NotAKeyword;\r\n }\r\n\r\n // move to next node\r\n this.currentNode = this.currentNode.get(lexeme);\r\n\r\n // Cache property checks to avoid repeated operations\r\n this.hasEndProperty = this.currentNode.has(\"__end__\");\r\n this.hasMoreProperties = this.currentNode.size > (this.hasEndProperty ? 1 : 0);\r\n\r\n if (this.hasEndProperty && !this.hasMoreProperties) {\r\n return KeywordMatchResult.Final;\r\n }\r\n if (this.hasEndProperty && this.hasMoreProperties) {\r\n return KeywordMatchResult.PartialOrFinal;\r\n }\r\n\r\n return KeywordMatchResult.PartialOnly;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\n\r\n/**\r\n * Reads SQL literal tokens (numbers, strings)\r\n */\r\n\r\nconst keywords = [\r\n [\"null\"],\r\n [\"true\"],\r\n [\"false\"],\r\n [\"current_date\"],\r\n [\"current_time\"],\r\n [\"current_timestamp\"],\r\n [\"localtime\"],\r\n [\"localtimestamp\"],\r\n [\"unbounded\"],\r\n [\"normalized\"],\r\n [\"nfc\", \"normalized\"],\r\n [\"nfd\", \"normalized\"],\r\n [\"nfkc\", \"normalized\"],\r\n [\"nfkd\", \"normalized\"],\r\n [\"nfc\"],\r\n [\"nfd\"],\r\n [\"nfkc\"],\r\n [\"nfkd\"],\r\n];\r\nconst trie = new KeywordTrie(keywords);\r\nexport const literalKeywordParser = new KeywordParser(trie);\r\n\r\nexport class LiteralTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read a literal token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // Check for keyword literals \r\n const keyword = this.tryReadKeyword();\r\n if (keyword) {\r\n return keyword;\r\n }\r\n\r\n // Decimal token starting with a dot\r\n if (char === '.' && this.canRead(1) && CharLookupTable.isDigit(this.input[this.position + 1])) {\r\n return this.createLexeme(TokenType.Literal, this.readDigit());\r\n }\r\n\r\n // String literal\r\n if (char === '\\'') {\r\n const value = this.readSingleQuotedString(false);\r\n return this.createLexeme(TokenType.Literal, value);\r\n }\r\n\r\n // Digit tokens\r\n if (CharLookupTable.isDigit(char)) {\r\n return this.createLexeme(TokenType.Literal, this.readDigit());\r\n }\r\n\r\n // Signed number\r\n if ((char === '+' || char === '-') && this.determineSignOrOperator(previous) === \"sign\") {\r\n const sign = char;\r\n this.position++;\r\n\r\n // Skip whitespace after sign\r\n const pos = this.position;\r\n while (this.canRead() && CharLookupTable.isWhitespace(this.input[this.position])) {\r\n this.position++;\r\n }\r\n\r\n if (this.canRead() && (\r\n CharLookupTable.isDigit(this.input[this.position]) ||\r\n (this.input[this.position] === '.' &&\r\n this.canRead(1) &&\r\n CharLookupTable.isDigit(this.input[this.position + 1]))\r\n )) {\r\n return this.createLexeme(\r\n TokenType.Literal,\r\n sign === '-' ? sign + this.readDigit() : this.readDigit()\r\n );\r\n }\r\n\r\n // Not a number, restore position\r\n this.position = pos - 1; // Adjust for the increment at the beginning\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private tryReadKeyword(): Lexeme | null {\r\n // Check for keyword literals\r\n const result = literalKeywordParser.parse(this.input, this.position);\r\n if (result) {\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Literal, result.keyword);\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Determines if the current context treats '+' or '-' as a numeric sign or an operator.\r\n * This method is used to differentiate between operators and numeric signs (e.g., '+' or '-').\r\n *\r\n * For example:\r\n * - In `1-1`, the '-' is treated as an operator, so the expression is split into `1`, `-`, and `1`.\r\n * - In `-1`, the '-' is treated as a sign, making `-1` a single, indivisible literal.\r\n *\r\n * The logic for determining whether '+' or '-' is a sign or an operator is as follows:\r\n * - If there is no previous lexeme, it is considered the start of the input, so the sign is valid.\r\n * - If the previous lexeme is a literal or an identifier (e.g., `a.id`), the sign is treated as an operator.\r\n * - If the previous lexeme is a closing parenthesis (e.g., `count(*)`), the sign is also treated as an operator.\r\n *\r\n * @param previous The previous lexeme in the input stream.\r\n * @returns \"sign\" if the context allows for a numeric sign, otherwise \"operator\".\r\n */\r\n private determineSignOrOperator(previous: Lexeme | null): \"sign\" | \"operator\" {\r\n // If there is no previous lexeme, treat as a sign\r\n if (previous === null) {\r\n return \"sign\";\r\n }\r\n\r\n // If the previous lexeme is a literal, identifier, or closing parenthesis, treat as an operator\r\n const isOperatorContext = previous.type === TokenType.Literal || previous.type === TokenType.Identifier || previous.type === TokenType.CloseParen;\r\n return isOperatorContext ? \"operator\" : \"sign\";\r\n }\r\n\r\n /**\r\n * Read a numeric value\r\n */\r\n private readDigit(): string {\r\n const start = this.position;\r\n let hasDot = false;\r\n let hasExponent = false;\r\n\r\n // Consider 0x, 0b, 0o\r\n if (this.canRead(1) &&\r\n this.input[this.position] === '0' &&\r\n \"xbo\".includes(this.input[this.position + 1].toLowerCase())) {\r\n\r\n const prefixType = this.input[this.position + 1].toLowerCase();\r\n this.position += 2;\r\n\r\n // Continue to get numeric and hexadecimal notation strings\r\n const isHex = prefixType === 'x';\r\n while (this.canRead()) {\r\n const c = this.input[this.position];\r\n if (CharLookupTable.isDigit(c) || (isHex && CharLookupTable.isHexChar(c))) {\r\n this.position++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n return this.input.slice(start, this.position);\r\n }\r\n\r\n // If starting with dot, note it\r\n if (this.input[start] === '.') {\r\n hasDot = true;\r\n this.position++;\r\n }\r\n\r\n // Consider decimal point and exponential notation\r\n while (this.canRead()) {\r\n const char = this.input[this.position];\r\n\r\n if (char === '.' && !hasDot) {\r\n hasDot = true;\r\n } else if ((char === 'e' || char === 'E') && !hasExponent) {\r\n hasExponent = true;\r\n if (this.canRead(1) && (this.input[this.position + 1] === '+' || this.input[this.position + 1] === '-')) {\r\n this.position++;\r\n }\r\n } else if (!CharLookupTable.isDigit(char)) {\r\n break;\r\n }\r\n\r\n this.position++;\r\n }\r\n\r\n if (start === this.position) {\r\n throw new Error(`Unexpected character. position: ${start}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n if (this.input[start] === '.') {\r\n // If the number starts with a dot, add 0 to the front\r\n return '0' + this.input.slice(start, this.position);\r\n }\r\n\r\n return this.input.slice(start, this.position);\r\n }\r\n\r\n /**\r\n * Read a string literal\r\n */\r\n private readSingleQuotedString(includeSingleQuote: boolean): string {\r\n const start = this.position;\r\n let closed = false;\r\n this.read(\"'\");\r\n\r\n while (this.canRead()) {\r\n const char = this.input[this.position];\r\n this.position++;\r\n\r\n // escape character check\r\n if (char === \"\\\\\" && this.canRead(1)) {\r\n this.position++;\r\n continue;\r\n }\r\n else if (char === '\\'') {\r\n closed = true;\r\n break;\r\n }\r\n }\r\n\r\n if (closed === false) {\r\n throw new Error(`Single quote is not closed. position: ${start}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n if (includeSingleQuote) {\r\n const value = this.input.slice(start, this.position);\r\n return value;\r\n } else {\r\n const value = this.input.slice(start + 1, this.position - 1);\r\n return value;\r\n }\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\n\r\n/**\r\n * Reads SQL parameter tokens (@param, :param, $param, ?, ${param})\r\n */\r\nexport class ParameterTokenReader extends BaseTokenReader {\r\n constructor(input: string) {\r\n super(input);\r\n }\r\n\r\n /**\r\n * Try to read a parameter token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // parameter with suffix (${param}) - check this first\r\n if (this.canRead(1) && this.input[this.position] === '$' && this.input[this.position + 1] === '{') {\r\n this.position += 2; // Skip ${\r\n const start = this.position;\r\n while (this.canRead() && this.input[this.position] !== '}') {\r\n this.position++;\r\n }\r\n if (this.isEndOfInput()) {\r\n throw new Error(`Unexpected end of input. Expected closing '}' for parameter at position ${start}`);\r\n }\r\n\r\n const identifier = this.input.slice(start, this.position);\r\n if (identifier.length === 0) {\r\n throw new Error('Empty parameter name is not allowed: found ${} at position ' + (start - 2));\r\n }\r\n\r\n this.position++; // Skip }\r\n return this.createLexeme(TokenType.Parameter, '${' + identifier + '}');\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // named parameter (@param, :param, $param)\r\n if (CharLookupTable.isNamedParameterPrefix(char)) {\r\n\r\n // However, do not recognize as a parameter if the next character is an operator symbol\r\n // To avoid postgres `::`\r\n if (this.canRead(1) && CharLookupTable.isOperatorSymbol(this.input[this.position + 1])) {\r\n return null;\r\n }\r\n\r\n this.position++;\r\n\r\n // Read the identifier part after the prefix\r\n const start = this.position;\r\n while (this.canRead() && !CharLookupTable.isDelimiter(this.input[this.position])) {\r\n this.position++;\r\n }\r\n\r\n const identifier = this.input.slice(start, this.position);\r\n return this.createLexeme(TokenType.Parameter, char + identifier);\r\n }\r\n\r\n // nameless parameter (?)\r\n if (char === '?') {\r\n this.position++;\r\n return this.createLexeme(TokenType.Parameter, char);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\n\r\n/**\r\n * Reads SQL symbol tokens (., ,, (, ))\r\n */\r\nexport class SpecialSymbolTokenReader extends BaseTokenReader {\r\n private static readonly SPECIAL_SYMBOL_TOKENS: Record<string, TokenType> = {\r\n '.': TokenType.Dot,\r\n ',': TokenType.Comma,\r\n '(': TokenType.OpenParen,\r\n ')': TokenType.CloseParen,\r\n '[': TokenType.OpenBracket,\r\n ']': TokenType.CloseBracket,\r\n };\r\n\r\n /**\r\n * Try to read a symbol token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // symbol tokens\r\n if (char in SpecialSymbolTokenReader.SPECIAL_SYMBOL_TOKENS) {\r\n this.position++;\r\n return this.createLexeme(\r\n SpecialSymbolTokenReader.SPECIAL_SYMBOL_TOKENS[char],\r\n char\r\n );\r\n }\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\n\r\n/**\r\n * Manages and coordinates multiple token readers\r\n */\r\nexport class TokenReaderManager {\r\n private readers: BaseTokenReader[];\r\n private input: string;\r\n private position: number;\r\n private tokenCache: Map<number, Lexeme | null>;\r\n private cacheHits: number = 0;\r\n private cacheMisses: number = 0;\r\n\r\n constructor(input: string, position: number = 0) {\r\n this.input = input;\r\n this.position = position;\r\n this.readers = [];\r\n this.tokenCache = new Map();\r\n }\r\n\r\n /**\r\n * Register a token reader\r\n * @param reader The reader to register\r\n * @returns This manager instance for chaining\r\n */\r\n public register(reader: BaseTokenReader): TokenReaderManager {\r\n this.readers.push(reader);\r\n return this;\r\n }\r\n\r\n /**\r\n * Register multiple token readers\r\n * @param readers The readers to register\r\n * @returns This manager instance for chaining\r\n */\r\n public registerAll(readers: BaseTokenReader[]): TokenReaderManager {\r\n readers.forEach(reader => this.register(reader));\r\n return this;\r\n }\r\n\r\n /**\r\n * Update the position for all readers\r\n */\r\n private setPosition(position: number): void {\r\n this.position = position;\r\n for (const reader of this.readers) {\r\n reader.setPosition(position);\r\n }\r\n }\r\n\r\n /**\r\n * Try to read a token using all registered readers\r\n * @param position The position to read from\r\n * @param previous The previous token, if any\r\n * @returns The lexeme if a reader could read it, null otherwise\r\n */\r\n public tryRead(position: number, previous: Lexeme | null): Lexeme | null {\r\n // Check cache - using position as the key\r\n if (this.tokenCache.has(position)) {\r\n // Cache hit\r\n this.cacheHits++;\r\n const lexeme = this.tokenCache.get(position) || null;\r\n return lexeme;\r\n }\r\n\r\n // Cache miss - create new entry\r\n this.cacheMisses++;\r\n this.setPosition(position);\r\n\r\n // Try to read with each reader\r\n let lexeme: Lexeme | null = null;\r\n for (const reader of this.readers) {\r\n lexeme = reader.tryRead(previous);\r\n if (lexeme) {\r\n this.position = reader.getPosition();\r\n break;\r\n }\r\n }\r\n\r\n // Update all readers' positions\r\n for (const reader of this.readers) {\r\n reader.setPosition(this.position);\r\n }\r\n\r\n // Save to cache (even if null)\r\n this.tokenCache.set(position, lexeme);\r\n return lexeme;\r\n }\r\n\r\n /**\r\n * Get the maximum position among all readers\r\n */\r\n public getMaxPosition(): number {\r\n let maxPosition = this.position;\r\n for (const reader of this.readers) {\r\n const position = reader.getPosition();\r\n if (position > maxPosition) {\r\n maxPosition = position;\r\n }\r\n }\r\n return maxPosition;\r\n }\r\n\r\n /**\r\n * Get the input string\r\n */\r\n public getInput(): string {\r\n return this.input;\r\n }\r\n\r\n /**\r\n * Get cache statistics\r\n */\r\n public getCacheStats(): { hits: number, misses: number, ratio: number } {\r\n const total = this.cacheHits + this.cacheMisses;\r\n const ratio = total > 0 ? this.cacheHits / total : 0;\r\n return {\r\n hits: this.cacheHits,\r\n misses: this.cacheMisses,\r\n ratio: ratio\r\n };\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\n\r\nconst trie = new KeywordTrie([\r\n // binary\r\n [\"and\"],\r\n [\"or\"],\r\n [\"is\"],\r\n [\"is\", \"not\"],\r\n [\"is\", \"distinct\", \"from\"],\r\n [\"is\", \"not\", \"distinct\", \"from\"],\r\n [\"like\"],\r\n [\"in\"],\r\n [\"exists\"],\r\n [\"between\"],\r\n [\"not\", \"like\"],\r\n [\"not\", \"in\"],\r\n [\"not\", \"exists\"],\r\n [\"not\", \"between\"],\r\n [\"escape\"], // e.g. '10% OFF on all items' like '10\\%%' escape '\\'\r\n [\"uescape\"], // e.g. U&'d!0061t!+000061' uescape '!'\r\n [\"similar\"], // e.g. substring('abcdef' similar '%#\"cd#\"%' escape '#')\r\n [\"placing\"], // e.g. overlay('abcdef' placing 'cd' from 3 for 2)\r\n // unary\r\n [\"not\"],\r\n // unary - trim\r\n [\"both\"],\r\n [\"leading\"],\r\n [\"trailing\"],\r\n [\"both\", \"from\"], // Postgres\r\n [\"leading\", \"from\"], // Postgres\r\n [\"trailing\", \"from\"], // Postgres\r\n // unary - extract\r\n [\"year\", \"from\"],\r\n [\"month\", \"from\"],\r\n [\"day\", \"from\"],\r\n [\"hour\", \"from\"],\r\n [\"minute\", \"from\"],\r\n [\"second\", \"from\"],\r\n [\"dow\", \"from\"],\r\n [\"doy\", \"from\"],\r\n [\"isodow\", \"from\"],\r\n [\"quarter\", \"from\"],\r\n [\"week\", \"from\"],\r\n [\"epoch\", \"from\"],\r\n [\"at\", \"time\", \"zone\"],\r\n // The following are not considered operators.\r\n // [\"from\"], can be used as an operator only within the substring function, but it cannot be distinguished from the Form Clause. This will be resolved with a dedicated substring parser.\r\n // [\"for\"], can be used as an operator only within the substring function, but it cannot be distinguished from the For Clause. This will be resolved with a dedicated substring parser.\r\n]);\r\n\r\n// Typed literal format\r\nconst operatorOrTypeTrie = new KeywordTrie([\r\n [\"date\"],\r\n [\"time\"],\r\n [\"timestamp\"],\r\n [\"timestamptz\"],// timestamp with time zone\r\n [\"timetz\"], // time with time zone\r\n [\"interval\"],\r\n [\"boolean\"],\r\n [\"integer\"],\r\n [\"bigint\"],\r\n [\"smallint\"],\r\n [\"numeric\"],\r\n [\"decimal\"],\r\n [\"real\"],\r\n [\"double\", \"precision\"],\r\n [\"double\", \"precision\"],\r\n [\"character\", \"varying\"],\r\n [\"time\", \"without\", \"time\", \"zone\"],\r\n [\"time\", \"with\", \"time\", \"zone\"],\r\n [\"timestamp\", \"without\", \"time\", \"zone\"],\r\n [\"timestamp\", \"with\", \"time\", \"zone\"],\r\n]);\r\n\r\nconst keywordParser = new KeywordParser(trie);\r\nconst operatorOrTypeParser = new KeywordParser(operatorOrTypeTrie);\r\n\r\n// Indicates the token may also represent a type (e.g., 'interval')\r\nconst MAYBE_TYPE = true;\r\n\r\nexport class OperatorTokenReader extends BaseTokenReader {\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n /*\r\n NOTE:\r\n Asterisks could potentially be wildcard identifiers,\r\n but since they're indistinguishable at this stage, they're treated as Operators at the token level.\r\n The Parser needs to determine whether they are appropriate Operators or Identifiers.\r\n */\r\n\r\n const char = this.input[this.position];\r\n\r\n if (CharLookupTable.isOperatorSymbol(char)) {\r\n const start = this.position;\r\n\r\n while (this.canRead() && CharLookupTable.isOperatorSymbol(this.input[this.position])) {\r\n // check for `--` and `/*` comments\r\n if (this.canRead(1)) {\r\n const current = this.input[this.position];\r\n if (current === '-' && this.input[this.position + 1] === '-') {\r\n break;\r\n } else if (current === '/' && this.input[this.position + 1] === '*') {\r\n break; // end of operator\r\n }\r\n }\r\n\r\n this.position++;\r\n }\r\n const resut = this.input.slice(start, this.position);\r\n return this.createLexeme(TokenType.Operator, resut);\r\n }\r\n\r\n // Logical operators\r\n let result = operatorOrTypeParser.parse(this.input, this.position);\r\n if (result !== null) {\r\n // Special handling for typed literal format.\r\n // Treated as an operator in cases like `interval '2 days'`,\r\n // but can also be used as a type in expressions like `'1 month'::interval`,\r\n // so we return it as both Operator and Type.\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Operator | TokenType.Type | TokenType.Identifier, result.keyword);\r\n }\r\n\r\n result = keywordParser.parse(this.input, this.position);\r\n if (result !== null) {\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Operator, result.keyword);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from \"./BaseTokenReader\";\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { KeywordTrie } from \"../models/KeywordTrie\";\r\nimport { KeywordParser } from \"../parsers/KeywordParser\";\r\n\r\n// Commands are those that require a dedicated parser.\r\n// Keywords composed of multiple words are also considered commands.\r\n// The exception is \"type\". Since types can be user-defined and cannot be accurately identified, they are treated as Identifiers.\r\n\r\nconst joinTrie = new KeywordTrie([\r\n [\"join\"],\r\n [\"inner\", \"join\"],\r\n [\"cross\", \"join\"],\r\n [\"left\", \"join\"],\r\n [\"left\", \"outer\", \"join\"],\r\n [\"right\", \"join\"],\r\n [\"right\", \"outer\", \"join\"],\r\n [\"full\", \"join\"],\r\n [\"full\", \"outer\", \"join\"],\r\n\r\n [\"natural\", \"join\"],\r\n [\"natural\", \"inner\", \"join\"],\r\n [\"natural\", \"left\", \"join\"],\r\n [\"natural\", \"left\", \"outer\", \"join\"],\r\n [\"natural\", \"right\", \"join\"],\r\n [\"natural\", \"right\", \"outer\", \"join\"],\r\n [\"natural\", \"full\", \"join\"],\r\n [\"natural\", \"full\", \"outer\", \"join\"],\r\n]);\r\nconst keywordTrie = new KeywordTrie([\r\n [\"with\"],\r\n [\"recursive\"],\r\n [\"materialized\"],\r\n [\"not\", \"materialized\"],\r\n [\"select\"],\r\n [\"from\"],\r\n [\"distinct\"],\r\n [\"distinct\", \"on\"],\r\n [\"where\"],\r\n [\"group\", \"by\"],\r\n [\"having\"],\r\n [\"order\", \"by\"],\r\n [\"limit\"],\r\n [\"offset\"],\r\n [\"fetch\"],\r\n [\"first\"],\r\n [\"next\"],\r\n [\"row\"],\r\n [\"row\", \"only\"],\r\n [\"rows\", \"only\"],\r\n [\"percent\"],\r\n [\"percent\", \"with\", \"ties\"],\r\n // for\r\n [\"for\"],\r\n [\"update\"],\r\n [\"share\"],\r\n [\"key\", \"share\"],\r\n [\"no\", \"key\", \"update\"],\r\n // set operations\r\n [\"union\"],\r\n [\"union\", \"all\"],\r\n [\"intersect\"],\r\n [\"intersect\", \"all\"],\r\n [\"except\"],\r\n [\"except\", \"all\"],\r\n // between and\r\n [\"beteen\"],\r\n // window functions\r\n [\"window\"],\r\n [\"over\"],\r\n [\"partition\", \"by\"],\r\n [\"range\"],\r\n [\"rows\"],\r\n [\"groups\"],\r\n // window frame\r\n [\"current\", \"row\"],\r\n [\"unbounded\", \"preceding\"],\r\n [\"unbounded\", \"following\"],\r\n [\"preceding\"],\r\n [\"following\"],\r\n // table join commands\r\n [\"on\"],\r\n [\"using\"],\r\n [\"lateral\"],\r\n // case \r\n [\"case\"],\r\n [\"case\", \"when\"],\r\n [\"when\"],\r\n [\"then\"],\r\n [\"else\"],\r\n [\"end\"],\r\n // others\r\n [\"insert\", \"into\"],\r\n [\"update\"],\r\n [\"delete\", \"from\"],\r\n [\"merge\", \"into\"],\r\n [\"matched\"],\r\n [\"not\", \"matched\"],\r\n [\"update\", \"set\"],\r\n [\"do\", \"nothing\"],\r\n [\"values\"],\r\n [\"set\"],\r\n [\"returning\"],\r\n [\"create\", \"table\"],\r\n [\"create\", \"temporary\", \"table\"],\r\n [\"tablesample\"],\r\n // cast\r\n [\"as\"],\r\n // odrder\r\n [\"asc\"],\r\n [\"desc\"],\r\n [\"nulls\", \"first\"],\r\n [\"nulls\", \"last\"],\r\n]);\r\nconst keywordParser = new KeywordParser(keywordTrie);\r\nexport const joinkeywordParser = new KeywordParser(joinTrie);\r\n\r\nexport class CommandTokenReader extends BaseTokenReader {\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const keywordJoin = joinkeywordParser.parse(this.input, this.position);\r\n if (keywordJoin !== null) {\r\n this.position = keywordJoin.newPosition;\r\n return this.createLexeme(TokenType.Command, keywordJoin.keyword);\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = keywordParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Command, keyword.keyword);\r\n }\r\n\r\n // check hint clause\r\n if (this.canRead(2) && this.input[this.position] === '/' && this.input[this.position + 1] === '*' && this.input[this.position + 2] === '+') {\r\n this.position += 3;\r\n const start = this.position;\r\n while (this.position + 1 < this.input.length) {\r\n if (this.input[this.position] === '*' && this.input[this.position + 1] === '/') {\r\n this.position += 2;\r\n return this.createLexeme(TokenType.Command, '/*+ ' + this.input.slice(start, this.position - 2).trim() + ' */');\r\n }\r\n this.position++;\r\n }\r\n throw new Error(`Block comment is not closed. position: ${this.position}`);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { BaseTokenReader } from './BaseTokenReader';\r\n\r\n// Prefix sets for quick checks\r\nconst STRING_SPECIFIERS = new Set(['e\\'', 'E\\'', 'x\\'', 'X\\'', 'b\\'', 'B\\'']);\r\nconst UNICODE_STRING_SPECIFIERS = new Set(['u&\\'', 'U&\\'']);\r\n\r\nexport class StringSpecifierTokenReader extends BaseTokenReader {\r\n\r\n /**\r\n * Try to read an escaped literal like e'...', x'...', etc.\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n const start = this.position;\r\n\r\n // Check for prefixed literals: e', x', b'\r\n if (this.canRead(1) && STRING_SPECIFIERS.has(this.input.slice(start, start + 2))) {\r\n this.position += 1;\r\n const result = this.createLexeme(TokenType.StringSpecifier, this.input.slice(start, this.position));\r\n return result;\r\n }\r\n\r\n // Check for unicode literal: u&'\r\n if (this.canRead(2) && UNICODE_STRING_SPECIFIERS.has(this.input.slice(start, start + 3))) {\r\n this.position += 2;\r\n const result = this.createLexeme(TokenType.StringSpecifier, this.input.slice(start, this.position));\r\n return result;\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\n\r\nconst trie = new KeywordTrie([\r\n [\"grouping\", \"sets\"],\r\n // ARRAY has special syntax with [] arguments, so it is forcibly treated as a function\r\n [\"array\"],\r\n]);\r\nconst keywordParser = new KeywordParser(trie);\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class FunctionTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = keywordParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Function, keyword.keyword);\r\n }\r\n\r\n // Regular identifier\r\n const result = StringUtils.tryReadRegularIdentifier(this.input, this.position);\r\n if (!result) {\r\n return null;\r\n }\r\n this.position = result.newPosition;\r\n\r\n // peek next token \r\n var shift = StringUtils.readWhiteSpaceAndComment(this.input, this.position).position - this.position;\r\n\r\n if (this.canRead(shift) && this.input[this.position + shift] === '(') {\r\n return this.createLexeme(TokenType.Function, result.identifier);\r\n }\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\n\r\n// Use KeywordTrie to identify type names composed of multiple words.\r\nconst trie = new KeywordTrie([\r\n // type\r\n [\"double\", \"precision\"],\r\n [\"character\", \"varying\"],\r\n [\"time\", \"without\", \"time\", \"zone\"],\r\n [\"time\", \"with\", \"time\", \"zone\"],\r\n [\"timestamp\", \"without\", \"time\", \"zone\"],\r\n [\"timestamp\", \"with\", \"time\", \"zone\"],\r\n]);\r\nconst typeParser = new KeywordParser(trie);\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class TypeTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = typeParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Type, keyword.keyword);\r\n }\r\n\r\n // check pervious token\r\n if (previous === null) {\r\n return null;\r\n }\r\n\r\n const result = StringUtils.tryReadRegularIdentifier(this.input, this.position);\r\n if (!result) {\r\n return null;\r\n }\r\n this.position = result.newPosition;\r\n\r\n // type cast command\r\n if (previous.type & TokenType.Command && previous.value === \"as\") {\r\n // If the previous token is the `as` keyword, it could be a type cast or an identifier\r\n return this.createLexeme(TokenType.Identifier | TokenType.Type, result.identifier);\r\n }\r\n\r\n // postgres type conversion\r\n if (previous.type & TokenType.Operator && previous.value === \"::\") {\r\n return this.createLexeme(TokenType.Type, result.identifier);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "import { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class EscapedIdentifierTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // MySQL escaped identifier (escape character is backtick)\r\n if (char === '`') {\r\n const identifier = this.readEscapedIdentifier('`');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n // Postgres escaped identifier (escape character is double quote)\r\n if (char === '\"') {\r\n const identifier = this.readEscapedIdentifier('\"');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n // SQLServer escaped identifier (escape character is square bracket)\r\n if (char === '[' && (previous === null || previous.value !== \"array\")) {\r\n const identifier = this.readEscapedIdentifier(']');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Read an escaped identifier (surrounded by delimiters)\r\n */\r\n private readEscapedIdentifier(delimiter: string): string {\r\n const start = this.position;\r\n\r\n // Skip the opening delimiter\r\n this.position++;\r\n\r\n while (this.canRead()) {\r\n if (this.input[this.position] === delimiter) {\r\n break;\r\n }\r\n this.position++;\r\n }\r\n\r\n if (start === this.position) {\r\n throw new Error(`Closing delimiter is not found. position: ${start}, delimiter: ${delimiter}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n // Skip the closing delimiter\r\n this.position++;\r\n\r\n // exclude the delimiter\r\n return this.input.slice(start + 1, this.position - 1);\r\n }\r\n}\r\n", "\uFEFFimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { IdentifierTokenReader } from '../tokenReaders/IdentifierTokenReader';\r\nimport { LiteralTokenReader } from '../tokenReaders/LiteralTokenReader';\r\nimport { ParameterTokenReader } from '../tokenReaders/ParameterTokenReader';\r\nimport { SpecialSymbolTokenReader } from '../tokenReaders/SymbolTokenReader';\r\nimport { TokenReaderManager } from '../tokenReaders/TokenReaderManager';\r\nimport { OperatorTokenReader } from '../tokenReaders/OperatorTokenReader';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { CommandTokenReader } from '../tokenReaders/CommandTokenReader';\r\nimport { StringSpecifierTokenReader } from '../tokenReaders/StringSpecifierTokenReader';\r\nimport { FunctionTokenReader } from '../tokenReaders/FunctionTokenReader';\r\nimport { TypeTokenReader } from '../tokenReaders/TypeTokenReader';\r\nimport { EscapedIdentifierTokenReader } from '../tokenReaders/EscapedIdentifierTokenReader';\r\n\r\n/**\r\n * Class responsible for tokenizing SQL input.\r\n */\r\nexport class SqlTokenizer {\r\n /**\r\n * The input SQL string to be tokenized.\r\n */\r\n private input: string;\r\n\r\n /**\r\n * Current position within the input string.\r\n */\r\n private position: number;\r\n\r\n /**\r\n * Manager responsible for handling token readers.\r\n */\r\n private readerManager: TokenReaderManager;\r\n\r\n /**\r\n * Initializes a new instance of the SqlTokenizer.\r\n */\r\n constructor(input: string) {\r\n this.input = input;\r\n this.position = 0;\r\n\r\n // Initialize the token reader manager and register all readers\r\n this.readerManager = new TokenReaderManager(input)\r\n .register(new EscapedIdentifierTokenReader(input))\r\n .register(new ParameterTokenReader(input))\r\n .register(new StringSpecifierTokenReader(input))\r\n // LiteralTokenReader should be registered before SpecialSymbolTokenReader and OperatorTokenReader\r\n // Reason: To prevent numeric literals starting with a dot or sign from being misrecognized as operators\r\n // e.g. `1.0` is a literal, not an operator\r\n .register(new LiteralTokenReader(input))\r\n .register(new SpecialSymbolTokenReader(input))\r\n .register(new CommandTokenReader(input))\r\n .register(new OperatorTokenReader(input))\r\n // TypeTokenReader should be registered before FunctionTokenReader\r\n // Reason: To prevent types containing parentheses from being misrecognized as functions\r\n // e.g. `numeric(10, 2)` is a type, not a function\r\n .register(new TypeTokenReader(input))\r\n .register(new FunctionTokenReader(input))\r\n .register(new IdentifierTokenReader(input)) // IdentifierTokenReader should be registered last\r\n ;\r\n }\r\n\r\n /**\r\n * Checks if the end of input is reached.\r\n * \r\n * @param shift - The shift to consider beyond the current position.\r\n * @returns True if the end of input is reached; otherwise, false.\r\n */\r\n private isEndOfInput(shift: number = 0): boolean {\r\n return this.position + shift >= this.input.length;\r\n }\r\n\r\n /**\r\n * Checks if more input can be read.\r\n * \r\n * @param shift - The shift to consider beyond the current position.\r\n * @returns True if more input can be read; otherwise, false.\r\n */\r\n private canRead(shift: number = 0): boolean {\r\n return !this.isEndOfInput(shift);\r\n }\r\n\r\n /**\r\n * Reads the lexemes from the input string.\r\n * \r\n * @returns An array of lexemes extracted from the input string.\r\n * @throws Error if an unexpected character is encountered.\r\n */\r\n public readLexmes(): Lexeme[] {\r\n // Pre-allocate array with estimated capacity for better performance\r\n const estimatedTokens = Math.ceil(this.input.length / 8); // Assuming average token length of 8 chars\r\n const lexemes: Lexeme[] = new Array(estimatedTokens);\r\n let lexemeCount = 0;\r\n\r\n // Read initial prefix comments\r\n const comment = this.readComment();\r\n let pendingComments = comment.lines;\r\n this.position = comment.position;\r\n\r\n // Track the previous token\r\n let previous: Lexeme | null = null;\r\n\r\n // Read tokens until the end of input is reached\r\n while (this.canRead()) {\r\n // Semicolon is a delimiter, so stop reading\r\n if (this.input[this.position] === ';') {\r\n break;\r\n }\r\n\r\n // Read using the token reader manager\r\n const lexeme = this.readerManager.tryRead(this.position, previous);\r\n\r\n if (lexeme === null) {\r\n throw new Error(`Unexpected character. actual: ${this.input[this.position]}, position: ${this.position}\\n${this.getDebugPositionInfo(this.position)}`);\r\n }\r\n\r\n // Update position\r\n this.position = this.readerManager.getMaxPosition();\r\n\r\n // Read suffix comments\r\n const currentComment = this.readComment();\r\n this.position = currentComment.position;\r\n\r\n if ((lexeme.type & TokenType.Comma) || (lexeme.type & TokenType.Operator)) {\r\n // Carry over comments after commas or operators\r\n if (currentComment.lines.length > 0) {\r\n pendingComments.push(...currentComment.lines);\r\n }\r\n } else {\r\n // Add comments to the current token if any\r\n const hasComments = pendingComments.length > 0 || currentComment.lines.length > 0;\r\n if (hasComments) {\r\n this.addCommentsToToken(lexeme, pendingComments, currentComment.lines);\r\n }\r\n pendingComments = []; // Clear as they are processed\r\n }\r\n\r\n lexemes[lexemeCount++] = lexeme;\r\n previous = lexeme;\r\n }\r\n\r\n // Add any pending comments to the last token\r\n if (pendingComments.length > 0 && lexemeCount > 0) {\r\n const lastToken = lexemes[lexemeCount - 1];\r\n if (lastToken.comments === null) {\r\n lastToken.comments = [];\r\n }\r\n lastToken.comments.push(...pendingComments);\r\n }\r\n\r\n // Trim the array to actual size used\r\n return lexemeCount === estimatedTokens ? lexemes : lexemes.slice(0, lexemeCount);\r\n }\r\n\r\n /**\r\n * Adds pending comments to the last token.\r\n */\r\n private addPendingCommentsToLastToken(lexemes: Lexeme[], pendingComments: string[]): void {\r\n if (pendingComments.length > 0 && lexemes.length > 0) {\r\n const lastToken = lexemes[lexemes.length - 1];\r\n if (lastToken.comments === null) {\r\n lastToken.comments = [];\r\n }\r\n lastToken.comments.push(...pendingComments);\r\n }\r\n }\r\n\r\n /**\r\n * Adds comments to the token.\r\n */\r\n private addCommentsToToken(lexeme: Lexeme, prefixComments: string[], suffixComments: string[]): void {\r\n const hasComments = prefixComments.length > 0 || suffixComments.length > 0;\r\n\r\n if (hasComments) {\r\n if (lexeme.comments === null) {\r\n lexeme.comments = [];\r\n }\r\n\r\n // Add prefix comments to the beginning.\r\n if (prefixComments.length > 0) {\r\n lexeme.comments.unshift(...prefixComments);\r\n }\r\n\r\n // Add suffix comments to the end.\r\n if (suffixComments.length > 0) {\r\n lexeme.comments.push(...suffixComments);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Skips whitespace characters and SQL comments in the input.\r\n * \r\n * @remarks This method updates the position pointer.\r\n */\r\n private readComment(): { position: number, lines: string[] } {\r\n return StringUtils.readWhiteSpaceAndComment(this.input, this.position);\r\n }\r\n\r\n /**\r\n * Gets debug information for error reporting.\r\n * \r\n * @param errPosition - The position where the error occurred.\r\n * @returns A string containing the debug position information.\r\n */\r\n private getDebugPositionInfo(errPosition: number): string {\r\n return StringUtils.getDebugPositionInfo(this.input, errPosition);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { IdentifierString } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\n\r\n/**\r\n * Utility class for parsing fully qualified names (e.g. db.schema.table or db.schema.table.column_name)\r\n * This can be used for both table and column references.\r\n */\r\nexport class FullNameParser {\r\n /**\r\n * Parses a fully qualified name from lexemes, returning namespaces, table, and new index.\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { namespaces: string[] | null, name: IdentifierString, newIndex: number, lastTokenType: number } {\r\n const { identifiers, newIndex } = FullNameParser.parseEscapedOrDotSeparatedIdentifiers(lexemes, index);\r\n const { namespaces, name } = FullNameParser.extractNamespacesAndName(identifiers);\r\n // Returns the type of the last token in the identifier sequence\r\n let lastTokenType = 0;\r\n if (newIndex > index) {\r\n lastTokenType = lexemes[newIndex - 1].type;\r\n }\r\n return { namespaces, name: new IdentifierString(name), newIndex, lastTokenType };\r\n }\r\n\r\n /**\r\n * Parses a fully qualified name from a string (e.g. 'db.schema.table')\r\n * Returns { namespaces, name }\r\n */\r\n public static parse(str: string): { namespaces: string[] | null, name: IdentifierString } {\r\n const tokenizer = new SqlTokenizer(str);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n // Use a context-agnostic error message since FullNameParser is used in multiple query types\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The name is complete but additional tokens were found.`);\r\n }\r\n return { namespaces: result.namespaces, name: result.name };\r\n }\r\n\r\n // Parses SQL Server-style escaped identifiers ([table]) and dot-separated identifiers, including namespaced wildcards (e.g., db.schema.*, [db].[schema].*)\r\n private static parseEscapedOrDotSeparatedIdentifiers(lexemes: Lexeme[], index: number): { identifiers: string[]; newIndex: number } {\r\n let idx = index;\r\n const identifiers: string[] = [];\r\n while (idx < lexemes.length) {\r\n if (lexemes[idx].type & TokenType.OpenBracket) {\r\n idx++; // skip [\r\n if (idx >= lexemes.length || !((lexemes[idx].type & TokenType.Identifier) || (lexemes[idx].type & TokenType.Command))) {\r\n throw new Error(`Expected identifier after '[' at position ${idx}`);\r\n }\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].value !== \"]\") {\r\n throw new Error(`Expected closing ']' after identifier at position ${idx}`);\r\n }\r\n idx++; // skip ]\r\n } else if (lexemes[idx].type & TokenType.Identifier) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].type & TokenType.Function) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].type & TokenType.Type) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].value === \"*\") {\r\n // The wildcard '*' is always treated as the terminal part of a qualified name in SQL (e.g., db.schema.* or [db].[schema].*).\r\n // No valid SQL syntax allows a wildcard in the middle of a multi-part name.\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n break;\r\n }\r\n // Handle dot for schema.table or db.schema.table\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Dot)) {\r\n idx++; // skip dot\r\n } else {\r\n break;\r\n }\r\n }\r\n return { identifiers, newIndex: idx };\r\n }\r\n\r\n // Utility to extract namespaces and the final name from an array of identifiers\r\n // Example: [\"db\", \"schema\", \"users\"] => { namespaces: [\"db\", \"schema\"], name: \"users\" }\r\n private static extractNamespacesAndName(identifiers: string[]): { namespaces: string[] | null, name: string } {\r\n if (!identifiers || identifiers.length === 0) {\r\n throw new Error(\"Identifier list is empty\");\r\n }\r\n if (identifiers.length === 1) {\r\n return { namespaces: null, name: identifiers[0] };\r\n }\r\n return { namespaces: identifiers.slice(0, -1), name: identifiers[identifiers.length - 1] };\r\n }\r\n}\r\n", "import { FullNameParser } from \"./FullNameParser\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { ColumnReference, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class IdentifierParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Use FullNameParser to robustly parse qualified identifiers, including wildcards and escaped names.\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, index);\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n }\r\n}", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { LiteralValue, RawString, ValueComponent } from \"../models/ValueComponent\";\r\nimport { literalKeywordParser } from \"../tokenReaders/LiteralTokenReader\";\r\n\r\nexport class LiteralParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Process literal value\r\n let idx = index;\r\n const valueText = lexemes[idx].value;\r\n let parsedValue: string | number | boolean | null;\r\n\r\n const lex = literalKeywordParser.parse(valueText.toLowerCase(), 0);\r\n if (lex) {\r\n const value = new RawString(lex.keyword);\r\n idx++\r\n return { value, newIndex: idx };\r\n }\r\n\r\n // Check if it is a number\r\n if (/^[+-]?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(valueText)) {\r\n parsedValue = Number(valueText);\r\n }\r\n // Otherwise, treat it as a string\r\n else {\r\n // Remove single quotes if enclosed\r\n if (valueText.startsWith(\"'\") && valueText.endsWith(\"'\")) {\r\n parsedValue = valueText.slice(1, -1);\r\n } else {\r\n parsedValue = valueText;\r\n }\r\n }\r\n idx++\r\n const value = new LiteralValue(parsedValue);\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { InlineQuery, ParenExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class ParenExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // check inline query\r\n if (idx + 1 < lexemes.length && lexemes[idx].type & TokenType.OpenParen && (\r\n lexemes[idx + 1].value === \"select\" || lexemes[idx + 1].value === \"values\" || lexemes[idx + 1].value === \"with\"\r\n )) {\r\n idx += 1; // Skip the '(' token\r\n const result = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n\r\n // Check for closing parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Expected ')' at index ${idx}, but found ${lexemes[idx].value}`);\r\n }\r\n idx++; // Skip the ')' token\r\n\r\n const value = new InlineQuery(result.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const result = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, index);\r\n idx = result.newIndex;\r\n\r\n const value = new ParenExpression(result.value);\r\n return { value, newIndex: idx };\r\n }\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference, IdentifierString, UnaryExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class UnaryExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Process unary operator\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operator = lexemes[idx].value;\r\n idx++;\r\n\r\n // Treat the asterisk as an Identifier, not as a unary operator\r\n if (operator === '*') {\r\n const v = new ColumnReference(null, '*');\r\n return { value: v, newIndex: idx };\r\n }\r\n\r\n // Get the right-hand side value of the unary operator\r\n const result = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n\r\n // Create unary expression\r\n const value = new UnaryExpression(operator, result.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Invalid unary expression at index ${index}: ${lexemes[index].value}`);\r\n }\r\n}", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { ParameterExpression, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class ParameterExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n let paramName = lexemes[idx].value;\r\n\r\n // Normalize parameter: Remove the parameter symbol and extract the parameter name.\r\n if (paramName.startsWith('${') && paramName.endsWith('}')) {\r\n // ${name} \u2192 name\r\n paramName = paramName.slice(2, -1);\r\n } else {\r\n // :name \u2192 name\r\n paramName = paramName.slice(1);\r\n }\r\n\r\n const value = new ParameterExpression(paramName);\r\n idx++;\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { StringSpecifierExpression, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class StringSpecifierExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const specifer = lexemes[idx].value;\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Literal) {\r\n throw new Error(`Expected string literal after string specifier at index ${idx}`);\r\n }\r\n const value = lexemes[idx].value;\r\n idx++;\r\n // Create StringSpecifierExpression\r\n const result = new StringSpecifierExpression(specifer, value);\r\n\r\n return { value: result, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ArrayExpression, CaseExpression, CaseKeyValuePair, SwitchCaseArgument, UnaryExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class CommandExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const current = lexemes[idx];\r\n if (current.value === \"case\") {\r\n idx++;\r\n return this.parseCaseExpression(lexemes, idx);\r\n } else if (current.value === \"case when\") {\r\n idx++;\r\n return this.parseCaseWhenExpression(lexemes, idx);\r\n }\r\n\r\n return this.parseModifierUnaryExpression(lexemes, idx);\r\n }\r\n\r\n private static parseModifierUnaryExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n // Check for modifier unary expression\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const command = lexemes[idx].value;\r\n idx++;\r\n const result = ValueParser.parseFromLexeme(lexemes, idx);\r\n return { value: new UnaryExpression(command!, result.value), newIndex: result.newIndex };\r\n }\r\n throw new Error(`Invalid modifier unary expression at index ${idx}, Lexeme: ${lexemes[idx].value}`);\r\n }\r\n\r\n private static parseCaseExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n\r\n const switchCaseResult = this.parseSwitchCaseArgument(lexemes, idx, []);\r\n idx = switchCaseResult.newIndex;\r\n\r\n // Create CASE expression\r\n const result = new CaseExpression(condition.value, switchCaseResult.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseCaseWhenExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n\r\n // Parse the first WHEN clause\r\n const casewhenResult = this.parseCaseConditionValuePair(lexemes, idx);\r\n idx = casewhenResult.newIndex;\r\n\r\n // Add the initial WHEN-THEN pair to the list\r\n const caseWhenList = [casewhenResult.value];\r\n\r\n // Process remaining WHEN-ELSE-END parts\r\n const switchCaseResult = this.parseSwitchCaseArgument(lexemes, idx, caseWhenList);\r\n idx = switchCaseResult.newIndex;\r\n\r\n // Create CASE expression with condition null (uses WHEN conditions instead of a simple CASE)\r\n const result = new CaseExpression(null, switchCaseResult.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n // parseSwitchCaseArgument method processes the WHEN, ELSE, and END clauses of a CASE expression.\r\n private static parseSwitchCaseArgument(\r\n lexemes: Lexeme[],\r\n index: number,\r\n initialWhenThenList: CaseKeyValuePair[]\r\n ): { value: SwitchCaseArgument; newIndex: number; } {\r\n let idx = index;\r\n const whenThenList = [...initialWhenThenList];\r\n let elseValue = null;\r\n\r\n // Process WHEN clauses\r\n while (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"when\")) {\r\n idx++;\r\n const whenResult = this.parseCaseConditionValuePair(lexemes, idx);\r\n idx = whenResult.newIndex;\r\n whenThenList.push(whenResult.value);\r\n }\r\n\r\n // Process ELSE\r\n if (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"else\")) {\r\n idx++;\r\n const elseResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n elseValue = elseResult.value;\r\n idx = elseResult.newIndex;\r\n }\r\n\r\n // Process END\r\n if (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"end\")) {\r\n idx++;\r\n } else {\r\n throw new Error(`The CASE expression requires 'end' keyword at the end (index ${idx})`);\r\n }\r\n\r\n if (whenThenList.length === 0) {\r\n throw new Error(`The CASE expression requires at least one WHEN clause (index ${idx})`);\r\n }\r\n\r\n // Create SwitchCaseArgument\r\n const value = new SwitchCaseArgument(whenThenList, elseValue);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n // Helper method: Check if a lexeme is a Command token with the specified value\r\n private static isCommandWithValue(lexeme: Lexeme, value: string): boolean {\r\n return ((lexeme.type & TokenType.Command) !== 0) && lexeme.value === value;\r\n }\r\n\r\n private static parseCaseConditionValuePair(lexemes: Lexeme[], index: number): { value: CaseKeyValuePair; newIndex: number; } {\r\n let idx = index;\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n\r\n // Check for the existence of the THEN keyword\r\n if (idx >= lexemes.length || !(lexemes[idx].type & TokenType.Command) || lexemes[idx].value !== \"then\") {\r\n throw new Error(`Expected 'then' after WHEN condition at index ${idx}`);\r\n }\r\n idx++; // Skip the THEN keyword\r\n\r\n // Parse the value after THEN\r\n const value = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = value.newIndex;\r\n\r\n return { value: new CaseKeyValuePair(condition.value, value.value), newIndex: idx };\r\n }\r\n}", "import { NullsSortDirection, OrderByClause, OrderByComponent, OrderByItem, SortDirection } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class OrderByClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): OrderByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The ORDER BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OrderByClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'order by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'ORDER BY' keyword but found \"${lexemes[idx].value}\". ORDER BY clauses must start with the ORDER BY keywords.`);\r\n }\r\n idx++;\r\n\r\n const items: OrderByComponent[] = [];\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No ordering expressions found. The ORDER BY clause requires at least one expression to order by.`);\r\n } else {\r\n const clause = new OrderByClause(items);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: OrderByComponent; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n if (idx >= lexemes.length) {\r\n return { value: value, newIndex: idx };\r\n }\r\n\r\n // asc, desc\r\n const sortDirection = idx >= lexemes.length\r\n ? null\r\n : lexemes[idx].value === 'asc'\r\n ? (idx++, SortDirection.Ascending)\r\n : lexemes[idx].value === 'desc'\r\n ? (idx++, SortDirection.Descending)\r\n : null;\r\n\r\n // nulls first, nulls last\r\n const nullsSortDirection = idx >= lexemes.length\r\n ? null\r\n : lexemes[idx].value === 'nulls first'\r\n ? (idx++, NullsSortDirection.First)\r\n : lexemes[idx].value === 'nulls last'\r\n ? (idx++, NullsSortDirection.Last)\r\n : null;\r\n\r\n if (sortDirection === null && nullsSortDirection === null) {\r\n return { value: value, newIndex: idx };\r\n }\r\n\r\n return { value: new OrderByItem(value, sortDirection, nullsSortDirection), newIndex: idx };\r\n }\r\n}\r\n", "import { PartitionByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueComponent, ValueList } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class PartitionByParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): PartitionByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The PARTITION BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: PartitionByClause; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].value !== 'partition by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'PARTITION BY' keyword but found \"${lexemes[idx].value}\". PARTITION BY clauses must start with the PARTITION BY keywords.`);\r\n }\r\n idx++;\r\n const items: ValueComponent[] = [];\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No partition expressions found. The PARTITION BY clause requires at least one expression to partition by.`);\r\n } else if (items.length === 1) {\r\n const clause = new PartitionByClause(items[0]);\r\n return { value: clause, newIndex: idx };\r\n } else {\r\n const clause = new PartitionByClause(new ValueList(items));\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n}\r\n", "import { OrderByClause, PartitionByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { WindowFrameBound, WindowFrameBoundaryValue, FrameBoundaryComponent, WindowFrameExpression, WindowFrameSpec, WindowFrameType, WindowFrameBoundStatic } from \"../models/ValueComponent\";\r\nimport { OrderByClauseParser } from \"./OrderByClauseParser\";\r\nimport { PartitionByParser } from \"./PartitionByParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class WindowExpressionParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WindowFrameExpression {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The window frame expression is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WindowFrameExpression; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis '(' but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n let partition: PartitionByClause | null = null;\r\n let order: OrderByClause | null = null;\r\n let frameSpec: WindowFrameSpec | null = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'partition by') {\r\n const partitionResult = PartitionByParser.parseFromLexeme(lexemes, idx);\r\n partition = partitionResult.value;\r\n idx = partitionResult.newIndex;\r\n }\r\n if (idx < lexemes.length && lexemes[idx].value === 'order by') {\r\n const orderResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);\r\n order = orderResult.value;\r\n idx = orderResult.newIndex;\r\n }\r\n // Parse frame clause (ROWS/RANGE/GROUPS)\r\n if (idx < lexemes.length && this.isFrameTypeKeyword(lexemes[idx].value)) {\r\n const frameSpecResult = this.parseFrameSpec(lexemes, idx);\r\n frameSpec = frameSpecResult.value;\r\n idx = frameSpecResult.newIndex;\r\n }\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for window frame. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n // Read close paren\r\n idx++;\r\n\r\n return { value: new WindowFrameExpression(partition, order, frameSpec), newIndex: idx };\r\n }\r\n\r\n private static isFrameTypeKeyword(value: string): boolean {\r\n const lowerValue = value;\r\n return lowerValue === 'rows' || lowerValue === 'range' || lowerValue === 'groups';\r\n }\r\n\r\n private static parseFrameSpec(lexemes: Lexeme[], index: number): { value: WindowFrameSpec; newIndex: number } {\r\n let idx = index;\r\n\r\n // Determine frame type (ROWS/RANGE/GROUPS)\r\n const frameTypeStr = lexemes[idx].value;\r\n let frameType: WindowFrameType;\r\n\r\n switch (frameTypeStr) {\r\n case 'rows':\r\n frameType = WindowFrameType.Rows;\r\n break;\r\n case 'range':\r\n frameType = WindowFrameType.Range;\r\n break;\r\n case 'groups':\r\n frameType = WindowFrameType.Groups;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid frame type \"${lexemes[idx].value}\". Expected one of: ROWS, RANGE, GROUPS.`);\r\n }\r\n idx++;\r\n\r\n // Check for BETWEEN ... AND ... syntax\r\n if (idx < lexemes.length && lexemes[idx].value === 'between') {\r\n // BETWEEN ... AND ... syntax\r\n idx++;\r\n\r\n // Parse start boundary\r\n const startBoundResult = this.parseFrameBoundary(lexemes, idx);\r\n const startBound = startBoundResult.value;\r\n idx = startBoundResult.newIndex;\r\n\r\n // Check for AND keyword - may be recognized as a separate token or part of a compound token\r\n if (idx >= lexemes.length || (lexemes[idx].value !== 'and')) {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AND' keyword in BETWEEN clause.`);\r\n }\r\n idx++; // Skip AND\r\n\r\n // Parse end boundary\r\n const endBoundResult = this.parseFrameBoundary(lexemes, idx);\r\n const endBound = endBoundResult.value;\r\n idx = endBoundResult.newIndex;\r\n\r\n return {\r\n value: new WindowFrameSpec(frameType, startBound, endBound),\r\n newIndex: idx\r\n };\r\n } else {\r\n // Single boundary specification\r\n const boundaryResult = this.parseFrameBoundary(lexemes, idx);\r\n const startBound = boundaryResult.value;\r\n idx = boundaryResult.newIndex;\r\n\r\n return {\r\n value: new WindowFrameSpec(frameType, startBound, null),\r\n newIndex: idx\r\n };\r\n }\r\n }\r\n\r\n private static parseFrameBoundary(lexemes: Lexeme[], index: number): { value: FrameBoundaryComponent, newIndex: number } {\r\n let idx = index;\r\n // Check for predefined boundaries\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const currentValue = lexemes[idx].value;\r\n let frameBound: WindowFrameBound;\r\n switch (currentValue) {\r\n case 'current row':\r\n frameBound = WindowFrameBound.CurrentRow;\r\n break;\r\n case 'unbounded preceding':\r\n frameBound = WindowFrameBound.UnboundedPreceding;\r\n break;\r\n case 'unbounded following':\r\n frameBound = WindowFrameBound.UnboundedFollowing;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid frame type \"${lexemes[idx].value}\". Expected one of: ROWS, RANGE, GROUPS.`);\r\n }\r\n const bound = new WindowFrameBoundStatic(frameBound);\r\n return { value: bound, newIndex: idx + 1 };\r\n } else if (idx < lexemes.length && (lexemes[idx].type & TokenType.Literal)) {\r\n // Parse the numeric/literal value\r\n const valueResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = valueResult.newIndex;\r\n // Next token must be 'preceding' or 'following'\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const direction = lexemes[idx].value;\r\n let isFollowing: boolean;\r\n if (direction === 'preceding') {\r\n isFollowing = false;\r\n } else if (direction === 'following') {\r\n isFollowing = true;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);\r\n }\r\n idx++;\r\n const bound = new WindowFrameBoundaryValue(valueResult.value, isFollowing);\r\n return { value: bound, newIndex: idx };\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);\r\n }\r\n }\r\n throw new Error(`Syntax error at position ${idx}: Expected a valid frame boundary component.`);\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { IdentifierString, OverExpression } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WindowExpressionParser } from \"./WindowExpressionParser\";\r\n\r\nexport class OverExpressionParser {\r\n public static parse(query: string): OverExpression {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The OVER expression is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OverExpression; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'over') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'OVER' keyword but found \"${lexemes[idx].value}\". OVER expressions must start with the OVER keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'OVER' keyword. Expected either a window name or an opening parenthesis '('.`);\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.Identifier) {\r\n // named window frame\r\n const name = lexemes[idx].value;\r\n idx++;\r\n return { value: new IdentifierString(name), newIndex: idx };\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.OpenParen) {\r\n // Delegate processing to WindowFrameExpressionParser\r\n const result = WindowExpressionParser.parseFromLexeme(lexemes, idx);\r\n return result;\r\n }\r\n\r\n throw new Error(`Syntax error at position ${idx}: Expected a window name or opening parenthesis '(' after OVER keyword, but found \"${lexemes[idx].value}\".`);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { FunctionCall, ValueComponent, BinaryExpression, TypeValue, CastExpression, BetweenExpression, RawString, ArrayExpression, ArrayQueryExpression } from \"../models/ValueComponent\";\r\nimport { SelectQuery } from \"../models/SelectQuery\";\r\nimport { OverExpressionParser } from \"./OverExpressionParser\";\r\nimport { ValueParser } from \"./ValueParser\";\r\nimport { FullNameParser } from \"./FullNameParser\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\n\r\nexport class FunctionExpressionParser {\r\n /**\r\n * Parse ARRAY expressions - handles both ARRAY[...] (literal) and ARRAY(...) (query) syntax\r\n * @param lexemes Array of lexemes to parse\r\n * @param index Current parsing index\r\n * @returns Parsed array expression and new index\r\n */\r\n private static parseArrayExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check if this is array literal (ARRAY[...]) or function call (ARRAY(...))\r\n if (idx + 1 < lexemes.length && (lexemes[idx + 1].type & TokenType.OpenBracket)) {\r\n idx++;\r\n const arg = ValueParser.parseArgument(TokenType.OpenBracket, TokenType.CloseBracket, lexemes, idx);\r\n idx = arg.newIndex;\r\n const value = new ArrayExpression(arg.value);\r\n return { value, newIndex: idx };\r\n } else if (idx + 1 < lexemes.length && (lexemes[idx + 1].type & TokenType.OpenParen)) {\r\n idx++;\r\n idx++; // Skip the opening parenthesis\r\n const arg = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = arg.newIndex;\r\n idx++; // Skip the closing parenthesis\r\n const value = new ArrayQueryExpression(arg.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Invalid ARRAY syntax at index ${idx}, expected ARRAY[... or ARRAY(...)`);\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const current = lexemes[idx];\r\n\r\n if (current.value === \"array\") {\r\n return this.parseArrayExpression(lexemes, idx);\r\n } else if (current.value === \"substring\" || current.value === \"overlay\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"from\", required: false },\r\n { key: \"for\", required: false }\r\n ]);\r\n } else if (current.value === \"cast\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"as\", required: true }\r\n ]);\r\n } else if (current.value === \"trim\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"from\", required: false }\r\n ]);\r\n }\r\n\r\n return this.parseFunctionCall(lexemes, idx);\r\n }\r\n\r\n public static tryParseBinaryExpression(lexemes: Lexeme[], index: number, left: ValueComponent, allowAndOperator: boolean = true, allowOrOperator: boolean = true): { value: ValueComponent; newIndex: number } | null {\r\n let idx = index;\r\n\r\n // If the next element is an operator, process it as a binary expression\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operator = lexemes[idx].value.toLowerCase();\r\n\r\n if (!allowAndOperator && operator === \"and\") {\r\n // Handle special case for \"and\" operator\r\n return null;\r\n }\r\n\r\n if (!allowOrOperator && operator === \"or\") {\r\n // Handle special case for \"or\" operator\r\n return null;\r\n }\r\n\r\n idx++;\r\n\r\n // between\r\n if (operator === \"between\") {\r\n return this.parseBetweenExpression(lexemes, idx, left, false);\r\n } else if (operator === \"not between\") {\r\n return this.parseBetweenExpression(lexemes, idx, left, true);\r\n }\r\n\r\n // ::\r\n if (operator === \"::\") {\r\n const typeValue = this.parseTypeValue(lexemes, idx);\r\n idx = typeValue.newIndex;\r\n const exp = new CastExpression(left, typeValue.value);\r\n return { value: exp, newIndex: idx };\r\n }\r\n\r\n // Get the right-hand side value\r\n const rightResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = rightResult.newIndex;\r\n\r\n // Create binary expression\r\n const value = new BinaryExpression(left, operator, rightResult.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n public static parseBetweenExpression(lexemes: Lexeme[], index: number, value: ValueComponent, negated: boolean): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n const lower = ValueParser.parseFromLexeme(lexemes, idx, false);\r\n idx = lower.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator) && lexemes[idx].value !== \"and\") {\r\n throw new Error(`Expected 'and' after 'between' at index ${idx}`);\r\n }\r\n idx++;\r\n\r\n // Parse upper bound with restricted scope - stop at logical operators\r\n const upper = this.parseBetweenUpperBound(lexemes, idx);\r\n idx = upper.newIndex;\r\n const result = new BetweenExpression(value, lower.value, upper.value, negated);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n /**\r\n * Parse the upper bound of a BETWEEN expression with logical operator precedence\r\n * This stops parsing when it encounters AND/OR operators at the same level\r\n */\r\n private static parseBetweenUpperBound(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Parse with higher precedence than AND/OR to ensure BETWEEN binds tighter\r\n // Use precedence 3 (higher than AND=2, OR=1) as minimum to stop at logical operators\r\n return ValueParser.parseFromLexeme(lexemes, index, false, false);\r\n }\r\n\r\n private static parseFunctionCall(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n // Parse namespaced function name (e.g., myschema.myfunc, dbo.util.myfunc)\r\n // Use FullNameParser to get namespaces and function name\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const namespaces = fullNameResult.namespaces;\r\n const name = fullNameResult.name;\r\n idx = fullNameResult.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n // General argument parsing\r\n const arg = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = arg.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === \"over\") {\r\n const over = OverExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = over.newIndex;\r\n const value = new FunctionCall(namespaces, name.name, arg.value, over.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new FunctionCall(namespaces, name.name, arg.value, null);\r\n return { value, newIndex: idx };\r\n }\r\n } else {\r\n throw new Error(`Expected opening parenthesis after function name '${name.name}' at index ${idx}`);\r\n }\r\n }\r\n\r\n private static parseKeywordFunction(\r\n lexemes: Lexeme[],\r\n index: number,\r\n keywords: { key: string, required: boolean }[]\r\n ): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n // Parse function name and namespaces at the beginning for consistent usage\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const namespaces = fullNameResult.namespaces;\r\n const name = fullNameResult.name;\r\n idx = fullNameResult.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n idx++;\r\n\r\n const input = ValueParser.parseFromLexeme(lexemes, idx);\r\n let arg = input.value;\r\n idx = input.newIndex;\r\n\r\n // Delegate to the standard function parser if parsing by comma\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n return this.parseFunctionCall(lexemes, index);\r\n }\r\n\r\n // Check for required/optional keywords in function arguments\r\n for (const { key, required } of keywords) {\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command) && lexemes[idx].value === key) {\r\n idx++;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Type)) {\r\n const typeValue = this.parseTypeValue(lexemes, idx);\r\n arg = new BinaryExpression(arg, key, typeValue.value);\r\n idx = typeValue.newIndex;\r\n } else {\r\n const right = ValueParser.parseFromLexeme(lexemes, idx);\r\n arg = new BinaryExpression(arg, key, right.value);\r\n idx = right.newIndex;\r\n }\r\n\r\n } else if (required) {\r\n throw new Error(`Keyword '${key}' is required at index ${idx}`);\r\n }\r\n }\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.CloseParen)) {\r\n idx++;\r\n // Use the previously parsed namespaces and function name for consistency\r\n if (idx < lexemes.length && lexemes[idx].value === \"over\") {\r\n idx++;\r\n const over = OverExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = over.newIndex;\r\n const value = new FunctionCall(namespaces, name.name, arg, over.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new FunctionCall(namespaces, name.name, arg, null);\r\n return { value, newIndex: idx };\r\n }\r\n } else {\r\n throw new Error(`Missing closing parenthesis for function '${name.name}' at index ${idx}`);\r\n }\r\n } else {\r\n throw new Error(`Missing opening parenthesis for function '${name.name}' at index ${idx}`);\r\n }\r\n }\r\n\r\n public static parseTypeValue(lexemes: Lexeme[], index: number): { value: TypeValue; newIndex: number; } {\r\n let idx = index;\r\n\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n idx = newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n const arg = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = arg.newIndex;\r\n const value = new TypeValue(namespaces, new RawString(name.name), arg.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new TypeValue(namespaces, new RawString(name.name));\r\n return { value, newIndex: idx };\r\n }\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\n\r\nexport class ParseError extends Error {\r\n constructor(message: string, public index: number, public context: string) {\r\n super(message);\r\n this.name = \"ParseError\";\r\n }\r\n\r\n public static fromUnparsedLexemes(lexemes: Lexeme[], index: number, messagePrefix: string): ParseError {\r\n const start = Math.max(0, index - 2);\r\n const end = Math.min(lexemes.length, index + 3);\r\n const context = lexemes.slice(start, end).map((lexeme, idx) => {\r\n const marker = idx + start === index ? '>' : ' ';\r\n const typeName = TokenType[lexeme.type] || lexeme.type; // Convert type to name if possible\r\n return `${marker} ${idx + start}:${lexeme.value} [${typeName}]`;\r\n }).join('\\n');\r\n\r\n const message = `${messagePrefix} Unparsed lexeme remains at index ${index}: ${lexemes[index].value}\\nContext:\\n${context}`;\r\n return new ParseError(message, index, context);\r\n }\r\n}\r\n", "/**\r\n * SQL operator precedence definitions\r\n * Higher numbers indicate higher precedence (tighter binding)\r\n */\r\nexport class OperatorPrecedence {\r\n private static readonly precedenceMap: Record<string, number> = {\r\n // Logical operators (lowest precedence)\r\n 'or': 1,\r\n 'and': 2,\r\n\r\n // Comparison operators\r\n '=': 10,\r\n '!=': 10,\r\n '<>': 10,\r\n '<': 10,\r\n '<=': 10,\r\n '>': 10,\r\n '>=': 10,\r\n 'like': 10,\r\n 'ilike': 10,\r\n 'not like': 10,\r\n 'not ilike': 10,\r\n 'in': 10,\r\n 'not in': 10,\r\n 'is': 10,\r\n 'is not': 10,\r\n 'between': 15, // BETWEEN has higher precedence than logical operators\r\n 'not between': 15,\r\n\r\n // Arithmetic operators\r\n '+': 20,\r\n '-': 20,\r\n '*': 30,\r\n '/': 30,\r\n '%': 30,\r\n '^': 40,\r\n\r\n // Type casting\r\n '::': 50,\r\n\r\n // Highest precedence operators\r\n 'unary+': 100,\r\n 'unary-': 100,\r\n 'not': 100\r\n };\r\n\r\n /**\r\n * Get the precedence of an operator\r\n * @param operator The operator string\r\n * @returns The precedence number (higher = tighter binding)\r\n */\r\n public static getPrecedence(operator: string): number {\r\n const precedence = this.precedenceMap[operator.toLowerCase()];\r\n return precedence !== undefined ? precedence : 0;\r\n }\r\n\r\n /**\r\n * Check if operator1 has higher or equal precedence than operator2\r\n */\r\n public static hasHigherOrEqualPrecedence(operator1: string, operator2: string): boolean {\r\n return this.getPrecedence(operator1) >= this.getPrecedence(operator2);\r\n }\r\n\r\n /**\r\n * Check if an operator is a logical operator (AND/OR)\r\n */\r\n public static isLogicalOperator(operator: string): boolean {\r\n const op = operator.toLowerCase();\r\n return op === 'and' || op === 'or';\r\n }\r\n\r\n /**\r\n * Check if an operator is a BETWEEN operator\r\n */\r\n public static isBetweenOperator(operator: string): boolean {\r\n const op = operator.toLowerCase();\r\n return op === 'between' || op === 'not between';\r\n }\r\n\r\n /**\r\n * Check if a string is a comparison operator\r\n */\r\n public static isComparisonOperator(operator: string): boolean {\r\n const lowerOp = operator.toLowerCase();\r\n return ['=', '!=', '<>', '<', '>', '<=', '>=', 'like', 'ilike', 'in', 'not in'].includes(lowerOp);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference, TypeValue, UnaryExpression, ValueComponent, ValueList, BinaryExpression, CastExpression } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { IdentifierParser } from \"./IdentifierParser\";\r\nimport { LiteralParser } from \"./LiteralParser\";\r\nimport { ParenExpressionParser } from \"./ParenExpressionParser\";\r\nimport { UnaryExpressionParser } from \"./UnaryExpressionParser\";\r\nimport { ParameterExpressionParser } from \"./ParameterExpressionParser\";\r\nimport { StringSpecifierExpressionParser } from \"./StringSpecifierExpressionParser\";\r\nimport { CommandExpressionParser } from \"./CommandExpressionParser\";\r\nimport { FunctionExpressionParser } from \"./FunctionExpressionParser\";\r\nimport { FullNameParser } from \"./FullNameParser\";\r\nimport { ParseError } from \"./ParseError\";\r\nimport { OperatorPrecedence } from \"../utils/OperatorPrecedence\";\r\n\r\nexport class ValueParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): ValueComponent {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw ParseError.fromUnparsedLexemes(\r\n lexemes,\r\n result.newIndex,\r\n `[ValueParser]`\r\n );\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parse from lexeme array with logical operator controls\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number, allowAndOperator: boolean = true, allowOrOperator: boolean = true): { value: ValueComponent; newIndex: number } {\r\n return this.parseExpressionWithPrecedence(lexemes, index, 0, allowAndOperator, allowOrOperator);\r\n }\r\n\r\n /**\r\n * Parse expressions with operator precedence handling\r\n * Uses precedence climbing algorithm\r\n */\r\n private static parseExpressionWithPrecedence(\r\n lexemes: Lexeme[],\r\n index: number,\r\n minPrecedence: number,\r\n allowAndOperator: boolean = true,\r\n allowOrOperator: boolean = true\r\n ): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Parse the primary expression (left side)\r\n const comment = lexemes[idx].comments;\r\n const left = this.parseItem(lexemes, idx);\r\n left.value.comments = comment;\r\n idx = left.newIndex;\r\n\r\n let result = left.value;\r\n\r\n // Process operators with precedence\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operatorToken = lexemes[idx];\r\n const operator = operatorToken.value;\r\n\r\n // Check if this operator is allowed\r\n if (!allowAndOperator && operator.toLowerCase() === \"and\") {\r\n break;\r\n }\r\n if (!allowOrOperator && operator.toLowerCase() === \"or\") {\r\n break;\r\n }\r\n\r\n // Get operator precedence\r\n const precedence = OperatorPrecedence.getPrecedence(operator);\r\n\r\n // If this operator has lower precedence than minimum, stop\r\n if (precedence < minPrecedence) {\r\n break;\r\n }\r\n\r\n idx++; // consume operator // Handle BETWEEN specially as it has different syntax\r\n if (OperatorPrecedence.isBetweenOperator(operator)) {\r\n const betweenResult = FunctionExpressionParser.parseBetweenExpression(\r\n lexemes, idx, result, operator.toLowerCase().includes('not')\r\n );\r\n result = betweenResult.value;\r\n idx = betweenResult.newIndex;\r\n continue;\r\n }\r\n\r\n // Handle :: (cast) operator specially\r\n if (operator === \"::\") {\r\n const typeValue = FunctionExpressionParser.parseTypeValue(lexemes, idx);\r\n result = new CastExpression(result, typeValue.value);\r\n idx = typeValue.newIndex;\r\n continue;\r\n }\r\n\r\n // For left-associative operators, use precedence + 1\r\n const nextMinPrecedence = precedence + 1;\r\n\r\n // Parse the right-hand side with higher precedence\r\n const rightResult = this.parseExpressionWithPrecedence(\r\n lexemes, idx, nextMinPrecedence, allowAndOperator, allowOrOperator\r\n );\r\n idx = rightResult.newIndex;\r\n\r\n // Create binary expression directly\r\n result = new BinaryExpression(result, operator, rightResult.value);\r\n }\r\n\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Range check\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Unexpected end of lexemes at index ${index}`);\r\n }\r\n\r\n const current = lexemes[idx];\r\n\r\n if (current.type & TokenType.Identifier && current.type & TokenType.Operator && current.type & TokenType.Type) {\r\n // Typed literal format pattern\r\n // e.g., `interval '2 days'`\r\n const first = IdentifierParser.parseFromLexeme(lexemes, idx);\r\n if (first.newIndex >= lexemes.length) {\r\n return first;\r\n }\r\n const next = lexemes[first.newIndex];\r\n if (next.type & TokenType.Literal) {\r\n // Typed literal format\r\n const second = LiteralParser.parseFromLexeme(lexemes, first.newIndex);\r\n const result = new UnaryExpression(lexemes[idx].value, second.value);\r\n return { value: result, newIndex: second.newIndex };\r\n }\r\n return first;\r\n } else if (current.type & TokenType.Identifier) {\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n // Namespace is also recognized as Identifier.\r\n // Since functions and types, as well as columns (tables), can have namespaces,\r\n // it is necessary to determine by the last element of the identifier.\r\n if (lexemes[newIndex - 1].type & (TokenType.Function | TokenType.Type)) {\r\n return FunctionExpressionParser.parseFromLexeme(lexemes, idx);\r\n }\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n } else if (current.type & TokenType.Literal) {\r\n return LiteralParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.OpenParen) {\r\n return ParenExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Function) {\r\n return FunctionExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Operator) {\r\n return UnaryExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Parameter) {\r\n return ParameterExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.StringSpecifier) {\r\n return StringSpecifierExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Command) {\r\n return CommandExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.OpenBracket) {\r\n // SQLServer escape identifier format. e.g. [dbo] or [dbo].[table]\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n } else if (current.type & TokenType.Type) {\r\n // Handle standalone type tokens\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const value = new TypeValue(namespaces, name);\r\n return { value, newIndex };\r\n }\r\n\r\n throw new Error(`[ValueParser] Invalid lexeme. index: ${idx}, type: ${lexemes[idx].type}, value: ${lexemes[idx].value}`);\r\n }\r\n\r\n public static parseArgument(openToken: TokenType, closeToken: TokenType, lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const args: ValueComponent[] = [];\r\n\r\n // Check for opening parenthesis\r\n if (idx < lexemes.length && lexemes[idx].type === openToken) {\r\n idx++;\r\n\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n // If there are no arguments, return an empty ValueList\r\n idx++;\r\n return { value: new ValueList([]), newIndex: idx };\r\n }\r\n\r\n // If the next element is `*`, treat `*` as an Identifier\r\n if (idx < lexemes.length && lexemes[idx].value === \"*\") {\r\n const wildcard = new ColumnReference(null, \"*\");\r\n idx++;\r\n // The next element must be closeToken\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n idx++;\r\n return { value: wildcard, newIndex: idx };\r\n } else {\r\n throw new Error(`Expected closing parenthesis at index ${idx}`);\r\n }\r\n }\r\n\r\n // Parse the value inside\r\n const result = this.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n args.push(result.value);\r\n\r\n // Continue reading if the next element is a comma\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const argResult = this.parseFromLexeme(lexemes, idx);\r\n idx = argResult.newIndex;\r\n args.push(argResult.value);\r\n }\r\n\r\n // Check for closing parenthesis\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n idx++;\r\n if (args.length === 1) {\r\n // Return as is if there is only one argument\r\n return { value: args[0], newIndex: idx };\r\n }\r\n // Create ValueCollection if there are multiple arguments\r\n const value = new ValueList(args);\r\n return { value, newIndex: idx };\r\n } else {\r\n throw new Error(`Missing closing parenthesis at index ${idx}`);\r\n }\r\n }\r\n\r\n throw new Error(`Expected opening parenthesis at index ${index}`);\r\n }\r\n}\r\n", "import { CommonTable, ForClause, FromClause, FunctionSource, GroupByClause, HavingClause, JoinClause, JoinOnClause, JoinUsingClause, LimitClause, OrderByClause, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue,\r\n ValueList,\r\n StringSpecifierExpression\r\n} from \"../models/ValueComponent\";\r\n\r\n/**\r\n * A visitor that collects all CommonTable instances from a SQL query structure.\r\n * This includes tables from:\r\n * - WITH clauses\r\n * - Subqueries\r\n * - Inline queries\r\n * - UNION queries\r\n * - Value components that may contain queries\r\n */\r\nexport class CTECollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private commonTables: CommonTable[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor() {\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for all component types that might contain CommonTables\r\n\r\n // SelectQuery types\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // WITH clause that directly contains CommonTables\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // SelectComponent types\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Identifiers and raw strings (leaf nodes that don't need traversal)\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n\r\n // Subqueries and inline queries\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // FROM and JOIN clauses\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // WHERE clause\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // Value components that might contain subqueries\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n\r\n // Add handlers for other clause types\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n }\r\n\r\n /**\r\n * Get all collected CommonTables\r\n */\r\n public getCommonTables(): CommonTable[] {\r\n return this.commonTables;\r\n }\r\n\r\n /**\r\n * Reset the collection of CommonTables\r\n */\r\n private reset(): void {\r\n this.commonTables = [];\r\n this.visitedNodes.clear();\r\n }\r\n\r\n public collect(query: SelectQuery): CommonTable[] {\r\n // Visit the query to collect all CommonTables\r\n this.visit(query);\r\n return this.getCommonTables();\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // Provide more detailed error message\r\n const kindSymbol = arg.getKind()?.toString() || 'unknown';\r\n const constructor = arg.constructor?.name || 'unknown';\r\n throw new Error(`[CTECollector] No handler for ${constructor} with kind ${kindSymbol}.`);\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // The order matters here!\r\n // First, visit all clauses that might contain nested CTEs\r\n // to ensure inner CTEs are collected before outer CTEs\r\n\r\n // Check FROM clause first (can contain subqueries with nested CTEs)\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n // Check WHERE clause (can contain subqueries with WITH clauses)\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n // Check other clauses that might contain CTEs\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n // Check SELECT clause\r\n query.selectClause.accept(this);\r\n\r\n // Finally check the WITH clause after all nested CTEs have been collected\r\n // This ensures inner CTEs are collected before outer CTEs\r\n if (query.withClause) {\r\n query.withClause.accept(this);\r\n }\r\n\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // Visit both sides of the binary query (UNION, EXCEPT, etc.)\r\n query.left.accept(this);\r\n query.right.accept(this);\r\n }\r\n\r\n private visitValuesQuery(query: ValuesQuery): void {\r\n // VALUES queries might contain subqueries in tuple expressions\r\n for (const tuple of query.tuples) {\r\n tuple.accept(this);\r\n }\r\n }\r\n\r\n private visitWithClause(withClause: WithClause): void {\r\n // Visit each CommonTable\r\n // Simply process tables in sequence\r\n // Note: visitCommonTable already handles nested CTEs\r\n for (let i = 0; i < withClause.tables.length; i++) {\r\n const commonTable = withClause.tables[i];\r\n commonTable.accept(this);\r\n }\r\n }\r\n\r\n private visitCommonTable(commonTable: CommonTable): void {\r\n // Process CommonTable directly within the query\r\n // Use the same instance to process the query instead of creating another Collector\r\n commonTable.query.accept(this);\r\n\r\n // Add current CTE after all nested CTEs have been added\r\n this.commonTables.push(commonTable);\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n // Check each item in the select clause\r\n for (const item of clause.items) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitSelectItem(item: SelectItem): void {\r\n // Select items might contain subqueries\r\n item.value.accept(this);\r\n }\r\n\r\n private visitFromClause(fromClause: FromClause): void {\r\n // Check the source\r\n fromClause.source.accept(this);\r\n\r\n // Check joins\r\n if (fromClause.joins) {\r\n for (const join of fromClause.joins) {\r\n join.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n source.datasource.accept(this);\r\n // The alias part doesn't contain subqueries so we skip it\r\n }\r\n\r\n private visitTableSource(source: TableSource): void {\r\n // Table sources don't contain subqueries, nothing to do\r\n }\r\n\r\n private visitFunctionSource(source: FunctionSource): void {\r\n // Function sources may have arguments that could contain subqueries\r\n if (source.argument) {\r\n source.argument.accept(this);\r\n }\r\n }\r\n\r\n private visitParenSource(source: ParenSource): void {\r\n source.source.accept(this);\r\n }\r\n\r\n private visitSubQuerySource(subQuery: SubQuerySource): void {\r\n subQuery.query.accept(this);\r\n }\r\n\r\n private visitInlineQuery(inlineQuery: InlineQuery): void {\r\n inlineQuery.selectQuery.accept(this);\r\n }\r\n\r\n private visitJoinClause(joinClause: JoinClause): void {\r\n // Check join source\r\n joinClause.source.accept(this);\r\n\r\n // Check join condition\r\n if (joinClause.condition) {\r\n joinClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOn: JoinOnClause): void {\r\n joinOn.condition.accept(this);\r\n }\r\n\r\n private visitJoinUsingClause(joinUsing: JoinUsingClause): void {\r\n joinUsing.condition.accept(this);\r\n }\r\n\r\n private visitWhereClause(whereClause: WhereClause): void {\r\n whereClause.condition.accept(this);\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n clause.condition.accept(this);\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitForClause(clause: ForClause): void {\r\n // FOR clause doesn't contain subqueries\r\n }\r\n\r\n private visitOrderByItem(item: OrderByItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n expr.switchCase.accept(this);\r\n }\r\n\r\n private visitSwitchCaseArgument(switchCase: SwitchCaseArgument): void {\r\n // Check all case expressions\r\n for (const caseItem of switchCase.cases) {\r\n caseItem.accept(this);\r\n }\r\n\r\n // Check ELSE expression\r\n if (switchCase.elseValue) {\r\n switchCase.elseValue.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseKeyValuePair(pair: CaseKeyValuePair): void {\r\n // Check the WHEN condition\r\n pair.key.accept(this);\r\n // Check the THEN value\r\n pair.value.accept(this);\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n expr.expression.accept(this);\r\n expr.lower.accept(this);\r\n expr.upper.accept(this);\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n\r\n // Check OVER clause if present\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitTupleExpression(expr: TupleExpression): void {\r\n // Check each value in the tuple for possible subqueries\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n // Check the input expression\r\n expr.input.accept(this);\r\n // Check the type expression\r\n expr.castType.accept(this);\r\n }\r\n\r\n private visitTypeValue(expr: TypeValue): void {\r\n // Visit the argument if present\r\n if (expr.argument) {\r\n expr.argument.accept(this);\r\n }\r\n // The type itself doesn't contain subqueries\r\n }\r\n\r\n private visitWindowFrameExpression(expr: WindowFrameExpression): void {\r\n if (expr.partition) {\r\n expr.partition.accept(this);\r\n }\r\n if (expr.order) {\r\n expr.order.accept(this);\r\n }\r\n if (expr.frameSpec) {\r\n expr.frameSpec.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameSpec(spec: WindowFrameSpec): void {\r\n // WindowFrameSpec is a simple value object, nothing to traverse\r\n }\r\n\r\n private visitIdentifierString(ident: IdentifierString): void {\r\n // Leaf node, nothing to traverse\r\n }\r\n\r\n private visitRawString(raw: RawString): void {\r\n // Leaf node, nothing to traverse\r\n }\r\n\r\n private visitColumnReference(column: ColumnReference): void {\r\n // Column references don't have subqueries\r\n }\r\n\r\n private visitParameterExpression(param: ParameterExpression): void {\r\n // Parameter expressions don't have child components\r\n }\r\n\r\n private visitLiteralValue(value: LiteralValue): void {\r\n // Literal values are leaf nodes\r\n }\r\n\r\n public visitPartitionByClause(partitionBy: PartitionByClause): void {\r\n // don't have subqueries\r\n }\r\n\r\n public visitValueList(valueList: ValueList): void {\r\n for (const value of valueList.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitStringSpecifierExpression(expr: StringSpecifierExpression): void {\r\n // StringSpecifierExpression contains RawString and LiteralValue which are leaf nodes\r\n // No need to visit children as they don't contain subqueries\r\n }\r\n}", "import { CommonTable, ForClause, FromClause, GroupByClause, HavingClause, JoinClause, JoinConditionComponent, JoinOnClause, JoinUsingClause, LimitClause, OrderByClause, OrderByComponent, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceAliasExpression, SourceComponent, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue\r\n} from \"../models/ValueComponent\";\r\n\r\n/**\r\n * A visitor that disables all WITH clauses in a SQL query structure.\r\n * This processes and removes WITH clauses from:\r\n * - Simple SELECT queries\r\n * - Binary queries (UNION, EXCEPT, etc.)\r\n * - Subqueries\r\n * - Inline queries\r\n * \r\n * It maintains the CTE queries themselves but restructures the query to not use\r\n * the WITH clause syntactical construct.\r\n */\r\nexport class CTEDisabler implements SqlComponentVisitor<SqlComponent> {\r\n private handlers: Map<symbol, (arg: any) => SqlComponent>;\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor() {\r\n this.handlers = new Map<symbol, (arg: any) => SqlComponent>();\r\n\r\n // Setup handlers for all component types that might contain WITH clauses\r\n\r\n // SelectQuery types\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // SelectComponent types\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Identifiers and raw strings\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n\r\n // Subqueries and inline queries\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // FROM and JOIN clauses\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // WHERE clause\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // Value components that might contain subqueries\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n\r\n // Add handlers for other clause types\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n }\r\n\r\n /**\r\n * Reset the visited nodes tracking\r\n */\r\n private reset(): void {\r\n this.visitedNodes.clear();\r\n }\r\n\r\n public execute(arg: SqlComponent): SelectQuery {\r\n // Reset the visited nodes before starting the visit\r\n this.reset();\r\n return this.visit(arg) as SelectQuery;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): SqlComponent {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n return this.visitNode(arg);\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n return this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): SqlComponent {\r\n // Check for circular references - if node already visited, return as is\r\n if (this.visitedNodes.has(arg)) {\r\n return arg;\r\n }\r\n\r\n // Mark as visited node\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n return handler(arg);\r\n }\r\n\r\n // Provide more detailed error message\r\n const kindSymbol = arg.getKind()?.toString() || 'unknown';\r\n const constructor = arg.constructor?.name || 'unknown';\r\n throw new Error(`[CTEDisabler] No handler for ${constructor} with kind ${kindSymbol}.`);\r\n }\r\n\r\n visitSimpleSelectQuery(arg: SimpleSelectQuery): SqlComponent {\r\n if (arg.withClause) {\r\n arg.withClause.tables.forEach(table => {\r\n this.visit(table.query);\r\n });\r\n }\r\n\r\n arg.withClause = null; // Explicitly remove WITH clause\r\n\r\n // Visit the components of the SimpleSelectQuery\r\n arg.selectClause = this.visit(arg.selectClause) as SelectClause;\r\n arg.fromClause = arg.fromClause ? this.visit(arg.fromClause) as FromClause : null;\r\n arg.whereClause = arg.whereClause ? this.visit(arg.whereClause) as WhereClause : null;\r\n arg.groupByClause = arg.groupByClause ? this.visit(arg.groupByClause) as GroupByClause : null;\r\n arg.havingClause = arg.havingClause ? this.visit(arg.havingClause) as HavingClause : null;\r\n arg.orderByClause = arg.orderByClause ? this.visit(arg.orderByClause) as OrderByClause : null;\r\n if (arg.windowClause) {\r\n arg.windowClause = new WindowsClause(arg.windowClause.windows.map(w => this.visit(w) as WindowFrameClause));\r\n }\r\n arg.limitClause = arg.limitClause ? this.visit(arg.limitClause) as LimitClause : null;\r\n arg.forClause = arg.forClause ? this.visit(arg.forClause) as ForClause : null;\r\n return arg;\r\n }\r\n\r\n visitBinarySelectQuery(query: BinarySelectQuery): SqlComponent {\r\n query.left = this.visit(query.left) as SelectQuery;\r\n query.right = this.visit(query.right) as SelectQuery;\r\n return query;\r\n }\r\n\r\n visitValuesQuery(query: ValuesQuery): SqlComponent {\r\n const newTuples = query.tuples.map(tuple => this.visit(tuple) as TupleExpression);\r\n return new ValuesQuery(newTuples);\r\n }\r\n\r\n visitSelectClause(clause: SelectClause): SqlComponent {\r\n const newItems = clause.items.map(item => {\r\n return this.visit(item) as SelectItem;\r\n });\r\n\r\n return new SelectClause(\r\n newItems,\r\n clause.distinct,\r\n );\r\n }\r\n\r\n visitFromClause(clause: FromClause): SqlComponent {\r\n const newSource = this.visit(clause.source) as SourceExpression;\r\n const newJoins = clause.joins ? clause.joins.map(join => this.visit(join) as JoinClause) : null;\r\n\r\n return new FromClause(newSource, newJoins);\r\n }\r\n\r\n visitSubQuerySource(subQuery: SubQuerySource): SqlComponent {\r\n const newQuery = this.visit(subQuery.query) as SelectQuery;\r\n return new SubQuerySource(newQuery);\r\n }\r\n\r\n visitInlineQuery(inlineQuery: InlineQuery): SqlComponent {\r\n const newQuery = this.visit(inlineQuery.selectQuery) as SelectQuery;\r\n return new InlineQuery(newQuery);\r\n }\r\n\r\n visitJoinClause(joinClause: JoinClause): SqlComponent {\r\n const newSource = this.visit(joinClause.source) as SourceExpression;\r\n const newCondition = joinClause.condition ? this.visit(joinClause.condition) as JoinConditionComponent : null;\r\n\r\n return new JoinClause(\r\n joinClause.joinType.value,\r\n newSource,\r\n newCondition,\r\n joinClause.lateral,\r\n );\r\n }\r\n\r\n visitJoinOnClause(joinOn: JoinOnClause): SqlComponent {\r\n const newCondition = this.visit(joinOn.condition) as ValueComponent;\r\n return new JoinOnClause(newCondition);\r\n }\r\n\r\n visitJoinUsingClause(joinUsing: JoinUsingClause): SqlComponent {\r\n const newCondition = this.visit(joinUsing.condition) as ValueComponent;\r\n return new JoinUsingClause(newCondition);\r\n }\r\n\r\n visitWhereClause(whereClause: WhereClause): SqlComponent {\r\n const newCondition = this.visit(whereClause.condition) as ValueComponent;\r\n return new WhereClause(newCondition);\r\n }\r\n\r\n visitGroupByClause(clause: GroupByClause): SqlComponent {\r\n const newGrouping = clause.grouping.map(item => this.visit(item) as ValueComponent);\r\n return new GroupByClause(newGrouping);\r\n }\r\n\r\n visitHavingClause(clause: HavingClause): SqlComponent {\r\n const newCondition = this.visit(clause.condition) as ValueComponent;\r\n return new HavingClause(newCondition);\r\n }\r\n\r\n visitOrderByClause(clause: OrderByClause): SqlComponent {\r\n const newOrder = clause.order.map(item => this.visit(item) as OrderByComponent);\r\n return new OrderByClause(newOrder);\r\n }\r\n\r\n visitWindowFrameClause(clause: WindowFrameClause): SqlComponent {\r\n const newExpression = this.visit(clause.expression) as WindowFrameExpression;\r\n return new WindowFrameClause(clause.name.name, newExpression);\r\n }\r\n\r\n visitLimitClause(clause: LimitClause): SqlComponent {\r\n const newLimit = this.visit(clause.value) as ValueComponent;\r\n return new LimitClause(newLimit);\r\n }\r\n\r\n visitForClause(clause: ForClause): SqlComponent {\r\n return new ForClause(clause.lockMode);\r\n }\r\n\r\n visitParenExpression(expr: ParenExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new ParenExpression(newExpression);\r\n }\r\n\r\n visitBinaryExpression(expr: BinaryExpression): SqlComponent {\r\n const newLeft = this.visit(expr.left) as ValueComponent;\r\n const newRight = this.visit(expr.right) as ValueComponent;\r\n return new BinaryExpression(newLeft, expr.operator.value, newRight);\r\n }\r\n\r\n visitUnaryExpression(expr: UnaryExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new UnaryExpression(expr.operator.value, newExpression);\r\n }\r\n\r\n visitCaseExpression(expr: CaseExpression): SqlComponent {\r\n const newCondition = expr.condition ? this.visit(expr.condition) as ValueComponent : null;\r\n const newSwitchCase = this.visit(expr.switchCase) as SwitchCaseArgument;\r\n return new CaseExpression(newCondition, newSwitchCase);\r\n }\r\n\r\n visitSwitchCaseArgument(switchCase: SwitchCaseArgument): SqlComponent {\r\n const newCases = switchCase.cases.map(caseItem => this.visit(caseItem) as CaseKeyValuePair);\r\n const newElseValue = switchCase.elseValue ? this.visit(switchCase.elseValue) as ValueComponent : null;\r\n return new SwitchCaseArgument(newCases, newElseValue);\r\n }\r\n\r\n visitCaseKeyValuePair(pair: CaseKeyValuePair): SqlComponent {\r\n const newKey = this.visit(pair.key) as ValueComponent;\r\n const newValue = this.visit(pair.value) as ValueComponent;\r\n return new CaseKeyValuePair(newKey, newValue);\r\n }\r\n\r\n visitBetweenExpression(expr: BetweenExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n const newLower = this.visit(expr.lower) as ValueComponent;\r\n const newUpper = this.visit(expr.upper) as ValueComponent;\r\n return new BetweenExpression(newExpression, newLower, newUpper, expr.negated);\r\n }\r\n\r\n visitFunctionCall(func: FunctionCall): SqlComponent {\r\n const newArgument = func.argument ? this.visit(func.argument) as ValueComponent : null;\r\n const newOver = func.over ? this.visit(func.over) as OverExpression : null;\r\n return new FunctionCall(func.namespaces, func.name, newArgument, newOver);\r\n }\r\n\r\n visitArrayExpression(expr: ArrayExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new ArrayExpression(newExpression);\r\n }\r\n\r\n visitArrayQueryExpression(expr: ArrayQueryExpression): SqlComponent {\r\n const newQuery = this.visit(expr.query) as SelectQuery;\r\n return new ArrayQueryExpression(newQuery);\r\n }\r\n\r\n visitTupleExpression(expr: TupleExpression): SqlComponent {\r\n const newValues = expr.values.map(value => this.visit(value) as ValueComponent);\r\n return new TupleExpression(newValues);\r\n }\r\n\r\n visitCastExpression(expr: CastExpression): SqlComponent {\r\n const newInput = this.visit(expr.input) as ValueComponent;\r\n const newCastType = this.visit(expr.castType) as TypeValue;\r\n return new CastExpression(newInput, newCastType);\r\n }\r\n\r\n visitTypeValue(typeValue: TypeValue): SqlComponent {\r\n const newArgument = typeValue.argument ? this.visit(typeValue.argument) as ValueComponent : null;\r\n return new TypeValue(typeValue.namespaces, typeValue.name, newArgument);\r\n }\r\n\r\n visitSelectItem(item: SelectItem): SqlComponent {\r\n const newValue = this.visit(item.value) as ValueComponent;\r\n return new SelectItem(newValue, item.identifier?.name);\r\n }\r\n\r\n visitIdentifierString(ident: IdentifierString): SqlComponent {\r\n // Identifiers don't have child components, so just return as-is\r\n return ident;\r\n }\r\n\r\n visitRawString(raw: RawString): SqlComponent {\r\n // Raw strings don't have child components, so just return as-is\r\n return raw;\r\n }\r\n\r\n visitColumnReference(column: ColumnReference): SqlComponent {\r\n // Column references don't have subqueries, so just return as-is\r\n return column;\r\n }\r\n\r\n visitSourceExpression(source: SourceExpression): SqlComponent {\r\n const newSource = this.visit(source.datasource) as SourceComponent;\r\n // SourceAliasEpression don't contain subqueries, so just return as-is\r\n const newAlias = source.aliasExpression;\r\n return new SourceExpression(newSource, newAlias);\r\n }\r\n\r\n visitTableSource(source: TableSource): SqlComponent {\r\n // Table sources don't contain subqueries, so just return as-is\r\n return source;\r\n }\r\n\r\n visitParenSource(source: ParenSource): SqlComponent {\r\n const newSource = this.visit(source.source) as SourceComponent;\r\n return new ParenSource(newSource);\r\n }\r\n\r\n visitParameterExpression(param: ParameterExpression): SqlComponent {\r\n // Parameter expressions don't have child components, so just return as-is\r\n return param;\r\n }\r\n\r\n visitWindowFrameExpression(expr: WindowFrameExpression): SqlComponent {\r\n const newPartition = expr.partition ? this.visit(expr.partition) as PartitionByClause : null;\r\n const newOrder = expr.order ? this.visit(expr.order) as OrderByClause : null;\r\n const newFrameSpec = expr.frameSpec ? this.visit(expr.frameSpec) as WindowFrameSpec : null;\r\n\r\n return new WindowFrameExpression(\r\n newPartition,\r\n newOrder,\r\n newFrameSpec\r\n );\r\n }\r\n\r\n visitWindowFrameSpec(spec: WindowFrameSpec): SqlComponent {\r\n // WindowFrameSpec is a simple value object, so return as-is\r\n return spec;\r\n }\r\n\r\n visitLiteralValue(value: ValueComponent): SqlComponent {\r\n // Literal values are returned as-is\r\n return value;\r\n }\r\n\r\n visitOrderByItem(item: OrderByItem): SqlComponent {\r\n const newValue = this.visit(item.value) as ValueComponent;\r\n return new OrderByItem(newValue, item.sortDirection, item.nullsPosition);\r\n }\r\n}", "import { CommonTable, FetchClause, ForClause, FromClause, FunctionSource, GroupByClause, HavingClause, JoinClause, JoinOnClause, JoinUsingClause, LimitClause, OffsetClause, OrderByClause, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent, ValueList,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue,\r\n StringSpecifierExpression\r\n} from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\n\r\n/**\r\n * A visitor that collects all table source names from a SQL query structure.\r\n * \r\n * When selectableOnly is true (default behavior):\r\n * - Includes only table sources from FROM and JOIN clauses\r\n * - Excludes inline queries, subqueries, and CTEs\r\n * \r\n * When selectableOnly is false:\r\n * - Scans all parts of the query including WITH clauses, subqueries, etc.\r\n * - Collects all table sources from the entire query\r\n * - Excludes tables that are managed by CTEs\r\n * \r\n * For UNION-like queries, it scans both the left and right parts.\r\n */\r\nexport class TableSourceCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private tableSources: TableSource[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private tableNameMap: Map<string, boolean> = new Map<string, boolean>();\r\n private selectableOnly: boolean;\r\n private cteNames: Set<string> = new Set<string>();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor(selectableOnly: boolean = true) {\r\n this.selectableOnly = selectableOnly;\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for query components\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // WITH clause and common tables\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // Handlers for FROM and JOIN components\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // Only register these handlers when not in selectableOnly mode\r\n if (!selectableOnly) {\r\n // Additional clause handlers for full scanning\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.visitOffsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Value components that might contain table references\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n }\r\n }\r\n\r\n /**\r\n * Gets all collected table sources\r\n */\r\n public getTableSources(): TableSource[] {\r\n return this.tableSources;\r\n }\r\n\r\n /**\r\n * Reset the collection of table sources\r\n */\r\n private reset(): void {\r\n this.tableSources = [];\r\n this.tableNameMap.clear();\r\n this.visitedNodes.clear();\r\n this.cteNames.clear();\r\n }\r\n\r\n /**\r\n * Gets a unique identifier for a table source\r\n */\r\n private getTableIdentifier(source: TableSource): string {\r\n // Use QualifiedName for identifier (dot-joined string)\r\n if (source.qualifiedName.namespaces && source.qualifiedName.namespaces.length > 0) {\r\n return source.qualifiedName.namespaces.map(ns => ns.name).join('.') + '.' + (source.qualifiedName.name instanceof RawString ? source.qualifiedName.name.value : source.qualifiedName.name.name);\r\n } else {\r\n return source.qualifiedName.name instanceof RawString ? source.qualifiedName.name.value : source.qualifiedName.name.name;\r\n }\r\n }\r\n\r\n public collect(query: SqlComponent): TableSource[] {\r\n // Visit the SQL component to collect table sources\r\n this.visit(query);\r\n return this.getTableSources();\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n // When in full scan mode, collect CTEs first to exclude them from table sources\r\n if (!this.selectableOnly) {\r\n this.collectCTEs(arg);\r\n }\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // If no handler found, that's ok - we only care about specific components\r\n }\r\n\r\n /**\r\n * Collects all CTE names to exclude them from real table sources\r\n */\r\n private collectCTEs(query: SqlComponent): void {\r\n // Use CommonTableCollector to get all CTEs\r\n const cteCollector = new CTECollector();\r\n cteCollector.visit(query);\r\n const commonTables = cteCollector.getCommonTables();\r\n\r\n // Add CTE names to the set\r\n for (const cte of commonTables) {\r\n // aliasExpression.table is TableSource, so use .table getter (IdentifierString)\r\n this.cteNames.add(cte.aliasExpression.table.name);\r\n }\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // Process the FROM and JOIN clauses\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n // If in full scan mode, visit all other clauses too\r\n if (!this.selectableOnly) {\r\n if (query.withClause) {\r\n query.withClause.accept(this);\r\n }\r\n\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.offsetClause) {\r\n query.offsetClause.accept(this);\r\n }\r\n\r\n if (query.fetchClause) {\r\n query.fetchClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n query.selectClause.accept(this);\r\n }\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // For UNION-like queries, visit both sides\r\n query.left.accept(this);\r\n query.right.accept(this);\r\n }\r\n\r\n private visitValuesQuery(query: ValuesQuery): void {\r\n if (!this.selectableOnly) {\r\n // VALUES queries might contain subqueries in tuple expressions\r\n for (const tuple of query.tuples) {\r\n tuple.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitWithClause(withClause: WithClause): void {\r\n if (!this.selectableOnly) {\r\n // Visit each CommonTable\r\n for (const table of withClause.tables) {\r\n table.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitCommonTable(commonTable: CommonTable): void {\r\n if (!this.selectableOnly) {\r\n // Process the query within the common table\r\n commonTable.query.accept(this);\r\n }\r\n }\r\n\r\n private visitFromClause(fromClause: FromClause): void {\r\n // Check the main source in FROM clause\r\n fromClause.source.accept(this);\r\n\r\n // Check all JOIN clauses\r\n if (fromClause.joins) {\r\n for (const join of fromClause.joins) {\r\n join.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n // Process the actual data source, ignoring aliases\r\n source.datasource.accept(this);\r\n }\r\n\r\n private visitTableSource(source: TableSource): void {\r\n // Get the table identifier for uniqueness check\r\n const identifier = this.getTableIdentifier(source);\r\n\r\n // Check if this is a table managed by a CTE\r\n if (!this.tableNameMap.has(identifier) && !this.isCTETable(source.table.name)) {\r\n this.tableNameMap.set(identifier, true);\r\n this.tableSources.push(source);\r\n }\r\n }\r\n\r\n private visitFunctionSource(source: FunctionSource): void {\r\n // Function sources are not regular table sources, but may contain subqueries in their arguments\r\n if (source.argument) {\r\n // Special handling for function arguments to ensure we traverse nested structures\r\n this.visitValueComponent(source.argument);\r\n }\r\n // Function sources themselves are not collected as table sources\r\n }\r\n\r\n /**\r\n * Helper method to visit value components, handling special cases like TupleExpression, ParenExpression, InlineQuery, and ArrayQueryExpression\r\n * even in selectableOnly mode when they appear in function arguments\r\n */\r\n private visitValueComponent(value: ValueComponent): void {\r\n // Always use the normal accept pattern - let handlers deal with the logic\r\n value.accept(this);\r\n }\r\n\r\n /**\r\n * Checks if a table name is a CTE name\r\n */\r\n private isCTETable(tableName: string): boolean {\r\n return this.cteNames.has(tableName);\r\n }\r\n\r\n private visitParenSource(source: ParenSource): void {\r\n // For parenthesized sources, visit the inner source\r\n source.source.accept(this);\r\n }\r\n\r\n private visitSubQuerySource(subQuery: SubQuerySource): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, we also check subqueries\r\n subQuery.query.accept(this);\r\n }\r\n // In selectableOnly mode, we don't collect sources from subqueries\r\n }\r\n\r\n private visitInlineQuery(inlineQuery: InlineQuery): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, visit inline queries too\r\n inlineQuery.selectQuery.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinClause(joinClause: JoinClause): void {\r\n // Visit the source being joined\r\n joinClause.source.accept(this);\r\n\r\n // If full scanning, also visit the join condition\r\n if (!this.selectableOnly && joinClause.condition) {\r\n joinClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOn: JoinOnClause): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, check ON condition for table references\r\n joinOn.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinUsingClause(joinUsing: JoinUsingClause): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, check USING condition for table references\r\n joinUsing.condition.accept(this);\r\n }\r\n }\r\n\r\n // Additional visitor methods only used in full scan mode\r\n\r\n private visitWhereClause(whereClause: WhereClause): void {\r\n whereClause.condition.accept(this);\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n clause.condition.accept(this);\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitOffsetClause(clause: OffsetClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitFetchClause(clause: FetchClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitForClause(clause: ForClause): void {\r\n // FOR clause doesn't contain table sources\r\n }\r\n\r\n private visitOrderByItem(item: OrderByItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitSelectItem(item: SelectItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n expr.switchCase.accept(this);\r\n }\r\n\r\n private visitSwitchCaseArgument(switchCase: SwitchCaseArgument): void {\r\n for (const caseItem of switchCase.cases) {\r\n caseItem.accept(this);\r\n }\r\n\r\n if (switchCase.elseValue) {\r\n switchCase.elseValue.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseKeyValuePair(pair: CaseKeyValuePair): void {\r\n pair.key.accept(this);\r\n pair.value.accept(this);\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n expr.expression.accept(this);\r\n expr.lower.accept(this);\r\n expr.upper.accept(this);\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitTupleExpression(expr: TupleExpression): void {\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n expr.input.accept(this);\r\n expr.castType.accept(this);\r\n }\r\n\r\n private visitValueList(valueList: ValueList): void {\r\n // Process all values in the list, this may include InlineQuery and other table-referencing components\r\n for (const value of valueList.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n // Handle StringSpecifierExpression (PostgreSQL E-strings)\r\n private visitStringSpecifierExpression(expr: StringSpecifierExpression): void {\r\n // StringSpecifierExpression is just a literal string with an escape specifier\r\n // It doesn't contain table references, so we don't need to visit any children\r\n // This is a no-op method to prevent \"No handler\" errors\r\n }\r\n}", "export enum SqlPrintTokenType {\r\n container = 0,\r\n keyword,\r\n value, // Represents non-keyword elements such as table names\r\n comma, // Represents comma ','\r\n parenthesis, // Represents parentheses: ( ) { } [ ]\r\n operator, // Represents operators such as +, -, *, /\r\n comment,\r\n parameter,\r\n dot,\r\n type,\r\n space,\r\n argumentSplitter,\r\n}\r\n\r\n// Enum for container type, used for formatting and context\r\nexport enum SqlPrintTokenContainerType {\r\n ColumnReference = 'ColumnReference',\r\n LiteralValue = 'LiteralValue',\r\n IdentifierString = 'IdentifierString',\r\n InlineQuery = 'InlineQuery',\r\n StringSpecifierExpression = 'StringSpecifierExpression',\r\n None = '',\r\n ValueList = 'ValueList',\r\n OrderByItem = 'OrderByItem',\r\n FunctionCall = 'FunctionCall',\r\n UnaryExpression = 'UnaryExpression',\r\n BinaryExpression = 'BinaryExpression',\r\n SwitchCaseArgument = 'SwitchCaseArgument',\r\n ElseClause = 'ElseClause',\r\n CaseKeyValuePair = 'CaseKeyValuePair',\r\n CaseThenValue = 'CaseThenValue',\r\n CaseElseValue = 'CaseElseValue',\r\n ParenExpression = 'ParenExpression',\r\n CastExpression = 'CastExpression',\r\n CaseExpression = 'CaseExpression',\r\n ArrayExpression = 'ArrayExpression',\r\n BetweenExpression = 'BetweenExpression',\r\n TypeValue = 'TypeValue',\r\n TupleExpression = 'TupleExpression',\r\n WindowFrameExpression = 'WindowFrameExpression',\r\n SelectItem = 'SelectItem',\r\n SelectClause = 'SelectClause',\r\n DistinctOn = 'DistinctOn',\r\n SourceExpression = 'SourceExpression',\r\n FromClause = 'FromClause',\r\n JoinClause = 'JoinClause',\r\n JoinOnClause = 'JoinOnClause',\r\n JoinUsingClause = 'JoinUsingClause',\r\n FunctionSource = 'FunctionSource',\r\n SourceAliasExpression = 'SourceAliasExpression',\r\n RawString = 'RawString',\r\n QualifiedName = \"QualifiedName\",\r\n WhereClause = \"WhereClause\",\r\n SimpleSelectQuery = \"SimpleSelectQuery\",\r\n OrderByClause = \"OrderByClause\",\r\n GroupByClause = \"GroupByClause\",\r\n HavingClause = \"HavingClause\",\r\n SubQuerySource = \"SubQuerySource\",\r\n PartitionByClause = \"PartitionByClause\",\r\n WindowFrameClause = \"WindowFrameClause\",\r\n LimitClause = \"LimitClause\",\r\n OffsetClause = \"OffsetClause\",\r\n ForClause = \"ForClause\",\r\n WindowClause = \"WindowClause\",\r\n BinarySelectQueryOperator = \"BinarySelectQueryOperator\",\r\n Values = \"Values\",\r\n ValuesQuery = \"ValuesQuery\",\r\n WithClause = \"WithClause\",\r\n CommonTable = \"CommonTable\",\r\n WindowFrameSpec = \"WindowFrameSpec\",\r\n WindowFrameBoundStatic = \"WindowFrameBoundStatic\",\r\n WindowFrameBoundaryValue = \"WindowFrameBoundaryValue\",\r\n FetchClause = \"FetchClause\",\r\n FetchExpression = \"FetchExpression\",\r\n InsertQuery = \"InsertQuery\",\r\n UpdateQuery = \"UpdateQuery\",\r\n UpdateClause = \"UpdateClause\",\r\n ReturningClause = \"ReturningClause\",\r\n SetClauseItem = \"SetClauseItem\",\r\n CreateTableQuery = \"CreateTableQuery\",\r\n // Add more as needed\r\n}\r\n\r\nexport class SqlPrintToken {\r\n /**\r\n * The type of this token, representing the general category (e.g. keyword, value, operator).\r\n */\r\n type: SqlPrintTokenType;\r\n /**\r\n * The actual text content of this token, following SQL syntax.\r\n */\r\n text: string;\r\n /**\r\n * The type of the container this token belongs to. Used for clauses, functions, or other groupings.\r\n */\r\n containerType: SqlPrintTokenContainerType;\r\n\r\n /**\r\n * Optional. Keywords that are part of this token, like DISTINCT in a SELECT clause.\r\n * These should typically be processed before innerTokens.\r\n */\r\n keywordTokens?: SqlPrintToken[];\r\n\r\n /**\r\n * Child tokens that belong to this container.\r\n */\r\n innerTokens: SqlPrintToken[] = [];\r\n\r\n constructor(type: SqlPrintTokenType, text: string = '', containerType: SqlPrintTokenContainerType = SqlPrintTokenContainerType.None) {\r\n this.type = type;\r\n this.text = text;\r\n this.containerType = containerType;\r\n }\r\n}\r\n", "import { ParameterExpression } from \"../models/ValueComponent\";\r\n\r\n/**\r\n * Utility class to collect all ParameterExpression nodes from an AST.\r\n */\r\nexport class ParameterCollector {\r\n /**\r\n * Recursively collect all ParameterExpression nodes from AST.\r\n * @param node AST root\r\n * @returns ParameterExpression[]\r\n */\r\n static collect(node: any): ParameterExpression[] {\r\n const result: ParameterExpression[] = [];\r\n function walk(n: any) {\r\n if (!n || typeof n !== 'object') return;\r\n if (n.constructor && n.constructor.kind === ParameterExpression.kind) {\r\n result.push(n);\r\n }\r\n for (const key of Object.keys(n)) {\r\n const v = n[key];\r\n if (Array.isArray(v)) {\r\n v.forEach(walk);\r\n } else if (v && typeof v === 'object' && v.constructor && v.constructor.kind) {\r\n walk(v);\r\n }\r\n }\r\n }\r\n walk(node);\r\n return result;\r\n }\r\n}\r\n", "export class IdentifierDecorator {\r\n start: string;\r\n end: string;\r\n\r\n constructor(identifierEscape?: { start?: string; end?: string }) {\r\n this.start = identifierEscape?.start ?? '\"';\r\n this.end = identifierEscape?.end ?? '\"';\r\n }\r\n\r\n decorate(text: string): string {\r\n // override\r\n text = this.start + text + this.end;\r\n return text;\r\n }\r\n}\r\n", "/**\r\n * This decorator formats parameter tokens according to DBMS-specific rules.\r\n * It supports prefix/suffix, and parameter style (named, indexed, anonymous).\r\n */\r\nexport class ParameterDecorator {\r\n prefix: string;\r\n suffix: string;\r\n style: 'named' | 'indexed' | 'anonymous';\r\n\r\n constructor(options?: { prefix?: string; suffix?: string; style?: 'named' | 'indexed' | 'anonymous' }) {\r\n this.prefix = options?.prefix ?? ':';\r\n this.suffix = options?.suffix ?? '';\r\n this.style = options?.style ?? 'named';\r\n }\r\n\r\n /**\r\n * Decorate a parameter token with DBMS-specific format.\r\n * @param token The parameter token\r\n * @param index The parameter index (for indexed/anonymous)\r\n */\r\n decorate(text: string, index: number): string {\r\n let paramText = '';\r\n if (this.style === 'anonymous') {\r\n // e.g. ?\r\n paramText = this.prefix;\r\n } else if (this.style === 'indexed') {\r\n // e.g. $1, ?1, :1\r\n paramText = this.prefix + index;\r\n } else if (this.style === 'named') {\r\n // e.g. :name, @name, ${name}\r\n paramText = this.prefix + text + this.suffix;\r\n }\r\n\r\n // override \r\n text = paramText;\r\n return text;\r\n }\r\n}\r\n", "// Represents an UPDATE query in SQL.\r\n// Supports SET, WHERE, and optional FROM/RETURNING clauses.\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { IdentifierString, ValueComponent } from \"./ValueComponent\";\r\nimport { FromClause, ReturningClause, SetClause, WhereClause, SourceExpression, UpdateClause } from \"./Clause\";\r\nimport { WithClause } from \"./Clause\";\r\n\r\nexport class UpdateQuery extends SqlComponent {\r\n static kind = Symbol(\"UpdateQuery\");\r\n withClause: WithClause | null;\r\n updateClause: UpdateClause;\r\n setClause: SetClause;\r\n whereClause: WhereClause | null;\r\n fromClause: FromClause | null;\r\n returningClause: ReturningClause | null;\r\n\r\n /**\r\n * @param params.source SourceExpression (table or subquery with optional alias)\r\n * @param params.setClause SetClause instance or array of {column, value} pairs\r\n * @param params.where WHERE clause (optional)\r\n * @param params.from FROM clause (optional)\r\n * @param params.returning RETURNING clause (optional)\r\n */\r\n\r\n constructor(params: {\r\n withClause?: WithClause | null;\r\n updateClause: UpdateClause;\r\n setClause: SetClause | { column: string | IdentifierString, value: ValueComponent }[];\r\n whereClause?: WhereClause | null;\r\n fromClause?: FromClause | null;\r\n returning?: ReturningClause | null;\r\n }) {\r\n super();\r\n this.withClause = params.withClause ?? null;\r\n this.updateClause = params.updateClause;\r\n this.setClause = params.setClause instanceof SetClause ? params.setClause : new SetClause(params.setClause);\r\n this.whereClause = params.whereClause ?? null;\r\n this.fromClause = params.fromClause ?? null;\r\n this.returningClause = params.returning ?? null;\r\n }\r\n}\r\n", "import { CommonTable, FromClause, JoinClause, ParenSource, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { ColumnReference, InlineQuery, LiteralValue, ValueComponent } from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableColumnResolver } from \"./TableColumnResolver\";\r\n\r\n/**\r\n * A visitor that collects all SelectItem instances from a SQL query structure.\r\n * This visitor scans through select clauses and collects all the SelectItem objects.\r\n * It can also resolve wildcard selectors (table.* or *) using a provided table column resolver.\r\n */\r\nexport class SelectValueCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private selectValues: { name: string, value: ValueComponent }[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n private tableColumnResolver: TableColumnResolver | null;\r\n private commonTableCollector: CTECollector;\r\n private commonTables: CommonTable[];\r\n public initialCommonTables: CommonTable[] | null;\r\n\r\n constructor(tableColumnResolver: TableColumnResolver | null = null, initialCommonTables: CommonTable[] | null = null) {\r\n this.tableColumnResolver = tableColumnResolver ?? null;\r\n this.commonTableCollector = new CTECollector();\r\n this.commonTables = [];\r\n this.initialCommonTables = initialCommonTables;\r\n\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n }\r\n\r\n /**\r\n * Get all collected SelectItems as an array of objects with name and value properties\r\n * @returns An array of objects with name (string) and value (ValueComponent) properties\r\n */\r\n public getValues(): { name: string, value: ValueComponent }[] {\r\n return this.selectValues;\r\n }\r\n\r\n /**\r\n * Reset the collection of SelectItems\r\n */\r\n private reset(): void {\r\n this.selectValues = [];\r\n this.visitedNodes.clear();\r\n if (this.initialCommonTables) {\r\n this.commonTables = this.initialCommonTables;\r\n } else {\r\n this.commonTables = [];\r\n }\r\n }\r\n\r\n public collect(arg: SqlComponent): { name: string, value: ValueComponent }[] {\r\n // Visit the component and return the collected select items\r\n this.visit(arg);\r\n const items = this.getValues();\r\n this.reset(); // Reset after collection\r\n return items;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n }\r\n\r\n /**\r\n * Process a SimpleSelectQuery to collect data and store the current context\r\n */\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n if (this.commonTables.length === 0 && this.initialCommonTables === null) {\r\n this.commonTables = this.commonTableCollector.collect(query);\r\n }\r\n\r\n if (query.selectClause) {\r\n query.selectClause.accept(this);\r\n }\r\n\r\n // no wildcard \r\n const wildcards = this.selectValues.filter(item => item.name === '*');\r\n if (wildcards.length === 0) {\r\n return;\r\n }\r\n\r\n // full wildcard\r\n if (this.selectValues.some(item => item.value instanceof ColumnReference && item.value.namespaces === null)) {\r\n if (query.fromClause) {\r\n this.processFromClause(query.fromClause, true);\r\n }\r\n // remove wildcard\r\n this.selectValues = this.selectValues.filter(item => item.name !== '*');\r\n return;\r\n };\r\n\r\n // table wildcard\r\n const wildSourceNames = wildcards.filter(item => item.value instanceof ColumnReference && item.value.namespaces)\r\n .map(item => (item.value as ColumnReference).getNamespace());\r\n\r\n if (query.fromClause) {\r\n const fromSourceName = query.fromClause.getSourceAliasName();\r\n if (fromSourceName && wildSourceNames.includes(fromSourceName)) {\r\n this.processFromClause(query.fromClause, false);\r\n }\r\n if (query.fromClause.joins) {\r\n for (const join of query.fromClause.joins) {\r\n const joinSourceName = join.getSourceAliasName();\r\n if (joinSourceName && wildSourceNames.includes(joinSourceName)) {\r\n this.processJoinClause(join);\r\n }\r\n }\r\n }\r\n }\r\n // remove wildcard\r\n this.selectValues = this.selectValues.filter(item => item.name !== '*');\r\n return;\r\n }\r\n\r\n private processFromClause(clause: FromClause, joinCascade: boolean): void {\r\n if (clause) {\r\n const fromSourceName = clause.getSourceAliasName();\r\n this.processSourceExpression(fromSourceName, clause.source);\r\n\r\n if (clause.joins && joinCascade) {\r\n for (const join of clause.joins) {\r\n this.processJoinClause(join);\r\n }\r\n }\r\n }\r\n return;\r\n }\r\n\r\n private processJoinClause(clause: JoinClause): void {\r\n const sourceName = clause.getSourceAliasName();\r\n this.processSourceExpression(sourceName, clause.source);\r\n }\r\n\r\n private processSourceExpression(sourceName: string | null, source: SourceExpression) {\r\n // check common table\r\n const commonTable = this.commonTables.find(item => item.aliasExpression.table.name === sourceName);\r\n if (commonTable) {\r\n // Exclude this CTE from consideration to prevent self-reference\r\n const innerCommonTables = this.commonTables.filter(item => item.aliasExpression.table.name !== sourceName);\r\n\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, innerCommonTables);\r\n const innerSelected = innerCollector.collect(commonTable.query);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n } else {\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const innerSelected = innerCollector.collect(source);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n }\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n this.processSelectItem(item);\r\n }\r\n }\r\n\r\n private processSelectItem(item: SelectItem): void {\r\n if (item.identifier) {\r\n this.addSelectValueAsUnique(item.identifier.name, item.value);\r\n }\r\n else if (item.value instanceof ColumnReference) { // Handle column reference\r\n // columnName can be '*'\r\n const columnName = item.value.column.name;\r\n if (columnName === '*') {\r\n // Force add without checking duplicates\r\n this.selectValues.push({ name: columnName, value: item.value });\r\n }\r\n else {\r\n // Add with duplicate checking\r\n this.addSelectValueAsUnique(columnName, item.value);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n // Column aliases have the highest priority if present\r\n // For physical tables, use external function to get column names\r\n // For subqueries, instantiate a new collector and get column names from the subquery\r\n // For parenthesized expressions, treat them the same as subqueries\r\n\r\n if (source.aliasExpression && source.aliasExpression.columns) {\r\n const sourceName = source.getAliasName();\r\n source.aliasExpression.columns.forEach(column => {\r\n this.addSelectValueAsUnique(column.name, new ColumnReference(sourceName ? [sourceName] : null, column.name));\r\n });\r\n return;\r\n } else if (source.datasource instanceof TableSource) {\r\n if (this.tableColumnResolver) {\r\n const sourceName = source.datasource.getSourceName();\r\n this.tableColumnResolver(sourceName).forEach(column => {\r\n this.addSelectValueAsUnique(column, new ColumnReference([sourceName], column));\r\n });\r\n }\r\n return;\r\n } else if (source.datasource instanceof SubQuerySource) {\r\n const sourceName = source.getAliasName();\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const innerSelected = innerCollector.collect(source.datasource.query);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n return;\r\n } else if (source.datasource instanceof ParenSource) {\r\n return this.visit(source.datasource.source);\r\n }\r\n }\r\n\r\n private visitFromClause(clause: FromClause): void {\r\n if (clause) {\r\n this.processFromClause(clause, true);\r\n }\r\n }\r\n\r\n private addSelectValueAsUnique(name: string, value: ValueComponent): void {\r\n // Check if a select value with the same name already exists before adding\r\n if (!this.selectValues.some(item => item.name === name)) {\r\n this.selectValues.push({ name, value });\r\n }\r\n }\r\n}\r\n", "import { SqlComponent } from \"./SqlComponent\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { ColumnReference, FunctionCall, IdentifierString, RawString } from \"./ValueComponent\";\r\nimport { SimpleSelectQuery } from \"./SimpleSelectQuery\";\r\nimport { SelectClause, SelectItem, FromClause, TableSource, SourceExpression } from \"./Clause\";\r\nimport { SelectValueCollector } from \"../transformers/SelectValueCollector\";\r\n\r\n// Represents a CREATE TABLE query model\r\n// Supports temporary tables and AS SELECT ...\r\nexport class CreateTableQuery extends SqlComponent {\r\n /** SqlComponent kind symbol for visitor pattern */\r\n static kind = Symbol(\"CreateTableQuery\");\r\n /** Table name (with optional schema) */\r\n tableName: IdentifierString;\r\n /** If true, this is a temporary table */\r\n isTemporary: boolean;\r\n /** Optional: SELECT query for AS SELECT ... */\r\n asSelectQuery?: SelectQuery;\r\n\r\n constructor(params: {\r\n tableName: string;\r\n isTemporary?: boolean;\r\n asSelectQuery?: SelectQuery;\r\n }) {\r\n super();\r\n this.tableName = new IdentifierString(params.tableName);\r\n this.isTemporary = params.isTemporary ?? false;\r\n this.asSelectQuery = params.asSelectQuery;\r\n }\r\n\r\n /**\r\n * Returns a SelectQuery that selects all columns from this table.\r\n */\r\n getSelectQuery(): SimpleSelectQuery {\r\n let selectItems: SelectItem[];\r\n if (this.asSelectQuery) {\r\n // Use SelectValueCollector to get columns from asSelectQuery\r\n const collector = new SelectValueCollector();\r\n const values = collector.collect(this.asSelectQuery);\r\n selectItems = values.map(val => new SelectItem(val.value, val.name));\r\n } else {\r\n // fallback: wildcard\r\n selectItems = [new SelectItem(new RawString(\"*\"))];\r\n }\r\n return new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, this.tableName.name),\r\n null\r\n ),\r\n null // joins\r\n ),\r\n });\r\n }\r\n\r\n /**\r\n * Returns a SelectQuery that counts all rows in this table.\r\n */\r\n getCountQuery(): SimpleSelectQuery {\r\n return new SimpleSelectQuery({\r\n selectClause: new SelectClause([\r\n new SelectItem(new FunctionCall(null, \"count\", new ColumnReference(null, \"*\"), null))\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, this.tableName.name),\r\n null\r\n ),\r\n null // joins\r\n ),\r\n });\r\n }\r\n}\r\n", "import { PartitionByClause, OrderByClause, OrderByItem, SelectClause, SelectItem, Distinct, DistinctOn, SortDirection, NullsSortDirection, TableSource, SourceExpression, FromClause, JoinClause, JoinOnClause, JoinUsingClause, FunctionSource, SourceAliasExpression, WhereClause, GroupByClause, HavingClause, SubQuerySource, WindowFrameClause, LimitClause, ForClause, OffsetClause, WindowsClause as WindowClause, CommonTable, WithClause, FetchClause, FetchExpression, InsertClause, UpdateClause, SetClause, ReturningClause, SetClauseItem } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { SqlPrintToken, SqlPrintTokenType, SqlPrintTokenContainerType } from \"../models/SqlPrintToken\";\r\nimport {\r\n ValueList,\r\n ColumnReference,\r\n FunctionCall,\r\n UnaryExpression,\r\n BinaryExpression,\r\n LiteralValue,\r\n ParameterExpression,\r\n SwitchCaseArgument,\r\n CaseKeyValuePair,\r\n RawString,\r\n IdentifierString,\r\n ParenExpression,\r\n CastExpression,\r\n CaseExpression,\r\n ArrayExpression,\r\n ArrayQueryExpression,\r\n BetweenExpression,\r\n StringSpecifierExpression,\r\n TypeValue,\r\n TupleExpression,\r\n WindowFrameExpression,\r\n QualifiedName,\r\n InlineQuery,\r\n WindowFrameSpec,\r\n WindowFrameBoundStatic,\r\n WindowFrameBoundaryValue\r\n} from \"../models/ValueComponent\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { IdentifierDecorator } from \"./IdentifierDecorator\";\r\nimport { ParameterDecorator } from \"./ParameterDecorator\";\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { UpdateQuery } from \"../models/UpdateQuery\";\r\nimport { CreateTableQuery } from \"../models/CreateTableQuery\";\r\n\r\nexport enum ParameterStyle {\r\n Anonymous = 'anonymous',\r\n Indexed = 'indexed',\r\n Named = 'named'\r\n}\r\n\r\nexport interface FormatterConfig {\r\n identifierEscape?: {\r\n start: string;\r\n end: string;\r\n };\r\n parameterSymbol?: string | { start: string; end: string };\r\n /**\r\n * Parameter style: anonymous (?), indexed ($1), or named (:name)\r\n */\r\n parameterStyle?: ParameterStyle;\r\n}\r\n\r\nexport const PRESETS: Record<string, FormatterConfig> = {\r\n mysql: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n postgres: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n postgresWithNamedParams: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n sqlserver: {\r\n identifierEscape: { start: '[', end: ']' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n sqlite: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n oracle: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n clickhouse: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n firebird: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n db2: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n snowflake: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n cloudspanner: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n duckdb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n cockroachdb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n athena: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n bigquery: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n hive: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n mariadb: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n redshift: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n flinksql: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n mongodb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n};\r\n\r\nexport class SqlPrintTokenParser implements SqlComponentVisitor<SqlPrintToken> {\r\n // Static tokens for common symbols\r\n private static readonly SPACE_TOKEN = new SqlPrintToken(SqlPrintTokenType.space, ' ');\r\n private static readonly COMMA_TOKEN = new SqlPrintToken(SqlPrintTokenType.comma, ',');\r\n private static readonly ARGUMENT_SPLIT_COMMA_TOKEN = new SqlPrintToken(SqlPrintTokenType.argumentSplitter, ',');\r\n private static readonly PAREN_OPEN_TOKEN = new SqlPrintToken(SqlPrintTokenType.parenthesis, '(');\r\n private static readonly PAREN_CLOSE_TOKEN = new SqlPrintToken(SqlPrintTokenType.parenthesis, ')');\r\n private static readonly DOT_TOKEN = new SqlPrintToken(SqlPrintTokenType.dot, '.');\r\n\r\n private handlers: Map<symbol, (arg: any) => SqlPrintToken> = new Map();\r\n parameterDecorator: ParameterDecorator;\r\n identifierDecorator: IdentifierDecorator;\r\n index: number = 1;\r\n\r\n constructor(options?: {\r\n preset?: FormatterConfig,\r\n identifierEscape?: { start: string; end: string },\r\n parameterSymbol?: string | { start: string; end: string },\r\n parameterStyle?: 'anonymous' | 'indexed' | 'named'\r\n }) {\r\n if (options?.preset) {\r\n const preset = options.preset\r\n options = { ...preset, ...options };\r\n }\r\n\r\n this.parameterDecorator = new ParameterDecorator({\r\n prefix: typeof options?.parameterSymbol === 'string' ? options.parameterSymbol : options?.parameterSymbol?.start ?? ':',\r\n suffix: typeof options?.parameterSymbol === 'object' ? options.parameterSymbol.end : '',\r\n style: options?.parameterStyle ?? 'named'\r\n });\r\n\r\n this.identifierDecorator = new IdentifierDecorator({\r\n start: options?.identifierEscape?.start ?? '\"',\r\n end: options?.identifierEscape?.end ?? '\"'\r\n });\r\n\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(QualifiedName.kind, (expr) => this.visitQualifiedName(expr as QualifiedName));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(WindowFrameBoundStatic.kind, (expr) => this.visitWindowFrameBoundStatic(expr as WindowFrameBoundStatic));\r\n this.handlers.set(WindowFrameBoundaryValue.kind, (expr) => this.visitWindowFrameBoundaryValue(expr as WindowFrameBoundaryValue));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr));\r\n\r\n // select\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(Distinct.kind, (expr) => this.visitDistinct(expr as Distinct));\r\n this.handlers.set(DistinctOn.kind, (expr) => this.visitDistinctOn(expr as DistinctOn));\r\n\r\n // from\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(SourceAliasExpression.kind, (expr) => this.visitSourceAliasExpression(expr as SourceAliasExpression));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // where\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // group\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n\r\n this.handlers.set(WindowClause.kind, (expr) => this.visitWindowClause(expr as WindowClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.visitOffsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n this.handlers.set(FetchExpression.kind, (expr) => this.visitFetchExpression(expr as FetchExpression));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n\r\n // With\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // Query\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n\r\n this.handlers.set(InsertQuery.kind, (expr) => this.visitInsertQuery(expr as InsertQuery));\r\n this.handlers.set(InsertClause.kind, (expr) => this.visitInsertClause(expr as InsertClause));\r\n this.handlers.set(UpdateQuery.kind, (expr) => this.visitUpdateQuery(expr as UpdateQuery));\r\n this.handlers.set(UpdateClause.kind, (expr) => this.visitUpdateClause(expr as UpdateClause));\r\n this.handlers.set(SetClause.kind, (expr) => this.visitSetClause(expr as SetClause));\r\n this.handlers.set(SetClauseItem.kind, (expr) => this.visitSetClauseItem(expr as SetClauseItem));\r\n this.handlers.set(ReturningClause.kind, (expr) => this.visitReturningClause(expr as ReturningClause));\r\n this.handlers.set(CreateTableQuery.kind, (expr) => this.visitCreateTableQuery(expr as CreateTableQuery));\r\n }\r\n\r\n /**\r\n * Pretty-prints a BinarySelectQuery (e.g., UNION, INTERSECT, EXCEPT).\r\n * This will recursively print left and right queries, separated by the operator.\r\n * @param arg BinarySelectQuery\r\n */\r\n private visitBinarySelectQuery(arg: BinarySelectQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(this.visit(arg.left));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.operator.value, SqlPrintTokenContainerType.BinarySelectQueryOperator));\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.right));\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Returns an array of tokens representing a comma followed by a space.\r\n * This is a common pattern in SQL pretty-printing.\r\n */\r\n private static commaSpaceTokens(): SqlPrintToken[] {\r\n return [SqlPrintTokenParser.COMMA_TOKEN, SqlPrintTokenParser.SPACE_TOKEN];\r\n }\r\n\r\n private static argumentCommaSpaceTokens(): SqlPrintToken[] {\r\n return [SqlPrintTokenParser.ARGUMENT_SPLIT_COMMA_TOKEN, SqlPrintTokenParser.SPACE_TOKEN];\r\n }\r\n\r\n\r\n private visitQualifiedName(arg: QualifiedName): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.QualifiedName);\r\n\r\n if (arg.namespaces) {\r\n for (let i = 0; i < arg.namespaces.length; i++) {\r\n token.innerTokens.push(arg.namespaces[i].accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.DOT_TOKEN);\r\n }\r\n }\r\n token.innerTokens.push(arg.name.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n private visitPartitionByClause(arg: PartitionByClause): SqlPrintToken {\r\n // Print as: partition by ...\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'partition by', SqlPrintTokenContainerType.PartitionByClause);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n return token;\r\n }\r\n\r\n private visitOrderByClause(arg: OrderByClause): SqlPrintToken {\r\n // Print as: order by ...\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'order by', SqlPrintTokenContainerType.OrderByClause);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.order.length; i++) {\r\n if (i > 0) token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n token.innerTokens.push(this.visit(arg.order[i]));\r\n }\r\n return token;\r\n }\r\n\r\n /**\r\n * Print an OrderByItem (expression [asc|desc] [nulls first|last])\r\n */\r\n private visitOrderByItem(arg: OrderByItem): SqlPrintToken {\r\n // arg: OrderByItem\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.OrderByItem);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n if (arg.sortDirection && arg.sortDirection !== SortDirection.Ascending) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'desc'));\r\n }\r\n\r\n if (arg.nullsPosition) {\r\n if (arg.nullsPosition === NullsSortDirection.First) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'nulls first'));\r\n } else if (arg.nullsPosition === NullsSortDirection.Last) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'nulls last'));\r\n }\r\n }\r\n return token;\r\n }\r\n\r\n public parse(arg: SqlComponent): { token: SqlPrintToken, params: any[] | Record<string, any>[] | Record<string, any> } {\r\n // reset parameter index before parsing\r\n this.index = 1;\r\n\r\n const token = this.visit(arg);\r\n const paramsRaw = ParameterCollector.collect(arg).sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\r\n\r\n const style = this.parameterDecorator.style;\r\n if (style === ParameterStyle.Named) {\r\n // Named: { name: value, ... }\r\n const paramsObj: Record<string, any> = {};\r\n for (const p of paramsRaw) {\r\n const key = p.name.value;\r\n if (paramsObj.hasOwnProperty(key)) {\r\n if (paramsObj[key] !== p.value) {\r\n throw new Error(`Duplicate parameter name '${key}' with different values detected during query composition.`);\r\n }\r\n // If value is the same, skip (already set)\r\n continue;\r\n }\r\n paramsObj[key] = p.value;\r\n }\r\n return { token, params: paramsObj };\r\n } else if (style === ParameterStyle.Indexed) {\r\n // Indexed: [value1, value2, ...] (sorted by index)\r\n const paramsArr = paramsRaw.map(p => p.value);\r\n return { token, params: paramsArr };\r\n } else if (style === ParameterStyle.Anonymous) {\r\n // Anonymous: [value1, value2, ...] (sorted by index, name is empty)\r\n const paramsArr = paramsRaw.map(p => p.value);\r\n return { token, params: paramsArr };\r\n }\r\n\r\n // Fallback (just in case)\r\n return { token, params: [] };\r\n }\r\n\r\n public visit(arg: SqlComponent): SqlPrintToken {\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n return handler(arg);\r\n }\r\n throw new Error(`[SqlPrintTokenParser] No handler for kind: ${arg.getKind().toString()}`);\r\n }\r\n\r\n private visitValueList(arg: ValueList): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ValueList);\r\n for (let i = 0; i < arg.values.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.values[i]));\r\n }\r\n return token;\r\n }\r\n\r\n private visitColumnReference(arg: ColumnReference): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ColumnReference);\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n return token;\r\n }\r\n\r\n private visitFunctionCall(arg: FunctionCall): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FunctionCall);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n if (arg.argument) {\r\n token.innerTokens.push(this.visit(arg.argument));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n if (arg.over) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'over'));\r\n\r\n if (arg.over instanceof IdentifierString) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.over.accept(this));\r\n }\r\n else {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.over));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitUnaryExpression(arg: UnaryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.UnaryExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.operator));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n\r\n return token;\r\n }\r\n\r\n private visitBinaryExpression(arg: BinaryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.BinaryExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.left));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, arg.operator.value));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.right));\r\n\r\n return token;\r\n }\r\n\r\n private visitLiteralValue(arg: LiteralValue): SqlPrintToken {\r\n let text;\r\n if (typeof arg.value === \"string\") {\r\n text = `'${arg.value.replace(/'/g, \"''\")}'`;\r\n } else if (arg.value === null) {\r\n text = \"null\";\r\n } else {\r\n text = arg.value.toString();\r\n }\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n text,\r\n SqlPrintTokenContainerType.LiteralValue\r\n );\r\n }\r\n\r\n private visitParameterExpression(arg: ParameterExpression): SqlPrintToken {\r\n // Create a parameter token and decorate it using the parameterDecorator\r\n arg.index = this.index;\r\n const text = this.parameterDecorator.decorate(arg.name.value, arg.index)\r\n const token = new SqlPrintToken(SqlPrintTokenType.parameter, text);\r\n\r\n this.index++;\r\n return token;\r\n }\r\n\r\n private visitSwitchCaseArgument(arg: SwitchCaseArgument): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SwitchCaseArgument);\r\n\r\n // Add each WHEN/THEN clause\r\n for (const kv of arg.cases) {\r\n // Create a new line for each WHEN clause\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(kv.accept(this));\r\n }\r\n\r\n // Add ELSE clause if present\r\n if (arg.elseValue) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.createElseToken(arg.elseValue));\r\n }\r\n return token;\r\n }\r\n\r\n private createElseToken(elseValue: SqlComponent): SqlPrintToken {\r\n // Creates a token for the ELSE clause in a CASE expression.\r\n const elseToken = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ElseClause); // Add the ELSE keyword\r\n elseToken.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'else'));\r\n\r\n // Create a container for the ELSE value to enable proper indentation\r\n elseToken.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n const elseValueContainer = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseElseValue);\r\n elseValueContainer.innerTokens.push(this.visit(elseValue));\r\n elseToken.innerTokens.push(elseValueContainer);\r\n\r\n return elseToken;\r\n }\r\n\r\n private visitCaseKeyValuePair(arg: CaseKeyValuePair): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseKeyValuePair);\r\n\r\n // Create WHEN clause\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'when'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.key)); // Create THEN clause\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'then'));\r\n\r\n // Create a container for the THEN value to enable proper indentation\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n const thenValueContainer = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseThenValue);\r\n thenValueContainer.innerTokens.push(this.visit(arg.value));\r\n token.innerTokens.push(thenValueContainer);\r\n\r\n return token;\r\n }\r\n\r\n private visitRawString(arg: RawString): SqlPrintToken {\r\n // Even for non-container tokens, set the container type for context\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n arg.value,\r\n SqlPrintTokenContainerType.RawString\r\n );\r\n }\r\n\r\n private visitIdentifierString(arg: IdentifierString): SqlPrintToken {\r\n // Create an identifier token and decorate it using the identifierDecorator\r\n const text = arg.name === \"*\" ? arg.name : this.identifierDecorator.decorate(arg.name)\r\n const token = new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n text,\r\n SqlPrintTokenContainerType.IdentifierString\r\n );\r\n return token;\r\n }\r\n\r\n private visitParenExpression(arg: ParenExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ParenExpression);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitCastExpression(arg: CastExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CastExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.input));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, '::'));\r\n token.innerTokens.push(this.visit(arg.castType));\r\n\r\n return token;\r\n }\r\n\r\n private visitCaseExpression(arg: CaseExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseExpression);\r\n\r\n // Add the CASE keyword\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'case'));\r\n\r\n // Add the condition if exists\r\n if (arg.condition) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n }\r\n\r\n // Add the WHEN/THEN pairs and ELSE\r\n token.innerTokens.push(this.visit(arg.switchCase));\r\n\r\n // Add the END keyword\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'end'));\r\n\r\n return token;\r\n }\r\n\r\n private visitArrayExpression(arg: ArrayExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ArrayExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'array'));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, '['));\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, ']'));\r\n\r\n return token;\r\n }\r\n\r\n private visitArrayQueryExpression(arg: ArrayQueryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ArrayExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'array'));\r\n // ARRAY(SELECT ...)\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, '('));\r\n token.innerTokens.push(this.visit(arg.query));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, ')'));\r\n\r\n return token;\r\n }\r\n\r\n private visitBetweenExpression(arg: BetweenExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.BetweenExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n if (arg.negated) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'not'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'between'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.lower));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'and'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.upper));\r\n\r\n return token;\r\n }\r\n\r\n private visitStringSpecifierExpression(arg: StringSpecifierExpression): SqlPrintToken {\r\n // Combine specifier and value into a single token\r\n const specifier = arg.specifier.accept(this).text;\r\n const value = arg.value.accept(this).text;\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n specifier + value,\r\n SqlPrintTokenContainerType.StringSpecifierExpression\r\n );\r\n }\r\n\r\n private visitTypeValue(arg: TypeValue): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.TypeValue);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n if (arg.argument) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.argument));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitTupleExpression(arg: TupleExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.TupleExpression);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.values.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.values[i]));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitWindowFrameExpression(arg: WindowFrameExpression): SqlPrintToken {\r\n // Compose window frame expression: over(partition by ... order by ... rows ...)\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameExpression);\r\n\r\n let first = true;\r\n if (arg.partition) {\r\n token.innerTokens.push(this.visit(arg.partition));\r\n first = false;\r\n }\r\n if (arg.order) {\r\n if (!first) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n } else {\r\n first = false;\r\n }\r\n token.innerTokens.push(this.visit(arg.order));\r\n }\r\n if (arg.frameSpec) {\r\n if (!first) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n } else {\r\n first = false;\r\n }\r\n token.innerTokens.push(this.visit(arg.frameSpec));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitWindowFrameSpec(arg: WindowFrameSpec): SqlPrintToken {\r\n // This method prints a window frame specification, such as \"rows between ... and ...\" or \"range ...\".\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameSpec);\r\n\r\n // Add frame type (e.g., \"rows\", \"range\", \"groups\")\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.frameType));\r\n\r\n if (arg.endBound === null) {\r\n // Only start bound: e.g., \"rows unbounded preceding\"\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.startBound.accept(this));\r\n } else {\r\n // Between: e.g., \"rows between unbounded preceding and current row\"\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'between'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.startBound.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'and'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.endBound.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Prints a window frame boundary value, such as \"5 preceding\" or \"3 following\".\r\n * @param arg WindowFrameBoundaryValue\r\n */\r\n private visitWindowFrameBoundaryValue(arg: WindowFrameBoundaryValue): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameBoundaryValue);\r\n\r\n token.innerTokens.push(arg.value.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // true for \"FOLLOWING\", false for \"PRECEDING\"\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.isFollowing ? 'following' : 'preceding'));\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Prints a static window frame bound, such as \"unbounded preceding\", \"current row\", or \"unbounded following\".\r\n * @param arg WindowFrameBoundStatic\r\n */\r\n private visitWindowFrameBoundStatic(arg: WindowFrameBoundStatic): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, arg.bound);\r\n return token;\r\n }\r\n\r\n private visitSelectItem(arg: SelectItem): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SelectItem);\r\n\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n if (!arg.identifier) {\r\n return token;\r\n }\r\n\r\n // No alias needed if it matches the default name\r\n if (arg.value instanceof ColumnReference) {\r\n const defaultName = arg.value.column.name;\r\n if (arg.identifier.name === defaultName) {\r\n return token;\r\n }\r\n }\r\n\r\n // Add alias if it is different from the default name\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.identifier));\r\n return token;\r\n }\r\n\r\n private visitSelectClause(arg: SelectClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'select', SqlPrintTokenContainerType.SelectClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n if (arg.distinct) {\r\n token.keywordTokens = [];\r\n token.keywordTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.keywordTokens.push(arg.distinct.accept(this));\r\n }\r\n\r\n for (let i = 0; i < arg.items.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.items[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitDistinct(arg: Distinct): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'distinct');\r\n return token;\r\n }\r\n\r\n private visitDistinctOn(arg: DistinctOn): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.DistinctOn);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'distinct on'));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(arg.value.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitTableSource(arg: TableSource): SqlPrintToken {\r\n // Print table name with optional namespaces and alias\r\n let fullName = '';\r\n if (Array.isArray(arg.namespaces) && arg.namespaces.length > 0) {\r\n fullName = arg.namespaces.map(ns => ns.accept(this).text).join('.') + '.';\r\n }\r\n fullName += arg.table.accept(this).text;\r\n const token = new SqlPrintToken(SqlPrintTokenType.value, fullName);\r\n // alias (if present and different from table name)\r\n if (arg.identifier && arg.identifier.name !== arg.table.name) {\r\n\r\n }\r\n return token;\r\n }\r\n\r\n private visitSourceExpression(arg: SourceExpression): SqlPrintToken {\r\n // Print source expression (e.g. \"table\", \"table as t\", \"schema.table t\")\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SourceExpression);\r\n token.innerTokens.push(arg.datasource.accept(this));\r\n\r\n if (!arg.aliasExpression) {\r\n return token;\r\n }\r\n\r\n if (arg.datasource instanceof TableSource) {\r\n // No alias needed if it matches the default name\r\n const defaultName = arg.datasource.table.name;\r\n if (arg.aliasExpression.table.name === defaultName) {\r\n return token;\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // exclude column aliases\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n return token;\r\n } else {\r\n // For other source types, just print the alias\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // included column aliases\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n return token;\r\n }\r\n }\r\n\r\n public visitFromClause(arg: FromClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'from', SqlPrintTokenContainerType.FromClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.source));\r\n\r\n if (arg.joins) {\r\n for (let i = 0; i < arg.joins.length; i++) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.joins[i]));\r\n }\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinClause(arg: JoinClause): SqlPrintToken {\r\n // Print join clause: [joinType] [lateral] [source] [on/using ...]\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinClause);\r\n\r\n // join type (e.g. inner join, left join, etc)\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.joinType.value));\r\n if (arg.lateral) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'lateral'));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.source));\r\n\r\n if (arg.condition) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinOnClause(arg: JoinOnClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinOnClause);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'on'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinUsingClause(arg: JoinUsingClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinUsingClause);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'using'));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitFunctionSource(arg: FunctionSource): SqlPrintToken {\r\n // Print function source: [functionName]([args])\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FunctionSource);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n if (arg.argument) {\r\n token.innerTokens.push(this.visit(arg.argument));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n return token;\r\n }\r\n\r\n public visitSourceAliasExpression(arg: SourceAliasExpression): SqlPrintToken {\r\n // Print source alias expression: [source] as [alias]\r\n const token = new SqlPrintToken(\r\n SqlPrintTokenType.container,\r\n '',\r\n SqlPrintTokenContainerType.SourceAliasExpression\r\n );\r\n\r\n token.innerTokens.push(this.visit(arg.table));\r\n\r\n if (arg.columns) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.columns[i]));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitWhereClause(arg: WhereClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'where', SqlPrintTokenContainerType.WhereClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitGroupByClause(arg: GroupByClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'group by', SqlPrintTokenContainerType.GroupByClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.grouping.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.grouping[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitHavingClause(arg: HavingClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'having', SqlPrintTokenContainerType.HavingClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitWindowClause(arg: WindowClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'window', SqlPrintTokenContainerType.WindowClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.windows.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.windows[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitWindowFrameClause(arg: WindowFrameClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameClause);\r\n\r\n token.innerTokens.push(arg.name.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitLimitClause(arg: LimitClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'limit', SqlPrintTokenContainerType.LimitClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n return token;\r\n }\r\n\r\n public visitOffsetClause(arg: OffsetClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'offset', SqlPrintTokenContainerType.OffsetClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n return token;\r\n }\r\n\r\n public visitFetchClause(arg: FetchClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'fetch', SqlPrintTokenContainerType.FetchClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n\r\n return token;\r\n }\r\n\r\n public visitFetchExpression(arg: FetchExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FetchExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.type));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.count.accept(this));\r\n\r\n if (arg.unit) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.unit));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitForClause(arg: ForClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'for', SqlPrintTokenContainerType.ForClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.lockMode));\r\n\r\n return token;\r\n }\r\n\r\n public visitWithClause(arg: WithClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'with', SqlPrintTokenContainerType.WithClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n if (arg.recursive) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'recursive'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n\r\n for (let i = 0; i < arg.tables.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(arg.tables[i].accept(this));\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n return token;\r\n }\r\n\r\n public visitCommonTable(arg: CommonTable): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CommonTable);\r\n\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n if (arg.materialized !== null) {\r\n if (arg.materialized) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'materialized'));\r\n } else {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'not materialized'));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const query = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SubQuerySource);\r\n query.innerTokens.push(arg.query.accept(this));\r\n\r\n token.innerTokens.push(query);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n // query\r\n public visitSimpleQuery(arg: SimpleSelectQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SimpleSelectQuery);\r\n\r\n if (arg.withClause) {\r\n token.innerTokens.push(arg.withClause.accept(this));\r\n }\r\n\r\n token.innerTokens.push(arg.selectClause.accept(this));\r\n\r\n if (!arg.fromClause) {\r\n return token;\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fromClause.accept(this));\r\n\r\n if (arg.whereClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.whereClause.accept(this));\r\n }\r\n\r\n if (arg.groupByClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.groupByClause.accept(this));\r\n }\r\n\r\n if (arg.havingClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.havingClause.accept(this));\r\n }\r\n\r\n if (arg.orderByClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.orderByClause.accept(this));\r\n }\r\n\r\n if (arg.windowClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.windowClause.accept(this));\r\n }\r\n\r\n if (arg.limitClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.limitClause.accept(this));\r\n }\r\n\r\n if (arg.offsetClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.offsetClause.accept(this));\r\n }\r\n\r\n if (arg.fetchClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fetchClause.accept(this));\r\n }\r\n\r\n if (arg.forClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.forClause.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitSubQuerySource(arg: SubQuerySource): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const subQuery = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SubQuerySource);\r\n subQuery.innerTokens.push(arg.query.accept(this));\r\n\r\n token.innerTokens.push(subQuery);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitValuesQuery(arg: ValuesQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'values', SqlPrintTokenContainerType.ValuesQuery);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n const values = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.Values);\r\n for (let i = 0; i < arg.tuples.length; i++) {\r\n if (i > 0) {\r\n values.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n values.innerTokens.push(arg.tuples[i].accept(this));\r\n }\r\n\r\n token.innerTokens.push(values);\r\n return token;\r\n }\r\n\r\n public visitInlineQuery(arg: InlineQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const queryToken = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.InlineQuery);\r\n queryToken.innerTokens.push(arg.selectQuery.accept(this));\r\n\r\n token.innerTokens.push(queryToken);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitInsertQuery(arg: InsertQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.InsertQuery);\r\n\r\n // Process the insert clause\r\n token.innerTokens.push(this.visit(arg.insertClause));\r\n\r\n // Process the select query if present\r\n if (arg.selectQuery) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.selectQuery));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitInsertClause(arg: InsertClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'insert into'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.source.accept(this));\r\n\r\n if (arg.columns.length > 0) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(arg.columns[i].accept(this));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitUpdateQuery(arg: UpdateQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.UpdateQuery);\r\n\r\n if (arg.withClause) {\r\n token.innerTokens.push(arg.withClause.accept(this));\r\n }\r\n\r\n token.innerTokens.push(arg.updateClause.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.setClause.accept(this));\r\n\r\n if (arg.fromClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fromClause.accept(this));\r\n }\r\n\r\n if (arg.whereClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.whereClause.accept(this));\r\n }\r\n\r\n if (arg.returningClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.returningClause.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitUpdateClause(arg: UpdateClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'update', SqlPrintTokenContainerType.UpdateClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.source.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n public visitSetClause(arg: SetClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'set', SqlPrintTokenContainerType.SelectClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.items.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.items[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitSetClauseItem(arg: SetClauseItem): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SetClauseItem);\r\n\r\n token.innerTokens.push(arg.column.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, '='));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.value.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n public visitReturningClause(arg: ReturningClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'returning', SqlPrintTokenContainerType.ReturningClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.columns[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitCreateTableQuery(arg: CreateTableQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, arg.isTemporary ? 'create temporary table' : 'create table', SqlPrintTokenContainerType.CreateTableQuery);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.tableName.accept(this));\r\n\r\n if (arg.asSelectQuery) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.asSelectQuery.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n}\r\n", "// Define the allowed newline options\r\nexport type NewlineOption = ' ' | '\\n' | '\\r\\n';\r\n\r\n// Define the allowed indent character options\r\nexport type IndentCharOption = '' | ' ' | '\\t';\r\n\r\n/**\r\n * SqlPrintHelper provides utility methods for SQL pretty printing.\r\n */\r\nexport class LinePrinter {\r\n indentChar: IndentCharOption; // Changed type to IndentCharOption\r\n indentSize: number;\r\n newline: NewlineOption; // Changed type to NewlineOption\r\n lines: PrintLine[];\r\n /**\r\n * @param indentChar Character used for indentation (default: ' ') // Updated comment to reflect options\r\n * @param indentSize Number of indentChar per level (default: 0)\r\n * @param newline Newline string (default: '\\r\\n') // Changed type and default value\r\n */\r\n constructor(indentChar: IndentCharOption = ' ', indentSize: number = 0, newline: NewlineOption = '\\r\\n') { // Changed type for indentChar\r\n this.indentChar = indentChar;\r\n this.indentSize = indentSize;\r\n this.newline = newline;\r\n this.lines = [];\r\n this.appendNewline(0);\r\n }\r\n\r\n public print(): string {\r\n let result = '';\r\n for (const line of this.lines) {\r\n if (line.text !== '') {\r\n // append indent and text\r\n result += this.indent(line.level) + line.text;\r\n }\r\n }\r\n return result.trimEnd();\r\n }\r\n\r\n /**\r\n * Returns the indent string for a given level.\r\n * @param level Indentation level\r\n */\r\n private indent(level: number): string {\r\n return this.indentChar.repeat(this.indentSize * level);\r\n }\r\n\r\n /**\r\n * Appends a newline token to the given tokens array if newline is set, or adds an empty line if tokens is empty.\r\n * @param tokens Array of token objects with 'level' and 'text' property\r\n * @param level Indentation level\r\n */\r\n appendNewline(level: number): void {\r\n if (this.lines.length > 0) {\r\n const current = this.lines[this.lines.length - 1];\r\n if (current.text !== '') {\r\n current.text = current.text.trimEnd() + this.newline;\r\n }\r\n }\r\n this.lines.push(new PrintLine(level, ''));\r\n }\r\n\r\n /**\r\n * Appends text to the last element of tokens array.\r\n * @param tokens Array of token objects with 'text' property\r\n * @param text Text to append\r\n */\r\n appendText(text: string): void {\r\n if (this.lines.length > 0) {\r\n const workingIndex = this.lines.length - 1;\r\n const workLine = this.lines[workingIndex]\r\n // Leading space is not needed\r\n if (!(text === ' ' && workLine.text === '')) {\r\n workLine.text += text;\r\n }\r\n } else {\r\n throw new Error('No tokens to append to.');\r\n }\r\n }\r\n\r\n getCurrentLine(): PrintLine {\r\n if (this.lines.length > 0) {\r\n return this.lines[this.lines.length - 1];\r\n } else {\r\n throw new Error('No tokens to get current line from.');\r\n }\r\n }\r\n}\r\n\r\nexport class PrintLine {\r\n level: number;\r\n text: string;\r\n\r\n constructor(level: number, text: string) {\r\n this.level = level;\r\n this.text = text;\r\n }\r\n}", "import { SqlPrintToken, SqlPrintTokenType, SqlPrintTokenContainerType } from \"../models/SqlPrintToken\";\r\nimport { IndentCharOption, LinePrinter, NewlineOption } from \"./LinePrinter\";\r\n\r\n/**\r\n * CommaBreakStyle determines how commas are placed in formatted SQL output.\r\n * - 'none': No line break for commas\r\n * - 'before': Line break before comma\r\n * - 'after': Line break after comma\r\n */\r\nexport type CommaBreakStyle = 'none' | 'before' | 'after';\r\n\r\n/**\r\n * AndBreakStyle determines how AND operators are placed in formatted SQL output.\r\n * - 'none': No line break for AND\r\n * - 'before': Line break before AND\r\n * - 'after': Line break after AND\r\n */\r\nexport type AndBreakStyle = 'none' | 'before' | 'after';\r\n\r\n/**\r\n * SqlPrinter formats a SqlPrintToken tree into a SQL string with flexible style options.\r\n */\r\nexport class SqlPrinter {\r\n /** Indent character (e.g., ' ' or '\\\\t') */\r\n indentChar: IndentCharOption; // Changed type from string\r\n /** Indent size (number of indentChar repetitions per level) */\r\n indentSize: number;\r\n /** Newline character (e.g., '\\\\n' or '\\\\r\\\\n') */\r\n newline: NewlineOption; // Changed type from string\r\n /** Comma break style: 'none', 'before', or 'after' */\r\n commaBreak: CommaBreakStyle;\r\n /** AND break style: 'none', 'before', or 'after' */\r\n andBreak: AndBreakStyle;\r\n\r\n /** Keyword case style: 'none', 'upper' | 'lower' */\r\n keywordCase: 'none' | 'upper' | 'lower';\r\n\r\n private linePrinter: LinePrinter;\r\n private indentIncrementContainers: Set<SqlPrintTokenContainerType>;\r\n\r\n /**\r\n * @param options Optional style settings for pretty printing\r\n */\r\n constructor(options?: {\r\n indentChar?: IndentCharOption;\r\n indentSize?: number;\r\n newline?: NewlineOption;\r\n commaBreak?: CommaBreakStyle;\r\n andBreak?: AndBreakStyle;\r\n keywordCase?: 'none' | 'upper' | 'lower';\r\n indentIncrementContainerTypes?: string[]; // Option to customize\r\n }) {\r\n this.indentChar = options?.indentChar ?? '';\r\n this.indentSize = options?.indentSize ?? 0;\r\n\r\n // The default newline character is set to a blank space (' ') to enable one-liner formatting.\r\n // This is intentional and differs from the LinePrinter default of '\\r\\n'.\r\n this.newline = options?.newline ?? ' ';\r\n\r\n this.commaBreak = options?.commaBreak ?? 'none';\r\n this.andBreak = options?.andBreak ?? 'none';\r\n this.keywordCase = options?.keywordCase ?? 'none';\r\n this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline);\r\n\r\n // Initialize\r\n this.indentIncrementContainers = new Set(\r\n (options?.indentIncrementContainerTypes as SqlPrintTokenContainerType[] | undefined) ?? [\r\n SqlPrintTokenContainerType.SelectClause,\r\n SqlPrintTokenContainerType.FromClause,\r\n SqlPrintTokenContainerType.WhereClause,\r\n SqlPrintTokenContainerType.GroupByClause,\r\n SqlPrintTokenContainerType.HavingClause,\r\n SqlPrintTokenContainerType.WindowFrameExpression,\r\n SqlPrintTokenContainerType.PartitionByClause,\r\n SqlPrintTokenContainerType.OrderByClause,\r\n SqlPrintTokenContainerType.WindowClause,\r\n SqlPrintTokenContainerType.LimitClause,\r\n SqlPrintTokenContainerType.OffsetClause,\r\n SqlPrintTokenContainerType.SubQuerySource,\r\n SqlPrintTokenContainerType.BinarySelectQueryOperator, SqlPrintTokenContainerType.Values,\r\n SqlPrintTokenContainerType.WithClause,\r\n SqlPrintTokenContainerType.SwitchCaseArgument,\r\n SqlPrintTokenContainerType.CaseKeyValuePair,\r\n SqlPrintTokenContainerType.CaseThenValue,\r\n SqlPrintTokenContainerType.ElseClause,\r\n SqlPrintTokenContainerType.CaseElseValue\r\n // CaseExpression, SwitchCaseArgument, CaseKeyValuePair, and ElseClause\r\n // are not included by default to maintain backward compatibility with tests\r\n //SqlPrintTokenContainerType.CommonTable\r\n ]\r\n );\r\n }\r\n\r\n /**\r\n * Converts a SqlPrintToken tree to a formatted SQL string.\r\n * @param token The root SqlPrintToken\r\n * @param level Indentation level (default: 0)\r\n */\r\n print(token: SqlPrintToken, level: number = 0): string {\r\n // initialize\r\n this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline);\r\n if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {\r\n this.linePrinter.lines[0].level = level;\r\n }\r\n\r\n this.appendToken(token, level);\r\n\r\n return this.linePrinter.print();\r\n }\r\n\r\n private appendToken(token: SqlPrintToken, level: number) {\r\n if (!token.innerTokens || token.innerTokens.length === 0) {\r\n if (token.text === '') {\r\n return;\r\n }\r\n }\r\n\r\n const current = this.linePrinter.getCurrentLine();\r\n\r\n if (token.type === SqlPrintTokenType.keyword) {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n this.linePrinter.appendText(text);\r\n } else if (token.type === SqlPrintTokenType.comma) {\r\n let text = token.text;\r\n if (this.commaBreak === 'before') {\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else if (this.commaBreak === 'after') {\r\n this.linePrinter.appendText(text);\r\n this.linePrinter.appendNewline(level);\r\n } else {\r\n this.linePrinter.appendText(text);\r\n }\r\n } else if (token.type === SqlPrintTokenType.operator && token.text.toLowerCase() === 'and') {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n\r\n if (this.andBreak === 'before') {\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else if (this.andBreak === 'after') {\r\n this.linePrinter.appendText(text);\r\n this.linePrinter.appendNewline(level);\r\n } else {\r\n this.linePrinter.appendText(text);\r\n }\r\n } else if (token.containerType === \"JoinClause\") {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n // before join clause, add newline\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else {\r\n this.linePrinter.appendText(token.text);\r\n }\r\n\r\n // append keyword tokens(not indented)\r\n if (token.keywordTokens && token.keywordTokens.length > 0) {\r\n for (let i = 0; i < token.keywordTokens.length; i++) {\r\n const keywordToken = token.keywordTokens[i];\r\n this.appendToken(keywordToken, level);\r\n }\r\n }\r\n\r\n let innerLevel = level;\r\n\r\n // indent level up\r\n if (this.newline !== ' ' && current.text !== '' && this.indentIncrementContainers.has(token.containerType)) { // Changed condition\r\n innerLevel++;\r\n this.linePrinter.appendNewline(innerLevel);\r\n }\r\n\r\n for (let i = 0; i < token.innerTokens.length; i++) {\r\n const child = token.innerTokens[i];\r\n this.appendToken(child, innerLevel);\r\n }\r\n\r\n // indent level down\r\n if (innerLevel !== level) {\r\n this.linePrinter.appendNewline(level);\r\n }\r\n }\r\n}", "import { SqlPrintTokenParser, FormatterConfig, PRESETS } from '../parsers/SqlPrintTokenParser';\r\nimport { SqlPrinter, CommaBreakStyle, AndBreakStyle } from './SqlPrinter';\r\nimport { IndentCharOption, NewlineOption } from './LinePrinter'; // Import types for compatibility\r\nimport { SelectQuery } from '../models/SelectQuery';\r\nimport { SqlComponent } from '../models/SqlComponent';\r\n\r\n// Define valid preset names as a union type\r\nexport const VALID_PRESETS = ['mysql', 'postgres', 'sqlserver', 'sqlite'] as const;\r\nexport type PresetName = (typeof VALID_PRESETS)[number];\r\n\r\n/**\r\n * SqlFormatter class combines parsing and printing of SQL queries into a single interface.\r\n */\r\nexport class SqlFormatter {\r\n private parser: SqlPrintTokenParser;\r\n private printer: SqlPrinter;\r\n\r\n constructor(options: {\r\n preset?: PresetName; // Restrict preset to specific strings\r\n identifierEscape?: { start: string; end: string }; // Allow custom identifier escape\r\n parameterSymbol?: string | { start: string; end: string }; // Allow custom parameter symbol\r\n parameterStyle?: 'anonymous' | 'indexed' | 'named'; // Allow custom parameter style\r\n indentSize?: number;\r\n indentChar?: IndentCharOption; // Updated type\r\n newline?: NewlineOption; // Updated type\r\n keywordCase?: 'none' | 'upper' | 'lower'; // Updated type\r\n commaBreak?: CommaBreakStyle; // Updated type\r\n andBreak?: AndBreakStyle; // Updated type\r\n } = {}) { // Default to 'sqlserver' if options is empty\r\n\r\n const presetConfig = options.preset ? PRESETS[options.preset] : undefined;\r\n\r\n if (options.preset && !presetConfig) {\r\n throw new Error(`Invalid preset: ${options.preset}`); // Throw error for invalid preset\r\n }\r\n\r\n const parserOptions = {\r\n ...presetConfig, // Apply preset configuration\r\n identifierEscape: options.identifierEscape ?? presetConfig?.identifierEscape,\r\n parameterSymbol: options.parameterSymbol ?? presetConfig?.parameterSymbol,\r\n parameterStyle: options.parameterStyle ?? presetConfig?.parameterStyle,\r\n };\r\n\r\n this.parser = new SqlPrintTokenParser(parserOptions);\r\n this.printer = new SqlPrinter(options);\r\n }\r\n\r\n /**\r\n * Formats a SQL query string with the given parameters.\r\n * @param sqlText The SQL query string to format.\r\n * @param parameters A dictionary of parameters to replace in the query.\r\n * @returns An object containing the formatted SQL string and the parameters.\r\n */\r\n format(sql: SqlComponent): { formattedSql: string; params: Record<string, any> } {\r\n const { token, params } = this.parser.parse(sql);\r\n const formattedSql = this.printer.print(token);\r\n\r\n return { formattedSql, params };\r\n }\r\n}\r\n", "import { SqlFormatter } from './SqlFormatter';\r\nimport { SelectQuery } from '../models/SelectQuery';\r\nimport { SqlComponent, SqlComponentVisitor } from '../models/SqlComponent';\r\nimport { FormatterConfig } from '../parsers/SqlPrintTokenParser';\r\n\r\n/**\r\n * @deprecated The Formatter class is deprecated. Use SqlFormatter instead.\r\n */\r\nexport class Formatter implements SqlComponentVisitor<string> {\r\n private sqlFormatter: SqlFormatter;\r\n\r\n constructor() {\r\n this.sqlFormatter = new SqlFormatter({\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: 'named' // Default to 'named' for backward compatibility\r\n });\r\n }\r\n\r\n public format(arg: SqlComponent, config: FormatterConfig | null = null): string {\r\n // Use the sqlFormatter instance to format the SQL component\r\n if (config) {\r\n this.sqlFormatter = new SqlFormatter(config);\r\n }\r\n const result = this.sqlFormatter.format(arg);\r\n return result.formattedSql;\r\n }\r\n\r\n public formatWithParameters(arg: SqlComponent, config: FormatterConfig | null = null): { sql: string, params: any[] | Record<string, any>[] | Record<string, any> } {\r\n // Use the sqlFormatter instance to format the SQL component with parameters\r\n if (config) {\r\n this.sqlFormatter = new SqlFormatter(config);\r\n }\r\n const result = this.sqlFormatter.format(arg);\r\n return { sql: result.formattedSql, params: result.params };\r\n }\r\n\r\n public visit(arg: SqlComponent): string {\r\n return this.format(arg);\r\n }\r\n}\r\n\r\nexport { SqlFormatter };", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableSourceCollector } from \"./TableSourceCollector\";\r\nimport { Formatter } from \"./Formatter\";\r\n\r\n/**\r\n * CTENameConflictResolver is responsible for resolving name conflicts among Common Table Expressions (CTEs).\r\n * It also sorts the tables in the proper order based on dependencies and recursiveness.\r\n */\r\nexport class CTEBuilder {\r\n private sourceCollector: TableSourceCollector;\r\n private cteCollector: CTECollector;\r\n private formatter: Formatter;\r\n\r\n constructor() {\r\n this.sourceCollector = new TableSourceCollector(true);\r\n this.cteCollector = new CTECollector();\r\n this.formatter = new Formatter();\r\n }\r\n\r\n /**\r\n * Resolves name conflicts among CommonTables.\r\n * If there are duplicate CTE names, they must have identical definitions.\r\n * Also sorts the tables so that:\r\n * 1. Recursive CTEs come first (CTEs that reference themselves)\r\n * 2. Then remaining tables are sorted so inner (deeper) CTEs come before outer CTEs\r\n * \r\n * @param commonTables The list of CommonTables to check for name conflicts\r\n * @returns An object containing:\r\n * - needRecursive: boolean indicating if any recursive CTEs are present\r\n * - commonTables: A new list of CommonTables with resolved name conflicts and proper order\r\n * @throws Error if there are duplicate CTE names with different definitions\r\n */\r\n public build(commonTables: CommonTable[]): WithClause {\r\n // Early return for empty CTEs\r\n // Note:\r\n // Although it may seem reasonable to return early when there is only one element,\r\n // the 'recursive' property is determined dynamically. Therefore, if there is at least one element,\r\n // the CTEs must be rebuilt to ensure correct recursive detection.\r\n if (commonTables.length === 0) {\r\n return new WithClause(\r\n false,\r\n commonTables\r\n );\r\n }\r\n\r\n // Step 1: Resolve name conflicts\r\n const resolvedTables = this.resolveDuplicateNames(commonTables);\r\n\r\n // Step 2: Identify recursive CTEs and build dependency graph\r\n const { tableMap, recursiveCTEs, dependencies } = this.buildDependencyGraph(resolvedTables);\r\n\r\n // Step 3: Sort tables according to dependencies and recursiveness\r\n const sortedTables = this.sortCommonTables(resolvedTables, tableMap, recursiveCTEs, dependencies);\r\n\r\n return new WithClause(\r\n recursiveCTEs.size > 0,\r\n sortedTables\r\n );\r\n }\r\n\r\n /**\r\n * Resolves duplicate CTE names by checking if they have identical definitions.\r\n * If definitions differ, throws an error.\r\n * \r\n * @param commonTables The list of CTEs to check for duplicates\r\n * @returns A list of CTEs with duplicates removed\r\n * @throws Error if there are duplicate CTE names with different definitions\r\n */\r\n private resolveDuplicateNames(commonTables: CommonTable[]): CommonTable[] {\r\n // Group CTEs by their names\r\n const ctesByName = new Map<string, CommonTable[]>();\r\n for (const table of commonTables) {\r\n const tableName = table.aliasExpression.table.name;\r\n if (!ctesByName.has(tableName)) {\r\n ctesByName.set(tableName, []);\r\n }\r\n ctesByName.get(tableName)!.push(table);\r\n }\r\n\r\n // Resolve name duplications\r\n const resolvedTables: CommonTable[] = [];\r\n for (const [name, tables] of ctesByName.entries()) {\r\n if (tables.length === 1) {\r\n // No duplication\r\n resolvedTables.push(tables[0]);\r\n continue;\r\n }\r\n\r\n // For duplicate names, check if definitions are identical\r\n const definitions = tables.map(table => this.formatter.format(table.query));\r\n const uniqueDefinitions = new Set(definitions);\r\n\r\n if (uniqueDefinitions.size === 1) {\r\n // If all definitions are identical, use only the first one\r\n resolvedTables.push(tables[0]);\r\n } else {\r\n // Error if definitions differ\r\n throw new Error(`CTE name conflict detected: '${name}' has multiple different definitions`);\r\n }\r\n }\r\n\r\n return resolvedTables;\r\n }\r\n\r\n /**\r\n * Builds a dependency graph of CTEs and identifies recursive CTEs.\r\n * \r\n * @param tables The list of CTEs to analyze\r\n * @returns Object containing the table map, set of recursive CTEs, and dependency map\r\n */\r\n private buildDependencyGraph(tables: CommonTable[]): {\r\n tableMap: Map<string, CommonTable>,\r\n recursiveCTEs: Set<string>,\r\n dependencies: Map<string, Set<string>>\r\n } {\r\n // Create a map of table names for quick lookup\r\n const tableMap = new Map<string, CommonTable>();\r\n for (const table of tables) {\r\n tableMap.set(table.aliasExpression.table.name, table);\r\n }\r\n\r\n // Identify recursive CTEs (those that reference themselves)\r\n const recursiveCTEs = new Set<string>();\r\n\r\n // Build dependency graph: which tables reference which other tables\r\n const dependencies = new Map<string, Set<string>>();\r\n const referencedBy = new Map<string, Set<string>>();\r\n\r\n for (const table of tables) {\r\n const tableName = table.aliasExpression.table.name;\r\n\r\n // Check for self-references (recursive CTEs)\r\n const referencedTables = this.sourceCollector.collect(table.query);\r\n\r\n // Check if this CTE references itself\r\n for (const referencedTable of referencedTables) {\r\n if (referencedTable.table.name === tableName) {\r\n recursiveCTEs.add(tableName);\r\n break;\r\n }\r\n }\r\n\r\n // Setup dependencies\r\n if (!dependencies.has(tableName)) {\r\n dependencies.set(tableName, new Set<string>());\r\n }\r\n\r\n // Find any references to other CTEs in this table's query\r\n const referencedCTEs = this.cteCollector.collect(table.query);\r\n\r\n for (const referencedCTE of referencedCTEs) {\r\n const referencedName = referencedCTE.aliasExpression.table.name;\r\n\r\n // Only consider references to tables in our collection\r\n if (tableMap.has(referencedName)) {\r\n dependencies.get(tableName)!.add(referencedName);\r\n\r\n // Add the reverse relationship\r\n if (!referencedBy.has(referencedName)) {\r\n referencedBy.set(referencedName, new Set<string>());\r\n }\r\n referencedBy.get(referencedName)!.add(tableName);\r\n }\r\n }\r\n }\r\n\r\n return { tableMap, recursiveCTEs, dependencies };\r\n }\r\n\r\n /**\r\n * Sorts the CTEs using topological sort, with recursive CTEs coming first.\r\n * \r\n * @param tables The list of CTEs to sort\r\n * @param tableMap Map of table names to their CommonTable objects\r\n * @param recursiveCTEs Set of table names that are recursive (self-referential)\r\n * @param dependencies Map of table dependencies\r\n * @returns Sorted list of CTEs\r\n * @throws Error if a circular reference is detected\r\n */\r\n private sortCommonTables(\r\n tables: CommonTable[],\r\n tableMap: Map<string, CommonTable>,\r\n recursiveCTEs: Set<string>,\r\n dependencies: Map<string, Set<string>>\r\n ): CommonTable[] {\r\n const recursiveResult: CommonTable[] = [];\r\n const nonRecursiveResult: CommonTable[] = [];\r\n const visited = new Set<string>();\r\n const visiting = new Set<string>();\r\n\r\n // Topological sort function\r\n const visit = (tableName: string) => {\r\n if (visited.has(tableName)) return;\r\n if (visiting.has(tableName)) {\r\n throw new Error(`Circular reference detected in CTE: ${tableName}`);\r\n }\r\n\r\n visiting.add(tableName);\r\n\r\n // Process dependencies first (inner CTEs)\r\n const deps = dependencies.get(tableName) || new Set<string>();\r\n for (const dep of deps) {\r\n visit(dep);\r\n }\r\n\r\n visiting.delete(tableName);\r\n visited.add(tableName);\r\n\r\n // Add this table after its dependencies\r\n // Recursive CTEs go to recursiveResult, others to nonRecursiveResult\r\n if (recursiveCTEs.has(tableName)) {\r\n recursiveResult.push(tableMap.get(tableName)!);\r\n } else {\r\n nonRecursiveResult.push(tableMap.get(tableName)!);\r\n }\r\n };\r\n\r\n // Process all tables\r\n for (const table of tables) {\r\n const tableName = table.aliasExpression.table.name;\r\n if (!visited.has(tableName)) {\r\n visit(tableName);\r\n }\r\n }\r\n\r\n // Combine the results: recursive CTEs first, then non-recursive CTEs\r\n return [...recursiveResult, ...nonRecursiveResult];\r\n }\r\n}\r\n", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { CTEBuilder } from \"./CTEBuilder\";\r\n\r\n/**\r\n * CTEInjector accepts a SelectQuery object and an array of CommonTables,\r\n * and inserts Common Table Expressions into the query.\r\n * For BinarySelectQuery, CTEs are inserted into the left query.\r\n * \r\n * Uses CTENameConflictResolver to resolve naming conflicts between CTEs.\r\n */\r\nexport class CTEInjector {\r\n private nameConflictResolver: CTEBuilder;\r\n private cteCollector: CTECollector;\r\n\r\n constructor() {\r\n this.nameConflictResolver = new CTEBuilder();\r\n this.cteCollector = new CTECollector();\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into a SelectQuery object.\r\n * \r\n * @param query The query to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @returns A new query with the injected CTEs\r\n */\r\n public inject(query: SelectQuery, commonTables: CommonTable[]): SelectQuery {\r\n // If the array is empty, return the query as is\r\n if (commonTables.length === 0) {\r\n return query;\r\n }\r\n\r\n // Collect CTEs from the query\r\n commonTables.push(...this.cteCollector.collect(query));\r\n\r\n // Use CTENameConflictResolver to resolve duplicates and sort in appropriate order\r\n const resolvedWithCaluse = this.nameConflictResolver.build(commonTables);\r\n\r\n // Process based on query type\r\n if (query instanceof SimpleSelectQuery) {\r\n return this.injectIntoSimpleQuery(query, resolvedWithCaluse);\r\n } else if (query instanceof BinarySelectQuery) {\r\n return this.injectIntoBinaryQuery(query, resolvedWithCaluse);\r\n }\r\n\r\n // Unsupported query type\r\n throw new Error(\"Unsupported query type\");\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into a SimpleSelectQuery.\r\n * \r\n * @param query The SimpleSelectQuery to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @param needRecursive Boolean indicating if recursive WITH clause is needed\r\n * @returns A new SimpleSelectQuery with the injected CTEs\r\n */\r\n private injectIntoSimpleQuery(query: SimpleSelectQuery, withClause: WithClause): SimpleSelectQuery {\r\n if (query.withClause) {\r\n throw new Error(\"The query already has a WITH clause. Please remove it before injecting new CTEs.\");\r\n }\r\n // If the query doesn't have a WITH clause, set the new one\r\n query.withClause = withClause;\r\n return query;\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into the left query of a BinarySelectQuery.\r\n * \r\n * @param query The BinarySelectQuery to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @param needRecursive Boolean indicating if recursive WITH clause is needed\r\n * @returns A new BinarySelectQuery with the injected CTEs\r\n */\r\n private injectIntoBinaryQuery(query: BinarySelectQuery, withClause: WithClause): BinarySelectQuery {\r\n // Insert CTEs into the left query\r\n if (query.left instanceof SimpleSelectQuery) {\r\n this.injectIntoSimpleQuery(query.left, withClause);\r\n return query;\r\n } else if (query.left instanceof BinarySelectQuery) {\r\n this.injectIntoBinaryQuery(query.left, withClause);\r\n return query;\r\n }\r\n throw new Error(\"Unsupported query type for BinarySelectQuery left side\");\r\n }\r\n}\r\n", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableSourceCollector } from \"./TableSourceCollector\";\r\nimport { CTEDisabler } from \"./CTEDisabler\";\r\nimport { Formatter } from \"./Formatter\";\r\nimport { CTEBuilder } from \"./CTEBuilder\";\r\nimport { CTEInjector } from \"./CTEInjector\";\r\n\r\n/**\r\n * CTENormalizer is responsible for normalizing Common Table Expressions (CTEs) within SQL queries.\r\n * It collects all CTEs from various parts of the query and consolidates them into a single WITH clause\r\n * at the root level of the query.\r\n * \r\n * This implementation uses:\r\n * 1. CommonTableCollector - to gather all CTEs from the query structure\r\n * 2. WithClauseDisabler - to remove all original WITH clauses from the query\r\n * 3. CTENameConflictResolver - to resolve name conflicts among CTEs and sort them properly\r\n */\r\nexport class CTENormalizer {\r\n /**\r\n * Private constructor to prevent instantiation of this utility class.\r\n */\r\n private constructor() {\r\n // This class is not meant to be instantiated.\r\n }\r\n /**\r\n * Normalizes a SQL query by consolidating all CTEs into a single WITH clause\r\n * at the root level of the query.\r\n * \r\n * @param query The query to normalize\r\n * @returns A new normalized query with all CTEs at the root level\r\n */\r\n public static normalize(query: SelectQuery): SelectQuery {\r\n // No need to normalize if the query doesn't have any CTEs\r\n const cteCollector = new CTECollector();\r\n const allCommonTables = cteCollector.collect(query);\r\n\r\n if (allCommonTables.length === 0) {\r\n return query;\r\n }\r\n\r\n // Remove all WITH clauses from the original query\r\n const cteDisabler = new CTEDisabler();\r\n cteDisabler.execute(query);\r\n\r\n const injector = new CTEInjector();\r\n return injector.inject(query, allCommonTables);\r\n }\r\n}", "/**\r\n * Enum for duplicate detection modes in SelectableColumnCollector.\r\n * Determines how duplicates are identified during column collection.\r\n */\r\nexport enum DuplicateDetectionMode {\r\n /**\r\n * Detect duplicates based only on column names.\r\n * This mode ignores the table name, so columns with the same name\r\n * from different tables are considered duplicates.\r\n */\r\n ColumnNameOnly = 'columnNameOnly',\r\n /**\r\n * Detect duplicates based on both table and column names.\r\n * This mode ensures that columns with the same name from different\r\n * tables are treated as distinct.\r\n */\r\n FullName = 'fullName',\r\n}\r\nimport { CommonTable, ForClause, FromClause, GroupByClause, HavingClause, LimitClause, OrderByClause, SelectClause, WhereClause, WindowFrameClause, WindowsClause, JoinClause, JoinOnClause, JoinUsingClause, TableSource, SubQuerySource, SourceExpression, SelectItem, PartitionByClause, FetchClause, OffsetClause } from \"../models/Clause\";\r\nimport { SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression, UnaryExpression, ValueComponent, ValueList, WindowFrameExpression } from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { SelectValueCollector } from \"./SelectValueCollector\";\r\nimport { TableColumnResolver } from \"./TableColumnResolver\";\r\n\r\n/**\r\n * A visitor that collects all ColumnReference instances from a SQL query structure.\r\n * This visitor scans through all clauses and collects all unique ColumnReference objects.\r\n * It does not scan Common Table Expressions (CTEs) or subqueries.\r\n * \r\n * Important: Only collects column references to tables defined in the root FROM/JOIN clauses,\r\n * as these are the only columns that can be directly referenced in the query.\r\n */\r\nexport class SelectableColumnCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private selectValues: { name: string, value: ValueComponent }[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n private tableColumnResolver: TableColumnResolver | null = null;\r\n private commonTableCollector: CTECollector;\r\n private commonTables: CommonTable[] = [];\r\n private includeWildCard: boolean; // This option controls whether wildcard columns are included in the collection.\r\n private duplicateDetection: DuplicateDetectionMode;\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n\r\n /**\r\n * Creates a new instance of SelectableColumnCollector.\r\n *\r\n * @param {TableColumnResolver | null} [tableColumnResolver=null] - The resolver used to resolve column references to their respective tables.\r\n * @param {boolean} [includeWildCard=false] - If true, wildcard columns (e.g., `*`) are included in the collection.\r\n * @param {DuplicateDetectionMode} [duplicateDetection=DuplicateDetectionMode.ColumnNameOnly] - Specifies the duplicate detection mode: 'columnNameOnly' (default, only column name is used), or 'fullName' (table name + column name).\r\n * @param {Object} [options={}] - Additional options for the collector.\r\n * @param {boolean} [options.ignoreCaseAndUnderscore=false] - If true, column names are compared without considering case and underscores.\r\n */\r\n constructor(\r\n tableColumnResolver?: TableColumnResolver | null,\r\n includeWildCard: boolean = false,\r\n duplicateDetection: DuplicateDetectionMode = DuplicateDetectionMode.ColumnNameOnly,\r\n options?: { ignoreCaseAndUnderscore?: boolean }\r\n ) {\r\n this.tableColumnResolver = tableColumnResolver ?? null;\r\n this.includeWildCard = includeWildCard;\r\n this.commonTableCollector = new CTECollector();\r\n this.commonTables = [];\r\n this.duplicateDetection = duplicateDetection;\r\n this.options = options || {};\r\n\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Main entry point is the SimpleSelectQuery\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n\r\n // Handlers for each clause type that might contain column references\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.offsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n\r\n // Add handlers for JOIN conditions\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // For value components that might contain column references\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n }\r\n\r\n public getValues(): { name: string, value: ValueComponent }[] {\r\n return this.selectValues;\r\n }\r\n\r\n public collect(arg: SqlComponent): { name: string, value: ValueComponent }[] {\r\n // Visit the component and return the collected select items\r\n this.visit(arg);\r\n const items = this.getValues();\r\n this.reset(); // Reset after collection\r\n return items;\r\n }\r\n\r\n /**\r\n * Reset the collection of ColumnReferences\r\n */\r\n private reset(): void {\r\n this.selectValues = []\r\n this.visitedNodes.clear();\r\n this.commonTables = [];\r\n }\r\n\r\n /**\r\n * Add a select value as unique, according to the duplicate detection option.\r\n * If duplicateDetection is 'columnNameOnly', only column name is checked.\r\n * If duplicateDetection is 'fullName', both table and column name are checked.\r\n */\r\n private addSelectValueAsUnique(name: string, value: ValueComponent): void {\r\n if (this.duplicateDetection === DuplicateDetectionMode.ColumnNameOnly) {\r\n if (!this.selectValues.some(item => item.name === name)) {\r\n this.selectValues.push({ name, value });\r\n }\r\n } else if (this.duplicateDetection === DuplicateDetectionMode.FullName) {\r\n // Try to get table name from ValueComponent if possible\r\n let tableName = '';\r\n if (value && typeof (value as any).getNamespace === 'function') {\r\n tableName = (value as any).getNamespace() || '';\r\n }\r\n const key = tableName ? tableName + '.' + name : name;\r\n if (!this.selectValues.some(item => {\r\n let itemTable = '';\r\n if (item.value && typeof (item.value as any).getNamespace === 'function') {\r\n itemTable = (item.value as any).getNamespace() || '';\r\n }\r\n const itemKey = itemTable ? itemTable + '.' + item.name : item.name;\r\n return itemKey === key;\r\n })) {\r\n this.selectValues.push({ name, value });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n if (!(arg instanceof SimpleSelectQuery)) {\r\n throw new Error(\"Root visit must be a SimpleSelectQuery\");\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n this.commonTables = this.commonTableCollector.collect(arg);\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // For any other component types, we don't need to do anything\r\n }\r\n\r\n /**\r\n * Process a SimpleSelectQuery to collect ColumnReferences from all its clauses\r\n */\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // Visit all clauses that might contain column references\r\n if (query.selectClause) {\r\n query.selectClause.accept(this);\r\n }\r\n\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.offsetClause) {\r\n query.offsetClause.accept(this);\r\n }\r\n\r\n if (query.fetchClause) {\r\n query.fetchClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n // Explicitly NOT processing query.WithClause to avoid scanning CTEs\r\n }\r\n\r\n // Clause handlers\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n if (item.identifier) {\r\n this.addSelectValueAsUnique(item.identifier.name, item.value);\r\n }\r\n item.value.accept(this);\r\n }\r\n }\r\n\r\n private visitFromClause(clause: FromClause): void {\r\n // import source values\r\n const collector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const sourceValues = collector.collect(clause);\r\n for (const item of sourceValues) {\r\n // Add the select value as unique to avoid duplicates\r\n this.addSelectValueAsUnique(item.name, item.value);\r\n }\r\n\r\n if (clause.joins) {\r\n for (const join of clause.joins) {\r\n if (join.condition) {\r\n join.condition.accept(this);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private visitWhereClause(clause: WhereClause): void {\r\n if (clause.condition) {\r\n clause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n if (clause.grouping) {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n if (clause.condition) {\r\n clause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n if (clause.order) {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitWindowFrameExpression(expr: WindowFrameExpression): void {\r\n if (expr.partition) {\r\n expr.partition.accept(this);\r\n }\r\n if (expr.order) {\r\n expr.order.accept(this);\r\n }\r\n if (expr.frameSpec) {\r\n expr.frameSpec.accept(this);\r\n }\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n if (clause.value) {\r\n clause.value.accept(this);\r\n }\r\n }\r\n\r\n private offsetClause(clause: OffsetClause): void {\r\n if (clause.value) {\r\n clause.value.accept(this);\r\n }\r\n }\r\n\r\n private visitFetchClause(clause: FetchClause): void {\r\n if (clause.expression) {\r\n clause.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOnClause: JoinOnClause): void {\r\n // Visit the join condition\r\n if (joinOnClause.condition) {\r\n joinOnClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinUsingClause(joinUsingClause: JoinUsingClause): void {\r\n // Visit the columns in the USING clause\r\n if (joinUsingClause.condition) {\r\n joinUsingClause.condition.accept(this);\r\n }\r\n }\r\n\r\n // Value component handlers\r\n private visitColumnReference(columnRef: ColumnReference): void {\r\n if (columnRef.column.name !== \"*\") {\r\n this.addSelectValueAsUnique(columnRef.column.name, columnRef);\r\n } else if (!this.includeWildCard) {\r\n return;\r\n } else {\r\n this.addSelectValueAsUnique(columnRef.column.name, columnRef);\r\n }\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n // Visit both sides of the expression\r\n if (expr.left) {\r\n expr.left.accept(this);\r\n }\r\n if (expr.right) {\r\n expr.right.accept(this);\r\n }\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n\r\n if (expr.switchCase) {\r\n expr.switchCase.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n if (expr.input) {\r\n expr.input.accept(this);\r\n }\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n\r\n if (expr.lower) {\r\n expr.lower.accept(this);\r\n }\r\n\r\n if (expr.upper) {\r\n expr.upper.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitValueList(expr: ValueList): void {\r\n if (expr.values) {\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitPartitionByClause(clause: PartitionByClause): void {\r\n clause.value.accept(this);\r\n }\r\n}", "import { FullNameParser } from \"./FullNameParser\";\r\nimport { FunctionSource, SourceComponent, SubQuerySource, TableSource } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class SourceParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SourceComponent {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The source component is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parses only a TableSource from the given lexemes, regardless of the presence of parentheses after the identifier.\r\n * This method is specifically used for cases like INSERT queries (e.g., \"insert into table_name (col1, col2)\")\r\n * where a parenthesis immediately following the table name could otherwise be misinterpreted as a function call.\r\n * By using this method, the parser forcibly treats the source as a TableSource.\r\n *\r\n * @param lexemes The array of lexemes to parse.\r\n * @param index The starting index in the lexeme array.\r\n * @returns An object containing the parsed TableSource and the new index.\r\n */\r\n public static parseTableSourceFromLexemes(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, index);\r\n return this.parseTableSource(fullNameResult);\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Handle subquery\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n return this.parseParenSource(lexemes, idx);\r\n }\r\n\r\n // Retrieve the full name only once and reuse the result\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n\r\n // Handle function-based source (determine by lastTokenType)\r\n if (fullNameResult.lastTokenType & TokenType.Function) {\r\n // Also use fullNameResult as argument for parseFunctionSource\r\n return SourceParser.parseFunctionSource(lexemes, fullNameResult);\r\n }\r\n\r\n // Handle table source (regular table, potentially schema-qualified)\r\n return SourceParser.parseTableSource(fullNameResult);\r\n }\r\n\r\n private static parseTableSource(fullNameResult: { namespaces: string[] | null, name: any, newIndex: number }): { value: TableSource; newIndex: number } {\r\n const { namespaces, name, newIndex } = fullNameResult;\r\n const value = new TableSource(namespaces, name.name);\r\n return { value, newIndex };\r\n }\r\n\r\n private static parseFunctionSource(\r\n lexemes: Lexeme[],\r\n fullNameResult: { namespaces: string[] | null, name: any, newIndex: number }\r\n ): { value: FunctionSource; newIndex: number } {\r\n let idx = fullNameResult.newIndex;\r\n const { namespaces, name } = fullNameResult;\r\n\r\n const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = argument.newIndex;\r\n\r\n const functionName = name.name;\r\n const result = new FunctionSource({ namespaces: namespaces, name: functionName }, argument.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseParenSource(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n let idx = index;\r\n // skip the open parenthesis\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input at position ${idx}. Expected a subquery or nested expression after opening parenthesis.`);\r\n }\r\n\r\n // Support both SELECT and VALUES in subqueries\r\n const keyword = lexemes[idx].value;\r\n if (keyword === \"select\" || keyword === \"values\" || keyword === \"with\") {\r\n const result = this.parseSubQuerySource(lexemes, idx);\r\n idx = result.newIndex;\r\n if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {\r\n // skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n return { value: result.value, newIndex: idx };\r\n } else if (lexemes[idx].type == TokenType.OpenParen) {\r\n const result = this.parseParenSource(lexemes, idx);\r\n idx = result.newIndex;\r\n if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {\r\n // skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n return { value: result.value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword, 'VALUES' keyword, or opening parenthesis '(' but found \"${lexemes[idx].value}\".`);\r\n }\r\n\r\n private static parseSubQuerySource(lexemes: Lexeme[], index: number): { value: SubQuerySource; newIndex: number } {\r\n let idx = index;\r\n\r\n // Use the new parseFromLexeme method and destructure the result\r\n const { value: selectQuery, newIndex } = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = newIndex;\r\n\r\n const subQuerySource = new SubQuerySource(selectQuery);\r\n return { value: subQuerySource, newIndex: idx };\r\n }\r\n}\r\n", "import { SelectQuery, SimpleSelectQuery, BinarySelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CommonTable, SubQuerySource, TableSource, WithClause } from \"../models/Clause\";\r\nimport { SelectableColumnCollector } from \"./SelectableColumnCollector\";\r\nimport { CTECollector } from \"./CTECollector\";\r\n\r\n/**\r\n * UpstreamSelectQueryFinder searches upstream queries for the specified columns.\r\n * If a query (including its upstream CTEs or subqueries) contains all columns,\r\n * it returns the highest such SelectQuery. Otherwise, it searches downstream.\r\n * For UNION queries, it checks each branch independently.\r\n */\r\nexport class UpstreamSelectQueryFinder {\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n private tableColumnResolver?: (tableName: string) => string[];\r\n private columnCollector: SelectableColumnCollector;\r\n\r\n constructor(tableColumnResolver?: (tableName: string) => string[], options?: { ignoreCaseAndUnderscore?: boolean }) {\r\n this.options = options || {};\r\n this.tableColumnResolver = tableColumnResolver;\r\n // Pass the tableColumnResolver instead of options to fix type mismatch.\r\n this.columnCollector = new SelectableColumnCollector(this.tableColumnResolver);\r\n }\r\n\r\n /**\r\n * Finds the highest SelectQuery containing all specified columns.\r\n * @param query The root SelectQuery to search.\r\n * @param columnNames A column name or array of column names to check for.\r\n * @returns An array of SelectQuery objects, or an empty array if not found.\r\n */\r\n public find(query: SelectQuery, columnNames: string | string[]): SimpleSelectQuery[] {\r\n // Normalize columnNames to array\r\n const namesArray = typeof columnNames === 'string' ? [columnNames] : columnNames;\r\n // Use CTECollector to collect CTEs from the root query only once and reuse\r\n const cteCollector = new CTECollector();\r\n const ctes = cteCollector.collect(query);\r\n const cteMap: Map<string, CommonTable> = new Map();\r\n for (const cte of ctes) {\r\n cteMap.set(cte.getSourceAliasName(), cte);\r\n }\r\n return this.findUpstream(query, namesArray, cteMap);\r\n }\r\n\r\n private handleTableSource(src: TableSource, columnNames: string[], cteMap: Map<string, CommonTable>): SimpleSelectQuery[] | null {\r\n // Handles the logic for TableSource in findUpstream\r\n const cte = cteMap.get(src.table.name);\r\n if (cte) {\r\n // Remove the current CTE name from the map to prevent infinite recursion\r\n const nextCteMap = new Map(cteMap);\r\n nextCteMap.delete(src.table.name);\r\n const result = this.findUpstream(cte.query, columnNames, nextCteMap);\r\n if (result.length === 0) {\r\n return null;\r\n }\r\n return result;\r\n }\r\n return null;\r\n }\r\n\r\n private handleSubQuerySource(src: SubQuerySource, columnNames: string[], cteMap: Map<string, WithClause[\"tables\"][number]>): SimpleSelectQuery[] | null {\r\n // Handles the logic for SubQuerySource in findUpstream\r\n const result = this.findUpstream(src.query, columnNames, cteMap);\r\n if (result.length === 0) {\r\n return null;\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Processes all source branches in a FROM clause and checks if all upstream queries contain the specified columns.\r\n * Returns a flat array of SelectQuery if all branches are valid, otherwise null.\r\n */\r\n private processFromClauseBranches(\r\n fromClause: any,\r\n columnNames: string[],\r\n cteMap: Map<string, CommonTable>\r\n ): SimpleSelectQuery[] | null {\r\n const sources = fromClause.getSources();\r\n if (sources.length === 0) return null;\r\n\r\n let allBranchResults: SimpleSelectQuery[][] = [];\r\n let allBranchesOk = true;\r\n let validBranchCount = 0; // Count only filterable branches\r\n\r\n for (const sourceExpr of sources) {\r\n const src = sourceExpr.datasource;\r\n let branchResult: SimpleSelectQuery[] | null = null;\r\n if (src instanceof TableSource) {\r\n branchResult = this.handleTableSource(src, columnNames, cteMap);\r\n validBranchCount++;\r\n } else if (src instanceof SubQuerySource) {\r\n branchResult = this.handleSubQuerySource(src, columnNames, cteMap);\r\n validBranchCount++;\r\n } else if (src instanceof ValuesQuery) {\r\n // Skip ValuesQuery: not filterable, do not count as a valid branch\r\n continue;\r\n } else {\r\n allBranchesOk = false;\r\n break;\r\n }\r\n\r\n // If the branch result is null, \r\n // it means it didn't find the required columns in this branch\r\n if (branchResult === null) {\r\n allBranchesOk = false;\r\n break;\r\n }\r\n allBranchResults.push(branchResult);\r\n }\r\n\r\n // Check if all valid (filterable) branches are valid and contain the required columns\r\n if (allBranchesOk && allBranchResults.length === validBranchCount) {\r\n return allBranchResults.flat();\r\n }\r\n return null;\r\n }\r\n\r\n private findUpstream(query: SelectQuery, columnNames: string[], cteMap: Map<string, CommonTable>): SimpleSelectQuery[] {\r\n if (query instanceof SimpleSelectQuery) {\r\n const fromClause = query.fromClause;\r\n if (fromClause) {\r\n const branchResult = this.processFromClauseBranches(fromClause, columnNames, cteMap);\r\n if (branchResult) {\r\n return branchResult;\r\n }\r\n }\r\n const columns = this.columnCollector.collect(query).map(col => col.name);\r\n const normalize = (s: string) =>\r\n this.options.ignoreCaseAndUnderscore ? s.toLowerCase().replace(/_/g, '') : s;\r\n // Normalize both the columns and the required names for comparison.\r\n const hasAll = columnNames.every(name => columns.some(col => normalize(col) === normalize(name)));\r\n if (hasAll) {\r\n return [query];\r\n }\r\n return [];\r\n } else if (query instanceof BinarySelectQuery) {\r\n const left = this.findUpstream(query.left, columnNames, cteMap);\r\n const right = this.findUpstream(query.right, columnNames, cteMap);\r\n return [...left, ...right];\r\n }\r\n return [];\r\n }\r\n}\r\n", "import { SourceAliasExpression } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\n\r\n\r\nexport class SourceAliasExpressionParser {\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceAliasExpression; newIndex: number; } {\r\n let idx = index;\r\n\r\n // If there is a column alias, it may be detected as a function, so functions are also processed.\r\n if (idx < lexemes.length && ((lexemes[idx].type & TokenType.Identifier) || (lexemes[idx].type & TokenType.Function))) {\r\n // Check for alias\r\n const table = lexemes[idx].value;\r\n idx++;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n // Check for column alias\r\n const columns: string[] = [];\r\n\r\n // Skip the open parenthesis\r\n idx++;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Identifier)) {\r\n columns.push(lexemes[idx].value);\r\n idx++;\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n } else {\r\n break; // Exit loop if not a comma\r\n }\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.CloseParen) {\r\n // Skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for column alias list. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n if (columns.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No column aliases found. Column alias declarations must contain at least one column name.`);\r\n }\r\n\r\n return { value: new SourceAliasExpression(table, columns), newIndex: idx };\r\n }\r\n\r\n return { value: new SourceAliasExpression(table, null), newIndex: idx };\r\n }\r\n\r\n throw new Error(`Syntax error at position ${index}: Expected an identifier for table alias but found \"${lexemes[index]?.value || 'end of input'}\".`);\r\n }\r\n}\r\n", "import { SourceAliasExpression, SourceExpression, TableSource } from \"../models/Clause\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SourceParser } from \"./SourceParser\";\r\nimport { SourceAliasExpressionParser } from \"./SourceAliasExpressionParser\";\r\n\r\nexport class SourceExpressionParser {\r\n /**\r\n * Parse SQL string to SourceExpression (e.g. \"table\", \"table as t\", \"schema.table t\")\r\n */\r\n public static parse(query: string): SourceExpression {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The source expression is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n public static parseTableSourceFromLexemes(lexemes: Lexeme[], index: number): { value: SourceExpression; newIndex: number } {\r\n const result = SourceParser.parseTableSourceFromLexemes(lexemes, index);\r\n // No alias for table source\r\n const sourceExpr = new SourceExpression(result.value, null);\r\n return { value: sourceExpr, newIndex: result.newIndex };\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceExpression; newIndex: number; } {\r\n let idx = index;\r\n\r\n const sourceResult = SourceParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n if (idx < lexemes.length) {\r\n if (lexemes[idx].value === \"as\") {\r\n idx++;\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);\r\n return { value: sourceExpr, newIndex: idx };\r\n }\r\n\r\n /**\r\n * Explanation:\r\n * Source aliases are typically identified as TokenType.Identifier.\r\n * However, when the 'AS' keyword is omitted and column alias names are specified,\r\n * they may sometimes be classified as TokenType.Function.\r\n * Since the TokenReader's responsibility is to perform coarse-grained classification,\r\n * the parser must interpret subsequent 'Function' tokens as source alias expressions\r\n * when they follow a source definition.\r\n * Example:\r\n * SQL: select t.* from (values(1)) t(id)\r\n * Explanation: The alias 't' and its column alias 'id' are parsed as a source alias expression.\r\n */\r\n if (idx < lexemes.length && this.isTokenTypeAliasCandidate(lexemes[idx].type)) {\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);\r\n return { value: sourceExpr, newIndex: idx };\r\n }\r\n }\r\n\r\n // no alias\r\n const expr = new SourceExpression(sourceResult.value, null);\r\n return { value: expr, newIndex: idx };\r\n }\r\n\r\n private static isTokenTypeAliasCandidate(type: number): boolean {\r\n return (type & TokenType.Identifier) !== 0 || (type & TokenType.Function) !== 0;\r\n }\r\n}\r\n", "import { SetClause, SetClauseItem, FromClause, WhereClause, SelectClause, SelectItem, SourceAliasExpression, SourceExpression, SubQuerySource, WithClause, TableSource, UpdateClause, InsertClause } from '../models/Clause';\r\nimport { UpdateQuery } from '../models/UpdateQuery';\r\nimport { BinaryExpression, ColumnReference } from '../models/ValueComponent';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { CTENormalizer } from \"./CTENormalizer\";\r\nimport { CreateTableQuery } from \"../models/CreateTableQuery\";\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { CTEDisabler } from './CTEDisabler';\r\nimport { SourceExpressionParser } from '../parsers/SourceExpressionParser';\r\n\r\n/**\r\n * QueryBuilder provides static methods to build or convert various SQL query objects.\r\n */\r\nexport class QueryBuilder {\r\n /**\r\n * Builds a BinarySelectQuery by combining an array of SelectQuery using the specified operator.\r\n * Throws if less than two queries are provided.\r\n * @param queries Array of SelectQuery to combine\r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @returns BinarySelectQuery\r\n */\r\n public static buildBinaryQuery(queries: SelectQuery[], operator: string): BinarySelectQuery {\r\n if (!queries || queries.length === 0) {\r\n throw new Error(\"No queries provided to combine.\");\r\n }\r\n if (queries.length === 1) {\r\n throw new Error(\"At least two queries are required to create a BinarySelectQuery.\");\r\n }\r\n\r\n // Always create a new BinarySelectQuery instance (never mutate input)\r\n const wrap = (q: SelectQuery) => q instanceof ValuesQuery ? QueryBuilder.buildSimpleQuery(q) : q;\r\n let result: BinarySelectQuery = new BinarySelectQuery(wrap(queries[0]), operator, wrap(queries[1]));\r\n CTENormalizer.normalize(result);\r\n\r\n for (let i = 2; i < queries.length; i++) {\r\n result.appendSelectQuery(operator, wrap(queries[i]));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private constructor() {\r\n // This class is not meant to be instantiated.\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to a standard SimpleSelectQuery form.\r\n * @param query The query to convert\r\n * @returns A SimpleSelectQuery\r\n */\r\n public static buildSimpleQuery(query: SelectQuery): SimpleSelectQuery {\r\n if (query instanceof SimpleSelectQuery) {\r\n return query;\r\n }\r\n else if (query instanceof BinarySelectQuery) {\r\n return QueryBuilder.buildSimpleBinaryQuery(query);\r\n }\r\n else if (query instanceof ValuesQuery) {\r\n return QueryBuilder.buildSimpleValuesQuery(query);\r\n }\r\n throw new Error(\"Unsupported query type for buildSimpleQuery\");\r\n }\r\n\r\n private static buildSimpleBinaryQuery(query: BinarySelectQuery): SimpleSelectQuery {\r\n // Create a subquery source from the binary query\r\n const subQuerySource = new SubQuerySource(query);\r\n\r\n // Create a source expression with alias\r\n const sourceExpr = new SourceExpression(\r\n subQuerySource,\r\n new SourceAliasExpression(\"bq\", null)\r\n );\r\n\r\n // Create FROM clause with the source expression\r\n const fromClause = new FromClause(sourceExpr, null);\r\n\r\n // Create SELECT clause with * (all columns)\r\n const selectClause = QueryBuilder.createSelectAllClause();\r\n\r\n // Create the final simple select query\r\n const q = new SimpleSelectQuery(\r\n {\r\n selectClause,\r\n fromClause\r\n }\r\n );\r\n\r\n return CTENormalizer.normalize(q) as SimpleSelectQuery;\r\n }\r\n\r\n /**\r\n * Converts a ValuesQuery to a SimpleSelectQuery with sequentially numbered columns or user-specified columns\r\n * \r\n * @param query The VALUES query to convert\r\n * @param columns Optional: column names\r\n * @returns A SimpleSelectQuery\r\n */\r\n private static buildSimpleValuesQuery(query: ValuesQuery): SimpleSelectQuery {\r\n // Figure out how many columns are in the VALUES clause\r\n const columnCount = query.tuples.length > 0 ? query.tuples[0].values.length : 0;\r\n if (query.tuples.length === 0) {\r\n throw new Error(\"Empty VALUES clause cannot be converted to a SimpleSelectQuery\");\r\n }\r\n if (!query.columnAliases) {\r\n throw new Error(\"Column aliases are required to convert a VALUES clause to SimpleSelectQuery. Please specify column aliases.\");\r\n }\r\n if (query.columnAliases.length !== columnCount) {\r\n throw new Error(`The number of column aliases (${query.columnAliases.length}) does not match the number of columns in the first tuple (${columnCount}).`);\r\n }\r\n\r\n // Create a subquery source from the VALUES query\r\n const subQuerySource = new SubQuerySource(query);\r\n const sourceExpr = new SourceExpression(\r\n subQuerySource,\r\n new SourceAliasExpression(\"vq\", query.columnAliases)\r\n );\r\n\r\n // Create FROM clause with the source expression\r\n const fromClause = new FromClause(sourceExpr, null);\r\n\r\n // Create SELECT clause with all columns\r\n const selectItems = query.columnAliases.map(name => new SelectItem(new ColumnReference(\"vq\", name), name));\r\n const selectClause = new SelectClause(selectItems, null);\r\n\r\n // Create the final simple select query\r\n return new SimpleSelectQuery(\r\n {\r\n selectClause,\r\n fromClause\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Creates a SELECT clause with a single * (all columns) item\r\n * \r\n * @returns A SELECT clause with *\r\n */\r\n private static createSelectAllClause(): SelectClause {\r\n // Create a column reference for *\r\n const columnRef = new ColumnReference(null, \"*\");\r\n\r\n // Create a SelectItem with the column reference\r\n const selectItem = new SelectItem(columnRef, \"*\");\r\n\r\n // Create and return a SelectClause with the item\r\n return new SelectClause([selectItem], null);\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to a CREATE TABLE query (CREATE [TEMPORARY] TABLE ... AS SELECT ...)\r\n * @param query The SELECT query to use as the source\r\n * @param tableName The name of the table to create\r\n * @param isTemporary If true, creates a temporary table\r\n * @returns A CreateTableQuery instance\r\n */\r\n public static buildCreateTableQuery(query: SelectQuery, tableName: string, isTemporary: boolean = false): CreateTableQuery {\r\n return new CreateTableQuery({\r\n tableName,\r\n isTemporary,\r\n asSelectQuery: query\r\n });\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to an INSERT query (INSERT INTO ... SELECT ...)\r\n * @param selectQuery The SELECT query to use as the source\r\n * @param tableName The name of the table to insert into\r\n * @param columns Optional: array of column names. If omitted, columns are inferred from the selectQuery\r\n * @returns An InsertQuery instance\r\n */\r\n public static buildInsertQuery(selectQuery: SimpleSelectQuery, tableName: string): InsertQuery {\r\n let cols: string[];\r\n\r\n const count = selectQuery.selectClause.items.length;\r\n\r\n // Try to infer columns from the selectQuery\r\n const collector = new SelectValueCollector();\r\n const items = collector.collect(selectQuery);\r\n cols = items.map(item => item.name);\r\n if (!cols.length || count !== cols.length) {\r\n throw new Error(\r\n `Columns cannot be inferred from the selectQuery. ` +\r\n `Make sure you are not using wildcards or unnamed columns.\\n` +\r\n `Select clause column count: ${count}, ` +\r\n `Columns with valid names: ${cols.length}\\n` +\r\n `Detected column names: [${cols.join(\", \")}]`\r\n );\r\n }\r\n\r\n // Generate SourceExpression (supports only table name, does not support alias or schema)\r\n const sourceExpr = SourceExpressionParser.parse(tableName);\r\n return new InsertQuery({\r\n insertClause: new InsertClause(sourceExpr, cols),\r\n selectQuery: selectQuery\r\n });\r\n }\r\n\r\n /**\r\n * Builds an UPDATE query from a SELECT query, table name, and primary key(s).\r\n * @param selectQuery The SELECT query providing new values (must select all columns to update and PKs)\r\n * @param updateTableExprRaw The table name to update\r\n * @param primaryKeys The primary key column name(s)\r\n * @returns UpdateQuery instance\r\n */\r\n public static buildUpdateQuery(selectQuery: SimpleSelectQuery, selectSourceName: string, updateTableExprRaw: string, primaryKeys: string | string[]) {\r\n const updateClause = new UpdateClause(SourceExpressionParser.parse(updateTableExprRaw));\r\n\r\n const pkArray = Array.isArray(primaryKeys) ? primaryKeys : [primaryKeys];\r\n const selectCollector = new SelectValueCollector();\r\n const selectItems = selectCollector.collect(selectQuery);\r\n\r\n const cteCollector = new CTECollector();\r\n const collectedCTEs = cteCollector.collect(selectQuery);\r\n const cteDisabler = new CTEDisabler();\r\n cteDisabler.execute(selectQuery);\r\n\r\n for (const pk of pkArray) {\r\n if (!selectItems.some(item => item.name === pk)) {\r\n throw new Error(`Primary key column '${pk}' is not present in selectQuery select list.`);\r\n }\r\n }\r\n\r\n const updateSourceName = updateClause.getSourceAliasName();\r\n if (!updateSourceName) {\r\n throw new Error(`Source expression does not have an alias. Please provide an alias for the source expression.`);\r\n }\r\n\r\n const setColumns = selectItems.filter(item => !pkArray.includes(item.name));\r\n const setItems = setColumns.map(col => new SetClauseItem(col.name, new ColumnReference(updateSourceName, col.name)));\r\n const setClause = new SetClause(setItems);\r\n\r\n const from = new FromClause(selectQuery.toSource(selectSourceName), null);\r\n\r\n let where: BinaryExpression | null = null;\r\n for (const pk of pkArray) {\r\n const cond = new BinaryExpression(\r\n new ColumnReference(updateSourceName, pk),\r\n '=',\r\n new ColumnReference(selectSourceName, pk)\r\n );\r\n where = where ? new BinaryExpression(where, 'and', cond) : cond;\r\n }\r\n const whereClause = new WhereClause(where!);\r\n\r\n const updateQuery = new UpdateQuery({\r\n updateClause: updateClause,\r\n setClause: setClause,\r\n fromClause: from,\r\n whereClause: whereClause,\r\n withClause: collectedCTEs.length > 0 ? new WithClause(false, collectedCTEs) : undefined,\r\n });\r\n return updateQuery;\r\n }\r\n}\r\n", "import { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { SqlComponent } from \"../models/SqlComponent\";\r\n\r\n/**\r\n * Utility class for parameter operations on SQL queries.\r\n */\r\nexport class ParameterHelper {\r\n /**\r\n * Sets the value of a parameter by name in the given query.\r\n * Throws an error if the parameter is not found.\r\n * @param query The query object (must be a SqlComponent)\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public static set(query: SqlComponent, name: string, value: any): void {\r\n const params = ParameterCollector.collect(query);\r\n\r\n let found = false;\r\n for (const p of params) {\r\n if (p.name.value === name) {\r\n p.value = value;\r\n found = true;\r\n }\r\n }\r\n\r\n if (!found) {\r\n throw new Error(`Parameter '${name}' not found in query.`);\r\n }\r\n }\r\n}\r\n", "import { SqlComponent } from \"./SqlComponent\";\r\nimport { ForClause, FromClause, GroupByClause, HavingClause, JoinClause, JoinOnClause, LimitClause, OrderByClause, SelectClause, SourceExpression, SubQuerySource, SourceAliasExpression, WhereClause, WindowsClause as WindowClause, WithClause, CommonTable, OffsetClause, FetchClause } from \"./Clause\";\r\nimport { BinaryExpression, ColumnReference, ValueComponent } from \"./ValueComponent\";\r\nimport { ValueParser } from \"../parsers/ValueParser\";\r\nimport { CTENormalizer } from \"../transformers/CTENormalizer\";\r\nimport { SelectableColumnCollector } from \"../transformers/SelectableColumnCollector\";\r\nimport { SourceParser } from \"../parsers/SourceParser\";\r\nimport { BinarySelectQuery } from \"./BinarySelectQuery\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\nimport { Formatter } from \"../transformers/Formatter\";\r\nimport { TableColumnResolver } from \"../transformers/TableColumnResolver\";\r\nimport { UpstreamSelectQueryFinder } from \"../transformers/UpstreamSelectQueryFinder\";\r\nimport { QueryBuilder } from \"../transformers/QueryBuilder\";\r\nimport { ParameterHelper } from \"../utils/ParameterHelper\";\r\n\r\n/**\r\n * Represents a simple SELECT query in SQL.\r\n */\r\nexport class SimpleSelectQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"SelectQuery\");\r\n withClause: WithClause | null;\r\n selectClause: SelectClause;\r\n fromClause: FromClause | null;\r\n whereClause: WhereClause | null;\r\n groupByClause: GroupByClause | null;\r\n havingClause: HavingClause | null;\r\n orderByClause: OrderByClause | null;\r\n windowClause: WindowClause | null;\r\n limitClause: LimitClause | null;\r\n offsetClause: OffsetClause | null;\r\n fetchClause: FetchClause | null;\r\n forClause: ForClause | null;\r\n\r\n constructor(params: {\r\n selectClause: SelectClause,\r\n fromClause?: FromClause | null,\r\n whereClause?: WhereClause | null,\r\n groupByClause?: GroupByClause | null,\r\n havingClause?: HavingClause | null,\r\n orderByClause?: OrderByClause | null,\r\n windowClause?: WindowClause | null,\r\n limitClause?: LimitClause | null,\r\n offsetClause?: OffsetClause | null,\r\n fetchClause?: FetchClause | null,\r\n forClause?: ForClause | null,\r\n withClause?: WithClause | null,\r\n }) {\r\n super();\r\n this.withClause = params.withClause ?? null;\r\n this.selectClause = params.selectClause;\r\n this.fromClause = params.fromClause ?? null;\r\n this.whereClause = params.whereClause ?? null;\r\n this.groupByClause = params.groupByClause ?? null;\r\n this.havingClause = params.havingClause ?? null;\r\n this.orderByClause = params.orderByClause ?? null;\r\n this.windowClause = params.windowClause ?? null;\r\n this.limitClause = params.limitClause ?? null;\r\n this.offsetClause = params.offsetClause ?? null;\r\n this.fetchClause = params.fetchClause ?? null;\r\n this.forClause = params.forClause ?? null;\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using UNION as the operator.\r\n * \r\n * @param rightQuery The right side of the UNION\r\n * @returns A new BinarySelectQuery representing \"this UNION rightQuery\"\r\n */\r\n public toUnion(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('union', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using UNION ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the UNION ALL\r\n * @returns A new BinarySelectQuery representing \"this UNION ALL rightQuery\"\r\n */\r\n public toUnionAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('union all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using INTERSECT as the operator.\r\n * \r\n * @param rightQuery The right side of the INTERSECT\r\n * @returns A new BinarySelectQuery representing \"this INTERSECT rightQuery\"\r\n */\r\n public toIntersect(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('intersect', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using INTERSECT ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the INTERSECT ALL\r\n * @returns A new BinarySelectQuery representing \"this INTERSECT ALL rightQuery\"\r\n */\r\n public toIntersectAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('intersect all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using EXCEPT as the operator.\r\n * \r\n * @param rightQuery The right side of the EXCEPT\r\n * @returns A new BinarySelectQuery representing \"this EXCEPT rightQuery\"\r\n */\r\n public toExcept(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('except', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using EXCEPT ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the EXCEPT ALL\r\n * @returns A new BinarySelectQuery representing \"this EXCEPT ALL rightQuery\"\r\n */\r\n public toExceptAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('except all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using the specified operator.\r\n * \r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @param rightQuery The right side of the binary operation\r\n * @returns A new BinarySelectQuery representing \"this [operator] rightQuery\"\r\n */\r\n public toBinaryQuery(operator: string, rightQuery: SelectQuery): BinarySelectQuery {\r\n return QueryBuilder.buildBinaryQuery([this, rightQuery], operator);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's WHERE clause using AND logic.\r\n * The condition is provided as a raw SQL string which is parsed internally.\r\n * \r\n * @param rawCondition Raw SQL string representing the condition (e.g. \"status = 'active'\")\r\n */\r\n public appendWhereRaw(rawCondition: string): void {\r\n const parsedCondition = ValueParser.parse(rawCondition);\r\n this.appendWhere(parsedCondition);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's WHERE clause using AND logic.\r\n * The condition is provided as a ValueComponent object.\r\n * \r\n * @param condition ValueComponent representing the condition\r\n */\r\n public appendWhere(condition: ValueComponent): void {\r\n if (!this.whereClause) {\r\n this.whereClause = new WhereClause(condition);\r\n } else {\r\n this.whereClause.condition = new BinaryExpression(\r\n this.whereClause.condition,\r\n 'and',\r\n condition\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's HAVING clause using AND logic.\r\n * The condition is provided as a raw SQL string which is parsed internally.\r\n * \r\n * @param rawCondition Raw SQL string representing the condition (e.g. \"count(*) > 5\")\r\n */\r\n public appendHavingRaw(rawCondition: string): void {\r\n const parsedCondition = ValueParser.parse(rawCondition);\r\n this.appendHaving(parsedCondition);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's HAVING clause using AND logic.\r\n * The condition is provided as a ValueComponent object.\r\n * \r\n * @param condition ValueComponent representing the condition\r\n */\r\n public appendHaving(condition: ValueComponent): void {\r\n if (!this.havingClause) {\r\n this.havingClause = new HavingClause(condition);\r\n } else {\r\n this.havingClause.condition = new BinaryExpression(\r\n this.havingClause.condition,\r\n 'and',\r\n condition\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Appends an INNER JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join (e.g., \"my_table\", \"schema.my_table\")\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition (e.g. [\"user_id\"] or \"user_id\")\r\n */\r\n public innerJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('inner join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a LEFT JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition\r\n */\r\n public leftJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('left join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a RIGHT JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition\r\n */\r\n public rightJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('right join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends an INNER JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public innerJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('inner join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a LEFT JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public leftJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('left join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a RIGHT JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public rightJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('right join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Internal helper to append a JOIN clause.\r\n * Parses the table source, finds the corresponding columns in the existing query context,\r\n * and builds the JOIN condition.\r\n * @param joinType Type of join (e.g., 'inner join', 'left join')\r\n * @param joinSourceRawText Raw text for the table/source to join (e.g., \"my_table\", \"schema.another_table\")\r\n * @param alias Alias for the table/source being joined\r\n * @param columns Array or string of column names to join on\r\n */\r\n private joinSourceRaw(joinType: string, joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n const tableSource = SourceParser.parse(joinSourceRawText);\r\n const sourceExpr = new SourceExpression(tableSource, new SourceAliasExpression(alias, null));\r\n this.joinSource(joinType, sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Internal helper to append a JOIN clause using a SourceExpression.\r\n * @param joinType Type of join (e.g., 'inner join', 'left join')\r\n * @param sourceExpr The source expression to join\r\n * @param columns Array or string of column names to join on\r\n */\r\n private joinSource(joinType: string, sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n if (!this.fromClause) {\r\n throw new Error('A FROM clause is required to add a JOIN condition.');\r\n }\r\n\r\n // Always treat columns as array\r\n const columnsArr = Array.isArray(columns) ? columns : [columns];\r\n\r\n const collector = new SelectableColumnCollector(resolver);\r\n const valueSets = collector.collect(this);\r\n let joinCondition: ValueComponent | null = null;\r\n let count = 0;\r\n\r\n const sourceAlias = sourceExpr.getAliasName();\r\n if (!sourceAlias) {\r\n throw new Error('An alias is required for the source expression to add a JOIN condition.');\r\n }\r\n\r\n for (const valueSet of valueSets) {\r\n if (columnsArr.some(col => col == valueSet.name)) {\r\n const expr = new BinaryExpression(\r\n valueSet.value,\r\n '=',\r\n new ColumnReference([sourceAlias], valueSet.name)\r\n );\r\n if (joinCondition) {\r\n joinCondition = new BinaryExpression(\r\n joinCondition,\r\n 'and',\r\n expr\r\n );\r\n } else {\r\n joinCondition = expr;\r\n }\r\n count++;\r\n }\r\n }\r\n\r\n if (!joinCondition || count !== columnsArr.length) {\r\n throw new Error(`Invalid JOIN condition. The specified columns were not found: ${columnsArr.join(', ')}`);\r\n }\r\n\r\n const joinOnClause = new JoinOnClause(joinCondition);\r\n const joinClause = new JoinClause(joinType, sourceExpr, joinOnClause, false);\r\n\r\n if (this.fromClause) {\r\n if (this.fromClause.joins) {\r\n this.fromClause.joins.push(joinClause);\r\n } else {\r\n this.fromClause.joins = [joinClause];\r\n }\r\n }\r\n\r\n CTENormalizer.normalize(this);\r\n }\r\n\r\n // Returns a SourceExpression wrapping this query as a subquery source.\r\n // Alias is required for correct SQL generation and join logic.\r\n public toSource(alias: string): SourceExpression {\r\n if (!alias || alias.trim() === \"\") {\r\n throw new Error(\"Alias is required for toSource(). Please specify a non-empty alias name.\");\r\n }\r\n return new SourceExpression(\r\n new SubQuerySource(this),\r\n new SourceAliasExpression(alias, null)\r\n );\r\n }\r\n\r\n public appendWith(commonTable: CommonTable | CommonTable[]): void {\r\n // Always treat as array for simplicity\r\n const tables = Array.isArray(commonTable) ? commonTable : [commonTable];\r\n if (!this.withClause) {\r\n this.withClause = new WithClause(false, tables);\r\n } else {\r\n this.withClause.tables.push(...tables);\r\n }\r\n\r\n CTENormalizer.normalize(this);\r\n }\r\n\r\n /**\r\n * Appends a CommonTable (CTE) to the WITH clause from raw SQL text and alias.\r\n * If alias is provided, it will be used as the CTE name.\r\n *\r\n * @param rawText Raw SQL string representing the CTE body (e.g. '(SELECT ...)')\r\n * @param alias Optional alias for the CTE (e.g. 'cte_name')\r\n */\r\n public appendWithRaw(rawText: string, alias: string): void {\r\n const query = SelectQueryParser.parse(rawText);\r\n const commonTable = new CommonTable(query, alias, null);\r\n this.appendWith(commonTable);\r\n }\r\n\r\n /**\r\n * Overrides a select item using a template literal function.\r\n * The callback receives the SQL string of the original expression and must return a new SQL string.\r\n * The result is parsed and set as the new select item value.\r\n *\r\n * Example usage:\r\n * query.overrideSelectItemRaw(\"journal_date\", expr => `greatest(${expr}, DATE '2025-01-01')`)\r\n *\r\n * @param columnName The name of the column to override\r\n * @param fn Callback that receives the SQL string of the original expression and returns a new SQL string\r\n */\r\n public overrideSelectItemExpr(columnName: string, fn: (expr: string) => string): void {\r\n const items = this.selectClause.items.filter(item => item.identifier?.name === columnName);\r\n if (items.length === 0) {\r\n throw new Error(`Column ${columnName} not found in the query`);\r\n }\r\n if (items.length > 1) {\r\n throw new Error(`Duplicate column name ${columnName} found in the query`);\r\n }\r\n const item = items[0];\r\n const formatter = new Formatter();\r\n const exprSql = formatter.visit(item.value);\r\n const newValue = fn(exprSql);\r\n item.value = ValueParser.parse(newValue);\r\n }\r\n\r\n /**\r\n * Appends a WHERE clause using the expression for the specified column.\r\n * If `options.upstream` is true, applies to all upstream queries containing the column.\r\n * If false or omitted, applies only to the current query.\r\n *\r\n * @param columnName The name of the column to target.\r\n * @param exprBuilder Function that receives the column expression as a string and returns the WHERE condition string.\r\n * @param options Optional settings. If `upstream` is true, applies to upstream queries.\r\n */\r\n public appendWhereExpr(\r\n columnName: string,\r\n exprBuilder: (expr: string) => string,\r\n options?: { upstream?: boolean }\r\n ): void {\r\n // If upstream option is true, find all upstream queries containing the column\r\n if (options && options.upstream) {\r\n // Use UpstreamSelectQueryFinder to find all relevant queries\r\n // (Assume UpstreamSelectQueryFinder is imported)\r\n const finder = new UpstreamSelectQueryFinder();\r\n const queries = finder.find(this, [columnName]);\r\n const collector = new SelectableColumnCollector();\r\n const formatter = new Formatter();\r\n for (const q of queries) {\r\n const exprs = collector.collect(q).filter(item => item.name === columnName).map(item => item.value);\r\n if (exprs.length !== 1) {\r\n throw new Error(`Expected exactly one expression for column '${columnName}'`);\r\n }\r\n const exprStr = formatter.format(exprs[0]);\r\n q.appendWhereRaw(exprBuilder(exprStr));\r\n }\r\n } else {\r\n // Only apply to the current query\r\n const collector = new SelectableColumnCollector();\r\n const formatter = new Formatter();\r\n const exprs = collector.collect(this).filter(item => item.name === columnName).map(item => item.value);\r\n if (exprs.length !== 1) {\r\n throw new Error(`Expected exactly one expression for column '${columnName}'`);\r\n }\r\n const exprStr = formatter.format(exprs[0]);\r\n this.appendWhereRaw(exprBuilder(exprStr));\r\n }\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { SourceExpression, SubQuerySource, SourceAliasExpression } from \"./Clause\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { RawString } from \"./ValueComponent\";\r\nimport { CTENormalizer } from \"../transformers/CTENormalizer\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { ParameterHelper } from \"../utils/ParameterHelper\";\r\n\r\n/**\r\n * Represents a binary SELECT query (e.g., UNION, INTERSECT, EXCEPT).\r\n */\r\nexport class BinarySelectQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"BinarySelectQuery\");\r\n left: SelectQuery;\r\n operator: RawString;\r\n right: SelectQuery;\r\n\r\n constructor(left: SelectQuery, operator: string, right: SelectQuery) {\r\n super();\r\n this.left = left;\r\n this.operator = new RawString(operator);\r\n this.right = right;\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with UNION\r\n * @returns A new BinarySelectQuery representing \"(this) UNION query\"\r\n */\r\n public union(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('union', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with UNION ALL\r\n * @returns A new BinarySelectQuery representing \"(this) UNION ALL query\"\r\n */\r\n public unionAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('union all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using INTERSECT as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with INTERSECT\r\n * @returns A new BinarySelectQuery representing \"(this) INTERSECT query\"\r\n */\r\n public intersect(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('intersect', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using INTERSECT ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with INTERSECT ALL\r\n * @returns A new BinarySelectQuery representing \"(this) INTERSECT ALL query\"\r\n */\r\n public intersectAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('intersect all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using EXCEPT as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with EXCEPT\r\n * @returns A new BinarySelectQuery representing \"(this) EXCEPT query\"\r\n */\r\n public except(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('except', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using EXCEPT ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with EXCEPT ALL\r\n * @returns A new BinarySelectQuery representing \"(this) EXCEPT ALL query\"\r\n */\r\n public exceptAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('except all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using the specified operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @param query The query to append with the specified operator\r\n * @returns A new BinarySelectQuery representing \"(this) [operator] query\"\r\n */\r\n public appendSelectQuery(operator: string, query: SelectQuery): BinarySelectQuery {\r\n this.left = new BinarySelectQuery(this.left, this.operator.value, this.right);\r\n this.operator = new RawString(operator);\r\n this.right = query;\r\n\r\n CTENormalizer.normalize(this);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION as the operator, accepting a raw SQL string.\r\n * This method parses the SQL string and appends the resulting query using UNION.\r\n * @param sql The SQL string to parse and union\r\n * @returns A new BinarySelectQuery representing \"(this) UNION (parsed query)\"\r\n */\r\n public unionRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.union(parsedQuery);\r\n }\r\n public unionAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.unionAll(parsedQuery);\r\n }\r\n public intersectRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.intersect(parsedQuery);\r\n }\r\n public intersectAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.intersectAll(parsedQuery);\r\n }\r\n public exceptRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.except(parsedQuery);\r\n }\r\n public exceptAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.exceptAll(parsedQuery);\r\n }\r\n\r\n // Returns a SourceExpression wrapping this query as a subquery source.\r\n // Optionally takes an alias name (default: \"subq\")\r\n public toSource(alias: string = \"subq\"): SourceExpression {\r\n return new SourceExpression(\r\n new SubQuerySource(this),\r\n new SourceAliasExpression(alias, null)\r\n );\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { ParameterHelper } from \"../utils/ParameterHelper\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { QueryBuilder } from \"../transformers/QueryBuilder\";\r\nimport { SelectQuery } from \"./SelectQuery\";\r\nimport { SimpleSelectQuery } from \"./SimpleSelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { TupleExpression } from \"./ValueComponent\";\r\n\r\n/**\r\n * Represents a VALUES query in SQL.\r\n */\r\nexport class ValuesQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"ValuesQuery\");\r\n tuples: TupleExpression[];\r\n /**\r\n * Column aliases for the VALUES query.\r\n * These represent the logical column names for each value tuple.\r\n * Note: This property is optional and is not referenced during SQL output, but is used when converting to a SimpleSelectQuery.\r\n */\r\n columnAliases: string[] | null;\r\n\r\n constructor(tuples: TupleExpression[], columnAliases: string[] | null = null) {\r\n super();\r\n this.tuples = tuples;\r\n this.columnAliases = columnAliases;\r\n }\r\n\r\n public toSimpleSelectQuery(): SimpleSelectQuery {\r\n return QueryBuilder.buildSimpleQuery(this);\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { Distinct, DistinctComponent, DistinctOn, SelectClause, SelectItem } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class SelectClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SelectClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The SELECT clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SelectClause; newIndex: number } {\r\n let idx = index;\r\n let distinct: DistinctComponent | null = null;\r\n\r\n if (lexemes[idx].value !== 'select') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found \"${lexemes[idx].value}\". SELECT clauses must start with the SELECT keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'distinct') {\r\n idx++;\r\n distinct = new Distinct();\r\n } else if (idx < lexemes.length && lexemes[idx].value === 'distinct on') {\r\n idx++;\r\n const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n distinct = new DistinctOn(argument.value);\r\n idx = argument.newIndex;\r\n }\r\n\r\n const items: SelectItem[] = [];\r\n const item = SelectItemParser.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = SelectItemParser.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No select items found. The SELECT clause requires at least one expression to select.`);\r\n } else {\r\n const clause = new SelectClause(items, distinct);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n}\r\n\r\n// Extracted SelectItemParser for parsing individual select items\r\nexport class SelectItemParser {\r\n /**\r\n * Parses a single select item from a SQL string.\r\n * @param query The SQL string representing a select item (e.g. 'id as user_id').\r\n * @returns The parsed SelectItem instance.\r\n */\r\n public static parse(query: string): SelectItem {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseItem(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The select item is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parses a single select item from lexemes.\r\n * @param lexemes The array of lexemes.\r\n * @param index The starting index.\r\n * @returns An object containing the SelectItem and the new index.\r\n */\r\n public static parseItem(lexemes: Lexeme[], index: number): { value: SelectItem; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'as') {\r\n // Skip 'AS' keyword\r\n idx++;\r\n }\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Identifier)) {\r\n const alias = lexemes[idx].value;\r\n idx++;\r\n return {\r\n value: new SelectItem(value, alias),\r\n newIndex: idx,\r\n };\r\n } else if (value instanceof ColumnReference && value.column.name !== \"*\") {\r\n // nameless select item\r\n return {\r\n value: new SelectItem(value, value.column.name),\r\n newIndex: idx,\r\n };\r\n }\r\n // nameless select item\r\n return {\r\n value: new SelectItem(value),\r\n newIndex: idx,\r\n };\r\n }\r\n}", "import { JoinOnClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class JoinOnClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinOnClause; newIndex: number } | null {\r\n let idx = index;\r\n if (idx < lexemes.length && lexemes[idx].value === 'on') {\r\n idx++; // Skip 'on' keyword\r\n // Parse the condition expression\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n const joinOn = new JoinOnClause(condition.value);\r\n return { value: joinOn, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n}\r\n", "import { JoinUsingClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class JoinUsingClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinUsingClause; newIndex: number } | null {\r\n let idx = index;\r\n if (idx < lexemes.length && lexemes[idx].value === 'using') {\r\n idx++; // Skip 'using' keyword\r\n // Parse the columns in parentheses\r\n const result = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n const usingColumns = result.value;\r\n idx = result.newIndex;\r\n const joinUsing = new JoinUsingClause(usingColumns);\r\n return { value: joinUsing, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n}\r\n", "import { JoinClause, SourceExpression } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { joinkeywordParser } from \"../tokenReaders/CommandTokenReader\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\nimport { JoinOnClauseParser } from \"./JoinOnClauseParser\";\r\nimport { JoinUsingClauseParser } from \"./JoinUsingClauseParser\";\r\n\r\nexport class JoinClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinClause[]; newIndex: number } | null {\r\n let idx = index;\r\n const joins: JoinClause[] = [];\r\n\r\n while (this.isJoinCommand(lexemes, idx)) {\r\n const joinClause = this.parseJoinClause(lexemes, idx);\r\n joins.push(joinClause.value);\r\n idx = joinClause.newIndex;\r\n }\r\n\r\n if (joins.length > 0) {\r\n return { value: joins, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n\r\n private static isJoinKeyword(value: string): boolean {\r\n // Although performance is not ideal,\r\n // we use keyword token reader to centralize keyword management\r\n const result = joinkeywordParser.parse(value, 0);\r\n if (result) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n private static parseLateral(lexemes: Lexeme[], index: number): { value: boolean; newIndex: number } {\r\n let idx = index;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'lateral') {\r\n // Skip 'lateral' keyword\r\n idx++;\r\n return { value: true, newIndex: idx };\r\n }\r\n\r\n return { value: false, newIndex: idx };\r\n }\r\n\r\n private static isJoinCommand(lexemes: Lexeme[], index: number): boolean {\r\n if (index >= lexemes.length) {\r\n return false;\r\n }\r\n\r\n if (lexemes[index].type & TokenType.Comma || this.isJoinKeyword(lexemes[index].value) === true) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n private static parseJoinClause(lexemes: Lexeme[], index: number): { value: JoinClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Get the join type\r\n const joinType = lexemes[idx].value === \",\" ? \"cross join\" : lexemes[idx].value;\r\n idx++;\r\n\r\n // Check for lateral join\r\n const lateralResult = this.parseLateral(lexemes, idx);\r\n const lateral = lateralResult.value;\r\n idx = lateralResult.newIndex;\r\n\r\n // Parse the source expression to join with\r\n const sourceResult = SourceExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n\r\n if (idx < lexemes.length) {\r\n // JoinOnClauseParser\r\n const onResult = JoinOnClauseParser.tryParse(lexemes, idx);\r\n if (onResult) {\r\n const joinClause = new JoinClause(joinType, sourceResult.value, onResult.value, lateral);\r\n return { value: joinClause, newIndex: onResult.newIndex };\r\n }\r\n // JoinUsingClauseParser\r\n const usingResult = JoinUsingClauseParser.tryParse(lexemes, idx);\r\n if (usingResult) {\r\n const joinClause = new JoinClause(joinType, sourceResult.value, usingResult.value, lateral);\r\n return { value: joinClause, newIndex: usingResult.newIndex };\r\n }\r\n }\r\n\r\n // If we reach the end of the input, we can treat it as a natural join\r\n const joinClause = new JoinClause(joinType, sourceResult.value, null, lateral);\r\n return { value: joinClause, newIndex: idx };\r\n }\r\n}", "import { FromClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { JoinClauseParser } from \"./JoinClauseParser\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\n\r\nexport class FromClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): FromClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The FROM clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FromClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'from') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FROM' keyword but found \"${lexemes[idx].value}\". FROM clauses must start with the FROM keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FROM' keyword. The FROM clause requires a table reference.`);\r\n }\r\n\r\n // Parse the main source expression\r\n const sourceExpression = SourceExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceExpression.newIndex;\r\n\r\n const join = JoinClauseParser.tryParse(lexemes, idx);\r\n idx = join?.newIndex || idx;\r\n\r\n if (join !== null) {\r\n const clause = new FromClause(sourceExpression.value, join.value);\r\n return { value: clause, newIndex: idx };\r\n } else {\r\n const clause = new FromClause(sourceExpression.value, null);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n}", "import { WhereClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class WhereClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WhereClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WHERE clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WhereClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'where') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'WHERE' keyword but found \"${lexemes[idx].value}\". WHERE clauses must start with the WHERE keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'WHERE' keyword. The WHERE clause requires a condition expression.`);\r\n }\r\n\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n const clause = new WhereClause(item.value);\r\n\r\n return { value: clause, newIndex: item.newIndex };\r\n }\r\n}", "import { GroupByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueComponent } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class GroupByClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): GroupByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The GROUP BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: GroupByClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'group by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'GROUP BY' keyword but found \"${lexemes[idx].value}\". GROUP BY clauses must start with the GROUP BY keywords.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'GROUP BY' keyword. The GROUP BY clause requires at least one expression to group by.`);\r\n }\r\n\r\n const items: ValueComponent[] = [];\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No grouping expressions found. The GROUP BY clause requires at least one expression to group by.`);\r\n } else {\r\n const clause = new GroupByClause(items);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { HavingClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class HavingClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): HavingClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The HAVING clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: HavingClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'having') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'HAVING' keyword but found \"${lexemes[idx].value}\". HAVING clauses must start with the HAVING keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'HAVING' keyword. The HAVING clause requires a condition expression.`);\r\n }\r\n\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n const clause = new HavingClause(item.value);\r\n\r\n return { value: clause, newIndex: item.newIndex };\r\n }\r\n}", "import { WindowFrameClause, WindowsClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WindowExpressionParser } from \"./WindowExpressionParser\";\r\n\r\nexport class WindowClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WindowsClause {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WINDOW clause is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WindowsClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'window') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'WINDOW' keyword but found \"${lexemes[idx].value}\". WINDOW clauses must start with the WINDOW keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'WINDOW' keyword. The WINDOW clause requires at least one window definition.`);\r\n }\r\n\r\n const windows: WindowFrameClause[] = [];\r\n while (idx < lexemes.length) {\r\n\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Identifier) {\r\n throw new Error(`Syntax error: Expected window name after 'WINDOW' keyword.`);\r\n }\r\n const name = lexemes[idx].value;\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].value !== 'as') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after window name.`);\r\n }\r\n idx++;\r\n const expr = WindowExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = expr.newIndex;\r\n windows.push(new WindowFrameClause(name, expr.value));\r\n\r\n if (idx < lexemes.length && lexemes[idx].type & TokenType.Comma) {\r\n idx++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n if (windows.length === 0) {\r\n throw new Error('At least one WINDOW clause is required after WINDOW keyword.');\r\n }\r\n return { value: new WindowsClause(windows), newIndex: idx };\r\n }\r\n}", "import { LimitClause as LimitClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class LimitClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): LimitClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The LIMIT clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: LimitClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'limit') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'LIMIT' keyword but found \"${lexemes[idx].value}\". LIMIT clauses must start with the LIMIT keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'LIMIT' keyword. The LIMIT clause requires a numeric expression.`);\r\n }\r\n\r\n // Parse LIMIT value\r\n const limitItem = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = limitItem.newIndex;\r\n\r\n const clause = new LimitClause(limitItem.value);\r\n\r\n return { value: clause, newIndex: idx };\r\n }\r\n}", "import { ForClause, LockMode } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\n\r\nexport class ForClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): ForClause {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The FOR clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ForClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check for FOR keyword\r\n if (lexemes[idx].value.toLowerCase() !== 'for') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FOR' keyword but found \"${lexemes[idx].value}\". FOR clauses must start with the FOR keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FOR' keyword. The FOR clause requires a lock mode specification.`);\r\n }\r\n\r\n // Parse lock mode\r\n const lockModeValue = lexemes[idx].value;\r\n let lockMode: LockMode;\r\n\r\n switch (lockModeValue) {\r\n case 'update':\r\n lockMode = LockMode.Update;\r\n idx++;\r\n break;\r\n case 'share':\r\n lockMode = LockMode.Share;\r\n idx++;\r\n break;\r\n case 'key share':\r\n lockMode = LockMode.KeyShare;\r\n idx++;\r\n break;\r\n case 'no key update':\r\n lockMode = LockMode.NokeyUpdate;\r\n idx++;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid lock mode \"${lockModeValue}\". Valid lock modes are: UPDATE, SHARE, KEY SHARE, NO KEY UPDATE.`);\r\n }\r\n\r\n const clause = new ForClause(lockMode);\r\n return { value: clause, newIndex: idx };\r\n }\r\n}", "import { CommonTable } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { SourceAliasExpressionParser } from \"./SourceAliasExpressionParser\";\r\n\r\nexport class CommonTableParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): CommonTable {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The CommonTable definition is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: CommonTable; newIndex: number } {\r\n let idx = index;\r\n\r\n // Parse alias and optional column aliases\r\n // SourceAliasExpressionParser already handles column aliases if present\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value !== \"as\") {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after CTE name but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip 'AS' keyword\r\n\r\n // Materialized flag\r\n let materialized: boolean | null = null;\r\n\r\n // Parse optional MATERIALIZED or NOT MATERIALIZED keywords\r\n if (idx < lexemes.length) {\r\n const currentValue = lexemes[idx].value;\r\n if (currentValue === \"materialized\") {\r\n materialized = true;\r\n idx++;\r\n } else if (currentValue === \"not materialized\") {\r\n materialized = false;\r\n idx++;\r\n }\r\n }\r\n\r\n if (idx < lexemes.length && lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected '(' after CTE name but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip opening parenthesis\r\n\r\n const queryResult = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = queryResult.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected ')' after CTE query but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip closing parenthesis\r\n\r\n const value = new CommonTable(queryResult.value, aliasResult.value, materialized);\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { CommonTableParser } from \"./CommonTableParser\";\r\n\r\nexport class WithClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WithClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WITH clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WithClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Expect WITH keyword\r\n if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === \"with\") {\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected WITH keyword.`);\r\n }\r\n\r\n // Check for RECURSIVE keyword\r\n const recursive = idx < lexemes.length && lexemes[idx].value.toLowerCase() === \"recursive\";\r\n if (recursive) {\r\n idx++;\r\n }\r\n\r\n // Parse CTEs\r\n const tables: CommonTable[] = [];\r\n\r\n // Parse first CTE (required)\r\n const firstCte = CommonTableParser.parseFromLexeme(lexemes, idx);\r\n tables.push(firstCte.value);\r\n idx = firstCte.newIndex;\r\n\r\n // Parse additional CTEs (optional)\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n const cteResult = CommonTableParser.parseFromLexeme(lexemes, idx);\r\n tables.push(cteResult.value);\r\n idx = cteResult.newIndex;\r\n }\r\n\r\n // Create WITH clause\r\n return {\r\n value: new WithClause(recursive, tables),\r\n newIndex: idx\r\n };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValuesQuery } from \"../models/SelectQuery\";\r\nimport { TupleExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class ValuesQueryParser {\r\n public static parse(query: string): ValuesQuery {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The VALUES clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValuesQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value.toLowerCase() !== 'values') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'VALUES' keyword but found \"${lexemes[idx].value}\". VALUES clauses must start with the VALUES keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'VALUES' keyword. The VALUES clause requires at least one tuple expression.`);\r\n }\r\n\r\n const tuples: TupleExpression[] = [];\r\n\r\n // Parse the first tuple\r\n const firstTuple = this.parseTuple(lexemes, idx);\r\n tuples.push(firstTuple.value);\r\n idx = firstTuple.newIndex;\r\n\r\n // Parse additional tuples if they exist\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n const tuple = this.parseTuple(lexemes, idx);\r\n tuples.push(tuple.value);\r\n idx = tuple.newIndex;\r\n }\r\n\r\n const query = new ValuesQuery(tuples);\r\n return { value: query, newIndex: idx };\r\n }\r\n\r\n private static parseTuple(lexemes: Lexeme[], index: number): { value: TupleExpression; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check for opening parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis but found \"${idx < lexemes.length ? lexemes[idx].value : \"end of input\"}\". Tuple expressions in VALUES clause must be enclosed in parentheses.`);\r\n }\r\n idx++;\r\n\r\n // Parse values inside the tuple\r\n const values: ValueComponent[] = [];\r\n\r\n // Parse first value\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after opening parenthesis in tuple expression.`);\r\n }\r\n\r\n // Check for empty tuple case\r\n if (lexemes[idx].type & TokenType.CloseParen) {\r\n idx++; // Skip closing parenthesis\r\n return { value: new TupleExpression([]), newIndex: idx };\r\n }\r\n\r\n // Parse the first value\r\n const firstValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n values.push(firstValue.value);\r\n idx = firstValue.newIndex;\r\n\r\n // Parse additional values\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after comma in tuple expression.`);\r\n }\r\n\r\n const value = ValueParser.parseFromLexeme(lexemes, idx);\r\n values.push(value.value);\r\n idx = value.newIndex;\r\n }\r\n\r\n // Check for closing parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected closing parenthesis but found \"${idx < lexemes.length ? lexemes[idx].value : \"end of input\"}\". Tuple expressions in VALUES clause must be enclosed in parentheses.`);\r\n }\r\n idx++; // Skip closing parenthesis\r\n\r\n return { value: new TupleExpression(values), newIndex: idx };\r\n }\r\n}", "import { FetchClause, FetchType, FetchUnit, FetchExpression } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { LiteralValue, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class FetchClauseParser {\r\n /**\r\n * Parses a FETCH clause from a lexeme array starting at the given index.\r\n * Supports syntax like: FETCH [FIRST|NEXT] <count> ROWS ONLY\r\n * @param lexemes The array of lexemes\r\n * @param index The starting index\r\n * @returns { value: FetchSpecification, newIndex: number }\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FetchClause; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].value !== 'fetch') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FETCH' keyword but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH' keyword.`);\r\n }\r\n\r\n const fetchExprResult = FetchExpressionParser.parseFromLexeme(lexemes, idx);\r\n const fetchExpr = fetchExprResult.value;\r\n idx = fetchExprResult.newIndex;\r\n\r\n return { value: new FetchClause(fetchExpr), newIndex: idx };\r\n }\r\n}\r\n\r\n// FetchExpressionParser: parses FETCH [FIRST|NEXT] <count> ROWS ONLY ...\r\nexport class FetchExpressionParser {\r\n /**\r\n * Parses a FETCH expression (not the whole clause, just the fetch part)\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FetchExpression; newIndex: number } {\r\n let idx = index;\r\n let type: FetchType;\r\n const typeToken = lexemes[idx].value;\r\n if (typeToken === 'first') {\r\n type = FetchType.First;\r\n } else if (typeToken === 'next') {\r\n type = FetchType.Next;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FIRST' or 'NEXT' after 'FETCH' but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT'.`);\r\n }\r\n\r\n let count: ValueComponent | null = null;\r\n let unit: FetchUnit | null = null;\r\n\r\n // Omitted count notation\r\n if (lexemes[idx].value === 'row only' || lexemes[idx].value === 'rows only') {\r\n count = new LiteralValue(1);\r\n unit = FetchUnit.RowsOnly;\r\n idx++;\r\n return { value: new FetchExpression(type, count, unit), newIndex: idx };\r\n }\r\n\r\n // <count>\r\n const countResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n count = countResult.value;\r\n idx = countResult.newIndex;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT <count>'.`);\r\n }\r\n // ROWS ONLY (or other unit)\r\n\r\n if (lexemes[idx].value === 'rows only') {\r\n unit = FetchUnit.RowsOnly;\r\n idx++;\r\n } else if (lexemes[idx].value === 'percent') {\r\n unit = FetchUnit.Percent;\r\n idx++;\r\n } else if (lexemes[idx].value === 'percent with ties') {\r\n unit = FetchUnit.PercentWithTies;\r\n idx++;\r\n }\r\n if (!unit) {\r\n throw new Error(`Syntax error: Expected 'ROWS ONLY', 'PERCENT', or 'PERCENT WITH TIES' after 'FETCH FIRST|NEXT <count>'.`);\r\n }\r\n return { value: new FetchExpression(type, count, unit), newIndex: idx };\r\n }\r\n}\r\n", "import { OffsetClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class OffsetClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): OffsetClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The OFFSET clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OffsetClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'offset') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'OFFSET' keyword but found \"${lexemes[idx].value}\". OFFSET clauses must start with the OFFSET keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'OFFSET' keyword. The OFFSET clause requires a numeric expression.`);\r\n }\r\n\r\n // Parse OFFSET value\r\n const offsetItem = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = offsetItem.newIndex;\r\n\r\n // If there is a \"row\" or \"rows\" command, skip it\r\n if (idx < lexemes.length && (lexemes[idx].value === 'row' || lexemes[idx].value === 'rows')) {\r\n idx++;\r\n }\r\n\r\n const clause = new OffsetClause(offsetItem.value);\r\n\r\n return { value: clause, newIndex: idx };\r\n }\r\n}\r\n", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SelectClauseParser } from \"./SelectClauseParser\";\r\nimport { FromClauseParser } from \"./FromClauseParser\";\r\nimport { WhereClauseParser } from \"./WhereClauseParser\";\r\nimport { GroupByClauseParser } from \"./GroupByParser\";\r\nimport { HavingClauseParser } from \"./HavingParser\";\r\nimport { OrderByClauseParser } from \"./OrderByClauseParser\";\r\nimport { WindowClauseParser } from \"./WindowClauseParser\";\r\nimport { LimitClauseParser } from \"./LimitClauseParser\";\r\nimport { ForClauseParser } from \"./ForClauseParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WithClauseParser } from \"./WithClauseParser\";\r\nimport { ValuesQueryParser } from \"./ValuesQueryParser\";\r\nimport { FetchClauseParser } from \"./FetchClauseParser\";\r\nimport { OffsetClauseParser } from \"./OffsetClauseParser\";\r\n\r\nexport class SelectQueryParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SelectQuery {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`[SelectQueryParser] Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The SELECT query is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Asynchronously parse SQL string to AST.\r\n * This method wraps the synchronous parse logic in a Promise for future extensibility.\r\n * @param query SQL string to parse\r\n * @returns Promise<SelectQuery>\r\n */\r\n public static async parseAsync(query: string): Promise<SelectQuery> {\r\n // For now, just wrap the sync parse in a resolved Promise\r\n return Promise.resolve(this.parse(query));\r\n }\r\n\r\n private static unionCommandSet = new Set<string>([\r\n \"union\",\r\n \"union all\",\r\n \"intersect\",\r\n \"intersect all\",\r\n \"except\",\r\n \"except all\",\r\n ]);\r\n private static selectCommandSet = new Set<string>([\"with\", \"select\"]);\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SelectQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input at position ${index}.`);\r\n }\r\n\r\n // Check if the first token is a SELECT keyword or VALUES\r\n const firstToken = lexemes[idx].value;\r\n if (!this.selectCommandSet.has(firstToken) && firstToken !== 'values') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' keyword but found \"${lexemes[idx].value}\".`);\r\n }\r\n\r\n let firstResult = this.selectCommandSet.has(firstToken)\r\n ? this.parseSimpleSelectQuery(lexemes, idx)\r\n : this.parseValuesQuery(lexemes, idx);\r\n\r\n let query: SelectQuery = firstResult.value;\r\n idx = firstResult.newIndex;\r\n\r\n // check 'union'\r\n while (idx < lexemes.length && this.unionCommandSet.has(lexemes[idx].value.toLowerCase())) {\r\n const operator = lexemes[idx].value.toLowerCase();\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error at position ${idx}: Expected a query after '${operator.toUpperCase()}' but found end of input.`);\r\n }\r\n\r\n const nextToken = lexemes[idx].value.toLowerCase();\r\n if (this.selectCommandSet.has(nextToken)) {\r\n const result = this.parseSimpleSelectQuery(lexemes, idx);\r\n query = new BinarySelectQuery(query, operator, result.value);\r\n idx = result.newIndex;\r\n } else if (nextToken === 'values') {\r\n const result = this.parseValuesQuery(lexemes, idx);\r\n query = new BinarySelectQuery(query, operator, result.value);\r\n idx = result.newIndex;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' after '${operator.toUpperCase()}' but found \"${lexemes[idx].value}\".`);\r\n }\r\n }\r\n\r\n return { value: query, newIndex: idx };\r\n }\r\n\r\n private static parseSimpleSelectQuery(lexemes: Lexeme[], index: number): { value: SimpleSelectQuery; newIndex: number } {\r\n let idx = index;\r\n let withClauseResult = null;\r\n\r\n // Parse optional WITH clause\r\n if (idx < lexemes.length && lexemes[idx].value === 'with') {\r\n withClauseResult = WithClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = withClauseResult.newIndex;\r\n }\r\n\r\n // Parse SELECT clause (required)\r\n if (idx >= lexemes.length || lexemes[idx].value !== 'select') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found \"${idx < lexemes.length ? lexemes[idx].value : 'end of input'}\". SELECT queries must start with the SELECT keyword.`);\r\n }\r\n\r\n const selectClauseResult = SelectClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = selectClauseResult.newIndex;\r\n\r\n // Parse FROM clause (optional)\r\n let fromClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'from') {\r\n fromClauseResult = FromClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = fromClauseResult.newIndex;\r\n }\r\n\r\n // Parse WHERE clause (optional)\r\n let whereClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'where') {\r\n whereClauseResult = WhereClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = whereClauseResult.newIndex;\r\n }\r\n\r\n // Parse GROUP BY clause (optional)\r\n let groupByClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'group by') {\r\n groupByClauseResult = GroupByClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = groupByClauseResult.newIndex;\r\n }\r\n\r\n // Parse HAVING clause (optional)\r\n let havingClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'having') {\r\n havingClauseResult = HavingClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = havingClauseResult.newIndex;\r\n }\r\n\r\n // Parse WINDOW clause (optional)\r\n let windowClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'window') {\r\n windowClauseResult = WindowClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = windowClauseResult.newIndex;\r\n }\r\n\r\n // Parse ORDER BY clause (optional)\r\n let orderByClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'order by') {\r\n orderByClauseResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = orderByClauseResult.newIndex;\r\n }\r\n\r\n // Parse LIMIT clause (optional)\r\n let limitClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'limit') {\r\n limitClauseResult = LimitClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = limitClauseResult.newIndex;\r\n }\r\n\r\n // Parse OFFSET clause (optional)\r\n let offsetClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'offset') {\r\n offsetClauseResult = OffsetClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = offsetClauseResult.newIndex;\r\n }\r\n\r\n // Parse FETCH clause (optional)\r\n let fetchClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'fetch') {\r\n fetchClauseResult = FetchClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = fetchClauseResult.newIndex;\r\n }\r\n\r\n // Parse FOR clause (optional)\r\n let forClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'for') {\r\n forClauseResult = ForClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = forClauseResult.newIndex;\r\n }\r\n\r\n // Create and return the SelectQuery object\r\n const selectQuery = new SimpleSelectQuery({\r\n withClause: withClauseResult ? withClauseResult.value : null,\r\n selectClause: selectClauseResult.value,\r\n fromClause: fromClauseResult ? fromClauseResult.value : null,\r\n whereClause: whereClauseResult ? whereClauseResult.value : null,\r\n groupByClause: groupByClauseResult ? groupByClauseResult.value : null,\r\n havingClause: havingClauseResult ? havingClauseResult.value : null,\r\n orderByClause: orderByClauseResult ? orderByClauseResult.value : null,\r\n windowClause: windowClauseResult ? windowClauseResult.value : null,\r\n limitClause: limitClauseResult ? limitClauseResult.value : null,\r\n offsetClause: offsetClauseResult ? offsetClauseResult.value : null,\r\n fetchClause: fetchClauseResult ? fetchClauseResult.value : null,\r\n forClause: forClauseResult ? forClauseResult.value : null\r\n });\r\n\r\n return { value: selectQuery, newIndex: idx };\r\n }\r\n\r\n private static parseValuesQuery(lexemes: Lexeme[], index: number): { value: SelectQuery; newIndex: number } {\r\n // Use ValuesQueryParser to parse VALUES clause\r\n const result = ValuesQueryParser.parseFromLexeme(lexemes, index);\r\n\r\n // Return the result from ValuesQueryParser directly\r\n return { value: result.value, newIndex: result.newIndex };\r\n }\r\n}", "// filepath: src/parsers/InsertQueryParser.ts\r\n// Provides parsing for INSERT queries, supporting optional columns and WITH/SELECT/VALUES structure.\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { WithClause } from \"../models/Clause\";\r\nimport { WithClauseParser } from \"./WithClauseParser\";\r\nimport { SimpleSelectQuery } from \"../models/SimpleSelectQuery\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\nimport { InsertClause } from \"../models/Clause\";\r\n\r\nexport class InsertQueryParser {\r\n /**\r\n * Parse SQL string to InsertQuery AST.\r\n * @param query SQL string\r\n */\r\n public static parse(query: string): InsertQuery {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The INSERT query is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parse from lexeme array (for internal use and tests)\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: InsertQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n let withclause: WithClause | null = null;\r\n if (lexemes[idx].value === \"with\") {\r\n const result = WithClauseParser.parseFromLexeme(lexemes, idx);\r\n withclause = result.value;\r\n idx = result.newIndex;\r\n }\r\n\r\n // Expect INSERT INTO\r\n if (lexemes[idx].value !== \"insert into\") {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'INSERT INTO' but found '${lexemes[idx].value}'.`);\r\n }\r\n idx++;\r\n\r\n // Parse table and optional alias/schema using SourceExpressionParser\r\n const sourceResult = SourceExpressionParser.parseTableSourceFromLexemes(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n // Optional columns\r\n let columns: string[] = [];\r\n if (lexemes[idx]?.type === TokenType.OpenParen) {\r\n idx++;\r\n while (idx < lexemes.length && lexemes[idx].type === TokenType.Identifier) {\r\n columns.push(lexemes[idx].value);\r\n idx++;\r\n if (lexemes[idx]?.type === TokenType.Comma) {\r\n idx++;\r\n } else {\r\n break;\r\n }\r\n }\r\n if (lexemes[idx]?.type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected ')' after column list.`);\r\n }\r\n idx++;\r\n }\r\n\r\n const selectResult = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n if (withclause) {\r\n if (selectResult.value instanceof SimpleSelectQuery) {\r\n selectResult.value.withClause = withclause;\r\n } else {\r\n throw new Error(`WITH clause is not supported in this context.`);\r\n }\r\n }\r\n\r\n idx = selectResult.newIndex;\r\n return {\r\n value: new InsertQuery({\r\n insertClause: new InsertClause(sourceResult.value, columns),\r\n selectQuery: selectResult.value\r\n }),\r\n newIndex: idx\r\n };\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, BinaryExpression, CaseExpression, SwitchCaseArgument, CaseKeyValuePair, RawString } from '../models/ValueComponent';\r\nimport { JsonMapping } from './PostgresJsonQueryBuilder';\r\n\r\n/**\r\n * Entity with processing metadata\r\n */\r\nexport interface ProcessableEntity {\r\n id: string;\r\n name: string;\r\n columns: { [jsonKey: string]: string };\r\n isRoot: boolean;\r\n propertyName: string;\r\n // For nested entities\r\n parentId?: string;\r\n relationshipType?: \"object\" | \"array\";\r\n}\r\n\r\n/**\r\n * Information for object entity processing\r\n */\r\ninterface ObjectEntityProcessingInfo {\r\n entity: ProcessableEntity;\r\n depth: number;\r\n}\r\n\r\n/**\r\n * PostgreSQL-specific builder for creating CTEs for object entities (object relationships).\r\n * This class handles the creation of CTEs that build JSON/JSONB objects for object entities,\r\n * processing them from the deepest level up to ensure proper dependency ordering.\r\n * \r\n * Features:\r\n * - Depth-based CTE naming (cte_object_depth_N)\r\n * - NULL handling for entity columns\r\n * - JSONB/JSON object construction\r\n * - Hierarchical processing of nested objects\r\n * \r\n * Why depth calculation is critical:\r\n * 1. Object entities can be nested at multiple levels. We must process the deepest\r\n * (most distant) objects first to ensure their JSON representations are available\r\n * when building their parent entities.\r\n * 2. Object entity processing is essentially a column compression operation. Entities\r\n * at the same depth level can be processed simultaneously since they don't depend\r\n * on each other.\r\n * \r\n * Example hierarchy:\r\n * Order (root, depth 0)\r\n * \u2514\u2500 Customer (depth 1)\r\n * \u2514\u2500 Address (depth 2)\r\n * \u2514\u2500 Shipping (depth 1)\r\n * \u2514\u2500 Carrier (depth 2)\r\n * \r\n * Processing order: depth 2 \u2192 depth 1 \u2192 depth 0\r\n */\r\nexport class PostgresObjectEntityCteBuilder { // Constants for consistent naming conventions\r\n private static readonly JSON_COLUMN_SUFFIX = '_json';\r\n private static readonly CTE_OBJECT_PREFIX = 'cte_object_depth_';\r\n private static readonly WILDCARD_COLUMN = '*'; /**\r\n * Build CTEs for all object entities in the correct dependency order\r\n * @param initialCte The starting CTE containing all raw data\r\n * @param allEntities Map of all entities in the mapping\r\n * @param mapping The JSON mapping configuration\r\n * @returns Array of CTEs and the alias of the last CTE created\r\n */\r\n public buildObjectEntityCtes(\r\n initialCte: CommonTable,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): { ctes: CommonTable[], lastCteAlias: string } {\r\n const ctes: CommonTable[] = [initialCte];\r\n let previousCteAlias = initialCte.aliasExpression.table.name; // Collect and sort object entities by depth\r\n const objectEntityInfos = this.collectAndSortObjectEntities(mapping, allEntities);\r\n\r\n // Group entities by depth\r\n const entitiesByDepth = this.groupEntitiesByDepth(objectEntityInfos);\r\n\r\n // Process each depth level, starting from the deepest\r\n const depths = Array.from(entitiesByDepth.keys()).sort((a, b) => b - a);\r\n\r\n for (const depth of depths) {\r\n const entitiesAtDepth = entitiesByDepth.get(depth)!;\r\n const cteAlias = `${PostgresObjectEntityCteBuilder.CTE_OBJECT_PREFIX}${depth}`;\r\n\r\n // Build CTE for all entities at this depth\r\n const cte = this.buildDepthCte(\r\n entitiesAtDepth,\r\n previousCteAlias,\r\n cteAlias,\r\n mapping,\r\n allEntities\r\n );\r\n\r\n ctes.push(cte);\r\n previousCteAlias = cteAlias;\r\n }\r\n\r\n return { ctes, lastCteAlias: previousCteAlias };\r\n } /**\r\n * Collect all object entities and calculate their depth from root.\r\n * \r\n * Depth calculation is crucial because:\r\n * - It determines the processing order (deepest first)\r\n * - It ensures dependencies are resolved before an entity is processed\r\n * - It allows parallel processing of entities at the same depth level\r\n * \r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n * @returns Array of object entity information with calculated depths\r\n */\r\n private collectAndSortObjectEntities(\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>): ObjectEntityProcessingInfo[] {\r\n const objectInfos: ObjectEntityProcessingInfo[] = [];\r\n\r\n // Helper function to calculate actual object nesting depth for a given OBJECT entity\r\n const calculateActualObjectNestingDepth = (entityIdOfObject: string): number => {\r\n const initialEntity = allEntities.get(entityIdOfObject);\r\n if (!initialEntity) {\r\n throw new Error(`Entity ${entityIdOfObject} not found for depth calculation.`);\r\n }\r\n // If the object itself is root, its depth is 0. (This function should ideally be called for nested entities, not the root itself as a \"parent CTE\" subject)\r\n if (initialEntity.isRoot) return 0;\r\n\r\n // If the object is not root and has no parentId, it's considered a top-level object, depth 1.\r\n if (!initialEntity.parentId) {\r\n return 1;\r\n }\r\n\r\n let currentParentIdInHierarchy: string | undefined = initialEntity.parentId;\r\n let calculatedObjectDepth = 0;\r\n const visitedInPath = new Set<string>();\r\n visitedInPath.add(entityIdOfObject); // Add the starting object itself to detect cycles\r\n\r\n while (currentParentIdInHierarchy) {\r\n if (visitedInPath.has(currentParentIdInHierarchy)) {\r\n throw new Error(`Circular dependency detected: ${currentParentIdInHierarchy} already visited in path for ${entityIdOfObject}`);\r\n }\r\n visitedInPath.add(currentParentIdInHierarchy);\r\n\r\n const parentEntityData = allEntities.get(currentParentIdInHierarchy);\r\n if (!parentEntityData) {\r\n throw new Error(`Parent entity ${currentParentIdInHierarchy} not found during depth calculation for ${entityIdOfObject}`);\r\n }\r\n\r\n let parentIsConsideredAnObjectForNesting = false;\r\n if (parentEntityData.isRoot) {\r\n parentIsConsideredAnObjectForNesting = true; // Root counts as an object ancestor\r\n } else {\r\n // For non-root parents, find their definition in nestedEntities to check their type\r\n const parentDefinition = mapping.nestedEntities.find(ne => ne.id === currentParentIdInHierarchy);\r\n if (parentDefinition) {\r\n if (parentDefinition.relationshipType === \"object\") {\r\n parentIsConsideredAnObjectForNesting = true;\r\n }\r\n // If parentDefinition.relationshipType === \"array\", it's not an object ancestor for depth counting\r\n } else {\r\n // This implies currentParentIdInHierarchy refers to an entity not defined as root or in nestedEntities\r\n // This should ideally not happen with a consistent mapping.\r\n throw new Error(`Parent entity ${currentParentIdInHierarchy} (ancestor of ${entityIdOfObject}) has no definition in mapping.nestedEntities and is not root.`);\r\n }\r\n }\r\n\r\n if (parentIsConsideredAnObjectForNesting) {\r\n calculatedObjectDepth++;\r\n }\r\n\r\n if (parentEntityData.isRoot) {\r\n break; // Stop when the root is processed as the highest object ancestor\r\n }\r\n currentParentIdInHierarchy = parentEntityData.parentId; // Move to the next ancestor\r\n }\r\n return calculatedObjectDepth;\r\n };\r\n\r\n mapping.nestedEntities.forEach(nestedEntity => {\r\n if (nestedEntity.relationshipType === \"object\") {\r\n const entity = allEntities.get(nestedEntity.id);\r\n // Ensure we don't process the root entity itself as a \"parent\" CTE,\r\n // and that the entity actually exists.\r\n if (entity && !entity.isRoot) {\r\n objectInfos.push({\r\n entity,\r\n depth: calculateActualObjectNestingDepth(nestedEntity.id)\r\n });\r\n }\r\n }\r\n });\r\n\r\n // The existing grouping and sorting by depth (b - a for descending) should still work correctly\r\n // as it processes deepest levels first, regardless of the absolute depth numbers.\r\n return objectInfos;\r\n }\r\n\r\n /**\r\n * Group entities by their depth level.\r\n * \r\n * Grouping by depth allows us to:\r\n * - Process all entities at the same level in a single CTE\r\n * - Optimize query performance by reducing the number of CTEs\r\n * - Maintain clear dependency ordering\r\n * \r\n * @param parentInfos Array of parent entity information with depths\r\n * @returns Map of depth level to entities at that depth\r\n */ private groupEntitiesByDepth(\r\n objectInfos: ObjectEntityProcessingInfo[]\r\n ): Map<number, ObjectEntityProcessingInfo[]> {\r\n const entitiesByDepth = new Map<number, ObjectEntityProcessingInfo[]>();\r\n\r\n objectInfos.forEach(info => {\r\n const depth = info.depth;\r\n if (!entitiesByDepth.has(depth)) {\r\n entitiesByDepth.set(depth, []);\r\n }\r\n entitiesByDepth.get(depth)!.push(info);\r\n });\r\n\r\n return entitiesByDepth;\r\n }\r\n\r\n /**\r\n * Build a CTE that processes all entities at a specific depth level\r\n */\r\n private buildDepthCte(\r\n entitiesAtDepth: ObjectEntityProcessingInfo[],\r\n previousCteAlias: string,\r\n cteAlias: string,\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): CommonTable {\r\n // Build SELECT items: * and JSON objects for all entities at this depth\r\n const selectItems: SelectItem[] = [\r\n // Select all columns from previous CTE\r\n new SelectItem(new ColumnReference(null, new IdentifierString(PostgresObjectEntityCteBuilder.WILDCARD_COLUMN)))\r\n ];\r\n\r\n // Process each entity at this depth\r\n for (const { entity } of entitiesAtDepth) {\r\n const jsonColumn = this.buildEntityJsonColumn(entity, mapping, allEntities);\r\n selectItems.push(jsonColumn);\r\n }\r\n\r\n // Create CTE that selects from previous CTE\r\n const cteSelect = new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(previousCteAlias)),\r\n null\r\n ),\r\n null\r\n )\r\n });\r\n\r\n return new CommonTable(cteSelect, new SourceAliasExpression(cteAlias, null), null);\r\n }\r\n\r\n /**\r\n * Build JSON column for a single entity with NULL handling\r\n */\r\n private buildEntityJsonColumn(\r\n entity: ProcessableEntity,\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): SelectItem {\r\n // Build JSON object arguments and NULL checks\r\n const { jsonObjectArgs, nullChecks } = this.prepareEntityColumns(entity);\r\n\r\n // Add child object relationships\r\n this.addChildObjectRelationships(entity, jsonObjectArgs, mapping, allEntities);\r\n\r\n // Create JSON object\r\n const jsonObject = this.createJsonObject(jsonObjectArgs, mapping.useJsonb);\r\n\r\n // Build NULL condition and CASE expression\r\n const nullCondition = this.buildNullCondition(nullChecks);\r\n const caseExpr = this.createCaseExpression(nullCondition, jsonObject);\r\n\r\n // Add JSON object as named column\r\n const jsonColumnName = `${entity.name.toLowerCase()}${PostgresObjectEntityCteBuilder.JSON_COLUMN_SUFFIX}`;\r\n return new SelectItem(caseExpr, jsonColumnName);\r\n }\r\n\r\n /**\r\n * Prepare entity columns and NULL checks.\r\n * \r\n * This method extracts column data and creates NULL checks for each column.\r\n * The NULL checking is essential for handling outer joins correctly.\r\n * \r\n * In outer join scenarios, when there's no matching row in the joined table,\r\n * all columns from that table will be NULL. Instead of creating an empty object\r\n * with all NULL properties (e.g., {id: null, name: null, email: null}),\r\n * we want to represent the absence of the entity as NULL itself.\r\n * \r\n * This ensures cleaner JSON output where missing relationships are represented\r\n * as NULL rather than objects with all NULL fields.\r\n * \r\n * @param entity The entity whose columns are being processed\r\n * @returns Object containing arrays of JSON object arguments and NULL check conditions\r\n */\r\n private prepareEntityColumns(entity: ProcessableEntity): {\r\n jsonObjectArgs: ValueComponent[],\r\n nullChecks: ValueComponent[]\r\n } {\r\n const jsonObjectArgs: ValueComponent[] = [];\r\n const nullChecks: ValueComponent[] = [];\r\n\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n jsonObjectArgs.push(new LiteralValue(jsonKey));\r\n jsonObjectArgs.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n\r\n // Collect NULL checks for each column\r\n nullChecks.push(\r\n new BinaryExpression(\r\n new ColumnReference(null, new IdentifierString(sqlColumn)),\r\n \"is\",\r\n new LiteralValue(null)\r\n )\r\n );\r\n });\r\n\r\n return { jsonObjectArgs, nullChecks };\r\n }\r\n\r\n /**\r\n * Add child object relationships to JSON object arguments.\r\n * \r\n * This method processes nested object-type entities that are direct children of the current entity.\r\n * For each child entity, it adds the property name and corresponding JSON column reference\r\n * to the arguments array that will be used to build the parent's JSON object.\r\n * \r\n * The child JSON columns are expected to already exist in the data source (created by deeper\r\n * level CTEs), as we process from the deepest level up to the root.\r\n * \r\n * Note: In this context, \"child\" refers to entities that have an object relationship (0..1)\r\n * with their parent. From a data perspective, these are typically entities referenced via\r\n * foreign keys, representing \"parent\" entities in traditional database terminology.\r\n * \r\n * @param entity The current entity being processed\r\n * @param jsonObjectArgs Array to which JSON object arguments will be added\r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n */\r\n private addChildObjectRelationships(\r\n entity: ProcessableEntity,\r\n jsonObjectArgs: ValueComponent[],\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): void {\r\n const childEntities = mapping.nestedEntities.filter(ne =>\r\n ne.parentId === entity.id && ne.relationshipType === \"object\"\r\n );\r\n\r\n childEntities.forEach(childEntity => {\r\n const child = allEntities.get(childEntity.id);\r\n if (child) {\r\n jsonObjectArgs.push(new LiteralValue(childEntity.propertyName));\r\n const jsonColumnName = `${child.name.toLowerCase()}${PostgresObjectEntityCteBuilder.JSON_COLUMN_SUFFIX}`;\r\n jsonObjectArgs.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Create JSON object function call\r\n */\r\n private createJsonObject(args: ValueComponent[], useJsonb: boolean = false): FunctionCall {\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n return new FunctionCall(\r\n null,\r\n new RawString(jsonBuildFunction),\r\n new ValueList(args),\r\n null\r\n );\r\n }\r\n\r\n /**\r\n * Build NULL condition from NULL checks\r\n */\r\n private buildNullCondition(nullChecks: ValueComponent[]): ValueComponent {\r\n return nullChecks.reduce((acc, check) =>\r\n acc ? new BinaryExpression(acc, \"and\", check) : check\r\n );\r\n }\r\n\r\n /**\r\n * Create CASE expression with NULL handling\r\n */\r\n private createCaseExpression(nullCondition: ValueComponent, jsonObject: ValueComponent): CaseExpression {\r\n return new CaseExpression(\r\n null,\r\n new SwitchCaseArgument(\r\n [new CaseKeyValuePair(nullCondition, new LiteralValue(null))],\r\n jsonObject // ELSE return the JSON object\r\n )\r\n );\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource, GroupByClause } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, RawString } from '../models/ValueComponent';\r\nimport { JsonMapping } from './PostgresJsonQueryBuilder';\r\nimport { ProcessableEntity } from './PostgresObjectEntityCteBuilder';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\n\r\n/**\r\n * Information for array entity processing\r\n */\r\ninterface ArrayEntityProcessingInfo {\r\n entity: ProcessableEntity;\r\n parentEntity: ProcessableEntity;\r\n parentIdColumnSqlName: string;\r\n depth: number;\r\n}\r\n\r\n/**\r\n * PostgreSQL-specific builder for creating CTEs for array entities (array relationships).\r\n * This class handles the creation of CTEs that build JSON/JSONB arrays for child entities,\r\n * processing them from the deepest level up to ensure proper dependency ordering.\r\n * \r\n * Features:\r\n * - Depth-based CTE naming (cte_array_depth_N)\r\n * - Row compression using GROUP BY operations\r\n * - JSONB/JSON array aggregation\r\n * - Hierarchical processing of nested arrays\r\n * - Column exclusion to avoid duplication\r\n * \r\n * Why depth calculation is critical:\r\n * 1. Array entities can be nested at multiple levels. We must process the deepest\r\n * (most distant) arrays first to ensure their JSON representations are available\r\n * when building their parent arrays.\r\n * 2. Array entity processing is essentially a row compression operation using GROUP BY.\r\n * Unlike parent entities which use column compression, arrays require grouping\r\n * to aggregate multiple rows into JSON arrays.\r\n * \r\n * Example hierarchy:\r\n * Order (root, depth 0)\r\n * \u2514\u2500 Items (array, depth 1)\r\n * \u2514\u2500 Details (array, depth 2)\r\n * \r\n * Processing order: depth 2 \u2192 depth 1 \u2192 depth 0\r\n */\r\nexport class PostgresArrayEntityCteBuilder {\r\n // Constants for consistent naming conventions\r\n private static readonly CTE_ARRAY_PREFIX = 'cte_array_depth_';\r\n\r\n /**\r\n * Build CTEs for all array entities in the correct dependency order\r\n * @param ctesSoFar Array of CTEs built so far (starts with the initial CTE)\r\n * @param aliasOfCteToBuildUpon Alias of the CTE from which the current array CTE will select\r\n * @param allEntities Map of all entities in the mapping\r\n * @param mapping The JSON mapping configuration\r\n * @returns Object containing the updated list of all CTEs and the alias of the last CTE created\r\n */\r\n public buildArrayEntityCtes(\r\n ctesSoFar: CommonTable[],\r\n aliasOfCteToBuildUpon: string,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): { updatedCtes: CommonTable[], lastCteAlias: string } {\r\n let currentCtes = [...ctesSoFar];\r\n let currentCteAlias = aliasOfCteToBuildUpon;\r\n\r\n // Collect and sort array entities by depth\r\n const sortedArrayInfos = this.collectAndSortArrayEntities(mapping, allEntities);\r\n\r\n if (sortedArrayInfos.length === 0) {\r\n return { updatedCtes: currentCtes, lastCteAlias: currentCteAlias };\r\n }\r\n\r\n // Group array entities by depth level for batch processing\r\n const entitiesByDepth = this.groupEntitiesByDepth(sortedArrayInfos);\r\n\r\n // Process from deepest to shallowest (depth-first)\r\n const depths = Array.from(entitiesByDepth.keys()).sort((a, b) => b - a);\r\n\r\n for (const depth of depths) {\r\n const infos = entitiesByDepth.get(depth)!;\r\n\r\n // Build CTE for all entities at this depth\r\n const { cte, newCteAlias } = this.buildDepthCte(\r\n infos,\r\n currentCteAlias,\r\n currentCtes,\r\n depth,\r\n mapping\r\n );\r\n\r\n currentCtes.push(cte);\r\n currentCteAlias = newCteAlias;\r\n }\r\n\r\n return { updatedCtes: currentCtes, lastCteAlias: currentCteAlias };\r\n }\r\n\r\n /**\r\n * Collect all array entities and calculate their depth from root.\r\n * \r\n * Depth calculation ensures proper processing order where deeper nested\r\n * arrays are processed first, making their aggregated data available\r\n * for parent array processing.\r\n * \r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n * @returns Array of array entity information with calculated depths, sorted deepest first\r\n */\r\n private collectAndSortArrayEntities(\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): ArrayEntityProcessingInfo[] {\r\n const arrayEntityInfos: ArrayEntityProcessingInfo[] = [];\r\n\r\n // Helper function to calculate depth for an entity\r\n const getDepth = (entityId: string): number => {\r\n const entity = allEntities.get(entityId);\r\n if (!entity || entity.isRoot) return 0;\r\n if (!entity.parentId) return 1;\r\n return 1 + getDepth(entity.parentId);\r\n };\r\n\r\n // Collect all array-type nested entities\r\n mapping.nestedEntities.forEach(ne => {\r\n if (ne.relationshipType === \"array\") {\r\n const currentArrayEntity = allEntities.get(ne.id);\r\n const parentEntity = allEntities.get(ne.parentId!);\r\n\r\n if (!currentArrayEntity || !parentEntity) {\r\n throw new Error(`Configuration error: Array entity '${ne.id}' or its parent '${ne.parentId}' not found.`);\r\n }\r\n\r\n // Determine the linking column from parent entity\r\n // This assumes the first column of the parent is a suitable key for linking.\r\n // More robust linking might require explicit configuration in the mapping.\r\n const parentSqlColumns = Object.values(parentEntity.columns);\r\n if (parentSqlColumns.length === 0) {\r\n throw new Error(`Configuration error: Parent entity '${parentEntity.name}' (ID: ${parentEntity.id}) must have at least one column defined to serve as a linking key for child array '${ne.name}'.`);\r\n }\r\n const parentIdColumnSqlName = parentSqlColumns[0];\r\n\r\n arrayEntityInfos.push({\r\n entity: currentArrayEntity,\r\n parentEntity: parentEntity,\r\n parentIdColumnSqlName: parentIdColumnSqlName,\r\n depth: getDepth(ne.id)\r\n });\r\n }\r\n });\r\n\r\n // Sort by depth, deepest arrays (higher depth number) processed first (bottom-up for arrays)\r\n arrayEntityInfos.sort((a, b) => b.depth - a.depth);\r\n return arrayEntityInfos;\r\n }\r\n\r\n /**\r\n * Group array entities by their depth level.\r\n * \r\n * Grouping by depth allows us to:\r\n * - Process all entities at the same level in a single CTE\r\n * - Optimize query performance by reducing the number of CTEs\r\n * - Maintain clear dependency ordering\r\n * \r\n * @param arrayInfos Array of array entity information with depths\r\n * @returns Map of depth level to entities at that depth\r\n */\r\n private groupEntitiesByDepth(\r\n arrayInfos: ArrayEntityProcessingInfo[]\r\n ): Map<number, ArrayEntityProcessingInfo[]> {\r\n const entitiesByDepth = new Map<number, ArrayEntityProcessingInfo[]>();\r\n\r\n arrayInfos.forEach(info => {\r\n const depth = info.depth;\r\n if (!entitiesByDepth.has(depth)) {\r\n entitiesByDepth.set(depth, []);\r\n }\r\n entitiesByDepth.get(depth)!.push(info);\r\n });\r\n\r\n return entitiesByDepth;\r\n }\r\n\r\n /**\r\n * Build a CTE that processes all array entities at a specific depth level.\r\n * \r\n * This method creates a single CTE that aggregates multiple array entities\r\n * at the same depth, using GROUP BY to compress rows into JSON arrays.\r\n * \r\n * @param infos Array entities at this depth level\r\n * @param currentCteAlias Alias of the CTE to build upon\r\n * @param currentCtes All CTEs built so far\r\n * @param depth Current depth level being processed\r\n * @param mapping JSON mapping configuration\r\n * @returns The new CTE and its alias\r\n */\r\n private buildDepthCte(\r\n infos: ArrayEntityProcessingInfo[],\r\n currentCteAlias: string,\r\n currentCtes: CommonTable[],\r\n depth: number,\r\n mapping: JsonMapping\r\n ): { cte: CommonTable, newCteAlias: string } {\r\n // Collect columns that will be compressed into arrays\r\n const arrayColumns = new Set<string>();\r\n infos.forEach(info => {\r\n Object.values(info.entity.columns).forEach(col => arrayColumns.add(col));\r\n });\r\n\r\n // Get columns from previous CTE\r\n const prevCte = currentCtes.find(c => c.aliasExpression.table.name === currentCteAlias)?.query;\r\n if (!prevCte) {\r\n throw new Error(`CTE not found: ${currentCteAlias}`);\r\n }\r\n\r\n const prevSelects = new SelectValueCollector(null, currentCtes).collect(prevCte);\r\n\r\n // Build SELECT items: columns that are NOT being compressed (for GROUP BY)\r\n const groupByItems: ValueComponent[] = [];\r\n const selectItems: SelectItem[] = [];\r\n\r\n prevSelects.forEach(sv => {\r\n if (!arrayColumns.has(sv.name)) {\r\n selectItems.push(new SelectItem(new ColumnReference(null, new IdentifierString(sv.name)), sv.name));\r\n groupByItems.push(new ColumnReference(null, new IdentifierString(sv.name)));\r\n }\r\n });\r\n\r\n // Add JSON aggregation columns for each array entity at this depth\r\n for (const info of infos) {\r\n const agg = this.buildAggregationDetailsForArrayEntity(\r\n info.entity,\r\n mapping.nestedEntities,\r\n new Map(), // allEntities - not needed for array aggregation\r\n mapping.useJsonb\r\n );\r\n selectItems.push(new SelectItem(agg.jsonAgg, info.entity.propertyName));\r\n }\r\n\r\n // Create the new CTE\r\n const cteAlias = `${PostgresArrayEntityCteBuilder.CTE_ARRAY_PREFIX}${depth}`;\r\n const cteSelect = new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(currentCteAlias)),\r\n null\r\n ),\r\n null\r\n ),\r\n groupByClause: groupByItems.length > 0 ? new GroupByClause(groupByItems) : null,\r\n });\r\n\r\n const cte = new CommonTable(cteSelect, new SourceAliasExpression(cteAlias, null), null);\r\n\r\n return { cte, newCteAlias: cteAlias };\r\n }\r\n\r\n /**\r\n * Build JSON aggregation function for an array entity.\r\n * \r\n * This method creates a jsonb_agg or json_agg function call that aggregates\r\n * the entity's columns into a JSON array. It also handles nested relationships\r\n * by including child entity properties in the JSON object.\r\n * \r\n * @param entity The array entity being processed\r\n * @param nestedEntities All nested entities from the mapping\r\n * @param allEntities Map of all entities (not used in current implementation)\r\n * @param useJsonb Whether to use JSONB functions\r\n * @returns Object containing the JSON aggregation function\r\n */\r\n private buildAggregationDetailsForArrayEntity(\r\n entity: ProcessableEntity,\r\n nestedEntities: any[],\r\n allEntities: Map<string, ProcessableEntity>,\r\n useJsonb: boolean = false\r\n ): { jsonAgg: ValueComponent } {\r\n // Build JSON object for array elements\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n const args: ValueComponent[] = [];\r\n\r\n // Add the entity's own columns\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n args.push(new LiteralValue(jsonKey));\r\n args.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n });\r\n\r\n // Find and process child entities (both object and array types)\r\n const childEntities = nestedEntities.filter((ne) => ne.parentId === entity.id);\r\n\r\n childEntities.forEach((childEntity) => {\r\n args.push(new LiteralValue(childEntity.propertyName));\r\n\r\n if (childEntity.relationshipType === \"object\") {\r\n // For object relationships, use pre-computed JSON column\r\n const jsonColumnName = `${childEntity.name.toLowerCase()}_json`;\r\n args.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n } else if (childEntity.relationshipType === \"array\") {\r\n // For array relationships, use the column directly\r\n args.push(new ColumnReference(null, new IdentifierString(childEntity.propertyName)));\r\n }\r\n });\r\n\r\n // Create JSON object\r\n const jsonObject = new FunctionCall(null, new RawString(jsonBuildFunction), new ValueList(args), null);\r\n\r\n // Create JSON aggregation\r\n const jsonAggFunction = useJsonb ? \"jsonb_agg\" : \"json_agg\";\r\n const jsonAgg = new FunctionCall(\r\n null,\r\n new RawString(jsonAggFunction),\r\n new ValueList([jsonObject]),\r\n null\r\n );\r\n\r\n return { jsonAgg };\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource, GroupByClause, WithClause, SubQuerySource, LimitClause } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, BinaryExpression, CaseExpression, SwitchCaseArgument, CaseKeyValuePair, RawString, UnaryExpression } from '../models/ValueComponent';\r\nimport { SelectValueCollector } from \"./SelectValueCollector\";\r\nimport { PostgresObjectEntityCteBuilder, ProcessableEntity } from './PostgresObjectEntityCteBuilder';\r\nimport { PostgresArrayEntityCteBuilder } from './PostgresArrayEntityCteBuilder';\r\n\r\n/**\r\n * Universal JSON mapping definition for creating any level of JSON structures.\r\n * Supports flat arrays, nested objects, and unlimited hierarchical structures.\r\n */\r\nexport interface JsonMapping {\r\n rootName: string;\r\n rootEntity: {\r\n id: string;\r\n name: string;\r\n columns: { [jsonKey: string]: string };\r\n };\r\n nestedEntities: Array<{\r\n id: string;\r\n name: string;\r\n parentId: string;\r\n propertyName: string;\r\n relationshipType?: \"object\" | \"array\";\r\n columns: { [jsonKey: string]: string };\r\n }>;\r\n useJsonb?: boolean;\r\n resultFormat?: \"array\" | \"single\";\r\n emptyResult?: string;\r\n}\r\n\r\n/**\r\n * PostgreSQL JSON query builder that transforms SimpleSelectQuery into queries\r\n * that return JSON arrays or single JSON objects using PostgreSQL JSON functions.\r\n */\r\nexport class PostgresJsonQueryBuilder {\r\n private selectValueCollector: SelectValueCollector;\r\n private objectEntityCteBuilder: PostgresObjectEntityCteBuilder;\r\n private arrayEntityCteBuilder: PostgresArrayEntityCteBuilder; constructor() {\r\n this.selectValueCollector = new SelectValueCollector(null);\r\n this.objectEntityCteBuilder = new PostgresObjectEntityCteBuilder();\r\n this.arrayEntityCteBuilder = new PostgresArrayEntityCteBuilder();\r\n }\r\n\r\n /**\r\n * Validates the JSON mapping and the original query.\r\n * @param query Original query to transform\r\n * @param mapping JSON mapping configuration\r\n */\r\n private validateMapping(query: SimpleSelectQuery, mapping: JsonMapping): void {\r\n const collector = new SelectValueCollector();\r\n const selectedValues = collector.collect(query);\r\n\r\n // sv.name is the alias or derived name\r\n const availableColumns = new Set(selectedValues.map(sv => sv.name));\r\n\r\n // Check root entity columns\r\n for (const jsonKey in mapping.rootEntity.columns) {\r\n const sourceColumn = mapping.rootEntity.columns[jsonKey];\r\n if (!availableColumns.has(sourceColumn)) {\r\n throw new Error(`Validation Error: Column \"${sourceColumn}\" for JSON key \"${jsonKey}\" in root entity \"${mapping.rootEntity.name}\" not found in the query's select list.`);\r\n }\r\n }\r\n\r\n // Check nested entity columns and parent-child relationships\r\n const entityIds = new Set<string>([mapping.rootEntity.id]);\r\n const parentToChildrenMap = new Map<string, string[]>();\r\n\r\n mapping.nestedEntities.forEach(ne => {\r\n entityIds.add(ne.id);\r\n if (!parentToChildrenMap.has(ne.parentId)) {\r\n parentToChildrenMap.set(ne.parentId, []);\r\n }\r\n parentToChildrenMap.get(ne.parentId)!.push(ne.id);\r\n });\r\n\r\n for (const entity of mapping.nestedEntities) {\r\n if (!entityIds.has(entity.parentId)) {\r\n throw new Error(`Validation Error: Parent entity with ID \"${entity.parentId}\" for nested entity \"${entity.name}\" (ID: ${entity.id}) not found.`);\r\n }\r\n for (const jsonKey in entity.columns) {\r\n const sourceColumn = entity.columns[jsonKey];\r\n if (!availableColumns.has(sourceColumn)) {\r\n throw new Error(`Validation Error: Column \"${sourceColumn}\" for JSON key \"${jsonKey}\" in nested entity \"${entity.name}\" (ID: ${entity.id}) not found in the query's select list.`);\r\n }\r\n }\r\n }\r\n\r\n // Validate: An entity should not have multiple direct array children.\r\n // Validate: Child propertyNames under a single parent must be unique.\r\n const allParentIds = new Set([mapping.rootEntity.id, ...mapping.nestedEntities.map(ne => ne.parentId)]);\r\n for (const parentId of allParentIds) {\r\n const directChildren = mapping.nestedEntities.filter(ne => ne.parentId === parentId);\r\n const directArrayChildrenCount = directChildren.filter(c => c.relationshipType === 'array').length;\r\n if (directArrayChildrenCount > 1) {\r\n const parentName = parentId === mapping.rootEntity.id ? mapping.rootEntity.name : mapping.nestedEntities.find(ne => ne.id === parentId)?.name;\r\n throw new Error(`Validation Error: Parent entity \"${parentName}\" (ID: ${parentId}) has multiple direct array children. This is not supported.`);\r\n }\r\n\r\n const propertyNames = new Set<string>();\r\n for (const child of directChildren) {\r\n if (propertyNames.has(child.propertyName)) {\r\n const parentName = parentId === mapping.rootEntity.id ? mapping.rootEntity.name : mapping.nestedEntities.find(ne => ne.id === parentId)?.name;\r\n throw new Error(`Validation Error: Parent entity \"${parentName}\" (ID: ${parentId}) has duplicate property name \"${child.propertyName}\" for its children.`);\r\n }\r\n propertyNames.add(child.propertyName);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Build JSON query from original query and mapping configuration.\r\n * @param originalQuery Original query to transform\r\n * @param mapping JSON mapping configuration\r\n * @returns Transformed query with JSON aggregation\r\n */\r\n public buildJsonQuery(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery {\r\n return this.buildJsonWithCteStrategy(originalQuery, mapping);\r\n }\r\n\r\n /**\r\n * Build JSON query from original query and mapping configuration.\r\n * @deprecated Use buildJsonQuery instead. This method will be removed in a future version.\r\n * @param originalQuery Original query to transform\r\n * @param mapping JSON mapping configuration\r\n * @returns Transformed query with JSON aggregation\r\n */\r\n public buildJson(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery {\r\n console.warn('buildJson is deprecated. Use buildJsonQuery instead.');\r\n return this.buildJsonQuery(originalQuery, mapping);\r\n }\r\n\r\n /**\r\n * Builds the JSON structure using a unified CTE-based strategy.\r\n * @param originalQuery Original query\r\n * @param mapping JSON mapping configuration\r\n * @returns Query with CTE-based JSON aggregation\r\n */\r\n private buildJsonWithCteStrategy(\r\n originalQuery: SimpleSelectQuery,\r\n mapping: JsonMapping,\r\n ): SimpleSelectQuery {\r\n this.validateMapping(originalQuery, mapping);\r\n\r\n // Step 1: Create the initial CTE from the original query\r\n const { initialCte, initialCteAlias } = this.createInitialCte(originalQuery);\r\n\r\n let ctesForProcessing: CommonTable[] = [initialCte];\r\n let currentAliasToBuildUpon = initialCteAlias;\r\n\r\n // Step 2: Prepare entity information\r\n const allEntities = new Map<string, ProcessableEntity>();\r\n allEntities.set(mapping.rootEntity.id, { ...mapping.rootEntity, isRoot: true, propertyName: mapping.rootName });\r\n mapping.nestedEntities.forEach(ne => allEntities.set(ne.id, { ...ne, isRoot: false, propertyName: ne.propertyName })); // Step 2.5: Build CTEs for object entities using dedicated builder\r\n const objectEntityResult = this.objectEntityCteBuilder.buildObjectEntityCtes(\r\n initialCte,\r\n allEntities,\r\n mapping\r\n );\r\n // Important: Replace the entire CTE list with the result from object entity builder\r\n // The object entity builder returns all CTEs including the initial one\r\n ctesForProcessing = objectEntityResult.ctes;\r\n currentAliasToBuildUpon = objectEntityResult.lastCteAlias;\r\n\r\n // Step 3: Build CTEs for array entities using dedicated builder\r\n const arrayCteBuildResult = this.arrayEntityCteBuilder.buildArrayEntityCtes(\r\n ctesForProcessing,\r\n currentAliasToBuildUpon,\r\n allEntities,\r\n mapping\r\n );\r\n ctesForProcessing = arrayCteBuildResult.updatedCtes;\r\n currentAliasToBuildUpon = arrayCteBuildResult.lastCteAlias;\r\n\r\n // Step 4: Build the final SELECT query using all generated CTEs\r\n return this.buildFinalSelectQuery(\r\n ctesForProcessing,\r\n currentAliasToBuildUpon,\r\n allEntities,\r\n mapping\r\n );\r\n }\r\n\r\n /**\r\n * Creates the initial Common Table Expression (CTE) from the original query.\r\n * @param originalQuery The base SimpleSelectQuery.\r\n * @returns An object containing the initial CTE and its alias.\r\n */\r\n private createInitialCte(originalQuery: SimpleSelectQuery): { initialCte: CommonTable, initialCteAlias: string } {\r\n const originCteAlias = \"origin_query\";\r\n const originCte = new CommonTable(\r\n originalQuery,\r\n new SourceAliasExpression(originCteAlias, null),\r\n null\r\n );\r\n return { initialCte: originCte, initialCteAlias: originCteAlias };\r\n }\r\n\r\n /**\r\n * Builds the final SELECT query that constructs the root JSON object (or array of objects).\r\n * This query uses all previously generated CTEs.\r\n * @param finalCtesList The complete list of all CTEs (initial and array CTEs).\r\n * @param lastCteAliasForFromClause Alias of the final CTE from which the root object will be built.\r\n * @param allEntities Map of all processable entities.\r\n * @param mapping JSON mapping configuration.\r\n * @returns The final SimpleSelectQuery.\r\n */\r\n private buildFinalSelectQuery(\r\n finalCtesList: CommonTable[],\r\n lastCteAliasForFromClause: string,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): SimpleSelectQuery {\r\n const currentCtes = [...finalCtesList];\r\n\r\n // Define rootObjectCteAlias outside of if block\r\n const rootObjectCteAlias = `cte_root_${mapping.rootName.toLowerCase().replace(/[^a-z0-9_]/g, '_')}`;\r\n const rootEntity = allEntities.get(mapping.rootEntity.id);\r\n if (!rootEntity) {\r\n throw new Error(`Root entity ${mapping.rootEntity.id} not found`);\r\n }\r\n\r\n if (mapping.resultFormat === \"array\" || !mapping.resultFormat) {\r\n // Step 4.1a: Create a CTE that wraps the final result as the root object\r\n // No alias needed for single table SELECT\r\n const rootObjectBuilderExpression = this.buildEntityJsonObject(\r\n rootEntity,\r\n null, // No source alias for single table\r\n mapping.nestedEntities,\r\n allEntities,\r\n mapping.useJsonb\r\n );\r\n\r\n const rootObjectSelectItem = new SelectItem(rootObjectBuilderExpression, mapping.rootName);\r\n const rootObjectCte = new CommonTable(\r\n new SimpleSelectQuery({\r\n selectClause: new SelectClause([rootObjectSelectItem]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(lastCteAliasForFromClause)),\r\n null // No alias\r\n ),\r\n null\r\n ),\r\n }),\r\n new SourceAliasExpression(rootObjectCteAlias, null),\r\n null\r\n );\r\n currentCtes.push(rootObjectCte);\r\n\r\n // Step 4.1b: Aggregate all the root objects\r\n const aggregationFunc = mapping.useJsonb ? \"jsonb_agg\" : \"json_agg\";\r\n const aggregateExpression = new FunctionCall(\r\n null,\r\n new RawString(aggregationFunc),\r\n new ValueList([new ColumnReference(null, new IdentifierString(mapping.rootName))]),\r\n null\r\n );\r\n\r\n return new SimpleSelectQuery({\r\n withClause: new WithClause(false, currentCtes),\r\n selectClause: new SelectClause([\r\n new SelectItem(aggregateExpression, `${mapping.rootName}_array`)\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(new TableSource(null, new IdentifierString(rootObjectCteAlias)), null),\r\n null\r\n ),\r\n });\r\n } else {\r\n // For a single object result, create root object CTE without alias\r\n const rootObjectBuilderExpression = this.buildEntityJsonObject(\r\n rootEntity,\r\n null, // No source alias for single table\r\n mapping.nestedEntities,\r\n allEntities,\r\n mapping.useJsonb\r\n );\r\n\r\n const rootObjectSelectItem = new SelectItem(rootObjectBuilderExpression, mapping.rootName);\r\n const rootObjectCte = new CommonTable(\r\n new SimpleSelectQuery({\r\n selectClause: new SelectClause([rootObjectSelectItem]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(lastCteAliasForFromClause)),\r\n null // No alias\r\n ),\r\n null\r\n ),\r\n }),\r\n new SourceAliasExpression(rootObjectCteAlias, null),\r\n null\r\n );\r\n currentCtes.push(rootObjectCte);\r\n\r\n // Select directly from the root_object_cte with LIMIT 1\r\n return new SimpleSelectQuery({\r\n withClause: new WithClause(false, currentCtes),\r\n selectClause: new SelectClause([\r\n new SelectItem(new ColumnReference(null, new IdentifierString(mapping.rootName)), mapping.rootName)\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(new TableSource(null, new IdentifierString(rootObjectCteAlias)), null),\r\n null\r\n ),\r\n limitClause: new LimitClause(new LiteralValue(1)) // Correctly use LimitClause\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Build JSON object for entity, using parent JSON columns when available\r\n */\r\n private buildEntityJsonObject(\r\n entity: ProcessableEntity,\r\n sourceAlias: string | null,\r\n nestedEntities: JsonMapping['nestedEntities'],\r\n allEntities: Map<string, ProcessableEntity>,\r\n useJsonb: boolean = false\r\n ): ValueComponent {\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n const args: ValueComponent[] = []; // Add the entity's own columns\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n args.push(new LiteralValue(jsonKey));\r\n args.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n });\r\n\r\n // Find and process child entities (both object and array types)\r\n const childEntities = nestedEntities.filter((ne) => ne.parentId === entity.id);\r\n\r\n childEntities.forEach((childEntity) => {\r\n const child = allEntities.get(childEntity.id);\r\n if (!child) return;\r\n\r\n args.push(new LiteralValue(childEntity.propertyName)); if (childEntity.relationshipType === \"object\") {\r\n // For object relationships, use pre-computed JSON column\r\n const jsonColumnName = `${child.name.toLowerCase()}_json`;\r\n args.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n } else if (childEntity.relationshipType === \"array\") {\r\n // For array relationships, use the column directly\r\n args.push(new ColumnReference(null, new IdentifierString(childEntity.propertyName)));\r\n }\r\n });\r\n\r\n return new FunctionCall(null, new RawString(jsonBuildFunction), new ValueList(args), null);\r\n }\r\n}", "import { SqlComponent, SqlComponentVisitor } from '../models/SqlComponent';\r\nimport { CommonTable, SubQuerySource, TableSource } from '../models/Clause';\r\nimport { SelectClause, SelectItem } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { CTECollector } from './CTECollector';\r\nimport { SelectableColumnCollector, DuplicateDetectionMode } from './SelectableColumnCollector';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\nimport { ColumnReference } from '../models/ValueComponent';\r\nimport { BinarySelectQuery, SelectQuery } from '../models/SelectQuery';\r\nimport { SourceExpression } from '../models/Clause';\r\nimport { TableColumnResolver } from './TableColumnResolver';\r\n\r\nexport class TableSchema {\r\n public name: string;\r\n public columns: string[];\r\n\r\n constructor(name: string, columns: string[]) {\r\n this.name = name;\r\n this.columns = columns;\r\n }\r\n}\r\n\r\n/**\r\n * A visitor that collects schema information (table names and column names) from a SQL query structure.\r\n */\r\nexport class SchemaCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n\r\n private tableSchemas: TableSchema[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private commonTables: CommonTable[] = [];\r\n private running = false;\r\n\r\n constructor(private tableColumnResolver: TableColumnResolver | null = null) {\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for query components\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n }\r\n\r\n /**\r\n * Collects schema information (table names and column names) from a SQL query structure.\r\n * This method ensures that the collected schema information is unique and sorted.\r\n * The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n *\r\n * @param arg The SQL query structure to analyze.\r\n */\r\n public collect(arg: SqlComponent): TableSchema[] {\r\n this.visit(arg);\r\n return this.tableSchemas;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n *\r\n * This method ensures that schema information is collected uniquely and sorted.\r\n * The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n *\r\n * @param arg The SQL component to visit.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (this.running) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.running = true;\r\n\r\n try {\r\n // Ensure the argument is a SelectQuery\r\n if (!(arg instanceof SimpleSelectQuery || arg instanceof BinarySelectQuery)) {\r\n throw new Error(`Unsupported SQL component type for schema collection. Received: ${arg.constructor.name}. Expected: SimpleSelectQuery or BinarySelectQuery.`);\r\n }\r\n\r\n // Collects Common Table Expressions (CTEs) using CTECollector\r\n const cteCollector = new CTECollector();\r\n this.commonTables = cteCollector.collect(arg);\r\n\r\n this.visitNode(arg);\r\n\r\n // Consolidate tableSchemas\r\n this.consolidateTableSchemas();\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.running = false;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // If no handler found, that's ok - we only care about specific components\r\n }\r\n\r\n /**\r\n * Resets the state of the collector for a new root visit.\r\n */\r\n private reset(): void {\r\n this.tableSchemas = [];\r\n this.visitedNodes = new Set();\r\n this.commonTables = [];\r\n }\r\n\r\n /**\r\n * Consolidates table schemas by merging columns for tables with the same name.\r\n * This ensures that each table name appears only once in the final schema list,\r\n * with all its columns combined while removing duplicates.\r\n *\r\n * Note: The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n */\r\n private consolidateTableSchemas(): void {\r\n const consolidatedSchemas: Map<string, Set<string>> = new Map();\r\n\r\n for (const schema of this.tableSchemas) {\r\n if (!consolidatedSchemas.has(schema.name)) {\r\n consolidatedSchemas.set(schema.name, new Set(schema.columns));\r\n } else {\r\n const existingColumns = consolidatedSchemas.get(schema.name);\r\n schema.columns.forEach(column => existingColumns?.add(column));\r\n }\r\n }\r\n\r\n this.tableSchemas = Array.from(consolidatedSchemas.entries())\r\n .sort(([nameA], [nameB]) => nameA.localeCompare(nameB)) // Sort by table name\r\n .map(([name, columns]) => {\r\n return new TableSchema(name, Array.from(columns).sort()); // Sort columns alphabetically\r\n });\r\n }\r\n\r\n private handleTableSource(source: SourceExpression, queryColumns: { table: string, column: string }[], includeUnnamed: boolean): void {\r\n if (source.datasource instanceof TableSource) {\r\n const tableName = source.datasource.getSourceName();\r\n const cte = this.commonTables.filter((table) => table.getSourceAliasName() === tableName);\r\n if (cte.length > 0) {\r\n cte[0].query.accept(this);\r\n } else {\r\n const tableAlias = source.getAliasName() ?? tableName;\r\n this.processCollectTableSchema(tableName, tableAlias, queryColumns, includeUnnamed);\r\n }\r\n } else {\r\n throw new Error(\"Datasource is not an instance of TableSource\");\r\n }\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n if (query.fromClause === null) {\r\n return;\r\n }\r\n\r\n // Collect columns used in the query\r\n const columnCollector = new SelectableColumnCollector(this.tableColumnResolver, true, DuplicateDetectionMode.FullName);\r\n const columns = columnCollector.collect(query);\r\n const queryColumns = columns.filter((column) => column.value instanceof ColumnReference)\r\n .map(column => column.value as ColumnReference)\r\n .map(columnRef => ({\r\n table: columnRef.getNamespace(),\r\n column: columnRef.column.name\r\n }));\r\n\r\n // Throw an error if there are columns without table names in queries with joins\r\n if (query.fromClause.joins !== null && query.fromClause.joins.length > 0) {\r\n const columnsWithoutTable = queryColumns.filter((columnRef) => columnRef.table === \"\").map((columnRef) => columnRef.column);\r\n if (columnsWithoutTable.length > 0) {\r\n throw new Error(`Column reference(s) without table name found in query: ${columnsWithoutTable.join(', ')}`);\r\n }\r\n }\r\n\r\n // Handle the main FROM clause table\r\n if (query.fromClause.source.datasource instanceof TableSource) {\r\n this.handleTableSource(query.fromClause.source, queryColumns, true);\r\n } else if (query.fromClause.source.datasource instanceof SubQuerySource) {\r\n query.fromClause.source.datasource.query.accept(this);\r\n }\r\n\r\n // Handle JOIN clause tables\r\n if (query.fromClause?.joins) {\r\n for (const join of query.fromClause.joins) {\r\n if (join.source.datasource instanceof TableSource) {\r\n this.handleTableSource(join.source, queryColumns, false);\r\n } else if (join.source.datasource instanceof SubQuerySource) {\r\n join.source.datasource.query.accept(this);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // Visit the left and right queries\r\n this.visitNode(query.left);\r\n this.visitNode(query.right);\r\n }\r\n\r\n private processCollectTableSchema(tableName: string, tableAlias: string, queryColumns: { table: string, column: string }[], includeUnnamed: boolean = false): void {\r\n // If a wildcard is present and no resolver is provided, throw an error\r\n if (this.tableColumnResolver === null) {\r\n const hasWildcard = queryColumns\r\n .filter((columnRef) => columnRef.table === tableAlias || (includeUnnamed && columnRef.table === \"\"))\r\n .filter((columnRef) => columnRef.column === \"*\")\r\n .length > 0;\r\n if (hasWildcard) {\r\n const errorMessage = tableName\r\n ? `Wildcard (*) is used. A TableColumnResolver is required to resolve wildcards. Target table: ${tableName}`\r\n : \"Wildcard (*) is used. A TableColumnResolver is required to resolve wildcards.\";\r\n throw new Error(errorMessage);\r\n }\r\n }\r\n\r\n let tableColumns = queryColumns\r\n .filter((columnRef) => columnRef.column !== \"*\")\r\n .filter((columnRef) => columnRef.table === tableAlias || (includeUnnamed && columnRef.table === \"\"))\r\n .map((columnRef) => columnRef.column);\r\n\r\n const tableSchema = new TableSchema(tableName, tableColumns);\r\n this.tableSchemas.push(tableSchema);\r\n }\r\n}\r\n", "import { SelectQuery, SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SelectableColumnCollector } from \"./SelectableColumnCollector\";\r\nimport { BinaryExpression, FunctionCall, ParameterExpression, ParenExpression, ValueComponent, ValueList } from \"../models/ValueComponent\";\r\nimport { UpstreamSelectQueryFinder } from \"./UpstreamSelectQueryFinder\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\n\r\n/**\r\n * SqlParamInjector injects state parameters into a SelectQuery model,\r\n * creating WHERE conditions and setting parameter values.\r\n */\r\nexport class SqlParamInjector {\r\n private tableColumnResolver?: (tableName: string) => string[];\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n\r\n constructor(optionsOrResolver?: { ignoreCaseAndUnderscore?: boolean } | ((tableName: string) => string[]), options?: { ignoreCaseAndUnderscore?: boolean }) {\r\n // Type-check to decide which argument was provided\r\n if (typeof optionsOrResolver === 'function') {\r\n this.tableColumnResolver = optionsOrResolver;\r\n this.options = options || {};\r\n } else {\r\n this.tableColumnResolver = undefined;\r\n this.options = optionsOrResolver || {};\r\n }\r\n }\r\n\r\n /**\r\n * Injects parameters as WHERE conditions into the given query model.\r\n * @param query The SelectQuery to modify\r\n * @param state A record of parameter names and values\r\n * @returns The modified SelectQuery\r\n */\r\n public inject(\r\n query: SimpleSelectQuery | string,\r\n state: Record<string, number | string | boolean | Date | null | undefined | Condition>\r\n ): SelectQuery {\r\n // Convert string query to SimpleSelectQuery using SelectQueryParser if needed\r\n if (typeof query === 'string') {\r\n query = SelectQueryParser.parse(query) as SimpleSelectQuery;\r\n }\r\n\r\n // Pass tableColumnResolver to finder and collector\r\n const finder = new UpstreamSelectQueryFinder(this.tableColumnResolver, this.options);\r\n const collector = new SelectableColumnCollector(this.tableColumnResolver);\r\n // Normalization is handled locally below.\r\n const normalize = (s: string) =>\r\n this.options.ignoreCaseAndUnderscore ? s.toLowerCase().replace(/_/g, '') : s;\r\n\r\n const allowedOps = ['min', 'max', 'like', 'in', 'any', '=', '<', '>', '!=', '<>', '<=', '>='];\r\n\r\n for (const [name, stateValue] of Object.entries(state)) {\r\n // skip undefined values\r\n if (stateValue === undefined) continue;\r\n\r\n const queries = finder.find(query, name);\r\n if (queries.length === 0) {\r\n throw new Error(`Column '${name}' not found in query`);\r\n }\r\n\r\n for (const q of queries) {\r\n const columns = collector.collect(q);\r\n const entry = columns.find(item => normalize(item.name) === normalize(name));\r\n if (!entry) {\r\n throw new Error(`Column '${name}' not found in query`);\r\n }\r\n const columnRef = entry.value;\r\n\r\n // if object, validate its keys\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && Object.getPrototypeOf(stateValue) === Object.prototype) {\r\n validateOperators(stateValue, allowedOps, name);\r\n }\r\n\r\n if (\r\n stateValue === null ||\r\n typeof stateValue !== 'object' ||\r\n Array.isArray(stateValue) ||\r\n stateValue instanceof Date\r\n ) {\r\n injectSimpleCondition(q, columnRef, name, stateValue);\r\n } else {\r\n injectComplexConditions(q, columnRef, name, stateValue);\r\n }\r\n }\r\n }\r\n\r\n function validateOperators(stateValue: object, allowedOps: string[], name: string): void {\r\n Object.keys(stateValue).forEach(op => {\r\n if (!allowedOps.includes(op)) {\r\n throw new Error(`Unsupported operator '${op}' for state key '${name}'`);\r\n }\r\n });\r\n }\r\n\r\n function injectSimpleCondition(q: SimpleSelectQuery, columnRef: ValueComponent, name: string, stateValue: any): void {\r\n const paramExpr = new ParameterExpression(name, stateValue);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", paramExpr));\r\n }\r\n\r\n function injectComplexConditions(q: SimpleSelectQuery, columnRef: ValueComponent, name: string, stateValue: Condition): void {\r\n if ('=' in stateValue) {\r\n const paramEq = new ParameterExpression(name, stateValue['=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", paramEq));\r\n }\r\n if ('min' in stateValue) {\r\n const paramMin = new ParameterExpression(name + \"_min\", stateValue.min);\r\n q.appendWhere(new BinaryExpression(columnRef, \">=\", paramMin));\r\n }\r\n if ('max' in stateValue) {\r\n const paramMax = new ParameterExpression(name + \"_max\", stateValue.max);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<=\", paramMax));\r\n }\r\n if ('like' in stateValue) {\r\n const paramLike = new ParameterExpression(name + \"_like\", stateValue.like);\r\n q.appendWhere(new BinaryExpression(columnRef, \"like\", paramLike));\r\n }\r\n if ('in' in stateValue) {\r\n const arr = stateValue['in'] as (number | string)[];\r\n const prms: ParameterExpression[] = arr.map((v, i) =>\r\n new ParameterExpression(`${name}_in_${i}`, v)\r\n );\r\n q.appendWhere(new BinaryExpression(columnRef, \"in\", new ParenExpression(new ValueList(prms))));\r\n }\r\n if ('any' in stateValue) {\r\n const paramAny = new ParameterExpression(name + \"_any\", stateValue.any);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", new FunctionCall(null, \"any\", paramAny, null)));\r\n }\r\n if ('<' in stateValue) {\r\n const paramLT = new ParameterExpression(name + \"_lt\", stateValue['<']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<\", paramLT));\r\n }\r\n if ('>' in stateValue) {\r\n const paramGT = new ParameterExpression(name + \"_gt\", stateValue['>']);\r\n q.appendWhere(new BinaryExpression(columnRef, \">\", paramGT));\r\n }\r\n if ('!=' in stateValue) {\r\n const paramNEQ = new ParameterExpression(name + \"_neq\", stateValue['!=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"!=\", paramNEQ));\r\n }\r\n if ('<>' in stateValue) {\r\n const paramNE = new ParameterExpression(name + \"_ne\", stateValue['<>']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<>\", paramNE));\r\n }\r\n if ('<=' in stateValue) {\r\n const paramLE = new ParameterExpression(name + \"_le\", stateValue['<=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<=\", paramLE));\r\n }\r\n if ('>=' in stateValue) {\r\n const paramGE = new ParameterExpression(name + \"_ge\", stateValue['>=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \">=\", paramGE));\r\n }\r\n }\r\n\r\n return query;\r\n }\r\n}\r\n\r\n// Define allowed condition keywords for state values (single declaration)\r\ntype Condition = {\r\n '='?: number | string | boolean | Date;\r\n min?: number | string | Date;\r\n max?: number | string | Date;\r\n like?: string;\r\n in?: (number | string | Date)[];\r\n any?: (number | string | Date)[];\r\n '<'?: number | string | Date;\r\n '>'?: number | string | Date;\r\n '!='?: number | string | boolean | Date;\r\n '<>'?: number | string | boolean | Date;\r\n '<='?: number | string | Date;\r\n '>='?: number | string | Date;\r\n};", "import { SchemaCollector, TableSchema } from '../transformers/SchemaCollector';\r\nimport { SqlComponent } from '../models/SqlComponent';\r\nimport { TableColumnResolver } from '../transformers/TableColumnResolver';\r\nimport { SelectQueryParser } from '../parsers/SelectQueryParser';\r\n\r\nexport class SqlSchemaValidator {\r\n /**\r\n * Validates a SQL query structure against a provided TableColumnResolver or TableSchema array.\r\n * @param sql The SQL query structure to validate, can be a SQL string or a SqlComponent.\r\n * @param tableResolver The TableColumnResolver or TableSchema array to validate against.\r\n * @throws Error if the query contains undefined tables or columns.\r\n */\r\n public static validate(\r\n sql: string | SqlComponent,\r\n tableResolver: TableColumnResolver | TableSchema[]\r\n ): void {\r\n const sqlComponent = typeof sql === 'string' ? SelectQueryParser.parse(sql) : sql;\r\n\r\n // Convert TableSchema[] to a resolver function if necessary\r\n const resolver = Array.isArray(tableResolver)\r\n ? (tableName: string) => {\r\n const schema = tableResolver.find((t) => t.name === tableName);\r\n return schema ? schema.columns : [];\r\n }\r\n : tableResolver;\r\n\r\n const schemaCollector = new SchemaCollector(resolver);\r\n const tableSchemas = schemaCollector.collect(sqlComponent);\r\n const errors: string[] = [];\r\n\r\n for (const tableSchema of tableSchemas) {\r\n const resolvedColumns = resolver(tableSchema.name);\r\n if (resolvedColumns.length === 0) {\r\n errors.push(`Table '${tableSchema.name}' is not defined.`);\r\n continue;\r\n }\r\n\r\n const undefinedColumns = tableSchema.columns.filter(column => !resolvedColumns.includes(column));\r\n if (undefinedColumns.length > 0) {\r\n errors.push(\r\n `Table '${tableSchema.name}' contains undefined columns: ${undefinedColumns.join(', ')}.`\r\n );\r\n }\r\n }\r\n\r\n if (errors.length > 0) {\r\n throw new Error(errors.join('\\n'));\r\n }\r\n }\r\n}\r\n", "/**\r\n * Schema Manager for rawsql-ts\r\n * Provides unified schema definition and automatic conversion to various formats\r\n * Eliminates code duplication and provides type-safe schema management\r\n */\r\n\r\n// Import JsonMapping interface for type safety\r\nimport type { JsonMapping } from '../transformers/PostgresJsonQueryBuilder';\r\n\r\n// === Core Types for User-defined Schemas ===\r\n\r\n/**\r\n * Database column metadata for schema mapping\r\n */\r\nexport interface ColumnDefinition {\r\n /** Column name in database */\r\n name: string;\r\n /** Primary key indicator - used for UPDATE/DELETE query WHERE conditions */\r\n isPrimaryKey?: boolean;\r\n /** Foreign key reference */\r\n foreignKey?: {\r\n table: string;\r\n column: string;\r\n };\r\n /** Alias for JSON output (useful for avoiding conflicts) */\r\n jsonAlias?: string;\r\n}\r\n\r\n/**\r\n * Table relationship definition\r\n */\r\nexport interface RelationshipDefinition {\r\n /** Type of relationship */\r\n type: 'object' | 'array';\r\n /** Target table name */\r\n table: string;\r\n /** Property name in JSON output */\r\n propertyName: string;\r\n /** Optional: Override target table's primary key */\r\n targetKey?: string;\r\n}\r\n\r\n/**\r\n * Complete table schema definition that users write\r\n */\r\nexport interface TableDefinition {\r\n /** Table name in database */\r\n name: string;\r\n /** Human-readable entity name */\r\n displayName?: string;\r\n /** Column definitions */\r\n columns: Record<string, ColumnDefinition>;\r\n /** Relationships with other tables */\r\n relationships?: RelationshipDefinition[];\r\n}\r\n\r\n/**\r\n * Schema registry containing all table definitions\r\n */\r\nexport interface SchemaRegistry {\r\n [tableName: string]: TableDefinition;\r\n}\r\n\r\n// === Schema Manager Class ===\r\n\r\n/**\r\n * Central schema management utility for rawsql-ts\r\n * Converts user-defined schemas to various internal formats\r\n */\r\nexport class SchemaManager {\r\n private schemas: SchemaRegistry;\r\n\r\n constructor(schemas: SchemaRegistry) {\r\n this.schemas = schemas;\r\n this.validateSchemas();\r\n }\r\n\r\n /**\r\n * Validate schema definitions for consistency\r\n * Ensures each table has a primary key (required for UPDATE/DELETE operations)\r\n * and validates relationship references\r\n */\r\n private validateSchemas(): void {\r\n const tableNames = Object.keys(this.schemas);\r\n const errors: string[] = [];\r\n\r\n // Validate each table\r\n Object.entries(this.schemas).forEach(([tableName, table]) => {\r\n // Check primary key exists (required for UPDATE/DELETE WHERE conditions)\r\n const primaryKeys = Object.entries(table.columns)\r\n .filter(([_, col]) => col.isPrimaryKey)\r\n .map(([name, _]) => name);\r\n\r\n if (primaryKeys.length === 0) {\r\n errors.push(`Table '${tableName}' has no primary key defined`);\r\n }\r\n\r\n // Validate foreign key references\r\n table.relationships?.forEach(rel => {\r\n if (!tableNames.includes(rel.table)) {\r\n errors.push(`Table '${tableName}' references unknown table '${rel.table}' in relationship`);\r\n }\r\n });\r\n });\r\n\r\n if (errors.length > 0) {\r\n throw new Error(`Schema validation failed:\\\\n${errors.join('\\\\n')}`);\r\n }\r\n }\r\n\r\n /**\r\n * Get table column names for SqlParamInjector TableColumnResolver\r\n * @param tableName Name of the table\r\n * @returns Array of column names\r\n */\r\n public getTableColumns(tableName: string): string[] {\r\n const table = this.schemas[tableName];\r\n if (!table) {\r\n return [];\r\n }\r\n return Object.keys(table.columns);\r\n }\r\n\r\n /**\r\n * Create TableColumnResolver function for SqlParamInjector\r\n * @returns Function compatible with SqlParamInjector\r\n */\r\n public createTableColumnResolver(): (tableName: string) => string[] {\r\n return (tableName: string) => this.getTableColumns(tableName);\r\n }\r\n\r\n /**\r\n * Generate JSON mapping configuration for PostgresJsonQueryBuilder\r\n * @param rootTableName Root table for the JSON structure\r\n * @returns JSON mapping configuration\r\n */\r\n public createJsonMapping(rootTableName: string): JsonMapping {\r\n const rootTable = this.schemas[rootTableName];\r\n if (!rootTable) {\r\n throw new Error(`Table '${rootTableName}' not found in schema registry`);\r\n }\r\n\r\n // Build root entity columns mapping\r\n const rootColumns: Record<string, string> = {};\r\n Object.entries(rootTable.columns).forEach(([columnName, column]) => {\r\n rootColumns[columnName] = column.jsonAlias || column.name;\r\n });\r\n\r\n // Build nested entities from relationships\r\n const nestedEntities: JsonMapping['nestedEntities'] = [];\r\n\r\n rootTable.relationships?.forEach(rel => {\r\n const relatedTable = this.schemas[rel.table];\r\n if (!relatedTable) {\r\n throw new Error(`Related table '${rel.table}' not found in schema registry`);\r\n }\r\n\r\n // Build columns mapping for related table\r\n const relatedColumns: Record<string, string> = {};\r\n Object.entries(relatedTable.columns).forEach(([columnName, column]) => {\r\n relatedColumns[columnName] = column.jsonAlias || column.name;\r\n });\r\n\r\n // Determine relationship type for JSON builder\r\n const relationshipType = rel.type;\r\n\r\n nestedEntities.push({\r\n id: rel.propertyName,\r\n name: relatedTable.displayName || rel.table,\r\n parentId: rootTableName,\r\n propertyName: rel.propertyName,\r\n relationshipType: relationshipType as 'object' | 'array',\r\n columns: relatedColumns\r\n });\r\n });\r\n\r\n return {\r\n rootName: rootTableName,\r\n rootEntity: {\r\n id: rootTableName,\r\n name: rootTable.displayName || rootTableName,\r\n columns: rootColumns\r\n },\r\n nestedEntities,\r\n useJsonb: true,\r\n resultFormat: \"single\" as const\r\n };\r\n }\r\n\r\n /**\r\n * Get all table names in the schema\r\n * @returns Array of table names\r\n */\r\n public getTableNames(): string[] {\r\n return Object.keys(this.schemas);\r\n }\r\n\r\n /**\r\n * Get table definition by name\r\n * @param tableName Name of the table\r\n * @returns Table definition or undefined\r\n */\r\n public getTable(tableName: string): TableDefinition | undefined {\r\n return this.schemas[tableName];\r\n }\r\n\r\n /**\r\n * Get primary key column name for a table\r\n * Used by QueryBuilder.buildUpdateQuery for WHERE clause conditions\r\n * @param tableName Name of the table\r\n * @returns Primary key column name or undefined\r\n */\r\n public getPrimaryKey(tableName: string): string | undefined {\r\n const table = this.schemas[tableName];\r\n if (!table) return undefined;\r\n\r\n const primaryKeyEntry = Object.entries(table.columns)\r\n .find(([_, col]) => col.isPrimaryKey);\r\n\r\n return primaryKeyEntry ? primaryKeyEntry[0] : undefined;\r\n }\r\n\r\n /**\r\n * Get foreign key relationships for a table\r\n * @param tableName Name of the table\r\n * @returns Array of foreign key relationships\r\n */\r\n public getForeignKeys(tableName: string): Array<{ column: string; referencedTable: string; referencedColumn: string }> {\r\n const table = this.schemas[tableName];\r\n if (!table) return [];\r\n\r\n const foreignKeys: Array<{ column: string; referencedTable: string; referencedColumn: string }> = [];\r\n\r\n Object.entries(table.columns).forEach(([columnName, column]) => {\r\n if (column.foreignKey) {\r\n foreignKeys.push({\r\n column: columnName,\r\n referencedTable: column.foreignKey.table,\r\n referencedColumn: column.foreignKey.column\r\n });\r\n }\r\n });\r\n\r\n return foreignKeys;\r\n }\r\n}\r\n\r\n// === Convenience Functions ===\r\n\r\n/**\r\n * Create a SchemaManager instance from schema definitions\r\n * @param schemas Schema registry object\r\n * @returns SchemaManager instance\r\n */\r\nexport function createSchemaManager(schemas: SchemaRegistry): SchemaManager {\r\n return new SchemaManager(schemas);\r\n}\r\n\r\n/**\r\n * Create TableColumnResolver function from schema definitions\r\n * @param schemas Schema registry object\r\n * @returns TableColumnResolver function for SqlParamInjector\r\n */\r\nexport function createTableColumnResolver(schemas: SchemaRegistry): (tableName: string) => string[] {\r\n const manager = new SchemaManager(schemas);\r\n return manager.createTableColumnResolver();\r\n}\r\n\r\n/**\r\n * Create JSON mapping from schema definitions\r\n * @param schemas Schema registry object\r\n * @param rootTableName Root table name\r\n * @returns JSON mapping for PostgresJsonQueryBuilder\r\n */\r\nexport function createJsonMappingFromSchema(schemas: SchemaRegistry, rootTableName: string): JsonMapping {\r\n const manager = new SchemaManager(schemas);\r\n return manager.createJsonMapping(rootTableName);\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["src_exports", "__export", "ArrayExpression", "ArrayQueryExpression", "BetweenExpression", "BinaryExpression", "BinarySelectQuery", "CTECollector", "CTENormalizer", "CaseExpression", "CaseKeyValuePair", "CastExpression", "ColumnReference", "DuplicateDetectionMode", "Formatter", "FunctionCall", "IdentifierString", "InlineQuery", "InsertQuery", "InsertQueryParser", "LiteralValue", "ParameterExpression", "ParenExpression", "PostgresJsonQueryBuilder", "QualifiedName", "QueryBuilder", "RawString", "SchemaCollector", "SchemaManager", "SelectQueryParser", "SelectValueCollector", "SelectableColumnCollector", "SimpleSelectQuery", "SqlFormatter", "SqlParamInjector", "SqlSchemaValidator", "StringSpecifierExpression", "SwitchCaseArgument", "TableSchema", "TableSourceCollector", "TupleExpression", "TypeValue", "UnaryExpression", "UpstreamSelectQueryFinder", "VALID_PRESETS", "ValueList", "ValuesQuery", "WindowFrameBound", "WindowFrameBoundStatic", "WindowFrameBoundaryValue", "WindowFrameExpression", "WindowFrameSpec", "WindowFrameType", "createJsonMappingFromSchema", "createSchemaManager", "createTableColumnResolver", "__toCommonJS", "SqlComponent", "visitor", "formatter", "InsertQuery", "SqlComponent", "params", "InlineQuery", "SqlComponent", "selectQuery", "ValueList", "values", "ColumnReference", "IdentifierString", "namespaces", "column", "col", "QualifiedName", "toIdentifierStringArray", "namespace", "FunctionCall", "name", "argument", "over", "WindowFrameType", "WindowFrameBound", "WindowFrameBoundStatic", "bound", "WindowFrameBoundaryValue", "value", "isFollowing", "WindowFrameSpec", "frameType", "startBound", "endBound", "WindowFrameExpression", "partition", "order", "frameSpec", "UnaryExpression", "operator", "expression", "RawString", "BinaryExpression", "left", "right", "LiteralValue", "ParameterExpression", "SwitchCaseArgument", "cases", "elseValue", "CaseKeyValuePair", "key", "alias", "ParenExpression", "CastExpression", "input", "castType", "CaseExpression", "condition", "switchCase", "ArrayExpression", "ArrayQueryExpression", "query", "BetweenExpression", "lower", "upper", "negated", "StringSpecifierExpression", "specifier", "TypeValue", "nameValue", "ns", "TupleExpression", "filteredStrings", "filteredIdentifiers", "SelectItem", "SqlComponent", "value", "name", "IdentifierString", "SelectClause", "items", "distinct", "Distinct", "DistinctOn", "WhereClause", "condition", "PartitionByClause", "WindowFrameClause", "expression", "WindowsClause", "windows", "OrderByClause", "SqlComponent", "items", "OrderByItem", "expression", "sortDirection", "nullsPosition", "GroupByClause", "HavingClause", "condition", "TableSource", "IdentifierString", "namespaces", "table", "tbl", "QualifiedName", "namespace", "RawString", "FunctionSource", "name", "argument", "nameObj", "ParenSource", "source", "SubQuerySource", "query", "SourceExpression", "datasource", "aliasExpression", "JoinOnClause", "JoinUsingClause", "JoinClause", "joinType", "lateral", "FromClause", "join", "sources", "CommonTable", "materialized", "SourceAliasExpression", "WithClause", "recursive", "tables", "LimitClause", "limit", "OffsetClause", "SqlComponent", "value", "FetchClause", "expression", "FetchExpression", "type", "count", "unit", "ForClause", "SqlComponent", "lockMode", "SourceAliasExpression", "alias", "columnAlias", "IdentifierString", "ReturningClause", "columns", "col", "SetClause", "items", "item", "SetClauseItem", "column", "value", "colObj", "QualifiedName", "UpdateClause", "source", "TableSource", "InsertClause", "TokenType", "CharLookupTable", "char", "code", "StringUtils", "_StringUtils", "input", "errPosition", "start", "end", "debugInfo", "caret", "position", "length", "charCode", "comment", "lines", "i", "oldPosition", "lineCommentResult", "blockCommentResult", "result", "CharLookupTable", "BaseTokenReader", "input", "position", "shift", "expectChar", "char", "type", "value", "comments", "errPosition", "StringUtils", "IdentifierTokenReader", "BaseTokenReader", "previous", "char", "result", "StringUtils", "KeywordParser", "trie", "input", "position", "shift", "result", "StringUtils", "matchResult", "lexeme", "previousMatchResult", "KeywordTrie", "keywords", "keyword", "node", "word", "lexeme", "keywords", "trie", "KeywordTrie", "literalKeywordParser", "KeywordParser", "LiteralTokenReader", "BaseTokenReader", "previous", "char", "keyword", "CharLookupTable", "value", "sign", "pos", "result", "start", "hasDot", "hasExponent", "prefixType", "isHex", "c", "includeSingleQuote", "closed", "ParameterTokenReader", "BaseTokenReader", "input", "previous", "start", "identifier", "char", "CharLookupTable", "SpecialSymbolTokenReader", "_SpecialSymbolTokenReader", "BaseTokenReader", "previous", "char", "TokenReaderManager", "input", "position", "reader", "readers", "previous", "lexeme", "maxPosition", "total", "ratio", "trie", "KeywordTrie", "operatorOrTypeTrie", "keywordParser", "KeywordParser", "operatorOrTypeParser", "OperatorTokenReader", "BaseTokenReader", "previous", "char", "CharLookupTable", "start", "current", "resut", "result", "operatorOrTypeParser", "keywordParser", "joinTrie", "KeywordTrie", "keywordTrie", "keywordParser", "KeywordParser", "joinkeywordParser", "CommandTokenReader", "BaseTokenReader", "previous", "keywordJoin", "keyword", "start", "STRING_SPECIFIERS", "UNICODE_STRING_SPECIFIERS", "StringSpecifierTokenReader", "BaseTokenReader", "previous", "start", "trie", "KeywordTrie", "keywordParser", "KeywordParser", "FunctionTokenReader", "BaseTokenReader", "previous", "keyword", "result", "StringUtils", "shift", "trie", "KeywordTrie", "typeParser", "KeywordParser", "TypeTokenReader", "BaseTokenReader", "previous", "keyword", "result", "StringUtils", "EscapedIdentifierTokenReader", "BaseTokenReader", "previous", "char", "identifier", "delimiter", "start", "SqlTokenizer", "input", "TokenReaderManager", "EscapedIdentifierTokenReader", "ParameterTokenReader", "StringSpecifierTokenReader", "LiteralTokenReader", "SpecialSymbolTokenReader", "CommandTokenReader", "OperatorTokenReader", "TypeTokenReader", "FunctionTokenReader", "IdentifierTokenReader", "shift", "estimatedTokens", "lexemes", "lexemeCount", "comment", "pendingComments", "previous", "lexeme", "currentComment", "lastToken", "prefixComments", "suffixComments", "StringUtils", "errPosition", "FullNameParser", "_FullNameParser", "lexemes", "index", "identifiers", "newIndex", "namespaces", "name", "lastTokenType", "IdentifierString", "str", "SqlTokenizer", "result", "idx", "IdentifierParser", "lexemes", "index", "namespaces", "name", "newIndex", "FullNameParser", "ColumnReference", "LiteralParser", "lexemes", "index", "idx", "valueText", "parsedValue", "lex", "literalKeywordParser", "value", "RawString", "LiteralValue", "ParenExpressionParser", "lexemes", "index", "idx", "result", "SelectQueryParser", "InlineQuery", "ValueParser", "ParenExpression", "UnaryExpressionParser", "lexemes", "index", "idx", "operator", "ColumnReference", "result", "ValueParser", "UnaryExpression", "ParameterExpressionParser", "lexemes", "index", "idx", "paramName", "value", "ParameterExpression", "StringSpecifierExpressionParser", "lexemes", "index", "idx", "specifer", "value", "StringSpecifierExpression", "CommandExpressionParser", "lexemes", "index", "idx", "current", "command", "result", "ValueParser", "UnaryExpression", "condition", "switchCaseResult", "CaseExpression", "casewhenResult", "caseWhenList", "initialWhenThenList", "whenThenList", "elseValue", "whenResult", "elseResult", "SwitchCaseArgument", "lexeme", "value", "CaseKeyValuePair", "OrderByClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "OrderByClause", "parsedValue", "ValueParser", "value", "sortDirection", "nullsSortDirection", "OrderByItem", "PartitionByParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "ValueParser", "PartitionByClause", "ValueList", "WindowExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "partition", "order", "frameSpec", "partitionResult", "PartitionByParser", "orderResult", "OrderByClauseParser", "frameSpecResult", "WindowFrameExpression", "value", "lowerValue", "frameTypeStr", "frameType", "startBoundResult", "startBound", "endBoundResult", "endBound", "WindowFrameSpec", "boundaryResult", "currentValue", "frameBound", "WindowFrameBoundStatic", "valueResult", "ValueParser", "direction", "isFollowing", "WindowFrameBoundaryValue", "OverExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "name", "IdentifierString", "WindowExpressionParser", "FunctionExpressionParser", "lexemes", "index", "idx", "arg", "ValueParser", "ArrayExpression", "SelectQueryParser", "ArrayQueryExpression", "current", "left", "allowAndOperator", "allowOrOperator", "operator", "typeValue", "CastExpression", "rightResult", "BinaryExpression", "value", "negated", "lower", "upper", "BetweenExpression", "fullNameResult", "FullNameParser", "namespaces", "name", "over", "OverExpressionParser", "FunctionCall", "keywords", "input", "key", "required", "right", "newIndex", "TypeValue", "RawString", "ParseError", "_ParseError", "message", "index", "context", "lexemes", "messagePrefix", "start", "end", "lexeme", "idx", "marker", "typeName", "TokenType", "OperatorPrecedence", "operator", "precedence", "operator1", "operator2", "op", "lowerOp", "ValueParser", "query", "lexemes", "SqlTokenizer", "result", "ParseError", "index", "allowAndOperator", "allowOrOperator", "minPrecedence", "idx", "comment", "left", "operator", "precedence", "OperatorPrecedence", "betweenResult", "FunctionExpressionParser", "typeValue", "CastExpression", "nextMinPrecedence", "rightResult", "BinaryExpression", "current", "first", "IdentifierParser", "second", "LiteralParser", "UnaryExpression", "namespaces", "name", "newIndex", "FullNameParser", "ColumnReference", "ParenExpressionParser", "UnaryExpressionParser", "ParameterExpressionParser", "StringSpecifierExpressionParser", "CommandExpressionParser", "TypeValue", "openToken", "closeToken", "args", "ValueList", "wildcard", "argResult", "CTECollector", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "WithClause", "CommonTable", "SelectItem", "IdentifierString", "RawString", "ColumnReference", "ParameterExpression", "LiteralValue", "SourceExpression", "TableSource", "FunctionSource", "ParenSource", "SubQuerySource", "InlineQuery", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "WindowFrameExpression", "WindowFrameSpec", "TypeValue", "ValueList", "StringSpecifierExpression", "SelectClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "ForClause", "OrderByItem", "PartitionByClause", "query", "arg", "handler", "kindSymbol", "constructor", "win", "tuple", "withClause", "i", "commonTable", "clause", "item", "fromClause", "join", "source", "subQuery", "inlineQuery", "joinClause", "joinOn", "joinUsing", "whereClause", "switchCase", "caseItem", "pair", "func", "value", "spec", "ident", "raw", "column", "param", "partitionBy", "valueList", "CTEDisabler", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "SelectItem", "IdentifierString", "RawString", "ColumnReference", "ParameterExpression", "LiteralValue", "SourceExpression", "TableSource", "ParenSource", "SubQuerySource", "InlineQuery", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "WindowFrameExpression", "WindowFrameSpec", "TypeValue", "SelectClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "ForClause", "OrderByItem", "arg", "handler", "kindSymbol", "constructor", "table", "WindowsClause", "w", "query", "newTuples", "tuple", "clause", "newItems", "item", "newSource", "newJoins", "join", "subQuery", "newQuery", "inlineQuery", "joinClause", "newCondition", "joinOn", "joinUsing", "whereClause", "newGrouping", "newOrder", "newExpression", "newLimit", "newLeft", "newRight", "newSwitchCase", "switchCase", "newCases", "caseItem", "newElseValue", "pair", "newKey", "newValue", "newLower", "newUpper", "func", "newArgument", "newOver", "newValues", "value", "newInput", "newCastType", "typeValue", "ident", "raw", "column", "source", "newAlias", "param", "newPartition", "newFrameSpec", "spec", "TableSourceCollector", "selectableOnly", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "WithClause", "CommonTable", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "SourceExpression", "TableSource", "FunctionSource", "ParenSource", "SubQuerySource", "InlineQuery", "WhereClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "ForClause", "OrderByItem", "SelectClause", "SelectItem", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "ValueList", "StringSpecifierExpression", "source", "ns", "RawString", "query", "arg", "handler", "cteCollector", "CTECollector", "commonTables", "cte", "win", "tuple", "withClause", "table", "commonTable", "fromClause", "join", "identifier", "value", "tableName", "subQuery", "inlineQuery", "joinClause", "joinOn", "joinUsing", "whereClause", "clause", "item", "switchCase", "caseItem", "pair", "func", "valueList", "SqlPrintToken", "type", "text", "containerType", "ParameterCollector", "node", "result", "walk", "n", "ParameterExpression", "key", "v", "IdentifierDecorator", "identifierEscape", "text", "ParameterDecorator", "options", "text", "index", "paramText", "UpdateQuery", "SqlComponent", "params", "SetClause", "SelectValueCollector", "_SelectValueCollector", "tableColumnResolver", "initialCommonTables", "CTECollector", "SimpleSelectQuery", "expr", "SelectClause", "SourceExpression", "FromClause", "arg", "items", "handler", "query", "wildcards", "item", "ColumnReference", "wildSourceNames", "fromSourceName", "join", "joinSourceName", "clause", "joinCascade", "sourceName", "source", "commonTable", "innerCommonTables", "columnName", "column", "TableSource", "SubQuerySource", "ParenSource", "name", "value", "CreateTableQuery", "SqlComponent", "params", "IdentifierString", "selectItems", "SelectValueCollector", "val", "SelectItem", "RawString", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "FunctionCall", "ColumnReference", "PRESETS", "SqlPrintTokenParser", "_SqlPrintTokenParser", "options", "ParameterDecorator", "IdentifierDecorator", "ValueList", "expr", "ColumnReference", "QualifiedName", "FunctionCall", "UnaryExpression", "BinaryExpression", "LiteralValue", "ParameterExpression", "SwitchCaseArgument", "CaseKeyValuePair", "RawString", "IdentifierString", "ParenExpression", "CastExpression", "CaseExpression", "ArrayExpression", "ArrayQueryExpression", "BetweenExpression", "StringSpecifierExpression", "TypeValue", "TupleExpression", "InlineQuery", "WindowFrameExpression", "WindowFrameSpec", "WindowFrameBoundStatic", "WindowFrameBoundaryValue", "PartitionByClause", "OrderByClause", "OrderByItem", "SelectItem", "SelectClause", "Distinct", "DistinctOn", "TableSource", "FunctionSource", "SourceExpression", "SourceAliasExpression", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "GroupByClause", "HavingClause", "WindowsClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "FetchExpression", "ForClause", "WithClause", "CommonTable", "SimpleSelectQuery", "SubQuerySource", "BinarySelectQuery", "ValuesQuery", "InsertQuery", "InsertClause", "UpdateQuery", "UpdateClause", "SetClause", "SetClauseItem", "ReturningClause", "CreateTableQuery", "SqlPrintToken", "arg", "token", "i", "paramsRaw", "ParameterCollector", "a", "b", "style", "paramsObj", "p", "key", "paramsArr", "handler", "text", "kv", "elseValue", "elseToken", "elseValueContainer", "thenValueContainer", "specifier", "value", "first", "defaultName", "fullName", "ns", "query", "subQuery", "values", "queryToken", "LinePrinter", "indentChar", "indentSize", "newline", "result", "line", "level", "current", "PrintLine", "text", "workingIndex", "workLine", "SqlPrinter", "options", "LinePrinter", "token", "level", "current", "text", "i", "keywordToken", "innerLevel", "child", "VALID_PRESETS", "SqlFormatter", "options", "presetConfig", "PRESETS", "parserOptions", "SqlPrintTokenParser", "SqlPrinter", "sql", "token", "params", "Formatter", "SqlFormatter", "arg", "config", "result", "CTEBuilder", "TableSourceCollector", "CTECollector", "Formatter", "commonTables", "WithClause", "resolvedTables", "tableMap", "recursiveCTEs", "dependencies", "sortedTables", "ctesByName", "table", "tableName", "name", "tables", "definitions", "referencedBy", "referencedTables", "referencedTable", "referencedCTEs", "referencedCTE", "referencedName", "recursiveResult", "nonRecursiveResult", "visited", "visiting", "visit", "deps", "dep", "CTEInjector", "CTEBuilder", "CTECollector", "query", "commonTables", "resolvedWithCaluse", "SimpleSelectQuery", "BinarySelectQuery", "withClause", "CTENormalizer", "query", "allCommonTables", "CTECollector", "CTEDisabler", "CTEInjector", "DuplicateDetectionMode", "SelectableColumnCollector", "tableColumnResolver", "includeWildCard", "duplicateDetection", "options", "CTECollector", "SimpleSelectQuery", "expr", "SelectClause", "FromClause", "WhereClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "JoinOnClause", "JoinUsingClause", "ColumnReference", "BinaryExpression", "UnaryExpression", "FunctionCall", "ParenExpression", "CaseExpression", "CastExpression", "BetweenExpression", "ArrayExpression", "ArrayQueryExpression", "ValueList", "WindowFrameExpression", "PartitionByClause", "arg", "items", "name", "value", "item", "tableName", "key", "itemTable", "handler", "query", "win", "clause", "sourceValues", "SelectValueCollector", "join", "joinOnClause", "joinUsingClause", "columnRef", "func", "SourceParser", "_SourceParser", "query", "lexemes", "SqlTokenizer", "result", "index", "fullNameResult", "FullNameParser", "idx", "namespaces", "name", "newIndex", "TableSource", "argument", "ValueParser", "functionName", "FunctionSource", "keyword", "selectQuery", "SelectQueryParser", "SubQuerySource", "UpstreamSelectQueryFinder", "tableColumnResolver", "options", "SelectableColumnCollector", "query", "columnNames", "namesArray", "ctes", "CTECollector", "cteMap", "cte", "src", "nextCteMap", "result", "fromClause", "sources", "allBranchResults", "allBranchesOk", "validBranchCount", "sourceExpr", "branchResult", "TableSource", "SubQuerySource", "ValuesQuery", "SimpleSelectQuery", "columns", "col", "normalize", "s", "name", "BinarySelectQuery", "left", "right", "SourceAliasExpressionParser", "lexemes", "index", "idx", "table", "columns", "SourceAliasExpression", "SourceExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "SourceParser", "SourceExpression", "idx", "sourceResult", "aliasResult", "SourceAliasExpressionParser", "type", "QueryBuilder", "_QueryBuilder", "queries", "operator", "wrap", "q", "ValuesQuery", "result", "BinarySelectQuery", "CTENormalizer", "i", "query", "SimpleSelectQuery", "subQuerySource", "SubQuerySource", "sourceExpr", "SourceExpression", "SourceAliasExpression", "fromClause", "FromClause", "selectClause", "columnCount", "selectItems", "name", "SelectItem", "ColumnReference", "SelectClause", "columnRef", "selectItem", "tableName", "isTemporary", "CreateTableQuery", "selectQuery", "cols", "count", "SelectValueCollector", "item", "SourceExpressionParser", "InsertQuery", "InsertClause", "selectSourceName", "updateTableExprRaw", "primaryKeys", "updateClause", "UpdateClause", "pkArray", "collectedCTEs", "CTECollector", "CTEDisabler", "pk", "updateSourceName", "setItems", "col", "SetClauseItem", "setClause", "SetClause", "from", "where", "cond", "BinaryExpression", "whereClause", "WhereClause", "UpdateQuery", "WithClause", "ParameterHelper", "query", "name", "value", "params", "ParameterCollector", "found", "p", "SimpleSelectQuery", "SqlComponent", "params", "rightQuery", "operator", "QueryBuilder", "rawCondition", "parsedCondition", "ValueParser", "condition", "BinaryExpression", "WhereClause", "HavingClause", "joinSourceRawText", "alias", "columns", "resolver", "sourceExpr", "joinType", "tableSource", "SourceParser", "SourceExpression", "SourceAliasExpression", "columnsArr", "valueSets", "SelectableColumnCollector", "joinCondition", "count", "sourceAlias", "valueSet", "col", "expr", "ColumnReference", "joinOnClause", "JoinOnClause", "joinClause", "JoinClause", "CTENormalizer", "SubQuerySource", "commonTable", "tables", "WithClause", "rawText", "query", "SelectQueryParser", "CommonTable", "columnName", "fn", "items", "item", "exprSql", "Formatter", "newValue", "exprBuilder", "options", "queries", "UpstreamSelectQueryFinder", "collector", "formatter", "q", "exprs", "exprStr", "name", "value", "ParameterHelper", "BinarySelectQuery", "_BinarySelectQuery", "SqlComponent", "left", "operator", "right", "RawString", "query", "CTENormalizer", "sql", "parsedQuery", "SelectQueryParser", "alias", "SourceExpression", "SubQuerySource", "SourceAliasExpression", "name", "value", "ParameterHelper", "ValuesQuery", "SqlComponent", "tuples", "columnAliases", "QueryBuilder", "name", "value", "ParameterHelper", "SelectClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "distinct", "Distinct", "argument", "ValueParser", "DistinctOn", "items", "item", "SelectItemParser", "SelectClause", "parsedValue", "value", "alias", "SelectItem", "ColumnReference", "JoinOnClauseParser", "lexemes", "index", "idx", "condition", "ValueParser", "JoinOnClause", "JoinUsingClauseParser", "lexemes", "index", "idx", "result", "ValueParser", "usingColumns", "JoinUsingClause", "JoinClauseParser", "lexemes", "index", "idx", "joins", "joinClause", "value", "joinkeywordParser", "joinType", "lateralResult", "lateral", "sourceResult", "SourceExpressionParser", "onResult", "JoinOnClauseParser", "JoinClause", "usingResult", "JoinUsingClauseParser", "FromClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "sourceExpression", "SourceExpressionParser", "join", "JoinClauseParser", "FromClause", "WhereClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "item", "ValueParser", "WhereClause", "GroupByClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "GroupByClause", "parsedValue", "ValueParser", "value", "HavingClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "item", "ValueParser", "HavingClause", "WindowClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "windows", "name", "expr", "WindowExpressionParser", "WindowFrameClause", "WindowsClause", "LimitClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "limitItem", "ValueParser", "LimitClause", "ForClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "lockModeValue", "lockMode", "ForClause", "CommonTableParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "aliasResult", "SourceAliasExpressionParser", "materialized", "currentValue", "queryResult", "SelectQueryParser", "CommonTable", "WithClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "recursive", "tables", "firstCte", "CommonTableParser", "cteResult", "WithClause", "ValuesQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "tuples", "firstTuple", "tuple", "ValuesQuery", "values", "TupleExpression", "firstValue", "ValueParser", "value", "FetchClauseParser", "lexemes", "index", "idx", "fetchExprResult", "FetchExpressionParser", "fetchExpr", "FetchClause", "type", "typeToken", "count", "unit", "LiteralValue", "FetchExpression", "countResult", "ValueParser", "OffsetClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "offsetItem", "ValueParser", "OffsetClause", "SelectQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "firstToken", "firstResult", "operator", "nextToken", "BinarySelectQuery", "withClauseResult", "WithClauseParser", "selectClauseResult", "SelectClauseParser", "fromClauseResult", "FromClauseParser", "whereClauseResult", "WhereClauseParser", "groupByClauseResult", "GroupByClauseParser", "havingClauseResult", "HavingClauseParser", "windowClauseResult", "WindowClauseParser", "orderByClauseResult", "OrderByClauseParser", "limitClauseResult", "LimitClauseParser", "offsetClauseResult", "OffsetClauseParser", "fetchClauseResult", "FetchClauseParser", "forClauseResult", "ForClauseParser", "SimpleSelectQuery", "ValuesQueryParser", "InsertQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "withclause", "WithClauseParser", "sourceResult", "SourceExpressionParser", "columns", "selectResult", "SelectQueryParser", "SimpleSelectQuery", "InsertQuery", "InsertClause", "PostgresObjectEntityCteBuilder", "_PostgresObjectEntityCteBuilder", "initialCte", "allEntities", "mapping", "ctes", "previousCteAlias", "objectEntityInfos", "entitiesByDepth", "depths", "a", "b", "depth", "entitiesAtDepth", "cteAlias", "cte", "objectInfos", "calculateActualObjectNestingDepth", "entityIdOfObject", "initialEntity", "currentParentIdInHierarchy", "calculatedObjectDepth", "visitedInPath", "parentEntityData", "parentIsConsideredAnObjectForNesting", "parentDefinition", "ne", "nestedEntity", "entity", "info", "selectItems", "SelectItem", "ColumnReference", "IdentifierString", "jsonColumn", "cteSelect", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "CommonTable", "SourceAliasExpression", "jsonObjectArgs", "nullChecks", "jsonObject", "nullCondition", "caseExpr", "jsonColumnName", "jsonKey", "sqlColumn", "LiteralValue", "BinaryExpression", "childEntity", "child", "args", "useJsonb", "jsonBuildFunction", "FunctionCall", "RawString", "ValueList", "acc", "check", "CaseExpression", "SwitchCaseArgument", "CaseKeyValuePair", "PostgresArrayEntityCteBuilder", "_PostgresArrayEntityCteBuilder", "ctesSoFar", "aliasOfCteToBuildUpon", "allEntities", "mapping", "currentCtes", "currentCteAlias", "sortedArrayInfos", "entitiesByDepth", "depths", "a", "b", "depth", "infos", "cte", "newCteAlias", "arrayEntityInfos", "getDepth", "entityId", "entity", "ne", "currentArrayEntity", "parentEntity", "parentSqlColumns", "parentIdColumnSqlName", "arrayInfos", "info", "arrayColumns", "col", "prevCte", "c", "prevSelects", "SelectValueCollector", "groupByItems", "selectItems", "sv", "SelectItem", "ColumnReference", "IdentifierString", "agg", "cteAlias", "cteSelect", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "GroupByClause", "CommonTable", "SourceAliasExpression", "nestedEntities", "useJsonb", "jsonBuildFunction", "args", "jsonKey", "sqlColumn", "LiteralValue", "childEntity", "jsonColumnName", "jsonObject", "FunctionCall", "RawString", "ValueList", "jsonAggFunction", "PostgresJsonQueryBuilder", "SelectValueCollector", "PostgresObjectEntityCteBuilder", "PostgresArrayEntityCteBuilder", "query", "mapping", "selectedValues", "availableColumns", "sv", "jsonKey", "sourceColumn", "entityIds", "parentToChildrenMap", "ne", "entity", "allParentIds", "parentId", "directChildren", "c", "parentName", "propertyNames", "child", "originalQuery", "initialCte", "initialCteAlias", "ctesForProcessing", "currentAliasToBuildUpon", "allEntities", "objectEntityResult", "arrayCteBuildResult", "originCteAlias", "CommonTable", "SourceAliasExpression", "finalCtesList", "lastCteAliasForFromClause", "currentCtes", "rootObjectCteAlias", "rootEntity", "rootObjectBuilderExpression", "rootObjectSelectItem", "SelectItem", "rootObjectCte", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "IdentifierString", "aggregationFunc", "aggregateExpression", "FunctionCall", "RawString", "ValueList", "ColumnReference", "WithClause", "LimitClause", "LiteralValue", "sourceAlias", "nestedEntities", "useJsonb", "jsonBuildFunction", "args", "sqlColumn", "childEntity", "jsonColumnName", "TableSchema", "name", "columns", "SchemaCollector", "tableColumnResolver", "SimpleSelectQuery", "expr", "BinarySelectQuery", "arg", "cteCollector", "CTECollector", "handler", "consolidatedSchemas", "schema", "existingColumns", "column", "nameA", "nameB", "source", "queryColumns", "includeUnnamed", "TableSource", "tableName", "cte", "table", "tableAlias", "query", "SelectableColumnCollector", "ColumnReference", "columnRef", "columnsWithoutTable", "SubQuerySource", "join", "errorMessage", "tableColumns", "tableSchema", "SqlParamInjector", "optionsOrResolver", "options", "query", "state", "SelectQueryParser", "finder", "UpstreamSelectQueryFinder", "collector", "SelectableColumnCollector", "normalize", "s", "allowedOps", "name", "stateValue", "queries", "q", "entry", "item", "columnRef", "validateOperators", "injectSimpleCondition", "injectComplexConditions", "op", "paramExpr", "ParameterExpression", "BinaryExpression", "paramEq", "paramMin", "paramMax", "paramLike", "prms", "v", "i", "ParenExpression", "ValueList", "paramAny", "FunctionCall", "paramLT", "paramGT", "paramNEQ", "paramNE", "paramLE", "paramGE", "SqlSchemaValidator", "sql", "tableResolver", "sqlComponent", "SelectQueryParser", "resolver", "tableName", "schema", "t", "tableSchemas", "SchemaCollector", "errors", "tableSchema", "resolvedColumns", "undefinedColumns", "column", "SchemaManager", "schemas", "tableNames", "errors", "tableName", "table", "_", "col", "name", "rel", "rootTableName", "rootTable", "rootColumns", "columnName", "column", "nestedEntities", "relatedTable", "relatedColumns", "relationshipType", "primaryKeyEntry", "foreignKeys", "createSchemaManager", "createTableColumnResolver", "createJsonMappingFromSchema"]
4
+ "sourcesContent": ["// Entry point for rawsql-ts package\r\nexport * from './parsers/SelectQueryParser';\r\nexport * from './parsers/InsertQueryParser';\r\n\r\nexport * from './models/BinarySelectQuery';\r\nexport * from './models/SelectQuery';\r\nexport * from './models/ValueComponent';\r\nexport * from './models/ValuesQuery';\r\n\r\nexport * from './transformers/CTECollector';\r\nexport * from './transformers/CTENormalizer';\r\nexport * from './transformers/Formatter';\r\nexport * from './transformers/SqlFormatter';\r\nexport * from './transformers/PostgresJsonQueryBuilder';\r\nexport * from './transformers/QueryBuilder'; // old name:QueryConverter\r\nexport * from './transformers/SelectValueCollector';\r\nexport * from './transformers/SelectableColumnCollector';\r\nexport * from './transformers/TableColumnResolver';\r\nexport * from './transformers/TableSourceCollector';\r\nexport * from './transformers/UpstreamSelectQueryFinder';\r\nexport * from './transformers/SchemaCollector';\r\nexport * from './transformers/SqlParamInjector';\r\n\r\nexport * from './utils/SqlSchemaValidator';\r\nexport * from './utils/SchemaManager';\r\n// Add more exports here if you want to expose additional public API\r\n", "\uFEFFexport abstract class SqlComponent {\r\n // `kind` is declared abstractly and defined concretely in a subclass.\r\n static kind: symbol;\r\n\r\n getKind(): symbol {\r\n return (this.constructor as typeof SqlComponent).kind;\r\n }\r\n\r\n accept<T>(visitor: SqlComponentVisitor<T>): T {\r\n return visitor.visit(this);\r\n }\r\n\r\n toSqlString(formatter: SqlComponentVisitor<string>): string {\r\n return this.accept(formatter);\r\n }\r\n\r\n comments: string[] | null = null;\r\n}\r\n\r\nexport interface SqlComponentVisitor<T> {\r\n visit(expr: SqlComponent): T;\r\n}\r\n\r\nexport class SqlDialectConfiguration {\r\n public parameterSymbol: string = \":\";\r\n public identifierEscape = { start: '\"', end: '\"' };\r\n public exportComment: boolean = true;\r\n}\r\n", "// Represents an INSERT query in SQL.\r\n// Supports single/multi-row VALUES and INSERT ... SELECT.\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { SelectQuery } from \"./SelectQuery\";\r\nimport { InsertClause } from \"./Clause\";\r\n\r\nexport class InsertQuery extends SqlComponent {\r\n static kind = Symbol(\"InsertQuery\");\r\n insertClause: InsertClause;\r\n selectQuery: SelectQuery | null;\r\n\r\n /**\r\n * @param params.insertClause InsertClause instance (target table and columns)\r\n * @param params.selectQuery SELECT/VALUES query (required)\r\n */\r\n constructor(params: {\r\n insertClause: InsertClause;\r\n selectQuery?: SelectQuery | null;\r\n }) {\r\n super();\r\n this.insertClause = params.insertClause;\r\n this.selectQuery = params.selectQuery ?? null;\r\n }\r\n}", "import { PartitionByClause, OrderByClause } from \"./Clause\";\r\nimport { SelectQuery, SimpleSelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\n\r\nexport type ValueComponent = ValueList |\r\n ColumnReference |\r\n FunctionCall |\r\n UnaryExpression |\r\n BinaryExpression |\r\n LiteralValue |\r\n ParameterExpression |\r\n SwitchCaseArgument |\r\n CaseKeyValuePair |\r\n RawString |\r\n IdentifierString |\r\n ParenExpression |\r\n CastExpression |\r\n CaseExpression |\r\n ArrayExpression |\r\n ArrayQueryExpression |\r\n BetweenExpression |\r\n InlineQuery |\r\n StringSpecifierExpression |\r\n TypeValue |\r\n TupleExpression;\r\n\r\nexport class InlineQuery extends SqlComponent {\r\n static kind = Symbol(\"InlineQuery\");\r\n selectQuery: SelectQuery;\r\n constructor(selectQuery: SelectQuery) {\r\n super();\r\n this.selectQuery = selectQuery;\r\n }\r\n}\r\n\r\nexport class ValueList extends SqlComponent {\r\n static kind = Symbol(\"ValueList\");\r\n values: ValueComponent[];\r\n constructor(values: ValueComponent[]) {\r\n super();\r\n this.values = values;\r\n }\r\n}\r\n\r\nexport class ColumnReference extends SqlComponent {\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the column name as IdentifierString (readonly)\r\n */\r\n get column(): IdentifierString {\r\n // If the name is RawString, convert to IdentifierString for compatibility\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n static kind = Symbol(\"ColumnReference\");\r\n qualifiedName: QualifiedName; constructor(namespaces: string | string[] | IdentifierString[] | null, column: string | IdentifierString) {\r\n super();\r\n const col = typeof column === \"string\" ? new IdentifierString(column) : column;\r\n this.qualifiedName = new QualifiedName(toIdentifierStringArray(namespaces), col);\r\n }\r\n\r\n public toString(): string {\r\n return this.qualifiedName.toString();\r\n }\r\n public getNamespace(): string {\r\n if (this.qualifiedName.namespaces) {\r\n return this.qualifiedName.namespaces.map((namespace) => namespace.name).join(\".\");\r\n } else {\r\n return '';\r\n }\r\n }\r\n}\r\n\r\nexport class FunctionCall extends SqlComponent {\r\n static kind = Symbol(\"FunctionCall\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n over: OverExpression | null; constructor(\r\n namespaces: string | string[] | IdentifierString[] | null,\r\n name: string | RawString | IdentifierString,\r\n argument: ValueComponent | null,\r\n over: OverExpression | null\r\n ) {\r\n super();\r\n this.qualifiedName = new QualifiedName(namespaces, name);\r\n this.argument = argument;\r\n this.over = over;\r\n }\r\n\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the function name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n}\r\n\r\nexport type OverExpression = WindowFrameExpression | IdentifierString;\r\n\r\nexport enum WindowFrameType {\r\n Rows = \"rows\",\r\n Range = \"range\",\r\n Groups = \"groups\",\r\n}\r\n\r\nexport enum WindowFrameBound {\r\n UnboundedPreceding = \"unbounded preceding\",\r\n UnboundedFollowing = \"unbounded following\",\r\n CurrentRow = \"current row\",\r\n}\r\n\r\nexport type FrameBoundaryComponent = WindowFrameBoundStatic | WindowFrameBoundaryValue;\r\n\r\nexport class WindowFrameBoundStatic extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameStaticBound\");\r\n bound: WindowFrameBound;\r\n constructor(bound: WindowFrameBound) {\r\n super();\r\n this.bound = bound;\r\n }\r\n}\r\n\r\nexport class WindowFrameBoundaryValue extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameBoundary\");\r\n value: ValueComponent;\r\n isFollowing: boolean; // true for \"FOLLOWING\", false for \"PRECEDING\"\r\n constructor(value: ValueComponent, isFollowing: boolean) {\r\n super();\r\n this.value = value;\r\n this.isFollowing = isFollowing;\r\n }\r\n}\r\n\r\nexport class WindowFrameSpec extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameSpec\");\r\n frameType: WindowFrameType;\r\n startBound: FrameBoundaryComponent;\r\n endBound: FrameBoundaryComponent | null; // null for single boundary specification\r\n constructor(frameType: WindowFrameType, startBound: FrameBoundaryComponent, endBound: FrameBoundaryComponent | null) {\r\n super();\r\n this.frameType = frameType;\r\n this.startBound = startBound;\r\n this.endBound = endBound;\r\n }\r\n}\r\n\r\nexport class WindowFrameExpression extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameExpression\");\r\n partition: PartitionByClause | null;\r\n order: OrderByClause | null;\r\n frameSpec: WindowFrameSpec | null;\r\n constructor(partition: PartitionByClause | null, order: OrderByClause | null, frameSpec: WindowFrameSpec | null = null) {\r\n super();\r\n this.partition = partition;\r\n this.order = order;\r\n this.frameSpec = frameSpec;\r\n }\r\n}\r\n\r\nexport class UnaryExpression extends SqlComponent {\r\n static kind = Symbol(\"UnaryExpression\");\r\n operator: RawString;\r\n expression: ValueComponent;\r\n constructor(operator: string, expression: ValueComponent) {\r\n super();\r\n this.operator = new RawString(operator);\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class BinaryExpression extends SqlComponent {\r\n static kind = Symbol(\"BinaryExpression\");\r\n left: ValueComponent;\r\n operator: RawString;\r\n right: ValueComponent;\r\n constructor(left: ValueComponent, operator: string, right: ValueComponent) {\r\n super();\r\n this.left = left;\r\n this.operator = new RawString(operator);\r\n this.right = right;\r\n }\r\n}\r\n\r\nexport class LiteralValue extends SqlComponent {\r\n static kind = Symbol(\"LiteralExpression\");\r\n // Use the string type instead of the RawString type because it has its own escaping process.\r\n value: string | number | boolean | null;\r\n constructor(value: string | number | boolean | null) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class ParameterExpression extends SqlComponent {\r\n static kind = Symbol(\"ParameterExpression\");\r\n name: RawString;\r\n value: any | null; // Holds the parameter value; can be provided via second argument.\r\n /**\r\n * The index assigned by the formatter when generating parameterized queries.\r\n * Used for naming parameters like $1, $2, etc.\r\n */\r\n index: number | null;\r\n constructor(name: string, value: any | null = null) {\r\n super();\r\n this.name = new RawString(name);\r\n this.value = value; // Value is now accepted as a second argument (optional)\r\n this.index = null;\r\n }\r\n}\r\n\r\nexport class SwitchCaseArgument extends SqlComponent {\r\n static kind = Symbol(\"SwitchCaseArgument\");\r\n cases: CaseKeyValuePair[];\r\n elseValue: ValueComponent | null;\r\n constructor(cases: CaseKeyValuePair[], elseValue: ValueComponent | null = null) {\r\n super();\r\n this.cases = cases;\r\n this.elseValue = elseValue;\r\n }\r\n}\r\n\r\nexport class CaseKeyValuePair extends SqlComponent {\r\n static kind = Symbol(\"CaseKeyValuePair\");\r\n key: ValueComponent;\r\n value: ValueComponent;\r\n constructor(key: ValueComponent, value: ValueComponent) {\r\n super();\r\n this.key = key;\r\n this.value = value;\r\n }\r\n}\r\n\r\n/*\r\n * Values \u200B\u200Bthat must be hard-coded, such as type names and function names.\r\n * A simple check is performed when decoding.\r\n */\r\nexport class RawString extends SqlComponent {\r\n static kind = Symbol(\"RawString\");\r\n value: string;\r\n constructor(value: string) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class IdentifierString extends SqlComponent {\r\n static kind = Symbol(\"IdentifierString\");\r\n name: string;\r\n constructor(alias: string) {\r\n super();\r\n this.name = alias;\r\n }\r\n}\r\n\r\nexport class ParenExpression extends SqlComponent {\r\n static kind = Symbol(\"ParenExpression\");\r\n expression: ValueComponent;\r\n constructor(expression: ValueComponent) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class CastExpression extends SqlComponent {\r\n static kind = Symbol(\"CastExpression\");\r\n input: ValueComponent;\r\n castType: TypeValue;\r\n constructor(input: ValueComponent, castType: TypeValue) {\r\n super();\r\n this.input = input;\r\n this.castType = castType;\r\n }\r\n}\r\n\r\nexport class CaseExpression extends SqlComponent {\r\n static kind = Symbol(\"CaseExpression\");\r\n condition: ValueComponent | null;\r\n switchCase: SwitchCaseArgument;\r\n\r\n constructor(condition: ValueComponent | null, switchCase: SwitchCaseArgument) {\r\n super();\r\n this.condition = condition;\r\n this.switchCase = switchCase;\r\n }\r\n}\r\n\r\nexport class ArrayExpression extends SqlComponent {\r\n static kind = Symbol(\"ArrayExpression\");\r\n expression: ValueComponent;\r\n constructor(expression: ValueComponent) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class ArrayQueryExpression extends SqlComponent {\r\n static kind = Symbol(\"ArrayQueryExpression\");\r\n query: SelectQuery;\r\n constructor(query: SelectQuery) {\r\n super();\r\n this.query = query;\r\n }\r\n}\r\n\r\nexport class BetweenExpression extends SqlComponent {\r\n static kind = Symbol(\"BetweenExpression\");\r\n expression: ValueComponent;\r\n lower: ValueComponent;\r\n upper: ValueComponent;\r\n negated: boolean;\r\n constructor(expression: ValueComponent, lower: ValueComponent, upper: ValueComponent, negated: boolean) {\r\n super();\r\n this.expression = expression;\r\n this.lower = lower;\r\n this.upper = upper;\r\n this.negated = negated;\r\n }\r\n}\r\n\r\nexport class StringSpecifierExpression extends SqlComponent {\r\n static kind = Symbol(\"StringSpecifierExpression\");\r\n // e.g. 'E', 'X', 'U&'\r\n specifier: RawString;\r\n value: LiteralValue;\r\n constructor(specifier: string, value: string) {\r\n super();\r\n this.specifier = new RawString(specifier);\r\n this.value = new LiteralValue(value);\r\n }\r\n}\r\n\r\n// other\r\n\r\nexport class TypeValue extends SqlComponent {\r\n static kind = Symbol(\"TypeValue\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n constructor(namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString, argument: ValueComponent | null = null) {\r\n super();\r\n this.qualifiedName = new QualifiedName(namespaces, name);\r\n this.argument = argument;\r\n }\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the type name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n public getTypeName(): string {\r\n const nameValue = this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name;\r\n if (this.qualifiedName.namespaces && this.qualifiedName.namespaces.length > 0) {\r\n return this.qualifiedName.namespaces.map(ns => ns.name).join(\".\") + \".\" + nameValue;\r\n } else {\r\n return nameValue;\r\n }\r\n }\r\n}\r\n\r\nexport class TupleExpression extends SqlComponent {\r\n static kind = Symbol(\"TupleExpression\");\r\n values: ValueComponent[];\r\n constructor(values: ValueComponent[]) {\r\n super();\r\n this.values = values;\r\n }\r\n}\r\n\r\nfunction toIdentifierStringArray(input: string | string[] | IdentifierString[] | null): IdentifierString[] | null {\r\n if (input == null) return null;\r\n\r\n if (typeof input === \"string\") {\r\n // Empty string should be treated as null\r\n return input.trim() === \"\" ? null : [new IdentifierString(input)];\r\n }\r\n\r\n if (Array.isArray(input)) {\r\n if (input.length === 0) return null;\r\n\r\n if (typeof input[0] === \"string\") {\r\n // Filter out empty strings from string array\r\n const filteredStrings = (input as string[]).filter(ns => ns.trim() !== \"\");\r\n return filteredStrings.length === 0 ? null : filteredStrings.map(ns => new IdentifierString(ns));\r\n } else {\r\n // Filter out empty IdentifierStrings from IdentifierString array\r\n const filteredIdentifiers = (input as IdentifierString[]).filter(ns => ns.name.trim() !== \"\");\r\n return filteredIdentifiers.length === 0 ? null : filteredIdentifiers;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Represents a qualified name with optional namespaces (e.g. schema.table, db.schema.function)\r\n */\r\nexport class QualifiedName extends SqlComponent {\r\n static kind = Symbol(\"QualifiedName\");\r\n\r\n /** List of namespaces (e.g. schema, database) */\r\n namespaces: IdentifierString[] | null;\r\n /** The actual name (e.g. table, function, type, column) */\r\n name: RawString | IdentifierString;\r\n\r\n constructor(namespaces: string | string[] | IdentifierString[] | null, name: string | RawString | IdentifierString) {\r\n super();\r\n this.namespaces = toIdentifierStringArray(namespaces);\r\n if (typeof name === \"string\") {\r\n this.name = new RawString(name);\r\n } else {\r\n this.name = name;\r\n }\r\n }\r\n\r\n /** Returns the full qualified name as a string (dot-separated) */\r\n toString(): string {\r\n const nameValue = this.name instanceof RawString ? this.name.value : this.name.name;\r\n if (this.namespaces && this.namespaces.length > 0) {\r\n return this.namespaces.map(ns => ns.name).join(\".\") + \".\" + nameValue;\r\n } else {\r\n return nameValue;\r\n }\r\n }\r\n}", "import { SelectQuery, SimpleSelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { IdentifierString, RawString, TupleExpression, ValueComponent, WindowFrameExpression, QualifiedName } from \"./ValueComponent\";\r\n\r\nexport class SelectItem extends SqlComponent {\r\n static kind = Symbol(\"SelectItem\");\r\n value: ValueComponent;\r\n identifier: IdentifierString | null;\r\n constructor(value: ValueComponent, name: string | null = null) {\r\n super();\r\n this.value = value;\r\n this.identifier = name ? new IdentifierString(name) : null;\r\n }\r\n}\r\n\r\nexport class SelectClause extends SqlComponent {\r\n static kind = Symbol(\"SelectClause\");\r\n items: SelectItem[];\r\n distinct: DistinctComponent | null;\r\n constructor(items: SelectItem[], distinct: DistinctComponent | null = null) {\r\n super();\r\n this.items = items;\r\n this.distinct = distinct;\r\n }\r\n}\r\n\r\nexport type DistinctComponent = Distinct | DistinctOn;\r\n\r\nexport class Distinct extends SqlComponent {\r\n static kind = Symbol(\"Distinct\");\r\n constructor() {\r\n super();\r\n }\r\n}\r\n\r\nexport class DistinctOn extends SqlComponent {\r\n static kind = Symbol(\"DistinctOn\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\n\r\nexport class WhereClause extends SqlComponent {\r\n static kind = Symbol(\"WhereClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class PartitionByClause extends SqlComponent {\r\n static kind = Symbol(\"PartitionByClause\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class WindowFrameClause extends SqlComponent {\r\n static kind = Symbol(\"WindowFrameClause\");\r\n name: IdentifierString;\r\n expression: WindowFrameExpression;\r\n constructor(name: string, expression: WindowFrameExpression) {\r\n super();\r\n this.name = new IdentifierString(name);\r\n this.expression = expression;\r\n }\r\n}\r\n\r\n/**\r\n * Represents a collection of window definitions (WINDOW clause in SQL).\r\n * @param windows Array of WindowFrameClause\r\n */\r\nexport class WindowsClause extends SqlComponent {\r\n static kind = Symbol(\"WindowsClause\");\r\n windows: WindowFrameClause[];\r\n constructor(windows: WindowFrameClause[]) {\r\n super();\r\n this.windows = windows;\r\n }\r\n}\r\n\r\nexport enum SortDirection {\r\n Ascending = \"asc\",\r\n Descending = \"desc\",\r\n}\r\nexport enum NullsSortDirection {\r\n First = \"first\",\r\n Last = \"last\",\r\n}\r\n\r\nexport type OrderByComponent = OrderByItem | ValueComponent;\r\n\r\nexport class OrderByClause extends SqlComponent {\r\n static kind = Symbol(\"OrderByClause\");\r\n order: OrderByComponent[];\r\n constructor(items: OrderByComponent[]) {\r\n super();\r\n this.order = items;\r\n }\r\n}\r\n\r\nexport class OrderByItem extends SqlComponent {\r\n static kind = Symbol(\"OrderByItem\");\r\n value: ValueComponent;\r\n sortDirection: SortDirection;\r\n nullsPosition: NullsSortDirection | null;\r\n constructor(expression: ValueComponent, sortDirection: SortDirection | null, nullsPosition: NullsSortDirection | null) {\r\n super();\r\n this.value = expression;\r\n this.sortDirection = sortDirection === null ? SortDirection.Ascending : sortDirection;\r\n this.nullsPosition = nullsPosition;\r\n }\r\n}\r\n\r\nexport class GroupByClause extends SqlComponent {\r\n static kind = Symbol(\"GroupByClause\");\r\n grouping: ValueComponent[];\r\n constructor(expression: ValueComponent[]) {\r\n super();\r\n this.grouping = expression;\r\n }\r\n}\r\n\r\nexport class HavingClause extends SqlComponent {\r\n static kind = Symbol(\"HavingClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport type SourceComponent = TableSource |\r\n FunctionSource |\r\n SubQuerySource |\r\n ParenSource;\r\n\r\nexport class TableSource extends SqlComponent {\r\n static kind = Symbol(\"TableSource\");\r\n qualifiedName: QualifiedName;\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the table name as IdentifierString (readonly)\r\n */\r\n get table(): IdentifierString {\r\n // If the name is RawString, convert to IdentifierString for compatibility\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n /**\r\n * For backward compatibility: returns the table name as IdentifierString (readonly)\r\n */\r\n get identifier(): IdentifierString {\r\n return this.table;\r\n }\r\n constructor(namespaces: string[] | IdentifierString[] | null, table: string | IdentifierString) {\r\n super();\r\n // Convert the table name to an IdentifierString if it is provided as a string.\r\n const tbl = typeof table === \"string\" ? new IdentifierString(table) : table;\r\n // Wrap the namespaces and table name in a QualifiedName object.\r\n // This design choice ensures backward compatibility by allowing the namespaces\r\n // and table name to be accessed in a way consistent with the previous implementation.\r\n this.qualifiedName = new QualifiedName(namespaces, tbl);\r\n }\r\n public getSourceName(): string {\r\n if (this.qualifiedName.namespaces && this.qualifiedName.namespaces.length > 0) {\r\n return this.qualifiedName.namespaces.map((namespace) => namespace.name).join(\".\") + \".\" + (this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name);\r\n } else {\r\n return this.qualifiedName.name instanceof RawString ? this.qualifiedName.name.value : this.qualifiedName.name.name;\r\n }\r\n }\r\n}\r\n\r\nexport class FunctionSource extends SqlComponent {\r\n static kind = Symbol(\"FunctionSource\");\r\n qualifiedName: QualifiedName;\r\n argument: ValueComponent | null;\r\n constructor(\r\n name: string | IdentifierString | { namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString },\r\n argument: ValueComponent | null\r\n ) {\r\n super();\r\n if (typeof name === \"object\" && name !== null && \"name\" in name) {\r\n // Accepts { namespaces, name }\r\n const nameObj = name as { namespaces: string[] | IdentifierString[] | null, name: string | RawString | IdentifierString };\r\n this.qualifiedName = new QualifiedName(nameObj.namespaces, nameObj.name);\r\n } else {\r\n this.qualifiedName = new QualifiedName(null, name as string | RawString | IdentifierString);\r\n }\r\n this.argument = argument;\r\n }\r\n\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the function name as RawString | IdentifierString (readonly)\r\n */\r\n get name(): RawString | IdentifierString {\r\n return this.qualifiedName.name;\r\n }\r\n}\r\n\r\nexport class ParenSource extends SqlComponent {\r\n static kind = Symbol(\"ParenSource\");\r\n source: SourceComponent;\r\n constructor(source: SourceComponent) {\r\n super();\r\n this.source = source;\r\n }\r\n}\r\n\r\nexport class SubQuerySource extends SqlComponent {\r\n static kind = Symbol(\"SubQuerySource\");\r\n query: SelectQuery;\r\n constructor(query: SelectQuery) {\r\n super();\r\n this.query = query;\r\n }\r\n}\r\n\r\nexport class SourceExpression extends SqlComponent {\r\n static kind = Symbol(\"SourceExpression\");\r\n datasource: SourceComponent;\r\n aliasExpression: SourceAliasExpression | null;\r\n constructor(datasource: SourceComponent, aliasExpression: SourceAliasExpression | null) {\r\n super();\r\n this.datasource = datasource;\r\n this.aliasExpression = aliasExpression;\r\n }\r\n public getAliasName(): string | null {\r\n if (this.aliasExpression) {\r\n return this.aliasExpression.table.name;\r\n }\r\n else if (this.datasource instanceof TableSource) {\r\n return this.datasource.getSourceName();\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nexport type JoinConditionComponent = JoinOnClause | JoinUsingClause;\r\n\r\nexport class JoinOnClause extends SqlComponent {\r\n static kind = Symbol(\"JoinOnClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class JoinUsingClause extends SqlComponent {\r\n static kind = Symbol(\"JoinUsingClause\");\r\n condition: ValueComponent;\r\n constructor(condition: ValueComponent) {\r\n super();\r\n this.condition = condition;\r\n }\r\n}\r\n\r\nexport class JoinClause extends SqlComponent {\r\n static kind = Symbol(\"JoinItem\");\r\n joinType: RawString;\r\n source: SourceExpression;\r\n condition: JoinConditionComponent | null;\r\n lateral: boolean;\r\n constructor(joinType: string, source: SourceExpression, condition: JoinConditionComponent | null, lateral: boolean) {\r\n super();\r\n this.joinType = new RawString(joinType);\r\n this.source = source;\r\n this.condition = condition;\r\n this.lateral = lateral;\r\n }\r\n public getSourceAliasName(): string | null {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source instanceof TableSource) {\r\n return this.source.table.name;\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nexport class FromClause extends SqlComponent {\r\n static kind = Symbol(\"FromClause\");\r\n source: SourceExpression;\r\n joins: JoinClause[] | null;\r\n constructor(source: SourceExpression, join: JoinClause[] | null) {\r\n super();\r\n this.source = source;\r\n this.joins = join;\r\n }\r\n public getSourceAliasName(): string | null {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source.datasource instanceof TableSource) {\r\n return this.source.datasource.table.name;\r\n }\r\n return null;\r\n }\r\n /**\r\n * Returns all SourceExpression objects in this FROM clause, including main source and all JOIN sources.\r\n */\r\n public getSources(): SourceExpression[] {\r\n const sources: SourceExpression[] = [this.source];\r\n if (this.joins) {\r\n for (const join of this.joins) {\r\n sources.push(join.source);\r\n }\r\n }\r\n return sources;\r\n }\r\n}\r\n\r\nexport class CommonTable extends SqlComponent {\r\n static kind = Symbol(\"CommonTable\");\r\n query: SelectQuery;\r\n materialized: boolean | null;\r\n aliasExpression: SourceAliasExpression;\r\n constructor(query: SelectQuery, aliasExpression: SourceAliasExpression | string, materialized: boolean | null) {\r\n super();\r\n this.query = query;\r\n this.materialized = materialized;\r\n if (typeof aliasExpression === \"string\") {\r\n this.aliasExpression = new SourceAliasExpression(aliasExpression, null);\r\n } else {\r\n this.aliasExpression = aliasExpression;\r\n }\r\n }\r\n public getSourceAliasName(): string {\r\n return this.aliasExpression.table.name;\r\n }\r\n}\r\n\r\nexport class WithClause extends SqlComponent {\r\n static kind = Symbol(\"WithClause\");\r\n recursive: boolean;\r\n tables: CommonTable[];\r\n constructor(recursive: boolean, tables: CommonTable[]) {\r\n super();\r\n this.recursive = recursive;\r\n this.tables = tables;\r\n }\r\n}\r\n\r\nexport class LimitClause extends SqlComponent {\r\n static kind = Symbol(\"LimitClause\");\r\n value: ValueComponent;\r\n constructor(limit: ValueComponent) {\r\n super();\r\n this.value = limit;\r\n }\r\n}\r\n\r\nexport enum FetchType {\r\n Next = \"next\",\r\n First = \"first\",\r\n}\r\n\r\nexport enum FetchUnit {\r\n RowsOnly = \"rows only\",\r\n Percent = \"percent\",\r\n PercentWithTies = \"percent with ties\",\r\n}\r\n\r\n\r\nexport class OffsetClause extends SqlComponent {\r\n static kind = Symbol(\"OffsetClause\");\r\n value: ValueComponent;\r\n constructor(value: ValueComponent) {\r\n super();\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class FetchClause extends SqlComponent {\r\n static kind = Symbol(\"FetchClause\");\r\n expression: FetchExpression;\r\n constructor(expression: FetchExpression) {\r\n super();\r\n this.expression = expression;\r\n }\r\n}\r\n\r\nexport class FetchExpression extends SqlComponent {\r\n static kind = Symbol(\"FetchExpression\");\r\n // type count unit\r\n type: FetchType;\r\n count: ValueComponent;\r\n unit: FetchUnit | null;\r\n constructor(type: FetchType, count: ValueComponent, unit: FetchUnit | null) {\r\n super();\r\n this.type = type;\r\n this.count = count;\r\n this.unit = unit;\r\n }\r\n}\r\n\r\nexport enum LockMode {\r\n Update = \"update\",\r\n Share = \"share\",\r\n KeyShare = \"key share\",\r\n NokeyUpdate = \"no key update\",\r\n}\r\n\r\nexport class ForClause extends SqlComponent {\r\n static kind = Symbol(\"ForClause\");\r\n lockMode: LockMode;\r\n constructor(lockMode: LockMode) {\r\n super();\r\n this.lockMode = lockMode;\r\n }\r\n}\r\n\r\nexport class SourceAliasExpression extends SqlComponent {\r\n static kind = Symbol(\"SourceAliasExpression\");\r\n table: IdentifierString;\r\n columns: IdentifierString[] | null;\r\n constructor(alias: string, columnAlias: string[] | null) {\r\n super();\r\n this.table = new IdentifierString(alias);\r\n this.columns = columnAlias !== null ? columnAlias.map((alias) => new IdentifierString(alias)) : null;\r\n }\r\n}\r\n\r\nexport class ReturningClause extends SqlComponent {\r\n static kind = Symbol(\"ReturningClause\");\r\n columns: IdentifierString[];\r\n /**\r\n * Constructs a ReturningClause.\r\n * @param columns Array of IdentifierString or string representing column names.\r\n */\r\n constructor(columns: (IdentifierString | string)[]) {\r\n super();\r\n this.columns = columns.map(col => typeof col === \"string\" ? new IdentifierString(col) : col);\r\n }\r\n}\r\n\r\nexport class SetClause extends SqlComponent {\r\n static kind = Symbol(\"SetClause\");\r\n items: SetClauseItem[];\r\n constructor(items: (SetClauseItem | { column: string | IdentifierString, value: ValueComponent })[]) {\r\n super();\r\n this.items = items.map(item => item instanceof SetClauseItem ? item : new SetClauseItem(item.column, item.value));\r\n }\r\n}\r\n\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n */\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n * Now supports namespaces for fully qualified column names (e.g. schema.table.column).\r\n */\r\n/**\r\n * Represents a single SET clause item in an UPDATE statement.\r\n * Now supports namespaces for fully qualified column names (e.g. schema.table.column).\r\n * Refactored to use QualifiedName for unified name/namespace handling.\r\n */\r\nexport class SetClauseItem extends SqlComponent {\r\n static kind = Symbol(\"SetClauseItem\");\r\n qualifiedName: QualifiedName;\r\n value: ValueComponent;\r\n constructor(\r\n column: string | IdentifierString | { namespaces: string[] | IdentifierString[] | null, column: string | IdentifierString },\r\n value: ValueComponent\r\n ) {\r\n super();\r\n // Accepts { namespaces, column } or just column\r\n if (typeof column === \"object\" && column !== null && \"column\" in column) {\r\n const colObj = column as { namespaces: string[] | IdentifierString[] | null, column: string | IdentifierString };\r\n const col = typeof colObj.column === \"string\" ? new IdentifierString(colObj.column) : colObj.column;\r\n this.qualifiedName = new QualifiedName(colObj.namespaces, col);\r\n } else {\r\n const col = typeof column === \"string\" ? new IdentifierString(column) : column as IdentifierString;\r\n this.qualifiedName = new QualifiedName(null, col);\r\n }\r\n this.value = value;\r\n }\r\n /**\r\n * For backward compatibility: returns the namespaces as IdentifierString[] | null (readonly)\r\n */\r\n get namespaces(): IdentifierString[] | null {\r\n return this.qualifiedName.namespaces;\r\n }\r\n /**\r\n * For backward compatibility: returns the column name as IdentifierString (readonly)\r\n */\r\n get column(): IdentifierString {\r\n if (this.qualifiedName.name instanceof IdentifierString) {\r\n return this.qualifiedName.name;\r\n } else {\r\n return new IdentifierString(this.qualifiedName.name.value);\r\n }\r\n }\r\n /**\r\n * Returns the fully qualified column name as a string.\r\n */\r\n public getFullName(): string {\r\n return this.qualifiedName.toString();\r\n }\r\n}\r\n\r\nexport class UpdateClause extends SqlComponent {\r\n static kind = Symbol(\"UpdateClause\");\r\n source: SourceExpression;\r\n constructor(source: SourceExpression) {\r\n super();\r\n this.source = source;\r\n }\r\n public getSourceAliasName() {\r\n if (this.source.aliasExpression) {\r\n return this.source.aliasExpression.table.name;\r\n }\r\n else if (this.source.datasource instanceof TableSource) {\r\n return this.source.datasource.table.name;\r\n }\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Represents the target table (with optional alias/schema) and columns for an INSERT statement.\r\n * @param source The target table as a SourceExpression (can include schema, alias, etc.)\r\n * @param columns Array of column names (as strings)\r\n */\r\nexport class InsertClause extends SqlComponent {\r\n source: SourceExpression;\r\n columns: IdentifierString[];\r\n\r\n constructor(source: SourceExpression, columns: string[]) {\r\n super();\r\n this.source = source;\r\n this.columns = columns.map((col) => new IdentifierString(col));\r\n }\r\n}", "\uFEFFexport enum TokenType {\r\n None = 0,\r\n Literal = 1 << 0,\r\n Operator = 1 << 1,\r\n OpenParen = 1 << 2,\r\n CloseParen = 1 << 3,\r\n Comma = 1 << 4,\r\n Dot = 1 << 5,\r\n Identifier = 1 << 6,\r\n Command = 1 << 7, // select, from, where as, on, array etc\r\n Parameter = 1 << 8,\r\n OpenBracket = 1 << 9,\r\n CloseBracket = 1 << 10,\r\n Function = 1 << 11, // next token is open paren\r\n StringSpecifier = 1 << 12, // next token is string literal\r\n Type = 1 << 13,\r\n}\r\n\r\n/**\r\n * Represents a lexical token in SQL parsing\r\n */\r\nexport interface Lexeme {\r\n type: number; // Bit flags for TokenType\r\n value: string;\r\n comments: string[] | null;\r\n}\r\n", "\uFEFF/**\r\n * Fast character classification utilities for SQL tokenization\r\n */\r\nexport class CharLookupTable {\r\n public static isWhitespace(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check for space(32), tab(9), line feed(10), carriage return(13)\r\n return code === 32 || code === 9 || code === 10 || code === 13;\r\n }\r\n\r\n public static isDigit(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check if within '0'(48) to '9'(57) range\r\n return code >= 48 && code <= 57;\r\n }\r\n\r\n public static isHexChar(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n // Check if '0'(48) to '9'(57) or 'a'(97) to 'f'(102) or 'A'(65) to 'F'(70)\r\n return (code >= 48 && code <= 57) ||\r\n (code >= 97 && code <= 102) ||\r\n (code >= 65 && code <= 70);\r\n }\r\n\r\n public static isOperatorSymbol(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // Check for specific operator character codes\r\n // '+'=43, '-'=45, '*'=42, '/'=47, '%'=37, '~'=126, '@'=64, '#'=35, '^'=94, \r\n // '&'=38, ':'=58, '!'=33, '<'=60, '>'=62, '='=61, '|'=124\r\n return code === 43 || code === 45 || code === 42 || code === 47 ||\r\n code === 37 || code === 126 || code === 64 || code === 35 ||\r\n code === 94 || code === 38 || code === 58 || code === 33 ||\r\n code === 60 || code === 62 || code === 61 || code === 124;\r\n }\r\n\r\n public static isDelimiter(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // First check delimiters: '.'=46, ','=44, '('=40, ')'=41, '['=91, ']'=93, '{'=123, '}'=125, ';'=59\r\n if (code === 46 || code === 44 || code === 40 || code === 41 ||\r\n code === 91 || code === 93 || code === 123 || code === 125 || code === 59) {\r\n return true;\r\n }\r\n\r\n // Then check for whitespace: ' '=32, '\\t'=9, '\\n'=10, '\\r'=13\r\n if (code === 32 || code === 9 || code === 10 || code === 13) {\r\n return true;\r\n }\r\n\r\n // Finally check for operator symbols\r\n // '+'=43, '-'=45, '*'=42, '/'=47, '%'=37, '~'=126, '@'=64, '#'=35, '^'=94, \r\n // '&'=38, ':'=58, '!'=33, '<'=60, '>'=62, '='=61, '|'=124\r\n return code === 43 || code === 45 || code === 42 || code === 47 ||\r\n code === 37 || code === 126 || code === 64 || code === 35 ||\r\n code === 94 || code === 38 || code === 58 || code === 33 ||\r\n code === 60 || code === 62 || code === 61 || code === 124;\r\n }\r\n\r\n public static isNamedParameterPrefix(char: string): boolean {\r\n if (char.length !== 1) return false;\r\n const code = char.charCodeAt(0);\r\n\r\n // Check for parameter prefix characters: '@'=64, ':'=58, '$'=36\r\n return code === 64 || code === 58 || code === 36;\r\n }\r\n}\r\n", "\uFEFFimport { CharLookupTable } from \"./charLookupTable\";\r\n\r\n/**\r\n * Utilities for string operations during tokenization\r\n */\r\nexport class StringUtils {\r\n /**\r\n * Creates a visual representation of an error position in text\r\n * @param input The input text\r\n * @param errPosition The error position\r\n * @returns A string with a caret pointing to the error position\r\n */\r\n public static getDebugPositionInfo(input: string, errPosition: number): string {\r\n // Get 5 characters before and after the error\r\n // If the start and end points are out of the string range, keep them within the range\r\n // Display ^ at the error position on the next line\r\n const start = Math.max(0, errPosition - 5);\r\n const end = Math.min(input.length, errPosition + 5);\r\n const debugInfo = input.slice(start, end);\r\n const caret = ' '.repeat(errPosition - start) + '^';\r\n return `${debugInfo}\\n${caret}`;\r\n }\r\n\r\n /**\r\n * Skip white space characters.\r\n */\r\n private static skipWhiteSpace(input: string, position: number): number {\r\n const length = input.length;\r\n\r\n /*\r\n * Optimization: Try to skip 4 spaces at once (for 4-space indents).\r\n * This is effective when SQL is deeply nested and uses 4-space indentation.\r\n * In typical cases, charCodeAt in a loop is fastest, but for large/indented SQL,\r\n * this can reduce the number of iterations and improve stability (lower error/deviation in benchmarks).\r\n * If indentation is not 4 spaces, this check is skipped quickly, so overhead is minimal.\r\n *\r\n * Even for 2-space indents or mixed indents (2, 4, tab),\r\n * the remaining whitespace is handled by the following loop, so there is no performance loss.\r\n *\r\n * Benchmark results show that this optimization does not slow down short queries,\r\n * and can make long/indented queries more stable and slightly faster.\r\n */\r\n while (position + 4 <= length && input.slice(position, position + 4) === ' ') {\r\n position += 4;\r\n }\r\n\r\n // Then skip remaining whitespace one by one (space, tab, newline, carriage return)\r\n while (position < length) {\r\n const charCode = input.charCodeAt(position);\r\n // ' '=32, '\\t'=9, '\\n'=10, '\\r'=13\r\n if (charCode !== 32 && charCode !== 9 && charCode !== 10 && charCode !== 13) {\r\n break;\r\n }\r\n position++;\r\n }\r\n\r\n return position;\r\n }\r\n\r\n /**\r\n * Skip line comment.\r\n */\r\n private static readLineComment(input: string, position: number): { newPosition: number, comment: string | null } {\r\n if (position + 1 >= input.length) {\r\n return { newPosition: position, comment: null };\r\n }\r\n\r\n // '-'=45\r\n if (input.charCodeAt(position) === 45 && input.charCodeAt(position + 1) === 45) {\r\n const start = position;\r\n position += 2;\r\n\r\n // '\\n'=10\r\n while (position < input.length && input.charCodeAt(position) !== 10) {\r\n position++;\r\n }\r\n\r\n // Return the trimmed comment content (excluding -- tokens)\r\n const comment = input.slice(start + 2, position).trim();\r\n return { newPosition: position, comment };\r\n }\r\n return { newPosition: position, comment: null };\r\n }\r\n\r\n /**\r\n * Skip block comment.\r\n */\r\n private static readBlockComment(input: string, position: number): { newPosition: number, comments: string[] | null } {\r\n if (position + 3 >= input.length) {\r\n return { newPosition: position, comments: null };\r\n }\r\n\r\n // '/'=47, '*'=42, '+'=43\r\n if (input.charCodeAt(position) === 47 && input.charCodeAt(position + 1) === 42 && input.charCodeAt(position + 2) !== 43) {\r\n const start = position;\r\n position += 2;\r\n\r\n while (position + 1 < input.length) {\r\n // '*'=42, '/'=47\r\n if (input.charCodeAt(position) === 42 && input.charCodeAt(position + 1) === 47) {\r\n position += 2;\r\n\r\n // Process the comment content\r\n const lines = input.slice(start + 2, position - 2).replace(/\\r/g, '').split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n lines[i] = lines[i].trim();\r\n }\r\n\r\n // Remove empty lines, but only at the beginning and end\r\n while (lines.length > 0 && lines[0] === '') {\r\n lines.shift();\r\n }\r\n while (lines.length > 0 && lines[lines.length - 1] === '') {\r\n lines.pop();\r\n }\r\n\r\n return { newPosition: position, comments: lines };\r\n }\r\n position++;\r\n }\r\n throw new Error(`Block comment is not closed. position: ${position}`);\r\n }\r\n return { newPosition: position, comments: null };\r\n }\r\n\r\n /**\r\n * Skip white space characters and SQL comments.\r\n * @returns Object containing the new position and an array of skipped comments\r\n */\r\n public static readWhiteSpaceAndComment(input: string, position: number): { position: number, lines: string[] } {\r\n const lines: string[] = [];\r\n const length = input.length;\r\n\r\n while (position < length) {\r\n // Store current position\r\n const oldPosition = position;\r\n\r\n // Skip whitespace first\r\n position = StringUtils.skipWhiteSpace(input, position);\r\n if (position !== oldPosition) {\r\n continue;\r\n }\r\n\r\n // Fast character code check\r\n const charCode = input.charCodeAt(position);\r\n\r\n // '-'=45 (Line comment)\r\n if (charCode === 45) {\r\n const lineCommentResult = StringUtils.readLineComment(input, position);\r\n if (lineCommentResult.newPosition !== position) {\r\n position = lineCommentResult.newPosition;\r\n if (lineCommentResult.comment) {\r\n lines.push(lineCommentResult.comment.trim());\r\n }\r\n continue;\r\n }\r\n }\r\n // '/'=47 (Block comment)\r\n else if (charCode === 47) {\r\n const blockCommentResult = StringUtils.readBlockComment(input, position);\r\n if (blockCommentResult.newPosition !== position) {\r\n position = blockCommentResult.newPosition;\r\n if (blockCommentResult.comments) {\r\n lines.push(...blockCommentResult.comments);\r\n }\r\n continue;\r\n }\r\n }\r\n\r\n // No more whitespace or comments found\r\n break;\r\n }\r\n\r\n return { position, lines: lines };\r\n }\r\n\r\n /**\r\n * Read a regular identifier.\r\n */\r\n public static readRegularIdentifier(input: string, position: number): { identifier: string, newPosition: number } {\r\n const result = this.tryReadRegularIdentifier(input, position);\r\n\r\n if (!result) {\r\n throw new Error(`Unexpected character. position: ${position}\\n${StringUtils.getDebugPositionInfo(input, position)}`);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public static tryReadRegularIdentifier(input: string, position: number): { identifier: string, newPosition: number } | null {\r\n const start = position;\r\n\r\n while (position < input.length) {\r\n if (CharLookupTable.isDelimiter(input[position])) {\r\n break;\r\n }\r\n position++;\r\n }\r\n\r\n if (start === position) {\r\n return null;\r\n }\r\n\r\n // Check index range before checking for [] (array type)\r\n while (\r\n position + 1 < input.length &&\r\n input[position] === '[' &&\r\n input[position + 1] === ']'\r\n ) {\r\n position += 2; // Skip the []\r\n }\r\n\r\n return {\r\n identifier: input.slice(start, position),\r\n newPosition: position\r\n };\r\n }\r\n}\r\n", "\uFEFFimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Base class for token readers\r\n */\r\nexport abstract class BaseTokenReader {\r\n protected input: string;\r\n protected position: number;\r\n\r\n constructor(input: string, position: number = 0) {\r\n this.input = input;\r\n this.position = position;\r\n }\r\n\r\n /**\r\n * Get the current position in the input\r\n */\r\n public getPosition(): number {\r\n return this.position;\r\n }\r\n\r\n /**\r\n * Set the position in the input\r\n */\r\n public setPosition(position: number): void {\r\n this.position = position;\r\n }\r\n\r\n /**\r\n * Check if we've reached the end of input\r\n */\r\n protected isEndOfInput(shift: number = 0): boolean {\r\n return this.position + shift >= this.input.length;\r\n }\r\n\r\n /**\r\n * Check if we can read more characters\r\n */\r\n protected canRead(shift: number = 0): boolean {\r\n return !this.isEndOfInput(shift);\r\n }\r\n\r\n /**\r\n * Read an expected character\r\n */\r\n protected read(expectChar: string): string {\r\n if (this.isEndOfInput()) {\r\n throw new Error(`Unexpected character. expect: ${expectChar}, actual: EndOfInput, position: ${this.position}`);\r\n }\r\n\r\n const char = this.input[this.position];\r\n if (char !== expectChar) {\r\n throw new Error(`Unexpected character. expect: ${expectChar}, actual: ${char}, position: ${this.position}`);\r\n }\r\n\r\n this.position++;\r\n return char;\r\n }\r\n\r\n /**\r\n * Create a lexeme with the specified type and value\r\n */\r\n protected createLexeme(type: TokenType, value: string, comments: string[] | null = null): Lexeme {\r\n if (type === TokenType.Command || type === TokenType.Operator || type === TokenType.Function) {\r\n // Benchmark tests showed that directly calling toLowerCase() is ~5x faster\r\n // than first checking if the string is already lowercase.\r\n // See benchmarks/lowercase-benchmark.js for detailed performance analysis.\r\n return {\r\n type,\r\n value: value.toLowerCase(),\r\n comments: comments,\r\n };\r\n }\r\n return {\r\n type,\r\n value,\r\n comments: comments,\r\n };\r\n }\r\n\r\n /**\r\n * Get debug info for error reporting\r\n */\r\n protected getDebugPositionInfo(errPosition: number): string {\r\n return StringUtils.getDebugPositionInfo(this.input, errPosition);\r\n }\r\n\r\n /**\r\n * Try to read a token from the current position\r\n * @param previous The previous token, if available\r\n * @returns The read token or null if no token could be read\r\n */\r\n public abstract tryRead(previous: Lexeme | null): Lexeme | null;\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class IdentifierTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // wildcard identifier\r\n if (char === '*') {\r\n // Assume that the OperatorTokenReader is executed before the IdentifierTokenReader.\r\n // Since we have determined that the OperatorTokenReader is not an Operator,\r\n // we treat '*' here as a wildcard identifier.\r\n this.position++;\r\n return this.createLexeme(TokenType.Identifier, char);\r\n }\r\n\r\n // Regular identifier\r\n const result = StringUtils.readRegularIdentifier(this.input, this.position);\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Identifier, result.identifier);\r\n }\r\n}\r\n", "\uFEFFimport { KeywordTrie } from \"../models/KeywordTrie\";\r\nimport { StringUtils } from \"../utils/stringUtils\";\r\n\r\nexport enum KeywordMatchResult {\r\n NotAKeyword, // \"Not recognized as a keyword\"\r\n PartialOnly, // \"Partial match (this will not be the end)\"\r\n PartialOrFinal, // \"Partial or complete match (it can stop here)\"\r\n Final // \"Complete match (no longer keywords after this)\"\r\n}\r\n\r\nexport class KeywordParser {\r\n private trie: KeywordTrie;\r\n\r\n constructor(trie: KeywordTrie) {\r\n this.trie = trie;\r\n }\r\n\r\n private isEndOfInput(input: string, position: number, shift: number = 0): boolean {\r\n return position + shift >= input.length;\r\n }\r\n\r\n private canParse(input: string, position: number, shift: number = 0): boolean {\r\n return !this.isEndOfInput(input, position, shift);\r\n }\r\n\r\n public parse(input: string, position: number): { keyword: string, newPosition: number } | null {\r\n if (this.isEndOfInput(input, position)) {\r\n return null;\r\n }\r\n\r\n // reset trie node\r\n this.trie.reset();\r\n const result = StringUtils.tryReadRegularIdentifier(input, position);\r\n\r\n if (result === null) {\r\n return null;\r\n }\r\n\r\n let matchResult = this.trie.pushLexeme(result.identifier.toLowerCase());\r\n\r\n if (matchResult === KeywordMatchResult.NotAKeyword) {\r\n return null;\r\n }\r\n\r\n if (matchResult === KeywordMatchResult.Final) {\r\n return {\r\n keyword: result.identifier,\r\n newPosition: result.newPosition\r\n };\r\n }\r\n\r\n // multi-word keyword\r\n let lexeme = result.identifier;\r\n position = StringUtils.readWhiteSpaceAndComment(input, result.newPosition).position;\r\n\r\n // end of input\r\n if (this.isEndOfInput(input, position)) {\r\n if (matchResult === KeywordMatchResult.PartialOrFinal) {\r\n // if the last match was partial or final, it means that the keyword is finished\r\n return {\r\n keyword: lexeme,\r\n newPosition: position\r\n };\r\n } else {\r\n\r\n return null;\r\n }\r\n }\r\n\r\n while (this.canParse(input, position)) {\r\n const previousMatchResult = matchResult;\r\n\r\n const result = StringUtils.tryReadRegularIdentifier(input, position);\r\n\r\n if (result !== null) {\r\n matchResult = this.trie.pushLexeme(result.identifier.toLowerCase());\r\n\r\n if (matchResult === KeywordMatchResult.NotAKeyword) {\r\n if (previousMatchResult === KeywordMatchResult.PartialOrFinal) {\r\n break;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n lexeme += ' ' + result.identifier;\r\n position = StringUtils.readWhiteSpaceAndComment(input, result.newPosition).position;\r\n\r\n if (matchResult === KeywordMatchResult.Final) {\r\n break;\r\n }\r\n } else if (previousMatchResult === KeywordMatchResult.PartialOrFinal) {\r\n break;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n keyword: lexeme,\r\n newPosition: position\r\n };\r\n }\r\n}\r\n\r\n", "\uFEFFimport { KeywordMatchResult } from \"../parsers/KeywordParser\";\r\n\r\n// Note: An object-based trie (string-keyed object) was tested, but benchmark results showed no improvement and sometimes worse performance for long queries.\r\n// Therefore, the original Map-based implementation is retained for best stability and speed.\r\n\r\nexport class KeywordTrie {\r\n private root: Map<string, any> = new Map();\r\n private currentNode: Map<string, any>;\r\n\r\n // cache properties\r\n private hasEndProperty: boolean = false;\r\n private hasMoreProperties: boolean = false;\r\n\r\n constructor(keywords: string[][]) {\r\n // initialize root node\r\n for (const keyword of keywords) {\r\n this.addKeyword(keyword);\r\n }\r\n // set current node to root\r\n this.currentNode = this.root;\r\n }\r\n\r\n private addKeyword(keyword: string[]) {\r\n let node = this.root;\r\n for (const word of keyword) {\r\n if (!node.has(word)) {\r\n node.set(word, new Map());\r\n }\r\n node = node.get(word);\r\n }\r\n node.set(\"__end__\", true);\r\n }\r\n\r\n public reset(): void {\r\n this.currentNode = this.root;\r\n this.hasEndProperty = false;\r\n this.hasMoreProperties = false;\r\n }\r\n\r\n public pushLexeme(lexeme: string): KeywordMatchResult {\r\n if (!this.currentNode.has(lexeme)) {\r\n return KeywordMatchResult.NotAKeyword;\r\n }\r\n\r\n // move to next node\r\n this.currentNode = this.currentNode.get(lexeme);\r\n\r\n // Cache property checks to avoid repeated operations\r\n this.hasEndProperty = this.currentNode.has(\"__end__\");\r\n this.hasMoreProperties = this.currentNode.size > (this.hasEndProperty ? 1 : 0);\r\n\r\n if (this.hasEndProperty && !this.hasMoreProperties) {\r\n return KeywordMatchResult.Final;\r\n }\r\n if (this.hasEndProperty && this.hasMoreProperties) {\r\n return KeywordMatchResult.PartialOrFinal;\r\n }\r\n\r\n return KeywordMatchResult.PartialOnly;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\n\r\n/**\r\n * Reads SQL literal tokens (numbers, strings)\r\n */\r\n\r\nconst keywords = [\r\n [\"null\"],\r\n [\"true\"],\r\n [\"false\"],\r\n [\"current_date\"],\r\n [\"current_time\"],\r\n [\"current_timestamp\"],\r\n [\"localtime\"],\r\n [\"localtimestamp\"],\r\n [\"unbounded\"],\r\n [\"normalized\"],\r\n [\"nfc\", \"normalized\"],\r\n [\"nfd\", \"normalized\"],\r\n [\"nfkc\", \"normalized\"],\r\n [\"nfkd\", \"normalized\"],\r\n [\"nfc\"],\r\n [\"nfd\"],\r\n [\"nfkc\"],\r\n [\"nfkd\"],\r\n];\r\nconst trie = new KeywordTrie(keywords);\r\nexport const literalKeywordParser = new KeywordParser(trie);\r\n\r\nexport class LiteralTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read a literal token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // Check for keyword literals \r\n const keyword = this.tryReadKeyword();\r\n if (keyword) {\r\n return keyword;\r\n }\r\n\r\n // Decimal token starting with a dot\r\n if (char === '.' && this.canRead(1) && CharLookupTable.isDigit(this.input[this.position + 1])) {\r\n return this.createLexeme(TokenType.Literal, this.readDigit());\r\n }\r\n\r\n // String literal\r\n if (char === '\\'') {\r\n const value = this.readSingleQuotedString(false);\r\n return this.createLexeme(TokenType.Literal, value);\r\n }\r\n\r\n // Digit tokens\r\n if (CharLookupTable.isDigit(char)) {\r\n return this.createLexeme(TokenType.Literal, this.readDigit());\r\n }\r\n\r\n // Signed number\r\n if ((char === '+' || char === '-') && this.determineSignOrOperator(previous) === \"sign\") {\r\n const sign = char;\r\n this.position++;\r\n\r\n // Skip whitespace after sign\r\n const pos = this.position;\r\n while (this.canRead() && CharLookupTable.isWhitespace(this.input[this.position])) {\r\n this.position++;\r\n }\r\n\r\n if (this.canRead() && (\r\n CharLookupTable.isDigit(this.input[this.position]) ||\r\n (this.input[this.position] === '.' &&\r\n this.canRead(1) &&\r\n CharLookupTable.isDigit(this.input[this.position + 1]))\r\n )) {\r\n return this.createLexeme(\r\n TokenType.Literal,\r\n sign === '-' ? sign + this.readDigit() : this.readDigit()\r\n );\r\n }\r\n\r\n // Not a number, restore position\r\n this.position = pos - 1; // Adjust for the increment at the beginning\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private tryReadKeyword(): Lexeme | null {\r\n // Check for keyword literals\r\n const result = literalKeywordParser.parse(this.input, this.position);\r\n if (result) {\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Literal, result.keyword);\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Determines if the current context treats '+' or '-' as a numeric sign or an operator.\r\n * This method is used to differentiate between operators and numeric signs (e.g., '+' or '-').\r\n *\r\n * For example:\r\n * - In `1-1`, the '-' is treated as an operator, so the expression is split into `1`, `-`, and `1`.\r\n * - In `-1`, the '-' is treated as a sign, making `-1` a single, indivisible literal.\r\n *\r\n * The logic for determining whether '+' or '-' is a sign or an operator is as follows:\r\n * - If there is no previous lexeme, it is considered the start of the input, so the sign is valid.\r\n * - If the previous lexeme is a literal or an identifier (e.g., `a.id`), the sign is treated as an operator.\r\n * - If the previous lexeme is a closing parenthesis (e.g., `count(*)`), the sign is also treated as an operator.\r\n *\r\n * @param previous The previous lexeme in the input stream.\r\n * @returns \"sign\" if the context allows for a numeric sign, otherwise \"operator\".\r\n */\r\n private determineSignOrOperator(previous: Lexeme | null): \"sign\" | \"operator\" {\r\n // If there is no previous lexeme, treat as a sign\r\n if (previous === null) {\r\n return \"sign\";\r\n }\r\n\r\n // If the previous lexeme is a literal, identifier, or closing parenthesis, treat as an operator\r\n const isOperatorContext = previous.type === TokenType.Literal || previous.type === TokenType.Identifier || previous.type === TokenType.CloseParen;\r\n return isOperatorContext ? \"operator\" : \"sign\";\r\n }\r\n\r\n /**\r\n * Read a numeric value\r\n */\r\n private readDigit(): string {\r\n const start = this.position;\r\n let hasDot = false;\r\n let hasExponent = false;\r\n\r\n // Consider 0x, 0b, 0o\r\n if (this.canRead(1) &&\r\n this.input[this.position] === '0' &&\r\n \"xbo\".includes(this.input[this.position + 1].toLowerCase())) {\r\n\r\n const prefixType = this.input[this.position + 1].toLowerCase();\r\n this.position += 2;\r\n\r\n // Continue to get numeric and hexadecimal notation strings\r\n const isHex = prefixType === 'x';\r\n while (this.canRead()) {\r\n const c = this.input[this.position];\r\n if (CharLookupTable.isDigit(c) || (isHex && CharLookupTable.isHexChar(c))) {\r\n this.position++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n return this.input.slice(start, this.position);\r\n }\r\n\r\n // If starting with dot, note it\r\n if (this.input[start] === '.') {\r\n hasDot = true;\r\n this.position++;\r\n }\r\n\r\n // Consider decimal point and exponential notation\r\n while (this.canRead()) {\r\n const char = this.input[this.position];\r\n\r\n if (char === '.' && !hasDot) {\r\n hasDot = true;\r\n } else if ((char === 'e' || char === 'E') && !hasExponent) {\r\n hasExponent = true;\r\n if (this.canRead(1) && (this.input[this.position + 1] === '+' || this.input[this.position + 1] === '-')) {\r\n this.position++;\r\n }\r\n } else if (!CharLookupTable.isDigit(char)) {\r\n break;\r\n }\r\n\r\n this.position++;\r\n }\r\n\r\n if (start === this.position) {\r\n throw new Error(`Unexpected character. position: ${start}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n if (this.input[start] === '.') {\r\n // If the number starts with a dot, add 0 to the front\r\n return '0' + this.input.slice(start, this.position);\r\n }\r\n\r\n return this.input.slice(start, this.position);\r\n }\r\n\r\n /**\r\n * Read a string literal\r\n */\r\n private readSingleQuotedString(includeSingleQuote: boolean): string {\r\n const start = this.position;\r\n let closed = false;\r\n this.read(\"'\");\r\n\r\n while (this.canRead()) {\r\n const char = this.input[this.position];\r\n this.position++;\r\n\r\n // escape character check\r\n if (char === \"\\\\\" && this.canRead(1)) {\r\n this.position++;\r\n continue;\r\n }\r\n else if (char === '\\'') {\r\n closed = true;\r\n break;\r\n }\r\n }\r\n\r\n if (closed === false) {\r\n throw new Error(`Single quote is not closed. position: ${start}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n if (includeSingleQuote) {\r\n const value = this.input.slice(start, this.position);\r\n return value;\r\n } else {\r\n const value = this.input.slice(start + 1, this.position - 1);\r\n return value;\r\n }\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\n\r\n/**\r\n * Reads SQL parameter tokens (@param, :param, $param, ?, ${param})\r\n */\r\nexport class ParameterTokenReader extends BaseTokenReader {\r\n constructor(input: string) {\r\n super(input);\r\n }\r\n\r\n /**\r\n * Try to read a parameter token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // parameter with suffix (${param}) - check this first\r\n if (this.canRead(1) && this.input[this.position] === '$' && this.input[this.position + 1] === '{') {\r\n this.position += 2; // Skip ${\r\n const start = this.position;\r\n while (this.canRead() && this.input[this.position] !== '}') {\r\n this.position++;\r\n }\r\n if (this.isEndOfInput()) {\r\n throw new Error(`Unexpected end of input. Expected closing '}' for parameter at position ${start}`);\r\n }\r\n\r\n const identifier = this.input.slice(start, this.position);\r\n if (identifier.length === 0) {\r\n throw new Error('Empty parameter name is not allowed: found ${} at position ' + (start - 2));\r\n }\r\n\r\n this.position++; // Skip }\r\n return this.createLexeme(TokenType.Parameter, '${' + identifier + '}');\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // named parameter (@param, :param, $param)\r\n if (CharLookupTable.isNamedParameterPrefix(char)) {\r\n\r\n // However, do not recognize as a parameter if the next character is an operator symbol\r\n // To avoid postgres `::`\r\n if (this.canRead(1) && CharLookupTable.isOperatorSymbol(this.input[this.position + 1])) {\r\n return null;\r\n }\r\n\r\n this.position++;\r\n\r\n // Read the identifier part after the prefix\r\n const start = this.position;\r\n while (this.canRead() && !CharLookupTable.isDelimiter(this.input[this.position])) {\r\n this.position++;\r\n }\r\n\r\n const identifier = this.input.slice(start, this.position);\r\n return this.createLexeme(TokenType.Parameter, char + identifier);\r\n }\r\n\r\n // nameless parameter (?)\r\n if (char === '?') {\r\n this.position++;\r\n return this.createLexeme(TokenType.Parameter, char);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\n\r\n/**\r\n * Reads SQL symbol tokens (., ,, (, ))\r\n */\r\nexport class SpecialSymbolTokenReader extends BaseTokenReader {\r\n private static readonly SPECIAL_SYMBOL_TOKENS: Record<string, TokenType> = {\r\n '.': TokenType.Dot,\r\n ',': TokenType.Comma,\r\n '(': TokenType.OpenParen,\r\n ')': TokenType.CloseParen,\r\n '[': TokenType.OpenBracket,\r\n ']': TokenType.CloseBracket,\r\n };\r\n\r\n /**\r\n * Try to read a symbol token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // symbol tokens\r\n if (char in SpecialSymbolTokenReader.SPECIAL_SYMBOL_TOKENS) {\r\n this.position++;\r\n return this.createLexeme(\r\n SpecialSymbolTokenReader.SPECIAL_SYMBOL_TOKENS[char],\r\n char\r\n );\r\n }\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\n\r\n/**\r\n * Manages and coordinates multiple token readers\r\n */\r\nexport class TokenReaderManager {\r\n private readers: BaseTokenReader[];\r\n private input: string;\r\n private position: number;\r\n private tokenCache: Map<number, Lexeme | null>;\r\n private cacheHits: number = 0;\r\n private cacheMisses: number = 0;\r\n\r\n constructor(input: string, position: number = 0) {\r\n this.input = input;\r\n this.position = position;\r\n this.readers = [];\r\n this.tokenCache = new Map();\r\n }\r\n\r\n /**\r\n * Register a token reader\r\n * @param reader The reader to register\r\n * @returns This manager instance for chaining\r\n */\r\n public register(reader: BaseTokenReader): TokenReaderManager {\r\n this.readers.push(reader);\r\n return this;\r\n }\r\n\r\n /**\r\n * Register multiple token readers\r\n * @param readers The readers to register\r\n * @returns This manager instance for chaining\r\n */\r\n public registerAll(readers: BaseTokenReader[]): TokenReaderManager {\r\n readers.forEach(reader => this.register(reader));\r\n return this;\r\n }\r\n\r\n /**\r\n * Update the position for all readers\r\n */\r\n private setPosition(position: number): void {\r\n this.position = position;\r\n for (const reader of this.readers) {\r\n reader.setPosition(position);\r\n }\r\n }\r\n\r\n /**\r\n * Try to read a token using all registered readers\r\n * @param position The position to read from\r\n * @param previous The previous token, if any\r\n * @returns The lexeme if a reader could read it, null otherwise\r\n */\r\n public tryRead(position: number, previous: Lexeme | null): Lexeme | null {\r\n // Check cache - using position as the key\r\n if (this.tokenCache.has(position)) {\r\n // Cache hit\r\n this.cacheHits++;\r\n const lexeme = this.tokenCache.get(position) || null;\r\n return lexeme;\r\n }\r\n\r\n // Cache miss - create new entry\r\n this.cacheMisses++;\r\n this.setPosition(position);\r\n\r\n // Try to read with each reader\r\n let lexeme: Lexeme | null = null;\r\n for (const reader of this.readers) {\r\n lexeme = reader.tryRead(previous);\r\n if (lexeme) {\r\n this.position = reader.getPosition();\r\n break;\r\n }\r\n }\r\n\r\n // Update all readers' positions\r\n for (const reader of this.readers) {\r\n reader.setPosition(this.position);\r\n }\r\n\r\n // Save to cache (even if null)\r\n this.tokenCache.set(position, lexeme);\r\n return lexeme;\r\n }\r\n\r\n /**\r\n * Get the maximum position among all readers\r\n */\r\n public getMaxPosition(): number {\r\n let maxPosition = this.position;\r\n for (const reader of this.readers) {\r\n const position = reader.getPosition();\r\n if (position > maxPosition) {\r\n maxPosition = position;\r\n }\r\n }\r\n return maxPosition;\r\n }\r\n\r\n /**\r\n * Get the input string\r\n */\r\n public getInput(): string {\r\n return this.input;\r\n }\r\n\r\n /**\r\n * Get cache statistics\r\n */\r\n public getCacheStats(): { hits: number, misses: number, ratio: number } {\r\n const total = this.cacheHits + this.cacheMisses;\r\n const ratio = total > 0 ? this.cacheHits / total : 0;\r\n return {\r\n hits: this.cacheHits,\r\n misses: this.cacheMisses,\r\n ratio: ratio\r\n };\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { CharLookupTable } from '../utils/charLookupTable';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\n\r\nconst trie = new KeywordTrie([\r\n // binary\r\n [\"and\"],\r\n [\"or\"],\r\n [\"is\"],\r\n [\"is\", \"not\"],\r\n [\"is\", \"distinct\", \"from\"],\r\n [\"is\", \"not\", \"distinct\", \"from\"],\r\n [\"like\"],\r\n [\"in\"],\r\n [\"exists\"],\r\n [\"between\"],\r\n [\"not\", \"like\"],\r\n [\"not\", \"in\"],\r\n [\"not\", \"exists\"],\r\n [\"not\", \"between\"],\r\n [\"escape\"], // e.g. '10% OFF on all items' like '10\\%%' escape '\\'\r\n [\"uescape\"], // e.g. U&'d!0061t!+000061' uescape '!'\r\n [\"similar\"], // e.g. substring('abcdef' similar '%#\"cd#\"%' escape '#')\r\n [\"placing\"], // e.g. overlay('abcdef' placing 'cd' from 3 for 2)\r\n // unary\r\n [\"not\"],\r\n // unary - trim\r\n [\"both\"],\r\n [\"leading\"],\r\n [\"trailing\"],\r\n [\"both\", \"from\"], // Postgres\r\n [\"leading\", \"from\"], // Postgres\r\n [\"trailing\", \"from\"], // Postgres\r\n // unary - extract\r\n [\"year\", \"from\"],\r\n [\"month\", \"from\"],\r\n [\"day\", \"from\"],\r\n [\"hour\", \"from\"],\r\n [\"minute\", \"from\"],\r\n [\"second\", \"from\"],\r\n [\"dow\", \"from\"],\r\n [\"doy\", \"from\"],\r\n [\"isodow\", \"from\"],\r\n [\"quarter\", \"from\"],\r\n [\"week\", \"from\"],\r\n [\"epoch\", \"from\"],\r\n [\"at\", \"time\", \"zone\"],\r\n // The following are not considered operators.\r\n // [\"from\"], can be used as an operator only within the substring function, but it cannot be distinguished from the Form Clause. This will be resolved with a dedicated substring parser.\r\n // [\"for\"], can be used as an operator only within the substring function, but it cannot be distinguished from the For Clause. This will be resolved with a dedicated substring parser.\r\n]);\r\n\r\n// Typed literal format\r\nconst operatorOrTypeTrie = new KeywordTrie([\r\n [\"date\"],\r\n [\"time\"],\r\n [\"timestamp\"],\r\n [\"timestamptz\"],// timestamp with time zone\r\n [\"timetz\"], // time with time zone\r\n [\"interval\"],\r\n [\"boolean\"],\r\n [\"integer\"],\r\n [\"bigint\"],\r\n [\"smallint\"],\r\n [\"numeric\"],\r\n [\"decimal\"],\r\n [\"real\"],\r\n [\"double\", \"precision\"],\r\n [\"double\", \"precision\"],\r\n [\"character\", \"varying\"],\r\n [\"time\", \"without\", \"time\", \"zone\"],\r\n [\"time\", \"with\", \"time\", \"zone\"],\r\n [\"timestamp\", \"without\", \"time\", \"zone\"],\r\n [\"timestamp\", \"with\", \"time\", \"zone\"],\r\n]);\r\n\r\nconst keywordParser = new KeywordParser(trie);\r\nconst operatorOrTypeParser = new KeywordParser(operatorOrTypeTrie);\r\n\r\n// Indicates the token may also represent a type (e.g., 'interval')\r\nconst MAYBE_TYPE = true;\r\n\r\nexport class OperatorTokenReader extends BaseTokenReader {\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n /*\r\n NOTE:\r\n Asterisks could potentially be wildcard identifiers,\r\n but since they're indistinguishable at this stage, they're treated as Operators at the token level.\r\n The Parser needs to determine whether they are appropriate Operators or Identifiers.\r\n */\r\n\r\n const char = this.input[this.position];\r\n\r\n if (CharLookupTable.isOperatorSymbol(char)) {\r\n const start = this.position;\r\n\r\n while (this.canRead() && CharLookupTable.isOperatorSymbol(this.input[this.position])) {\r\n // check for `--` and `/*` comments\r\n if (this.canRead(1)) {\r\n const current = this.input[this.position];\r\n if (current === '-' && this.input[this.position + 1] === '-') {\r\n break;\r\n } else if (current === '/' && this.input[this.position + 1] === '*') {\r\n break; // end of operator\r\n }\r\n }\r\n\r\n this.position++;\r\n }\r\n const resut = this.input.slice(start, this.position);\r\n return this.createLexeme(TokenType.Operator, resut);\r\n }\r\n\r\n // Logical operators\r\n let result = operatorOrTypeParser.parse(this.input, this.position);\r\n if (result !== null) {\r\n // Special handling for typed literal format.\r\n // Treated as an operator in cases like `interval '2 days'`,\r\n // but can also be used as a type in expressions like `'1 month'::interval`,\r\n // so we return it as both Operator and Type.\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Operator | TokenType.Type | TokenType.Identifier, result.keyword);\r\n }\r\n\r\n result = keywordParser.parse(this.input, this.position);\r\n if (result !== null) {\r\n this.position = result.newPosition;\r\n return this.createLexeme(TokenType.Operator, result.keyword);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from \"./BaseTokenReader\";\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { KeywordTrie } from \"../models/KeywordTrie\";\r\nimport { KeywordParser } from \"../parsers/KeywordParser\";\r\n\r\n// Commands are those that require a dedicated parser.\r\n// Keywords composed of multiple words are also considered commands.\r\n// The exception is \"type\". Since types can be user-defined and cannot be accurately identified, they are treated as Identifiers.\r\n\r\nconst joinTrie = new KeywordTrie([\r\n [\"join\"],\r\n [\"inner\", \"join\"],\r\n [\"cross\", \"join\"],\r\n [\"left\", \"join\"],\r\n [\"left\", \"outer\", \"join\"],\r\n [\"right\", \"join\"],\r\n [\"right\", \"outer\", \"join\"],\r\n [\"full\", \"join\"],\r\n [\"full\", \"outer\", \"join\"],\r\n\r\n [\"natural\", \"join\"],\r\n [\"natural\", \"inner\", \"join\"],\r\n [\"natural\", \"left\", \"join\"],\r\n [\"natural\", \"left\", \"outer\", \"join\"],\r\n [\"natural\", \"right\", \"join\"],\r\n [\"natural\", \"right\", \"outer\", \"join\"],\r\n [\"natural\", \"full\", \"join\"],\r\n [\"natural\", \"full\", \"outer\", \"join\"],\r\n]);\r\nconst keywordTrie = new KeywordTrie([\r\n [\"with\"],\r\n [\"recursive\"],\r\n [\"materialized\"],\r\n [\"not\", \"materialized\"],\r\n [\"select\"],\r\n [\"from\"],\r\n [\"distinct\"],\r\n [\"distinct\", \"on\"],\r\n [\"where\"],\r\n [\"group\", \"by\"],\r\n [\"having\"],\r\n [\"order\", \"by\"],\r\n [\"limit\"],\r\n [\"offset\"],\r\n [\"fetch\"],\r\n [\"first\"],\r\n [\"next\"],\r\n [\"row\"],\r\n [\"row\", \"only\"],\r\n [\"rows\", \"only\"],\r\n [\"percent\"],\r\n [\"percent\", \"with\", \"ties\"],\r\n // for\r\n [\"for\"],\r\n [\"update\"],\r\n [\"share\"],\r\n [\"key\", \"share\"],\r\n [\"no\", \"key\", \"update\"],\r\n // set operations\r\n [\"union\"],\r\n [\"union\", \"all\"],\r\n [\"intersect\"],\r\n [\"intersect\", \"all\"],\r\n [\"except\"],\r\n [\"except\", \"all\"],\r\n // between and\r\n [\"beteen\"],\r\n // window functions\r\n [\"window\"],\r\n [\"over\"],\r\n [\"partition\", \"by\"],\r\n [\"range\"],\r\n [\"rows\"],\r\n [\"groups\"],\r\n // window frame\r\n [\"current\", \"row\"],\r\n [\"unbounded\", \"preceding\"],\r\n [\"unbounded\", \"following\"],\r\n [\"preceding\"],\r\n [\"following\"],\r\n // table join commands\r\n [\"on\"],\r\n [\"using\"],\r\n [\"lateral\"],\r\n // case \r\n [\"case\"],\r\n [\"case\", \"when\"],\r\n [\"when\"],\r\n [\"then\"],\r\n [\"else\"],\r\n [\"end\"],\r\n // others\r\n [\"insert\", \"into\"],\r\n [\"update\"],\r\n [\"delete\", \"from\"],\r\n [\"merge\", \"into\"],\r\n [\"matched\"],\r\n [\"not\", \"matched\"],\r\n [\"update\", \"set\"],\r\n [\"do\", \"nothing\"],\r\n [\"values\"],\r\n [\"set\"],\r\n [\"returning\"],\r\n [\"create\", \"table\"],\r\n [\"create\", \"temporary\", \"table\"],\r\n [\"tablesample\"],\r\n // cast\r\n [\"as\"],\r\n // odrder\r\n [\"asc\"],\r\n [\"desc\"],\r\n [\"nulls\", \"first\"],\r\n [\"nulls\", \"last\"],\r\n]);\r\nconst keywordParser = new KeywordParser(keywordTrie);\r\nexport const joinkeywordParser = new KeywordParser(joinTrie);\r\n\r\nexport class CommandTokenReader extends BaseTokenReader {\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const keywordJoin = joinkeywordParser.parse(this.input, this.position);\r\n if (keywordJoin !== null) {\r\n this.position = keywordJoin.newPosition;\r\n return this.createLexeme(TokenType.Command, keywordJoin.keyword);\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = keywordParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Command, keyword.keyword);\r\n }\r\n\r\n // check hint clause\r\n if (this.canRead(2) && this.input[this.position] === '/' && this.input[this.position + 1] === '*' && this.input[this.position + 2] === '+') {\r\n this.position += 3;\r\n const start = this.position;\r\n while (this.position + 1 < this.input.length) {\r\n if (this.input[this.position] === '*' && this.input[this.position + 1] === '/') {\r\n this.position += 2;\r\n return this.createLexeme(TokenType.Command, '/*+ ' + this.input.slice(start, this.position - 2).trim() + ' */');\r\n }\r\n this.position++;\r\n }\r\n throw new Error(`Block comment is not closed. position: ${this.position}`);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { BaseTokenReader } from './BaseTokenReader';\r\n\r\n// Prefix sets for quick checks\r\nconst STRING_SPECIFIERS = new Set(['e\\'', 'E\\'', 'x\\'', 'X\\'', 'b\\'', 'B\\'']);\r\nconst UNICODE_STRING_SPECIFIERS = new Set(['u&\\'', 'U&\\'']);\r\n\r\nexport class StringSpecifierTokenReader extends BaseTokenReader {\r\n\r\n /**\r\n * Try to read an escaped literal like e'...', x'...', etc.\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n const start = this.position;\r\n\r\n // Check for prefixed literals: e', x', b'\r\n if (this.canRead(1) && STRING_SPECIFIERS.has(this.input.slice(start, start + 2))) {\r\n this.position += 1;\r\n const result = this.createLexeme(TokenType.StringSpecifier, this.input.slice(start, this.position));\r\n return result;\r\n }\r\n\r\n // Check for unicode literal: u&'\r\n if (this.canRead(2) && UNICODE_STRING_SPECIFIERS.has(this.input.slice(start, start + 3))) {\r\n this.position += 2;\r\n const result = this.createLexeme(TokenType.StringSpecifier, this.input.slice(start, this.position));\r\n return result;\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\n\r\nconst trie = new KeywordTrie([\r\n [\"grouping\", \"sets\"],\r\n // ARRAY has special syntax with [] arguments, so it is forcibly treated as a function\r\n [\"array\"],\r\n]);\r\nconst keywordParser = new KeywordParser(trie);\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class FunctionTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = keywordParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Function, keyword.keyword);\r\n }\r\n\r\n // Regular identifier\r\n const result = StringUtils.tryReadRegularIdentifier(this.input, this.position);\r\n if (!result) {\r\n return null;\r\n }\r\n this.position = result.newPosition;\r\n\r\n // peek next token \r\n var shift = StringUtils.readWhiteSpaceAndComment(this.input, this.position).position - this.position;\r\n\r\n if (this.canRead(shift) && this.input[this.position + shift] === '(') {\r\n return this.createLexeme(TokenType.Function, result.identifier);\r\n }\r\n return null;\r\n }\r\n}\r\n", "\uFEFFimport { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { KeywordTrie } from '../models/KeywordTrie';\r\nimport { KeywordParser } from '../parsers/KeywordParser';\r\n\r\n// Use KeywordTrie to identify type names composed of multiple words.\r\nconst trie = new KeywordTrie([\r\n // type\r\n [\"double\", \"precision\"],\r\n [\"character\", \"varying\"],\r\n [\"time\", \"without\", \"time\", \"zone\"],\r\n [\"time\", \"with\", \"time\", \"zone\"],\r\n [\"timestamp\", \"without\", \"time\", \"zone\"],\r\n [\"timestamp\", \"with\", \"time\", \"zone\"],\r\n]);\r\nconst typeParser = new KeywordParser(trie);\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class TypeTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n // Check for keyword identifiers\r\n const keyword = typeParser.parse(this.input, this.position);\r\n if (keyword !== null) {\r\n this.position = keyword.newPosition;\r\n return this.createLexeme(TokenType.Type, keyword.keyword);\r\n }\r\n\r\n // check pervious token\r\n if (previous === null) {\r\n return null;\r\n }\r\n\r\n const result = StringUtils.tryReadRegularIdentifier(this.input, this.position);\r\n if (!result) {\r\n return null;\r\n }\r\n this.position = result.newPosition;\r\n\r\n // type cast command\r\n if (previous.type & TokenType.Command && previous.value === \"as\") {\r\n // If the previous token is the `as` keyword, it could be a type cast or an identifier\r\n return this.createLexeme(TokenType.Identifier | TokenType.Type, result.identifier);\r\n }\r\n\r\n // postgres type conversion\r\n if (previous.type & TokenType.Operator && previous.value === \"::\") {\r\n return this.createLexeme(TokenType.Type, result.identifier);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "import { BaseTokenReader } from './BaseTokenReader';\r\nimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { StringUtils } from '../utils/stringUtils';\r\n\r\n/**\r\n * Reads SQL identifier tokens\r\n */\r\nexport class EscapedIdentifierTokenReader extends BaseTokenReader {\r\n /**\r\n * Try to read an identifier token\r\n */\r\n public tryRead(previous: Lexeme | null): Lexeme | null {\r\n if (this.isEndOfInput()) {\r\n return null;\r\n }\r\n\r\n const char = this.input[this.position];\r\n\r\n // MySQL escaped identifier (escape character is backtick)\r\n if (char === '`') {\r\n const identifier = this.readEscapedIdentifier('`');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n // Postgres escaped identifier (escape character is double quote)\r\n if (char === '\"') {\r\n const identifier = this.readEscapedIdentifier('\"');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n // SQLServer escaped identifier (escape character is square bracket)\r\n if (char === '[' && (previous === null || previous.value !== \"array\")) {\r\n const identifier = this.readEscapedIdentifier(']');\r\n return this.createLexeme(TokenType.Identifier, identifier);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Read an escaped identifier (surrounded by delimiters)\r\n */\r\n private readEscapedIdentifier(delimiter: string): string {\r\n const start = this.position;\r\n\r\n // Skip the opening delimiter\r\n this.position++;\r\n\r\n while (this.canRead()) {\r\n if (this.input[this.position] === delimiter) {\r\n break;\r\n }\r\n this.position++;\r\n }\r\n\r\n if (start === this.position) {\r\n throw new Error(`Closing delimiter is not found. position: ${start}, delimiter: ${delimiter}\\n${this.getDebugPositionInfo(start)}`);\r\n }\r\n\r\n // Skip the closing delimiter\r\n this.position++;\r\n\r\n // exclude the delimiter\r\n return this.input.slice(start + 1, this.position - 1);\r\n }\r\n}\r\n", "\uFEFFimport { Lexeme, TokenType } from '../models/Lexeme';\r\nimport { IdentifierTokenReader } from '../tokenReaders/IdentifierTokenReader';\r\nimport { LiteralTokenReader } from '../tokenReaders/LiteralTokenReader';\r\nimport { ParameterTokenReader } from '../tokenReaders/ParameterTokenReader';\r\nimport { SpecialSymbolTokenReader } from '../tokenReaders/SymbolTokenReader';\r\nimport { TokenReaderManager } from '../tokenReaders/TokenReaderManager';\r\nimport { OperatorTokenReader } from '../tokenReaders/OperatorTokenReader';\r\nimport { StringUtils } from '../utils/stringUtils';\r\nimport { CommandTokenReader } from '../tokenReaders/CommandTokenReader';\r\nimport { StringSpecifierTokenReader } from '../tokenReaders/StringSpecifierTokenReader';\r\nimport { FunctionTokenReader } from '../tokenReaders/FunctionTokenReader';\r\nimport { TypeTokenReader } from '../tokenReaders/TypeTokenReader';\r\nimport { EscapedIdentifierTokenReader } from '../tokenReaders/EscapedIdentifierTokenReader';\r\n\r\n/**\r\n * Class responsible for tokenizing SQL input.\r\n */\r\nexport class SqlTokenizer {\r\n /**\r\n * The input SQL string to be tokenized.\r\n */\r\n private input: string;\r\n\r\n /**\r\n * Current position within the input string.\r\n */\r\n private position: number;\r\n\r\n /**\r\n * Manager responsible for handling token readers.\r\n */\r\n private readerManager: TokenReaderManager;\r\n\r\n /**\r\n * Initializes a new instance of the SqlTokenizer.\r\n */\r\n constructor(input: string) {\r\n this.input = input;\r\n this.position = 0;\r\n\r\n // Initialize the token reader manager and register all readers\r\n this.readerManager = new TokenReaderManager(input)\r\n .register(new EscapedIdentifierTokenReader(input))\r\n .register(new ParameterTokenReader(input))\r\n .register(new StringSpecifierTokenReader(input))\r\n // LiteralTokenReader should be registered before SpecialSymbolTokenReader and OperatorTokenReader\r\n // Reason: To prevent numeric literals starting with a dot or sign from being misrecognized as operators\r\n // e.g. `1.0` is a literal, not an operator\r\n .register(new LiteralTokenReader(input))\r\n .register(new SpecialSymbolTokenReader(input))\r\n .register(new CommandTokenReader(input))\r\n .register(new OperatorTokenReader(input))\r\n // TypeTokenReader should be registered before FunctionTokenReader\r\n // Reason: To prevent types containing parentheses from being misrecognized as functions\r\n // e.g. `numeric(10, 2)` is a type, not a function\r\n .register(new TypeTokenReader(input))\r\n .register(new FunctionTokenReader(input))\r\n .register(new IdentifierTokenReader(input)) // IdentifierTokenReader should be registered last\r\n ;\r\n }\r\n\r\n /**\r\n * Checks if the end of input is reached.\r\n * \r\n * @param shift - The shift to consider beyond the current position.\r\n * @returns True if the end of input is reached; otherwise, false.\r\n */\r\n private isEndOfInput(shift: number = 0): boolean {\r\n return this.position + shift >= this.input.length;\r\n }\r\n\r\n /**\r\n * Checks if more input can be read.\r\n * \r\n * @param shift - The shift to consider beyond the current position.\r\n * @returns True if more input can be read; otherwise, false.\r\n */\r\n private canRead(shift: number = 0): boolean {\r\n return !this.isEndOfInput(shift);\r\n }\r\n\r\n /**\r\n * Reads the lexemes from the input string.\r\n * \r\n * @returns An array of lexemes extracted from the input string.\r\n * @throws Error if an unexpected character is encountered.\r\n */\r\n public readLexmes(): Lexeme[] {\r\n // Pre-allocate array with estimated capacity for better performance\r\n const estimatedTokens = Math.ceil(this.input.length / 8); // Assuming average token length of 8 chars\r\n const lexemes: Lexeme[] = new Array(estimatedTokens);\r\n let lexemeCount = 0;\r\n\r\n // Read initial prefix comments\r\n const comment = this.readComment();\r\n let pendingComments = comment.lines;\r\n this.position = comment.position;\r\n\r\n // Track the previous token\r\n let previous: Lexeme | null = null;\r\n\r\n // Read tokens until the end of input is reached\r\n while (this.canRead()) {\r\n // Semicolon is a delimiter, so stop reading\r\n if (this.input[this.position] === ';') {\r\n break;\r\n }\r\n\r\n // Read using the token reader manager\r\n const lexeme = this.readerManager.tryRead(this.position, previous);\r\n\r\n if (lexeme === null) {\r\n throw new Error(`Unexpected character. actual: ${this.input[this.position]}, position: ${this.position}\\n${this.getDebugPositionInfo(this.position)}`);\r\n }\r\n\r\n // Update position\r\n this.position = this.readerManager.getMaxPosition();\r\n\r\n // Read suffix comments\r\n const currentComment = this.readComment();\r\n this.position = currentComment.position;\r\n\r\n if ((lexeme.type & TokenType.Comma) || (lexeme.type & TokenType.Operator)) {\r\n // Carry over comments after commas or operators\r\n if (currentComment.lines.length > 0) {\r\n pendingComments.push(...currentComment.lines);\r\n }\r\n } else {\r\n // Add comments to the current token if any\r\n const hasComments = pendingComments.length > 0 || currentComment.lines.length > 0;\r\n if (hasComments) {\r\n this.addCommentsToToken(lexeme, pendingComments, currentComment.lines);\r\n }\r\n pendingComments = []; // Clear as they are processed\r\n }\r\n\r\n lexemes[lexemeCount++] = lexeme;\r\n previous = lexeme;\r\n }\r\n\r\n // Add any pending comments to the last token\r\n if (pendingComments.length > 0 && lexemeCount > 0) {\r\n const lastToken = lexemes[lexemeCount - 1];\r\n if (lastToken.comments === null) {\r\n lastToken.comments = [];\r\n }\r\n lastToken.comments.push(...pendingComments);\r\n }\r\n\r\n // Trim the array to actual size used\r\n return lexemeCount === estimatedTokens ? lexemes : lexemes.slice(0, lexemeCount);\r\n }\r\n\r\n /**\r\n * Adds pending comments to the last token.\r\n */\r\n private addPendingCommentsToLastToken(lexemes: Lexeme[], pendingComments: string[]): void {\r\n if (pendingComments.length > 0 && lexemes.length > 0) {\r\n const lastToken = lexemes[lexemes.length - 1];\r\n if (lastToken.comments === null) {\r\n lastToken.comments = [];\r\n }\r\n lastToken.comments.push(...pendingComments);\r\n }\r\n }\r\n\r\n /**\r\n * Adds comments to the token.\r\n */\r\n private addCommentsToToken(lexeme: Lexeme, prefixComments: string[], suffixComments: string[]): void {\r\n const hasComments = prefixComments.length > 0 || suffixComments.length > 0;\r\n\r\n if (hasComments) {\r\n if (lexeme.comments === null) {\r\n lexeme.comments = [];\r\n }\r\n\r\n // Add prefix comments to the beginning.\r\n if (prefixComments.length > 0) {\r\n lexeme.comments.unshift(...prefixComments);\r\n }\r\n\r\n // Add suffix comments to the end.\r\n if (suffixComments.length > 0) {\r\n lexeme.comments.push(...suffixComments);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Skips whitespace characters and SQL comments in the input.\r\n * \r\n * @remarks This method updates the position pointer.\r\n */\r\n private readComment(): { position: number, lines: string[] } {\r\n return StringUtils.readWhiteSpaceAndComment(this.input, this.position);\r\n }\r\n\r\n /**\r\n * Gets debug information for error reporting.\r\n * \r\n * @param errPosition - The position where the error occurred.\r\n * @returns A string containing the debug position information.\r\n */\r\n private getDebugPositionInfo(errPosition: number): string {\r\n return StringUtils.getDebugPositionInfo(this.input, errPosition);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { IdentifierString } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\n\r\n/**\r\n * Utility class for parsing fully qualified names (e.g. db.schema.table or db.schema.table.column_name)\r\n * This can be used for both table and column references.\r\n */\r\nexport class FullNameParser {\r\n /**\r\n * Parses a fully qualified name from lexemes, returning namespaces, table, and new index.\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { namespaces: string[] | null, name: IdentifierString, newIndex: number, lastTokenType: number } {\r\n const { identifiers, newIndex } = FullNameParser.parseEscapedOrDotSeparatedIdentifiers(lexemes, index);\r\n const { namespaces, name } = FullNameParser.extractNamespacesAndName(identifiers);\r\n // Returns the type of the last token in the identifier sequence\r\n let lastTokenType = 0;\r\n if (newIndex > index) {\r\n lastTokenType = lexemes[newIndex - 1].type;\r\n }\r\n return { namespaces, name: new IdentifierString(name), newIndex, lastTokenType };\r\n }\r\n\r\n /**\r\n * Parses a fully qualified name from a string (e.g. 'db.schema.table')\r\n * Returns { namespaces, name }\r\n */\r\n public static parse(str: string): { namespaces: string[] | null, name: IdentifierString } {\r\n const tokenizer = new SqlTokenizer(str);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n // Use a context-agnostic error message since FullNameParser is used in multiple query types\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The name is complete but additional tokens were found.`);\r\n }\r\n return { namespaces: result.namespaces, name: result.name };\r\n }\r\n\r\n // Parses SQL Server-style escaped identifiers ([table]) and dot-separated identifiers, including namespaced wildcards (e.g., db.schema.*, [db].[schema].*)\r\n private static parseEscapedOrDotSeparatedIdentifiers(lexemes: Lexeme[], index: number): { identifiers: string[]; newIndex: number } {\r\n let idx = index;\r\n const identifiers: string[] = [];\r\n while (idx < lexemes.length) {\r\n if (lexemes[idx].type & TokenType.OpenBracket) {\r\n idx++; // skip [\r\n if (idx >= lexemes.length || !((lexemes[idx].type & TokenType.Identifier) || (lexemes[idx].type & TokenType.Command))) {\r\n throw new Error(`Expected identifier after '[' at position ${idx}`);\r\n }\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].value !== \"]\") {\r\n throw new Error(`Expected closing ']' after identifier at position ${idx}`);\r\n }\r\n idx++; // skip ]\r\n } else if (lexemes[idx].type & TokenType.Identifier) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].type & TokenType.Function) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].type & TokenType.Type) {\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n } else if (lexemes[idx].value === \"*\") {\r\n // The wildcard '*' is always treated as the terminal part of a qualified name in SQL (e.g., db.schema.* or [db].[schema].*).\r\n // No valid SQL syntax allows a wildcard in the middle of a multi-part name.\r\n identifiers.push(lexemes[idx].value);\r\n idx++;\r\n break;\r\n }\r\n // Handle dot for schema.table or db.schema.table\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Dot)) {\r\n idx++; // skip dot\r\n } else {\r\n break;\r\n }\r\n }\r\n return { identifiers, newIndex: idx };\r\n }\r\n\r\n // Utility to extract namespaces and the final name from an array of identifiers\r\n // Example: [\"db\", \"schema\", \"users\"] => { namespaces: [\"db\", \"schema\"], name: \"users\" }\r\n private static extractNamespacesAndName(identifiers: string[]): { namespaces: string[] | null, name: string } {\r\n if (!identifiers || identifiers.length === 0) {\r\n throw new Error(\"Identifier list is empty\");\r\n }\r\n if (identifiers.length === 1) {\r\n return { namespaces: null, name: identifiers[0] };\r\n }\r\n return { namespaces: identifiers.slice(0, -1), name: identifiers[identifiers.length - 1] };\r\n }\r\n}\r\n", "import { FullNameParser } from \"./FullNameParser\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { ColumnReference, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class IdentifierParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Use FullNameParser to robustly parse qualified identifiers, including wildcards and escaped names.\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, index);\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n }\r\n}", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { LiteralValue, RawString, ValueComponent } from \"../models/ValueComponent\";\r\nimport { literalKeywordParser } from \"../tokenReaders/LiteralTokenReader\";\r\n\r\nexport class LiteralParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Process literal value\r\n let idx = index;\r\n const valueText = lexemes[idx].value;\r\n let parsedValue: string | number | boolean | null;\r\n\r\n const lex = literalKeywordParser.parse(valueText.toLowerCase(), 0);\r\n if (lex) {\r\n const value = new RawString(lex.keyword);\r\n idx++\r\n return { value, newIndex: idx };\r\n }\r\n\r\n // Check if it is a number\r\n if (/^[+-]?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(valueText)) {\r\n parsedValue = Number(valueText);\r\n }\r\n // Otherwise, treat it as a string\r\n else {\r\n // Remove single quotes if enclosed\r\n if (valueText.startsWith(\"'\") && valueText.endsWith(\"'\")) {\r\n parsedValue = valueText.slice(1, -1);\r\n } else {\r\n parsedValue = valueText;\r\n }\r\n }\r\n idx++\r\n const value = new LiteralValue(parsedValue);\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { InlineQuery, ParenExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class ParenExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // check inline query\r\n if (idx + 1 < lexemes.length && lexemes[idx].type & TokenType.OpenParen && (\r\n lexemes[idx + 1].value === \"select\" || lexemes[idx + 1].value === \"values\" || lexemes[idx + 1].value === \"with\"\r\n )) {\r\n idx += 1; // Skip the '(' token\r\n const result = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n\r\n // Check for closing parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Expected ')' at index ${idx}, but found ${lexemes[idx].value}`);\r\n }\r\n idx++; // Skip the ')' token\r\n\r\n const value = new InlineQuery(result.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const result = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, index);\r\n idx = result.newIndex;\r\n\r\n const value = new ParenExpression(result.value);\r\n return { value, newIndex: idx };\r\n }\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference, IdentifierString, UnaryExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class UnaryExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Process unary operator\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operator = lexemes[idx].value;\r\n idx++;\r\n\r\n // Treat the asterisk as an Identifier, not as a unary operator\r\n if (operator === '*') {\r\n const v = new ColumnReference(null, '*');\r\n return { value: v, newIndex: idx };\r\n }\r\n\r\n // Get the right-hand side value of the unary operator\r\n const result = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n\r\n // Create unary expression\r\n const value = new UnaryExpression(operator, result.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Invalid unary expression at index ${index}: ${lexemes[index].value}`);\r\n }\r\n}", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { ParameterExpression, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class ParameterExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n let paramName = lexemes[idx].value;\r\n\r\n // Normalize parameter: Remove the parameter symbol and extract the parameter name.\r\n if (paramName.startsWith('${') && paramName.endsWith('}')) {\r\n // ${name} \u2192 name\r\n paramName = paramName.slice(2, -1);\r\n } else {\r\n // :name \u2192 name\r\n paramName = paramName.slice(1);\r\n }\r\n\r\n const value = new ParameterExpression(paramName);\r\n idx++;\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { StringSpecifierExpression, ValueComponent } from \"../models/ValueComponent\";\r\n\r\nexport class StringSpecifierExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const specifer = lexemes[idx].value;\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Literal) {\r\n throw new Error(`Expected string literal after string specifier at index ${idx}`);\r\n }\r\n const value = lexemes[idx].value;\r\n idx++;\r\n // Create StringSpecifierExpression\r\n const result = new StringSpecifierExpression(specifer, value);\r\n\r\n return { value: result, newIndex: idx };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ArrayExpression, CaseExpression, CaseKeyValuePair, SwitchCaseArgument, UnaryExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class CommandExpressionParser {\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const current = lexemes[idx];\r\n if (current.value === \"case\") {\r\n idx++;\r\n return this.parseCaseExpression(lexemes, idx);\r\n } else if (current.value === \"case when\") {\r\n idx++;\r\n return this.parseCaseWhenExpression(lexemes, idx);\r\n }\r\n\r\n return this.parseModifierUnaryExpression(lexemes, idx);\r\n }\r\n\r\n private static parseModifierUnaryExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n // Check for modifier unary expression\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const command = lexemes[idx].value;\r\n idx++;\r\n const result = ValueParser.parseFromLexeme(lexemes, idx);\r\n return { value: new UnaryExpression(command!, result.value), newIndex: result.newIndex };\r\n }\r\n throw new Error(`Invalid modifier unary expression at index ${idx}, Lexeme: ${lexemes[idx].value}`);\r\n }\r\n\r\n private static parseCaseExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n\r\n const switchCaseResult = this.parseSwitchCaseArgument(lexemes, idx, []);\r\n idx = switchCaseResult.newIndex;\r\n\r\n // Create CASE expression\r\n const result = new CaseExpression(condition.value, switchCaseResult.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseCaseWhenExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n\r\n // Parse the first WHEN clause\r\n const casewhenResult = this.parseCaseConditionValuePair(lexemes, idx);\r\n idx = casewhenResult.newIndex;\r\n\r\n // Add the initial WHEN-THEN pair to the list\r\n const caseWhenList = [casewhenResult.value];\r\n\r\n // Process remaining WHEN-ELSE-END parts\r\n const switchCaseResult = this.parseSwitchCaseArgument(lexemes, idx, caseWhenList);\r\n idx = switchCaseResult.newIndex;\r\n\r\n // Create CASE expression with condition null (uses WHEN conditions instead of a simple CASE)\r\n const result = new CaseExpression(null, switchCaseResult.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n // parseSwitchCaseArgument method processes the WHEN, ELSE, and END clauses of a CASE expression.\r\n private static parseSwitchCaseArgument(\r\n lexemes: Lexeme[],\r\n index: number,\r\n initialWhenThenList: CaseKeyValuePair[]\r\n ): { value: SwitchCaseArgument; newIndex: number; } {\r\n let idx = index;\r\n const whenThenList = [...initialWhenThenList];\r\n let elseValue = null;\r\n\r\n // Process WHEN clauses\r\n while (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"when\")) {\r\n idx++;\r\n const whenResult = this.parseCaseConditionValuePair(lexemes, idx);\r\n idx = whenResult.newIndex;\r\n whenThenList.push(whenResult.value);\r\n }\r\n\r\n // Process ELSE\r\n if (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"else\")) {\r\n idx++;\r\n const elseResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n elseValue = elseResult.value;\r\n idx = elseResult.newIndex;\r\n }\r\n\r\n // Process END\r\n if (idx < lexemes.length && this.isCommandWithValue(lexemes[idx], \"end\")) {\r\n idx++;\r\n } else {\r\n throw new Error(`The CASE expression requires 'end' keyword at the end (index ${idx})`);\r\n }\r\n\r\n if (whenThenList.length === 0) {\r\n throw new Error(`The CASE expression requires at least one WHEN clause (index ${idx})`);\r\n }\r\n\r\n // Create SwitchCaseArgument\r\n const value = new SwitchCaseArgument(whenThenList, elseValue);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n // Helper method: Check if a lexeme is a Command token with the specified value\r\n private static isCommandWithValue(lexeme: Lexeme, value: string): boolean {\r\n return ((lexeme.type & TokenType.Command) !== 0) && lexeme.value === value;\r\n }\r\n\r\n private static parseCaseConditionValuePair(lexemes: Lexeme[], index: number): { value: CaseKeyValuePair; newIndex: number; } {\r\n let idx = index;\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n\r\n // Check for the existence of the THEN keyword\r\n if (idx >= lexemes.length || !(lexemes[idx].type & TokenType.Command) || lexemes[idx].value !== \"then\") {\r\n throw new Error(`Expected 'then' after WHEN condition at index ${idx}`);\r\n }\r\n idx++; // Skip the THEN keyword\r\n\r\n // Parse the value after THEN\r\n const value = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = value.newIndex;\r\n\r\n return { value: new CaseKeyValuePair(condition.value, value.value), newIndex: idx };\r\n }\r\n}", "import { NullsSortDirection, OrderByClause, OrderByComponent, OrderByItem, SortDirection } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class OrderByClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): OrderByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The ORDER BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OrderByClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'order by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'ORDER BY' keyword but found \"${lexemes[idx].value}\". ORDER BY clauses must start with the ORDER BY keywords.`);\r\n }\r\n idx++;\r\n\r\n const items: OrderByComponent[] = [];\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No ordering expressions found. The ORDER BY clause requires at least one expression to order by.`);\r\n } else {\r\n const clause = new OrderByClause(items);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: OrderByComponent; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n if (idx >= lexemes.length) {\r\n return { value: value, newIndex: idx };\r\n }\r\n\r\n // asc, desc\r\n const sortDirection = idx >= lexemes.length\r\n ? null\r\n : lexemes[idx].value === 'asc'\r\n ? (idx++, SortDirection.Ascending)\r\n : lexemes[idx].value === 'desc'\r\n ? (idx++, SortDirection.Descending)\r\n : null;\r\n\r\n // nulls first, nulls last\r\n const nullsSortDirection = idx >= lexemes.length\r\n ? null\r\n : lexemes[idx].value === 'nulls first'\r\n ? (idx++, NullsSortDirection.First)\r\n : lexemes[idx].value === 'nulls last'\r\n ? (idx++, NullsSortDirection.Last)\r\n : null;\r\n\r\n if (sortDirection === null && nullsSortDirection === null) {\r\n return { value: value, newIndex: idx };\r\n }\r\n\r\n return { value: new OrderByItem(value, sortDirection, nullsSortDirection), newIndex: idx };\r\n }\r\n}\r\n", "import { PartitionByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueComponent, ValueList } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class PartitionByParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): PartitionByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The PARTITION BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: PartitionByClause; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].value !== 'partition by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'PARTITION BY' keyword but found \"${lexemes[idx].value}\". PARTITION BY clauses must start with the PARTITION BY keywords.`);\r\n }\r\n idx++;\r\n const items: ValueComponent[] = [];\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No partition expressions found. The PARTITION BY clause requires at least one expression to partition by.`);\r\n } else if (items.length === 1) {\r\n const clause = new PartitionByClause(items[0]);\r\n return { value: clause, newIndex: idx };\r\n } else {\r\n const clause = new PartitionByClause(new ValueList(items));\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n}\r\n", "import { OrderByClause, PartitionByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { WindowFrameBound, WindowFrameBoundaryValue, FrameBoundaryComponent, WindowFrameExpression, WindowFrameSpec, WindowFrameType, WindowFrameBoundStatic } from \"../models/ValueComponent\";\r\nimport { OrderByClauseParser } from \"./OrderByClauseParser\";\r\nimport { PartitionByParser } from \"./PartitionByParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class WindowExpressionParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WindowFrameExpression {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The window frame expression is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WindowFrameExpression; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis '(' but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n let partition: PartitionByClause | null = null;\r\n let order: OrderByClause | null = null;\r\n let frameSpec: WindowFrameSpec | null = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'partition by') {\r\n const partitionResult = PartitionByParser.parseFromLexeme(lexemes, idx);\r\n partition = partitionResult.value;\r\n idx = partitionResult.newIndex;\r\n }\r\n if (idx < lexemes.length && lexemes[idx].value === 'order by') {\r\n const orderResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);\r\n order = orderResult.value;\r\n idx = orderResult.newIndex;\r\n }\r\n // Parse frame clause (ROWS/RANGE/GROUPS)\r\n if (idx < lexemes.length && this.isFrameTypeKeyword(lexemes[idx].value)) {\r\n const frameSpecResult = this.parseFrameSpec(lexemes, idx);\r\n frameSpec = frameSpecResult.value;\r\n idx = frameSpecResult.newIndex;\r\n }\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for window frame. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n // Read close paren\r\n idx++;\r\n\r\n return { value: new WindowFrameExpression(partition, order, frameSpec), newIndex: idx };\r\n }\r\n\r\n private static isFrameTypeKeyword(value: string): boolean {\r\n const lowerValue = value;\r\n return lowerValue === 'rows' || lowerValue === 'range' || lowerValue === 'groups';\r\n }\r\n\r\n private static parseFrameSpec(lexemes: Lexeme[], index: number): { value: WindowFrameSpec; newIndex: number } {\r\n let idx = index;\r\n\r\n // Determine frame type (ROWS/RANGE/GROUPS)\r\n const frameTypeStr = lexemes[idx].value;\r\n let frameType: WindowFrameType;\r\n\r\n switch (frameTypeStr) {\r\n case 'rows':\r\n frameType = WindowFrameType.Rows;\r\n break;\r\n case 'range':\r\n frameType = WindowFrameType.Range;\r\n break;\r\n case 'groups':\r\n frameType = WindowFrameType.Groups;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid frame type \"${lexemes[idx].value}\". Expected one of: ROWS, RANGE, GROUPS.`);\r\n }\r\n idx++;\r\n\r\n // Check for BETWEEN ... AND ... syntax\r\n if (idx < lexemes.length && lexemes[idx].value === 'between') {\r\n // BETWEEN ... AND ... syntax\r\n idx++;\r\n\r\n // Parse start boundary\r\n const startBoundResult = this.parseFrameBoundary(lexemes, idx);\r\n const startBound = startBoundResult.value;\r\n idx = startBoundResult.newIndex;\r\n\r\n // Check for AND keyword - may be recognized as a separate token or part of a compound token\r\n if (idx >= lexemes.length || (lexemes[idx].value !== 'and')) {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AND' keyword in BETWEEN clause.`);\r\n }\r\n idx++; // Skip AND\r\n\r\n // Parse end boundary\r\n const endBoundResult = this.parseFrameBoundary(lexemes, idx);\r\n const endBound = endBoundResult.value;\r\n idx = endBoundResult.newIndex;\r\n\r\n return {\r\n value: new WindowFrameSpec(frameType, startBound, endBound),\r\n newIndex: idx\r\n };\r\n } else {\r\n // Single boundary specification\r\n const boundaryResult = this.parseFrameBoundary(lexemes, idx);\r\n const startBound = boundaryResult.value;\r\n idx = boundaryResult.newIndex;\r\n\r\n return {\r\n value: new WindowFrameSpec(frameType, startBound, null),\r\n newIndex: idx\r\n };\r\n }\r\n }\r\n\r\n private static parseFrameBoundary(lexemes: Lexeme[], index: number): { value: FrameBoundaryComponent, newIndex: number } {\r\n let idx = index;\r\n // Check for predefined boundaries\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const currentValue = lexemes[idx].value;\r\n let frameBound: WindowFrameBound;\r\n switch (currentValue) {\r\n case 'current row':\r\n frameBound = WindowFrameBound.CurrentRow;\r\n break;\r\n case 'unbounded preceding':\r\n frameBound = WindowFrameBound.UnboundedPreceding;\r\n break;\r\n case 'unbounded following':\r\n frameBound = WindowFrameBound.UnboundedFollowing;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid frame type \"${lexemes[idx].value}\". Expected one of: ROWS, RANGE, GROUPS.`);\r\n }\r\n const bound = new WindowFrameBoundStatic(frameBound);\r\n return { value: bound, newIndex: idx + 1 };\r\n } else if (idx < lexemes.length && (lexemes[idx].type & TokenType.Literal)) {\r\n // Parse the numeric/literal value\r\n const valueResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = valueResult.newIndex;\r\n // Next token must be 'preceding' or 'following'\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command)) {\r\n const direction = lexemes[idx].value;\r\n let isFollowing: boolean;\r\n if (direction === 'preceding') {\r\n isFollowing = false;\r\n } else if (direction === 'following') {\r\n isFollowing = true;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);\r\n }\r\n idx++;\r\n const bound = new WindowFrameBoundaryValue(valueResult.value, isFollowing);\r\n return { value: bound, newIndex: idx };\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);\r\n }\r\n }\r\n throw new Error(`Syntax error at position ${idx}: Expected a valid frame boundary component.`);\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { IdentifierString, OverExpression } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WindowExpressionParser } from \"./WindowExpressionParser\";\r\n\r\nexport class OverExpressionParser {\r\n public static parse(query: string): OverExpression {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The OVER expression is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OverExpression; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'over') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'OVER' keyword but found \"${lexemes[idx].value}\". OVER expressions must start with the OVER keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'OVER' keyword. Expected either a window name or an opening parenthesis '('.`);\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.Identifier) {\r\n // named window frame\r\n const name = lexemes[idx].value;\r\n idx++;\r\n return { value: new IdentifierString(name), newIndex: idx };\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.OpenParen) {\r\n // Delegate processing to WindowFrameExpressionParser\r\n const result = WindowExpressionParser.parseFromLexeme(lexemes, idx);\r\n return result;\r\n }\r\n\r\n throw new Error(`Syntax error at position ${idx}: Expected a window name or opening parenthesis '(' after OVER keyword, but found \"${lexemes[idx].value}\".`);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { FunctionCall, ValueComponent, BinaryExpression, TypeValue, CastExpression, BetweenExpression, RawString, ArrayExpression, ArrayQueryExpression } from \"../models/ValueComponent\";\r\nimport { SelectQuery } from \"../models/SelectQuery\";\r\nimport { OverExpressionParser } from \"./OverExpressionParser\";\r\nimport { ValueParser } from \"./ValueParser\";\r\nimport { FullNameParser } from \"./FullNameParser\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\n\r\nexport class FunctionExpressionParser {\r\n /**\r\n * Parse ARRAY expressions - handles both ARRAY[...] (literal) and ARRAY(...) (query) syntax\r\n * @param lexemes Array of lexemes to parse\r\n * @param index Current parsing index\r\n * @returns Parsed array expression and new index\r\n */\r\n private static parseArrayExpression(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check if this is array literal (ARRAY[...]) or function call (ARRAY(...))\r\n if (idx + 1 < lexemes.length && (lexemes[idx + 1].type & TokenType.OpenBracket)) {\r\n idx++;\r\n const arg = ValueParser.parseArgument(TokenType.OpenBracket, TokenType.CloseBracket, lexemes, idx);\r\n idx = arg.newIndex;\r\n const value = new ArrayExpression(arg.value);\r\n return { value, newIndex: idx };\r\n } else if (idx + 1 < lexemes.length && (lexemes[idx + 1].type & TokenType.OpenParen)) {\r\n idx++;\r\n idx++; // Skip the opening parenthesis\r\n const arg = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = arg.newIndex;\r\n idx++; // Skip the closing parenthesis\r\n const value = new ArrayQueryExpression(arg.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Invalid ARRAY syntax at index ${idx}, expected ARRAY[... or ARRAY(...)`);\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const current = lexemes[idx];\r\n\r\n if (current.value === \"array\") {\r\n return this.parseArrayExpression(lexemes, idx);\r\n } else if (current.value === \"substring\" || current.value === \"overlay\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"from\", required: false },\r\n { key: \"for\", required: false }\r\n ]);\r\n } else if (current.value === \"cast\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"as\", required: true }\r\n ]);\r\n } else if (current.value === \"trim\") {\r\n return this.parseKeywordFunction(lexemes, idx, [\r\n { key: \"from\", required: false }\r\n ]);\r\n }\r\n\r\n return this.parseFunctionCall(lexemes, idx);\r\n }\r\n\r\n public static tryParseBinaryExpression(lexemes: Lexeme[], index: number, left: ValueComponent, allowAndOperator: boolean = true, allowOrOperator: boolean = true): { value: ValueComponent; newIndex: number } | null {\r\n let idx = index;\r\n\r\n // If the next element is an operator, process it as a binary expression\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operator = lexemes[idx].value.toLowerCase();\r\n\r\n if (!allowAndOperator && operator === \"and\") {\r\n // Handle special case for \"and\" operator\r\n return null;\r\n }\r\n\r\n if (!allowOrOperator && operator === \"or\") {\r\n // Handle special case for \"or\" operator\r\n return null;\r\n }\r\n\r\n idx++;\r\n\r\n // between\r\n if (operator === \"between\") {\r\n return this.parseBetweenExpression(lexemes, idx, left, false);\r\n } else if (operator === \"not between\") {\r\n return this.parseBetweenExpression(lexemes, idx, left, true);\r\n }\r\n\r\n // ::\r\n if (operator === \"::\") {\r\n const typeValue = this.parseTypeValue(lexemes, idx);\r\n idx = typeValue.newIndex;\r\n const exp = new CastExpression(left, typeValue.value);\r\n return { value: exp, newIndex: idx };\r\n }\r\n\r\n // Get the right-hand side value\r\n const rightResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = rightResult.newIndex;\r\n\r\n // Create binary expression\r\n const value = new BinaryExpression(left, operator, rightResult.value);\r\n return { value, newIndex: idx };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n public static parseBetweenExpression(lexemes: Lexeme[], index: number, value: ValueComponent, negated: boolean): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n const lower = ValueParser.parseFromLexeme(lexemes, idx, false);\r\n idx = lower.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator) && lexemes[idx].value !== \"and\") {\r\n throw new Error(`Expected 'and' after 'between' at index ${idx}`);\r\n }\r\n idx++;\r\n\r\n // Parse upper bound with restricted scope - stop at logical operators\r\n const upper = this.parseBetweenUpperBound(lexemes, idx);\r\n idx = upper.newIndex;\r\n const result = new BetweenExpression(value, lower.value, upper.value, negated);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n /**\r\n * Parse the upper bound of a BETWEEN expression with logical operator precedence\r\n * This stops parsing when it encounters AND/OR operators at the same level\r\n */\r\n private static parseBetweenUpperBound(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n // Parse with higher precedence than AND/OR to ensure BETWEEN binds tighter\r\n // Use precedence 3 (higher than AND=2, OR=1) as minimum to stop at logical operators\r\n return ValueParser.parseFromLexeme(lexemes, index, false, false);\r\n }\r\n\r\n private static parseFunctionCall(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n // Parse namespaced function name (e.g., myschema.myfunc, dbo.util.myfunc)\r\n // Use FullNameParser to get namespaces and function name\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const namespaces = fullNameResult.namespaces;\r\n const name = fullNameResult.name;\r\n idx = fullNameResult.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n // General argument parsing\r\n const arg = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = arg.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === \"over\") {\r\n const over = OverExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = over.newIndex;\r\n const value = new FunctionCall(namespaces, name.name, arg.value, over.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new FunctionCall(namespaces, name.name, arg.value, null);\r\n return { value, newIndex: idx };\r\n }\r\n } else {\r\n throw new Error(`Expected opening parenthesis after function name '${name.name}' at index ${idx}`);\r\n }\r\n }\r\n\r\n private static parseKeywordFunction(\r\n lexemes: Lexeme[],\r\n index: number,\r\n keywords: { key: string, required: boolean }[]\r\n ): { value: ValueComponent; newIndex: number; } {\r\n let idx = index;\r\n // Parse function name and namespaces at the beginning for consistent usage\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const namespaces = fullNameResult.namespaces;\r\n const name = fullNameResult.name;\r\n idx = fullNameResult.newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n idx++;\r\n\r\n const input = ValueParser.parseFromLexeme(lexemes, idx);\r\n let arg = input.value;\r\n idx = input.newIndex;\r\n\r\n // Delegate to the standard function parser if parsing by comma\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n return this.parseFunctionCall(lexemes, index);\r\n }\r\n\r\n // Check for required/optional keywords in function arguments\r\n for (const { key, required } of keywords) {\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Command) && lexemes[idx].value === key) {\r\n idx++;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Type)) {\r\n const typeValue = this.parseTypeValue(lexemes, idx);\r\n arg = new BinaryExpression(arg, key, typeValue.value);\r\n idx = typeValue.newIndex;\r\n } else {\r\n const right = ValueParser.parseFromLexeme(lexemes, idx);\r\n arg = new BinaryExpression(arg, key, right.value);\r\n idx = right.newIndex;\r\n }\r\n\r\n } else if (required) {\r\n throw new Error(`Keyword '${key}' is required at index ${idx}`);\r\n }\r\n }\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.CloseParen)) {\r\n idx++;\r\n // Use the previously parsed namespaces and function name for consistency\r\n if (idx < lexemes.length && lexemes[idx].value === \"over\") {\r\n idx++;\r\n const over = OverExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = over.newIndex;\r\n const value = new FunctionCall(namespaces, name.name, arg, over.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new FunctionCall(namespaces, name.name, arg, null);\r\n return { value, newIndex: idx };\r\n }\r\n } else {\r\n throw new Error(`Missing closing parenthesis for function '${name.name}' at index ${idx}`);\r\n }\r\n } else {\r\n throw new Error(`Missing opening parenthesis for function '${name.name}' at index ${idx}`);\r\n }\r\n }\r\n\r\n public static parseTypeValue(lexemes: Lexeme[], index: number): { value: TypeValue; newIndex: number; } {\r\n let idx = index;\r\n\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n idx = newIndex;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n const arg = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = arg.newIndex;\r\n const value = new TypeValue(namespaces, new RawString(name.name), arg.value);\r\n return { value, newIndex: idx };\r\n } else {\r\n const value = new TypeValue(namespaces, new RawString(name.name));\r\n return { value, newIndex: idx };\r\n }\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\n\r\nexport class ParseError extends Error {\r\n constructor(message: string, public index: number, public context: string) {\r\n super(message);\r\n this.name = \"ParseError\";\r\n }\r\n\r\n public static fromUnparsedLexemes(lexemes: Lexeme[], index: number, messagePrefix: string): ParseError {\r\n const start = Math.max(0, index - 2);\r\n const end = Math.min(lexemes.length, index + 3);\r\n const context = lexemes.slice(start, end).map((lexeme, idx) => {\r\n const marker = idx + start === index ? '>' : ' ';\r\n const typeName = TokenType[lexeme.type] || lexeme.type; // Convert type to name if possible\r\n return `${marker} ${idx + start}:${lexeme.value} [${typeName}]`;\r\n }).join('\\n');\r\n\r\n const message = `${messagePrefix} Unparsed lexeme remains at index ${index}: ${lexemes[index].value}\\nContext:\\n${context}`;\r\n return new ParseError(message, index, context);\r\n }\r\n}\r\n", "/**\r\n * SQL operator precedence definitions\r\n * Higher numbers indicate higher precedence (tighter binding)\r\n */\r\nexport class OperatorPrecedence {\r\n private static readonly precedenceMap: Record<string, number> = {\r\n // Logical operators (lowest precedence)\r\n 'or': 1,\r\n 'and': 2,\r\n\r\n // Comparison operators\r\n '=': 10,\r\n '!=': 10,\r\n '<>': 10,\r\n '<': 10,\r\n '<=': 10,\r\n '>': 10,\r\n '>=': 10,\r\n 'like': 10,\r\n 'ilike': 10,\r\n 'not like': 10,\r\n 'not ilike': 10,\r\n 'in': 10,\r\n 'not in': 10,\r\n 'is': 10,\r\n 'is not': 10,\r\n 'between': 15, // BETWEEN has higher precedence than logical operators\r\n 'not between': 15,\r\n\r\n // Arithmetic operators\r\n '+': 20,\r\n '-': 20,\r\n '*': 30,\r\n '/': 30,\r\n '%': 30,\r\n '^': 40,\r\n\r\n // Type casting\r\n '::': 50,\r\n\r\n // Highest precedence operators\r\n 'unary+': 100,\r\n 'unary-': 100,\r\n 'not': 100\r\n };\r\n\r\n /**\r\n * Get the precedence of an operator\r\n * @param operator The operator string\r\n * @returns The precedence number (higher = tighter binding)\r\n */\r\n public static getPrecedence(operator: string): number {\r\n const precedence = this.precedenceMap[operator.toLowerCase()];\r\n return precedence !== undefined ? precedence : 0;\r\n }\r\n\r\n /**\r\n * Check if operator1 has higher or equal precedence than operator2\r\n */\r\n public static hasHigherOrEqualPrecedence(operator1: string, operator2: string): boolean {\r\n return this.getPrecedence(operator1) >= this.getPrecedence(operator2);\r\n }\r\n\r\n /**\r\n * Check if an operator is a logical operator (AND/OR)\r\n */\r\n public static isLogicalOperator(operator: string): boolean {\r\n const op = operator.toLowerCase();\r\n return op === 'and' || op === 'or';\r\n }\r\n\r\n /**\r\n * Check if an operator is a BETWEEN operator\r\n */\r\n public static isBetweenOperator(operator: string): boolean {\r\n const op = operator.toLowerCase();\r\n return op === 'between' || op === 'not between';\r\n }\r\n\r\n /**\r\n * Check if a string is a comparison operator\r\n */\r\n public static isComparisonOperator(operator: string): boolean {\r\n const lowerOp = operator.toLowerCase();\r\n return ['=', '!=', '<>', '<', '>', '<=', '>=', 'like', 'ilike', 'in', 'not in'].includes(lowerOp);\r\n }\r\n}\r\n", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference, TypeValue, UnaryExpression, ValueComponent, ValueList, BinaryExpression, CastExpression } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { IdentifierParser } from \"./IdentifierParser\";\r\nimport { LiteralParser } from \"./LiteralParser\";\r\nimport { ParenExpressionParser } from \"./ParenExpressionParser\";\r\nimport { UnaryExpressionParser } from \"./UnaryExpressionParser\";\r\nimport { ParameterExpressionParser } from \"./ParameterExpressionParser\";\r\nimport { StringSpecifierExpressionParser } from \"./StringSpecifierExpressionParser\";\r\nimport { CommandExpressionParser } from \"./CommandExpressionParser\";\r\nimport { FunctionExpressionParser } from \"./FunctionExpressionParser\";\r\nimport { FullNameParser } from \"./FullNameParser\";\r\nimport { ParseError } from \"./ParseError\";\r\nimport { OperatorPrecedence } from \"../utils/OperatorPrecedence\";\r\n\r\nexport class ValueParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): ValueComponent {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw ParseError.fromUnparsedLexemes(\r\n lexemes,\r\n result.newIndex,\r\n `[ValueParser]`\r\n );\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parse from lexeme array with logical operator controls\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number, allowAndOperator: boolean = true, allowOrOperator: boolean = true): { value: ValueComponent; newIndex: number } {\r\n return this.parseExpressionWithPrecedence(lexemes, index, 0, allowAndOperator, allowOrOperator);\r\n }\r\n\r\n /**\r\n * Parse expressions with operator precedence handling\r\n * Uses precedence climbing algorithm\r\n */\r\n private static parseExpressionWithPrecedence(\r\n lexemes: Lexeme[],\r\n index: number,\r\n minPrecedence: number,\r\n allowAndOperator: boolean = true,\r\n allowOrOperator: boolean = true\r\n ): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Parse the primary expression (left side)\r\n const comment = lexemes[idx].comments;\r\n const left = this.parseItem(lexemes, idx);\r\n left.value.comments = comment;\r\n idx = left.newIndex;\r\n\r\n let result = left.value;\r\n\r\n // Process operators with precedence\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Operator)) {\r\n const operatorToken = lexemes[idx];\r\n const operator = operatorToken.value;\r\n\r\n // Check if this operator is allowed\r\n if (!allowAndOperator && operator.toLowerCase() === \"and\") {\r\n break;\r\n }\r\n if (!allowOrOperator && operator.toLowerCase() === \"or\") {\r\n break;\r\n }\r\n\r\n // Get operator precedence\r\n const precedence = OperatorPrecedence.getPrecedence(operator);\r\n\r\n // If this operator has lower precedence than minimum, stop\r\n if (precedence < minPrecedence) {\r\n break;\r\n }\r\n\r\n idx++; // consume operator // Handle BETWEEN specially as it has different syntax\r\n if (OperatorPrecedence.isBetweenOperator(operator)) {\r\n const betweenResult = FunctionExpressionParser.parseBetweenExpression(\r\n lexemes, idx, result, operator.toLowerCase().includes('not')\r\n );\r\n result = betweenResult.value;\r\n idx = betweenResult.newIndex;\r\n continue;\r\n }\r\n\r\n // Handle :: (cast) operator specially\r\n if (operator === \"::\") {\r\n const typeValue = FunctionExpressionParser.parseTypeValue(lexemes, idx);\r\n result = new CastExpression(result, typeValue.value);\r\n idx = typeValue.newIndex;\r\n continue;\r\n }\r\n\r\n // For left-associative operators, use precedence + 1\r\n const nextMinPrecedence = precedence + 1;\r\n\r\n // Parse the right-hand side with higher precedence\r\n const rightResult = this.parseExpressionWithPrecedence(\r\n lexemes, idx, nextMinPrecedence, allowAndOperator, allowOrOperator\r\n );\r\n idx = rightResult.newIndex;\r\n\r\n // Create binary expression directly\r\n result = new BinaryExpression(result, operator, rightResult.value);\r\n }\r\n\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Range check\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Unexpected end of lexemes at index ${index}`);\r\n }\r\n\r\n const current = lexemes[idx];\r\n\r\n if (current.type & TokenType.Identifier && current.type & TokenType.Operator && current.type & TokenType.Type) {\r\n // Typed literal format pattern\r\n // e.g., `interval '2 days'`\r\n const first = IdentifierParser.parseFromLexeme(lexemes, idx);\r\n if (first.newIndex >= lexemes.length) {\r\n return first;\r\n }\r\n const next = lexemes[first.newIndex];\r\n if (next.type & TokenType.Literal) {\r\n // Typed literal format\r\n const second = LiteralParser.parseFromLexeme(lexemes, first.newIndex);\r\n const result = new UnaryExpression(lexemes[idx].value, second.value);\r\n return { value: result, newIndex: second.newIndex };\r\n }\r\n return first;\r\n } else if (current.type & TokenType.Identifier) {\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n // Namespace is also recognized as Identifier.\r\n // Since functions and types, as well as columns (tables), can have namespaces,\r\n // it is necessary to determine by the last element of the identifier.\r\n if (lexemes[newIndex - 1].type & (TokenType.Function | TokenType.Type)) {\r\n return FunctionExpressionParser.parseFromLexeme(lexemes, idx);\r\n }\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n } else if (current.type & TokenType.Literal) {\r\n return LiteralParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.OpenParen) {\r\n return ParenExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Function) {\r\n return FunctionExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Operator) {\r\n return UnaryExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Parameter) {\r\n return ParameterExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.StringSpecifier) {\r\n return StringSpecifierExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.Command) {\r\n return CommandExpressionParser.parseFromLexeme(lexemes, idx);\r\n } else if (current.type & TokenType.OpenBracket) {\r\n // SQLServer escape identifier format. e.g. [dbo] or [dbo].[table]\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const value = new ColumnReference(namespaces, name);\r\n return { value, newIndex };\r\n } else if (current.type & TokenType.Type) {\r\n // Handle standalone type tokens\r\n const { namespaces, name, newIndex } = FullNameParser.parseFromLexeme(lexemes, idx);\r\n const value = new TypeValue(namespaces, name);\r\n return { value, newIndex };\r\n }\r\n\r\n throw new Error(`[ValueParser] Invalid lexeme. index: ${idx}, type: ${lexemes[idx].type}, value: ${lexemes[idx].value}`);\r\n }\r\n\r\n public static parseArgument(openToken: TokenType, closeToken: TokenType, lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const args: ValueComponent[] = [];\r\n\r\n // Check for opening parenthesis\r\n if (idx < lexemes.length && lexemes[idx].type === openToken) {\r\n idx++;\r\n\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n // If there are no arguments, return an empty ValueList\r\n idx++;\r\n return { value: new ValueList([]), newIndex: idx };\r\n }\r\n\r\n // If the next element is `*`, treat `*` as an Identifier\r\n if (idx < lexemes.length && lexemes[idx].value === \"*\") {\r\n const wildcard = new ColumnReference(null, \"*\");\r\n idx++;\r\n // The next element must be closeToken\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n idx++;\r\n return { value: wildcard, newIndex: idx };\r\n } else {\r\n throw new Error(`Expected closing parenthesis at index ${idx}`);\r\n }\r\n }\r\n\r\n // Parse the value inside\r\n const result = this.parseFromLexeme(lexemes, idx);\r\n idx = result.newIndex;\r\n args.push(result.value);\r\n\r\n // Continue reading if the next element is a comma\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const argResult = this.parseFromLexeme(lexemes, idx);\r\n idx = argResult.newIndex;\r\n args.push(argResult.value);\r\n }\r\n\r\n // Check for closing parenthesis\r\n if (idx < lexemes.length && lexemes[idx].type === closeToken) {\r\n idx++;\r\n if (args.length === 1) {\r\n // Return as is if there is only one argument\r\n return { value: args[0], newIndex: idx };\r\n }\r\n // Create ValueCollection if there are multiple arguments\r\n const value = new ValueList(args);\r\n return { value, newIndex: idx };\r\n } else {\r\n throw new Error(`Missing closing parenthesis at index ${idx}`);\r\n }\r\n }\r\n\r\n throw new Error(`Expected opening parenthesis at index ${index}`);\r\n }\r\n}\r\n", "import { CommonTable, ForClause, FromClause, FunctionSource, GroupByClause, HavingClause, JoinClause, JoinOnClause, JoinUsingClause, LimitClause, OrderByClause, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue,\r\n ValueList,\r\n StringSpecifierExpression\r\n} from \"../models/ValueComponent\";\r\n\r\n/**\r\n * A visitor that collects all CommonTable instances from a SQL query structure.\r\n * This includes tables from:\r\n * - WITH clauses\r\n * - Subqueries\r\n * - Inline queries\r\n * - UNION queries\r\n * - Value components that may contain queries\r\n */\r\nexport class CTECollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private commonTables: CommonTable[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor() {\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for all component types that might contain CommonTables\r\n\r\n // SelectQuery types\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // WITH clause that directly contains CommonTables\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // SelectComponent types\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Identifiers and raw strings (leaf nodes that don't need traversal)\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n\r\n // Subqueries and inline queries\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // FROM and JOIN clauses\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // WHERE clause\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // Value components that might contain subqueries\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n\r\n // Add handlers for other clause types\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n }\r\n\r\n /**\r\n * Get all collected CommonTables\r\n */\r\n public getCommonTables(): CommonTable[] {\r\n return this.commonTables;\r\n }\r\n\r\n /**\r\n * Reset the collection of CommonTables\r\n */\r\n private reset(): void {\r\n this.commonTables = [];\r\n this.visitedNodes.clear();\r\n }\r\n\r\n public collect(query: SelectQuery): CommonTable[] {\r\n // Visit the query to collect all CommonTables\r\n this.visit(query);\r\n return this.getCommonTables();\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // Provide more detailed error message\r\n const kindSymbol = arg.getKind()?.toString() || 'unknown';\r\n const constructor = arg.constructor?.name || 'unknown';\r\n throw new Error(`[CTECollector] No handler for ${constructor} with kind ${kindSymbol}.`);\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // The order matters here!\r\n // First, visit all clauses that might contain nested CTEs\r\n // to ensure inner CTEs are collected before outer CTEs\r\n\r\n // Check FROM clause first (can contain subqueries with nested CTEs)\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n // Check WHERE clause (can contain subqueries with WITH clauses)\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n // Check other clauses that might contain CTEs\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n // Check SELECT clause\r\n query.selectClause.accept(this);\r\n\r\n // Finally check the WITH clause after all nested CTEs have been collected\r\n // This ensures inner CTEs are collected before outer CTEs\r\n if (query.withClause) {\r\n query.withClause.accept(this);\r\n }\r\n\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // Visit both sides of the binary query (UNION, EXCEPT, etc.)\r\n query.left.accept(this);\r\n query.right.accept(this);\r\n }\r\n\r\n private visitValuesQuery(query: ValuesQuery): void {\r\n // VALUES queries might contain subqueries in tuple expressions\r\n for (const tuple of query.tuples) {\r\n tuple.accept(this);\r\n }\r\n }\r\n\r\n private visitWithClause(withClause: WithClause): void {\r\n // Visit each CommonTable\r\n // Simply process tables in sequence\r\n // Note: visitCommonTable already handles nested CTEs\r\n for (let i = 0; i < withClause.tables.length; i++) {\r\n const commonTable = withClause.tables[i];\r\n commonTable.accept(this);\r\n }\r\n }\r\n\r\n private visitCommonTable(commonTable: CommonTable): void {\r\n // Process CommonTable directly within the query\r\n // Use the same instance to process the query instead of creating another Collector\r\n commonTable.query.accept(this);\r\n\r\n // Add current CTE after all nested CTEs have been added\r\n this.commonTables.push(commonTable);\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n // Check each item in the select clause\r\n for (const item of clause.items) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitSelectItem(item: SelectItem): void {\r\n // Select items might contain subqueries\r\n item.value.accept(this);\r\n }\r\n\r\n private visitFromClause(fromClause: FromClause): void {\r\n // Check the source\r\n fromClause.source.accept(this);\r\n\r\n // Check joins\r\n if (fromClause.joins) {\r\n for (const join of fromClause.joins) {\r\n join.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n source.datasource.accept(this);\r\n // The alias part doesn't contain subqueries so we skip it\r\n }\r\n\r\n private visitTableSource(source: TableSource): void {\r\n // Table sources don't contain subqueries, nothing to do\r\n }\r\n\r\n private visitFunctionSource(source: FunctionSource): void {\r\n // Function sources may have arguments that could contain subqueries\r\n if (source.argument) {\r\n source.argument.accept(this);\r\n }\r\n }\r\n\r\n private visitParenSource(source: ParenSource): void {\r\n source.source.accept(this);\r\n }\r\n\r\n private visitSubQuerySource(subQuery: SubQuerySource): void {\r\n subQuery.query.accept(this);\r\n }\r\n\r\n private visitInlineQuery(inlineQuery: InlineQuery): void {\r\n inlineQuery.selectQuery.accept(this);\r\n }\r\n\r\n private visitJoinClause(joinClause: JoinClause): void {\r\n // Check join source\r\n joinClause.source.accept(this);\r\n\r\n // Check join condition\r\n if (joinClause.condition) {\r\n joinClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOn: JoinOnClause): void {\r\n joinOn.condition.accept(this);\r\n }\r\n\r\n private visitJoinUsingClause(joinUsing: JoinUsingClause): void {\r\n joinUsing.condition.accept(this);\r\n }\r\n\r\n private visitWhereClause(whereClause: WhereClause): void {\r\n whereClause.condition.accept(this);\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n clause.condition.accept(this);\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitForClause(clause: ForClause): void {\r\n // FOR clause doesn't contain subqueries\r\n }\r\n\r\n private visitOrderByItem(item: OrderByItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n expr.switchCase.accept(this);\r\n }\r\n\r\n private visitSwitchCaseArgument(switchCase: SwitchCaseArgument): void {\r\n // Check all case expressions\r\n for (const caseItem of switchCase.cases) {\r\n caseItem.accept(this);\r\n }\r\n\r\n // Check ELSE expression\r\n if (switchCase.elseValue) {\r\n switchCase.elseValue.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseKeyValuePair(pair: CaseKeyValuePair): void {\r\n // Check the WHEN condition\r\n pair.key.accept(this);\r\n // Check the THEN value\r\n pair.value.accept(this);\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n expr.expression.accept(this);\r\n expr.lower.accept(this);\r\n expr.upper.accept(this);\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n\r\n // Check OVER clause if present\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitTupleExpression(expr: TupleExpression): void {\r\n // Check each value in the tuple for possible subqueries\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n // Check the input expression\r\n expr.input.accept(this);\r\n // Check the type expression\r\n expr.castType.accept(this);\r\n }\r\n\r\n private visitTypeValue(expr: TypeValue): void {\r\n // Visit the argument if present\r\n if (expr.argument) {\r\n expr.argument.accept(this);\r\n }\r\n // The type itself doesn't contain subqueries\r\n }\r\n\r\n private visitWindowFrameExpression(expr: WindowFrameExpression): void {\r\n if (expr.partition) {\r\n expr.partition.accept(this);\r\n }\r\n if (expr.order) {\r\n expr.order.accept(this);\r\n }\r\n if (expr.frameSpec) {\r\n expr.frameSpec.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameSpec(spec: WindowFrameSpec): void {\r\n // WindowFrameSpec is a simple value object, nothing to traverse\r\n }\r\n\r\n private visitIdentifierString(ident: IdentifierString): void {\r\n // Leaf node, nothing to traverse\r\n }\r\n\r\n private visitRawString(raw: RawString): void {\r\n // Leaf node, nothing to traverse\r\n }\r\n\r\n private visitColumnReference(column: ColumnReference): void {\r\n // Column references don't have subqueries\r\n }\r\n\r\n private visitParameterExpression(param: ParameterExpression): void {\r\n // Parameter expressions don't have child components\r\n }\r\n\r\n private visitLiteralValue(value: LiteralValue): void {\r\n // Literal values are leaf nodes\r\n }\r\n\r\n public visitPartitionByClause(partitionBy: PartitionByClause): void {\r\n // don't have subqueries\r\n }\r\n\r\n public visitValueList(valueList: ValueList): void {\r\n for (const value of valueList.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitStringSpecifierExpression(expr: StringSpecifierExpression): void {\r\n // StringSpecifierExpression contains RawString and LiteralValue which are leaf nodes\r\n // No need to visit children as they don't contain subqueries\r\n }\r\n}", "import { CommonTable, ForClause, FromClause, GroupByClause, HavingClause, JoinClause, JoinConditionComponent, JoinOnClause, JoinUsingClause, LimitClause, OrderByClause, OrderByComponent, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceAliasExpression, SourceComponent, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue\r\n} from \"../models/ValueComponent\";\r\n\r\n/**\r\n * A visitor that disables all WITH clauses in a SQL query structure.\r\n * This processes and removes WITH clauses from:\r\n * - Simple SELECT queries\r\n * - Binary queries (UNION, EXCEPT, etc.)\r\n * - Subqueries\r\n * - Inline queries\r\n * \r\n * It maintains the CTE queries themselves but restructures the query to not use\r\n * the WITH clause syntactical construct.\r\n */\r\nexport class CTEDisabler implements SqlComponentVisitor<SqlComponent> {\r\n private handlers: Map<symbol, (arg: any) => SqlComponent>;\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor() {\r\n this.handlers = new Map<symbol, (arg: any) => SqlComponent>();\r\n\r\n // Setup handlers for all component types that might contain WITH clauses\r\n\r\n // SelectQuery types\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // SelectComponent types\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Identifiers and raw strings\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n\r\n // Subqueries and inline queries\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // FROM and JOIN clauses\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // WHERE clause\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // Value components that might contain subqueries\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n\r\n // Add handlers for other clause types\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n }\r\n\r\n /**\r\n * Reset the visited nodes tracking\r\n */\r\n private reset(): void {\r\n this.visitedNodes.clear();\r\n }\r\n\r\n public execute(arg: SqlComponent): SelectQuery {\r\n // Reset the visited nodes before starting the visit\r\n this.reset();\r\n return this.visit(arg) as SelectQuery;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): SqlComponent {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n return this.visitNode(arg);\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n return this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): SqlComponent {\r\n // Check for circular references - if node already visited, return as is\r\n if (this.visitedNodes.has(arg)) {\r\n return arg;\r\n }\r\n\r\n // Mark as visited node\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n return handler(arg);\r\n }\r\n\r\n // Provide more detailed error message\r\n const kindSymbol = arg.getKind()?.toString() || 'unknown';\r\n const constructor = arg.constructor?.name || 'unknown';\r\n throw new Error(`[CTEDisabler] No handler for ${constructor} with kind ${kindSymbol}.`);\r\n }\r\n\r\n visitSimpleSelectQuery(arg: SimpleSelectQuery): SqlComponent {\r\n if (arg.withClause) {\r\n arg.withClause.tables.forEach(table => {\r\n this.visit(table.query);\r\n });\r\n }\r\n\r\n arg.withClause = null; // Explicitly remove WITH clause\r\n\r\n // Visit the components of the SimpleSelectQuery\r\n arg.selectClause = this.visit(arg.selectClause) as SelectClause;\r\n arg.fromClause = arg.fromClause ? this.visit(arg.fromClause) as FromClause : null;\r\n arg.whereClause = arg.whereClause ? this.visit(arg.whereClause) as WhereClause : null;\r\n arg.groupByClause = arg.groupByClause ? this.visit(arg.groupByClause) as GroupByClause : null;\r\n arg.havingClause = arg.havingClause ? this.visit(arg.havingClause) as HavingClause : null;\r\n arg.orderByClause = arg.orderByClause ? this.visit(arg.orderByClause) as OrderByClause : null;\r\n if (arg.windowClause) {\r\n arg.windowClause = new WindowsClause(arg.windowClause.windows.map(w => this.visit(w) as WindowFrameClause));\r\n }\r\n arg.limitClause = arg.limitClause ? this.visit(arg.limitClause) as LimitClause : null;\r\n arg.forClause = arg.forClause ? this.visit(arg.forClause) as ForClause : null;\r\n return arg;\r\n }\r\n\r\n visitBinarySelectQuery(query: BinarySelectQuery): SqlComponent {\r\n query.left = this.visit(query.left) as SelectQuery;\r\n query.right = this.visit(query.right) as SelectQuery;\r\n return query;\r\n }\r\n\r\n visitValuesQuery(query: ValuesQuery): SqlComponent {\r\n const newTuples = query.tuples.map(tuple => this.visit(tuple) as TupleExpression);\r\n return new ValuesQuery(newTuples);\r\n }\r\n\r\n visitSelectClause(clause: SelectClause): SqlComponent {\r\n const newItems = clause.items.map(item => {\r\n return this.visit(item) as SelectItem;\r\n });\r\n\r\n return new SelectClause(\r\n newItems,\r\n clause.distinct,\r\n );\r\n }\r\n\r\n visitFromClause(clause: FromClause): SqlComponent {\r\n const newSource = this.visit(clause.source) as SourceExpression;\r\n const newJoins = clause.joins ? clause.joins.map(join => this.visit(join) as JoinClause) : null;\r\n\r\n return new FromClause(newSource, newJoins);\r\n }\r\n\r\n visitSubQuerySource(subQuery: SubQuerySource): SqlComponent {\r\n const newQuery = this.visit(subQuery.query) as SelectQuery;\r\n return new SubQuerySource(newQuery);\r\n }\r\n\r\n visitInlineQuery(inlineQuery: InlineQuery): SqlComponent {\r\n const newQuery = this.visit(inlineQuery.selectQuery) as SelectQuery;\r\n return new InlineQuery(newQuery);\r\n }\r\n\r\n visitJoinClause(joinClause: JoinClause): SqlComponent {\r\n const newSource = this.visit(joinClause.source) as SourceExpression;\r\n const newCondition = joinClause.condition ? this.visit(joinClause.condition) as JoinConditionComponent : null;\r\n\r\n return new JoinClause(\r\n joinClause.joinType.value,\r\n newSource,\r\n newCondition,\r\n joinClause.lateral,\r\n );\r\n }\r\n\r\n visitJoinOnClause(joinOn: JoinOnClause): SqlComponent {\r\n const newCondition = this.visit(joinOn.condition) as ValueComponent;\r\n return new JoinOnClause(newCondition);\r\n }\r\n\r\n visitJoinUsingClause(joinUsing: JoinUsingClause): SqlComponent {\r\n const newCondition = this.visit(joinUsing.condition) as ValueComponent;\r\n return new JoinUsingClause(newCondition);\r\n }\r\n\r\n visitWhereClause(whereClause: WhereClause): SqlComponent {\r\n const newCondition = this.visit(whereClause.condition) as ValueComponent;\r\n return new WhereClause(newCondition);\r\n }\r\n\r\n visitGroupByClause(clause: GroupByClause): SqlComponent {\r\n const newGrouping = clause.grouping.map(item => this.visit(item) as ValueComponent);\r\n return new GroupByClause(newGrouping);\r\n }\r\n\r\n visitHavingClause(clause: HavingClause): SqlComponent {\r\n const newCondition = this.visit(clause.condition) as ValueComponent;\r\n return new HavingClause(newCondition);\r\n }\r\n\r\n visitOrderByClause(clause: OrderByClause): SqlComponent {\r\n const newOrder = clause.order.map(item => this.visit(item) as OrderByComponent);\r\n return new OrderByClause(newOrder);\r\n }\r\n\r\n visitWindowFrameClause(clause: WindowFrameClause): SqlComponent {\r\n const newExpression = this.visit(clause.expression) as WindowFrameExpression;\r\n return new WindowFrameClause(clause.name.name, newExpression);\r\n }\r\n\r\n visitLimitClause(clause: LimitClause): SqlComponent {\r\n const newLimit = this.visit(clause.value) as ValueComponent;\r\n return new LimitClause(newLimit);\r\n }\r\n\r\n visitForClause(clause: ForClause): SqlComponent {\r\n return new ForClause(clause.lockMode);\r\n }\r\n\r\n visitParenExpression(expr: ParenExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new ParenExpression(newExpression);\r\n }\r\n\r\n visitBinaryExpression(expr: BinaryExpression): SqlComponent {\r\n const newLeft = this.visit(expr.left) as ValueComponent;\r\n const newRight = this.visit(expr.right) as ValueComponent;\r\n return new BinaryExpression(newLeft, expr.operator.value, newRight);\r\n }\r\n\r\n visitUnaryExpression(expr: UnaryExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new UnaryExpression(expr.operator.value, newExpression);\r\n }\r\n\r\n visitCaseExpression(expr: CaseExpression): SqlComponent {\r\n const newCondition = expr.condition ? this.visit(expr.condition) as ValueComponent : null;\r\n const newSwitchCase = this.visit(expr.switchCase) as SwitchCaseArgument;\r\n return new CaseExpression(newCondition, newSwitchCase);\r\n }\r\n\r\n visitSwitchCaseArgument(switchCase: SwitchCaseArgument): SqlComponent {\r\n const newCases = switchCase.cases.map(caseItem => this.visit(caseItem) as CaseKeyValuePair);\r\n const newElseValue = switchCase.elseValue ? this.visit(switchCase.elseValue) as ValueComponent : null;\r\n return new SwitchCaseArgument(newCases, newElseValue);\r\n }\r\n\r\n visitCaseKeyValuePair(pair: CaseKeyValuePair): SqlComponent {\r\n const newKey = this.visit(pair.key) as ValueComponent;\r\n const newValue = this.visit(pair.value) as ValueComponent;\r\n return new CaseKeyValuePair(newKey, newValue);\r\n }\r\n\r\n visitBetweenExpression(expr: BetweenExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n const newLower = this.visit(expr.lower) as ValueComponent;\r\n const newUpper = this.visit(expr.upper) as ValueComponent;\r\n return new BetweenExpression(newExpression, newLower, newUpper, expr.negated);\r\n }\r\n\r\n visitFunctionCall(func: FunctionCall): SqlComponent {\r\n const newArgument = func.argument ? this.visit(func.argument) as ValueComponent : null;\r\n const newOver = func.over ? this.visit(func.over) as OverExpression : null;\r\n return new FunctionCall(func.namespaces, func.name, newArgument, newOver);\r\n }\r\n\r\n visitArrayExpression(expr: ArrayExpression): SqlComponent {\r\n const newExpression = this.visit(expr.expression) as ValueComponent;\r\n return new ArrayExpression(newExpression);\r\n }\r\n\r\n visitArrayQueryExpression(expr: ArrayQueryExpression): SqlComponent {\r\n const newQuery = this.visit(expr.query) as SelectQuery;\r\n return new ArrayQueryExpression(newQuery);\r\n }\r\n\r\n visitTupleExpression(expr: TupleExpression): SqlComponent {\r\n const newValues = expr.values.map(value => this.visit(value) as ValueComponent);\r\n return new TupleExpression(newValues);\r\n }\r\n\r\n visitCastExpression(expr: CastExpression): SqlComponent {\r\n const newInput = this.visit(expr.input) as ValueComponent;\r\n const newCastType = this.visit(expr.castType) as TypeValue;\r\n return new CastExpression(newInput, newCastType);\r\n }\r\n\r\n visitTypeValue(typeValue: TypeValue): SqlComponent {\r\n const newArgument = typeValue.argument ? this.visit(typeValue.argument) as ValueComponent : null;\r\n return new TypeValue(typeValue.namespaces, typeValue.name, newArgument);\r\n }\r\n\r\n visitSelectItem(item: SelectItem): SqlComponent {\r\n const newValue = this.visit(item.value) as ValueComponent;\r\n return new SelectItem(newValue, item.identifier?.name);\r\n }\r\n\r\n visitIdentifierString(ident: IdentifierString): SqlComponent {\r\n // Identifiers don't have child components, so just return as-is\r\n return ident;\r\n }\r\n\r\n visitRawString(raw: RawString): SqlComponent {\r\n // Raw strings don't have child components, so just return as-is\r\n return raw;\r\n }\r\n\r\n visitColumnReference(column: ColumnReference): SqlComponent {\r\n // Column references don't have subqueries, so just return as-is\r\n return column;\r\n }\r\n\r\n visitSourceExpression(source: SourceExpression): SqlComponent {\r\n const newSource = this.visit(source.datasource) as SourceComponent;\r\n // SourceAliasEpression don't contain subqueries, so just return as-is\r\n const newAlias = source.aliasExpression;\r\n return new SourceExpression(newSource, newAlias);\r\n }\r\n\r\n visitTableSource(source: TableSource): SqlComponent {\r\n // Table sources don't contain subqueries, so just return as-is\r\n return source;\r\n }\r\n\r\n visitParenSource(source: ParenSource): SqlComponent {\r\n const newSource = this.visit(source.source) as SourceComponent;\r\n return new ParenSource(newSource);\r\n }\r\n\r\n visitParameterExpression(param: ParameterExpression): SqlComponent {\r\n // Parameter expressions don't have child components, so just return as-is\r\n return param;\r\n }\r\n\r\n visitWindowFrameExpression(expr: WindowFrameExpression): SqlComponent {\r\n const newPartition = expr.partition ? this.visit(expr.partition) as PartitionByClause : null;\r\n const newOrder = expr.order ? this.visit(expr.order) as OrderByClause : null;\r\n const newFrameSpec = expr.frameSpec ? this.visit(expr.frameSpec) as WindowFrameSpec : null;\r\n\r\n return new WindowFrameExpression(\r\n newPartition,\r\n newOrder,\r\n newFrameSpec\r\n );\r\n }\r\n\r\n visitWindowFrameSpec(spec: WindowFrameSpec): SqlComponent {\r\n // WindowFrameSpec is a simple value object, so return as-is\r\n return spec;\r\n }\r\n\r\n visitLiteralValue(value: ValueComponent): SqlComponent {\r\n // Literal values are returned as-is\r\n return value;\r\n }\r\n\r\n visitOrderByItem(item: OrderByItem): SqlComponent {\r\n const newValue = this.visit(item.value) as ValueComponent;\r\n return new OrderByItem(newValue, item.sortDirection, item.nullsPosition);\r\n }\r\n}", "import { CommonTable, FetchClause, ForClause, FromClause, FunctionSource, GroupByClause, HavingClause, JoinClause, JoinOnClause, JoinUsingClause, LimitClause, OffsetClause, OrderByClause, OrderByItem, ParenSource, PartitionByClause, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource, WhereClause, WindowFrameClause, WindowsClause, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport {\r\n ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CaseKeyValuePair,\r\n CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression,\r\n ParameterExpression, SwitchCaseArgument, TupleExpression, UnaryExpression, ValueComponent, ValueList,\r\n OverExpression, WindowFrameExpression, IdentifierString, RawString,\r\n WindowFrameSpec,\r\n LiteralValue,\r\n TypeValue,\r\n StringSpecifierExpression\r\n} from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\n\r\n/**\r\n * A visitor that collects all table source names from a SQL query structure.\r\n * \r\n * When selectableOnly is true (default behavior):\r\n * - Includes only table sources from FROM and JOIN clauses\r\n * - Excludes inline queries, subqueries, and CTEs\r\n * \r\n * When selectableOnly is false:\r\n * - Scans all parts of the query including WITH clauses, subqueries, etc.\r\n * - Collects all table sources from the entire query\r\n * - Excludes tables that are managed by CTEs\r\n * \r\n * For UNION-like queries, it scans both the left and right parts.\r\n */\r\nexport class TableSourceCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private tableSources: TableSource[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private tableNameMap: Map<string, boolean> = new Map<string, boolean>();\r\n private selectableOnly: boolean;\r\n private cteNames: Set<string> = new Set<string>();\r\n private isRootVisit: boolean = true;\r\n\r\n constructor(selectableOnly: boolean = true) {\r\n this.selectableOnly = selectableOnly;\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for query components\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n\r\n // WITH clause and common tables\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // Handlers for FROM and JOIN components\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // Source components\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(ParenSource.kind, (expr) => this.visitParenSource(expr as ParenSource));\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n // Only register these handlers when not in selectableOnly mode\r\n if (!selectableOnly) {\r\n // Additional clause handlers for full scanning\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.visitOffsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr as OrderByItem));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n\r\n // Value components that might contain table references\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n }\r\n }\r\n\r\n /**\r\n * Gets all collected table sources\r\n */\r\n public getTableSources(): TableSource[] {\r\n return this.tableSources;\r\n }\r\n\r\n /**\r\n * Reset the collection of table sources\r\n */\r\n private reset(): void {\r\n this.tableSources = [];\r\n this.tableNameMap.clear();\r\n this.visitedNodes.clear();\r\n this.cteNames.clear();\r\n }\r\n\r\n /**\r\n * Gets a unique identifier for a table source\r\n */\r\n private getTableIdentifier(source: TableSource): string {\r\n // Use QualifiedName for identifier (dot-joined string)\r\n if (source.qualifiedName.namespaces && source.qualifiedName.namespaces.length > 0) {\r\n return source.qualifiedName.namespaces.map(ns => ns.name).join('.') + '.' + (source.qualifiedName.name instanceof RawString ? source.qualifiedName.name.value : source.qualifiedName.name.name);\r\n } else {\r\n return source.qualifiedName.name instanceof RawString ? source.qualifiedName.name.value : source.qualifiedName.name.name;\r\n }\r\n }\r\n\r\n public collect(query: SqlComponent): TableSource[] {\r\n // Visit the SQL component to collect table sources\r\n this.visit(query);\r\n return this.getTableSources();\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n // When in full scan mode, collect CTEs first to exclude them from table sources\r\n if (!this.selectableOnly) {\r\n this.collectCTEs(arg);\r\n }\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // If no handler found, that's ok - we only care about specific components\r\n }\r\n\r\n /**\r\n * Collects all CTE names to exclude them from real table sources\r\n */\r\n private collectCTEs(query: SqlComponent): void {\r\n // Use CommonTableCollector to get all CTEs\r\n const cteCollector = new CTECollector();\r\n cteCollector.visit(query);\r\n const commonTables = cteCollector.getCommonTables();\r\n\r\n // Add CTE names to the set\r\n for (const cte of commonTables) {\r\n // aliasExpression.table is TableSource, so use .table getter (IdentifierString)\r\n this.cteNames.add(cte.aliasExpression.table.name);\r\n }\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // Process the FROM and JOIN clauses\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n // If in full scan mode, visit all other clauses too\r\n if (!this.selectableOnly) {\r\n if (query.withClause) {\r\n query.withClause.accept(this);\r\n }\r\n\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.offsetClause) {\r\n query.offsetClause.accept(this);\r\n }\r\n\r\n if (query.fetchClause) {\r\n query.fetchClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n query.selectClause.accept(this);\r\n }\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // For UNION-like queries, visit both sides\r\n query.left.accept(this);\r\n query.right.accept(this);\r\n }\r\n\r\n private visitValuesQuery(query: ValuesQuery): void {\r\n if (!this.selectableOnly) {\r\n // VALUES queries might contain subqueries in tuple expressions\r\n for (const tuple of query.tuples) {\r\n tuple.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitWithClause(withClause: WithClause): void {\r\n if (!this.selectableOnly) {\r\n // Visit each CommonTable\r\n for (const table of withClause.tables) {\r\n table.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitCommonTable(commonTable: CommonTable): void {\r\n if (!this.selectableOnly) {\r\n // Process the query within the common table\r\n commonTable.query.accept(this);\r\n }\r\n }\r\n\r\n private visitFromClause(fromClause: FromClause): void {\r\n // Check the main source in FROM clause\r\n fromClause.source.accept(this);\r\n\r\n // Check all JOIN clauses\r\n if (fromClause.joins) {\r\n for (const join of fromClause.joins) {\r\n join.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n // Process the actual data source, ignoring aliases\r\n source.datasource.accept(this);\r\n }\r\n\r\n private visitTableSource(source: TableSource): void {\r\n // Get the table identifier for uniqueness check\r\n const identifier = this.getTableIdentifier(source);\r\n\r\n // Check if this is a table managed by a CTE\r\n if (!this.tableNameMap.has(identifier) && !this.isCTETable(source.table.name)) {\r\n this.tableNameMap.set(identifier, true);\r\n this.tableSources.push(source);\r\n }\r\n }\r\n\r\n private visitFunctionSource(source: FunctionSource): void {\r\n // Function sources are not regular table sources, but may contain subqueries in their arguments\r\n if (source.argument) {\r\n // Special handling for function arguments to ensure we traverse nested structures\r\n this.visitValueComponent(source.argument);\r\n }\r\n // Function sources themselves are not collected as table sources\r\n }\r\n\r\n /**\r\n * Helper method to visit value components, handling special cases like TupleExpression, ParenExpression, InlineQuery, and ArrayQueryExpression\r\n * even in selectableOnly mode when they appear in function arguments\r\n */\r\n private visitValueComponent(value: ValueComponent): void {\r\n // Always use the normal accept pattern - let handlers deal with the logic\r\n value.accept(this);\r\n }\r\n\r\n /**\r\n * Checks if a table name is a CTE name\r\n */\r\n private isCTETable(tableName: string): boolean {\r\n return this.cteNames.has(tableName);\r\n }\r\n\r\n private visitParenSource(source: ParenSource): void {\r\n // For parenthesized sources, visit the inner source\r\n source.source.accept(this);\r\n }\r\n\r\n private visitSubQuerySource(subQuery: SubQuerySource): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, we also check subqueries\r\n subQuery.query.accept(this);\r\n }\r\n // In selectableOnly mode, we don't collect sources from subqueries\r\n }\r\n\r\n private visitInlineQuery(inlineQuery: InlineQuery): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, visit inline queries too\r\n inlineQuery.selectQuery.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinClause(joinClause: JoinClause): void {\r\n // Visit the source being joined\r\n joinClause.source.accept(this);\r\n\r\n // If full scanning, also visit the join condition\r\n if (!this.selectableOnly && joinClause.condition) {\r\n joinClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOn: JoinOnClause): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, check ON condition for table references\r\n joinOn.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinUsingClause(joinUsing: JoinUsingClause): void {\r\n if (!this.selectableOnly) {\r\n // In full scan mode, check USING condition for table references\r\n joinUsing.condition.accept(this);\r\n }\r\n }\r\n\r\n // Additional visitor methods only used in full scan mode\r\n\r\n private visitWhereClause(whereClause: WhereClause): void {\r\n whereClause.condition.accept(this);\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n clause.condition.accept(this);\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitOffsetClause(clause: OffsetClause): void {\r\n clause.value.accept(this);\r\n }\r\n\r\n private visitFetchClause(clause: FetchClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitForClause(clause: ForClause): void {\r\n // FOR clause doesn't contain table sources\r\n }\r\n\r\n private visitOrderByItem(item: OrderByItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n item.accept(this);\r\n }\r\n }\r\n\r\n private visitSelectItem(item: SelectItem): void {\r\n item.value.accept(this);\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n expr.switchCase.accept(this);\r\n }\r\n\r\n private visitSwitchCaseArgument(switchCase: SwitchCaseArgument): void {\r\n for (const caseItem of switchCase.cases) {\r\n caseItem.accept(this);\r\n }\r\n\r\n if (switchCase.elseValue) {\r\n switchCase.elseValue.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseKeyValuePair(pair: CaseKeyValuePair): void {\r\n pair.key.accept(this);\r\n pair.value.accept(this);\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n expr.expression.accept(this);\r\n expr.lower.accept(this);\r\n expr.upper.accept(this);\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n expr.expression.accept(this);\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitTupleExpression(expr: TupleExpression): void {\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n expr.input.accept(this);\r\n expr.castType.accept(this);\r\n }\r\n\r\n private visitValueList(valueList: ValueList): void {\r\n // Process all values in the list, this may include InlineQuery and other table-referencing components\r\n for (const value of valueList.values) {\r\n value.accept(this);\r\n }\r\n }\r\n\r\n // Handle StringSpecifierExpression (PostgreSQL E-strings)\r\n private visitStringSpecifierExpression(expr: StringSpecifierExpression): void {\r\n // StringSpecifierExpression is just a literal string with an escape specifier\r\n // It doesn't contain table references, so we don't need to visit any children\r\n // This is a no-op method to prevent \"No handler\" errors\r\n }\r\n}", "export enum SqlPrintTokenType {\r\n container = 0,\r\n keyword,\r\n value, // Represents non-keyword elements such as table names\r\n comma, // Represents comma ','\r\n parenthesis, // Represents parentheses: ( ) { } [ ]\r\n operator, // Represents operators such as +, -, *, /\r\n comment,\r\n parameter,\r\n dot,\r\n type,\r\n space,\r\n argumentSplitter,\r\n}\r\n\r\n// Enum for container type, used for formatting and context\r\nexport enum SqlPrintTokenContainerType {\r\n ColumnReference = 'ColumnReference',\r\n LiteralValue = 'LiteralValue',\r\n IdentifierString = 'IdentifierString',\r\n InlineQuery = 'InlineQuery',\r\n StringSpecifierExpression = 'StringSpecifierExpression',\r\n None = '',\r\n ValueList = 'ValueList',\r\n OrderByItem = 'OrderByItem',\r\n FunctionCall = 'FunctionCall',\r\n UnaryExpression = 'UnaryExpression',\r\n BinaryExpression = 'BinaryExpression',\r\n SwitchCaseArgument = 'SwitchCaseArgument',\r\n ElseClause = 'ElseClause',\r\n CaseKeyValuePair = 'CaseKeyValuePair',\r\n CaseThenValue = 'CaseThenValue',\r\n CaseElseValue = 'CaseElseValue',\r\n ParenExpression = 'ParenExpression',\r\n CastExpression = 'CastExpression',\r\n CaseExpression = 'CaseExpression',\r\n ArrayExpression = 'ArrayExpression',\r\n BetweenExpression = 'BetweenExpression',\r\n TypeValue = 'TypeValue',\r\n TupleExpression = 'TupleExpression',\r\n WindowFrameExpression = 'WindowFrameExpression',\r\n SelectItem = 'SelectItem',\r\n SelectClause = 'SelectClause',\r\n DistinctOn = 'DistinctOn',\r\n SourceExpression = 'SourceExpression',\r\n FromClause = 'FromClause',\r\n JoinClause = 'JoinClause',\r\n JoinOnClause = 'JoinOnClause',\r\n JoinUsingClause = 'JoinUsingClause',\r\n FunctionSource = 'FunctionSource',\r\n SourceAliasExpression = 'SourceAliasExpression',\r\n RawString = 'RawString',\r\n QualifiedName = \"QualifiedName\",\r\n WhereClause = \"WhereClause\",\r\n SimpleSelectQuery = \"SimpleSelectQuery\",\r\n OrderByClause = \"OrderByClause\",\r\n GroupByClause = \"GroupByClause\",\r\n HavingClause = \"HavingClause\",\r\n SubQuerySource = \"SubQuerySource\",\r\n PartitionByClause = \"PartitionByClause\",\r\n WindowFrameClause = \"WindowFrameClause\",\r\n LimitClause = \"LimitClause\",\r\n OffsetClause = \"OffsetClause\",\r\n ForClause = \"ForClause\",\r\n WindowClause = \"WindowClause\",\r\n BinarySelectQueryOperator = \"BinarySelectQueryOperator\",\r\n Values = \"Values\",\r\n ValuesQuery = \"ValuesQuery\",\r\n WithClause = \"WithClause\",\r\n CommonTable = \"CommonTable\",\r\n WindowFrameSpec = \"WindowFrameSpec\",\r\n WindowFrameBoundStatic = \"WindowFrameBoundStatic\",\r\n WindowFrameBoundaryValue = \"WindowFrameBoundaryValue\",\r\n FetchClause = \"FetchClause\",\r\n FetchExpression = \"FetchExpression\",\r\n InsertQuery = \"InsertQuery\",\r\n UpdateQuery = \"UpdateQuery\",\r\n UpdateClause = \"UpdateClause\",\r\n ReturningClause = \"ReturningClause\",\r\n SetClauseItem = \"SetClauseItem\",\r\n CreateTableQuery = \"CreateTableQuery\",\r\n // Add more as needed\r\n}\r\n\r\nexport class SqlPrintToken {\r\n /**\r\n * The type of this token, representing the general category (e.g. keyword, value, operator).\r\n */\r\n type: SqlPrintTokenType;\r\n /**\r\n * The actual text content of this token, following SQL syntax.\r\n */\r\n text: string;\r\n /**\r\n * The type of the container this token belongs to. Used for clauses, functions, or other groupings.\r\n */\r\n containerType: SqlPrintTokenContainerType;\r\n\r\n /**\r\n * Optional. Keywords that are part of this token, like DISTINCT in a SELECT clause.\r\n * These should typically be processed before innerTokens.\r\n */\r\n keywordTokens?: SqlPrintToken[];\r\n\r\n /**\r\n * Child tokens that belong to this container.\r\n */\r\n innerTokens: SqlPrintToken[] = [];\r\n\r\n constructor(type: SqlPrintTokenType, text: string = '', containerType: SqlPrintTokenContainerType = SqlPrintTokenContainerType.None) {\r\n this.type = type;\r\n this.text = text;\r\n this.containerType = containerType;\r\n }\r\n}\r\n", "import { ParameterExpression } from \"../models/ValueComponent\";\r\n\r\n/**\r\n * Utility class to collect all ParameterExpression nodes from an AST.\r\n */\r\nexport class ParameterCollector {\r\n /**\r\n * Recursively collect all ParameterExpression nodes from AST.\r\n * @param node AST root\r\n * @returns ParameterExpression[]\r\n */\r\n static collect(node: any): ParameterExpression[] {\r\n const result: ParameterExpression[] = [];\r\n function walk(n: any) {\r\n if (!n || typeof n !== 'object') return;\r\n if (n.constructor && n.constructor.kind === ParameterExpression.kind) {\r\n result.push(n);\r\n }\r\n for (const key of Object.keys(n)) {\r\n const v = n[key];\r\n if (Array.isArray(v)) {\r\n v.forEach(walk);\r\n } else if (v && typeof v === 'object' && v.constructor && v.constructor.kind) {\r\n walk(v);\r\n }\r\n }\r\n }\r\n walk(node);\r\n return result;\r\n }\r\n}\r\n", "export class IdentifierDecorator {\r\n start: string;\r\n end: string;\r\n\r\n constructor(identifierEscape?: { start?: string; end?: string }) {\r\n this.start = identifierEscape?.start ?? '\"';\r\n this.end = identifierEscape?.end ?? '\"';\r\n }\r\n\r\n decorate(text: string): string {\r\n // override\r\n text = this.start + text + this.end;\r\n return text;\r\n }\r\n}\r\n", "/**\r\n * This decorator formats parameter tokens according to DBMS-specific rules.\r\n * It supports prefix/suffix, and parameter style (named, indexed, anonymous).\r\n */\r\nexport class ParameterDecorator {\r\n prefix: string;\r\n suffix: string;\r\n style: 'named' | 'indexed' | 'anonymous';\r\n\r\n constructor(options?: { prefix?: string; suffix?: string; style?: 'named' | 'indexed' | 'anonymous' }) {\r\n this.prefix = options?.prefix ?? ':';\r\n this.suffix = options?.suffix ?? '';\r\n this.style = options?.style ?? 'named';\r\n }\r\n\r\n /**\r\n * Decorate a parameter token with DBMS-specific format.\r\n * @param token The parameter token\r\n * @param index The parameter index (for indexed/anonymous)\r\n */\r\n decorate(text: string, index: number): string {\r\n let paramText = '';\r\n if (this.style === 'anonymous') {\r\n // e.g. ?\r\n paramText = this.prefix;\r\n } else if (this.style === 'indexed') {\r\n // e.g. $1, ?1, :1\r\n paramText = this.prefix + index;\r\n } else if (this.style === 'named') {\r\n // e.g. :name, @name, ${name}\r\n paramText = this.prefix + text + this.suffix;\r\n }\r\n\r\n // override \r\n text = paramText;\r\n return text;\r\n }\r\n}\r\n", "// Represents an UPDATE query in SQL.\r\n// Supports SET, WHERE, and optional FROM/RETURNING clauses.\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { IdentifierString, ValueComponent } from \"./ValueComponent\";\r\nimport { FromClause, ReturningClause, SetClause, WhereClause, SourceExpression, UpdateClause } from \"./Clause\";\r\nimport { WithClause } from \"./Clause\";\r\n\r\nexport class UpdateQuery extends SqlComponent {\r\n static kind = Symbol(\"UpdateQuery\");\r\n withClause: WithClause | null;\r\n updateClause: UpdateClause;\r\n setClause: SetClause;\r\n whereClause: WhereClause | null;\r\n fromClause: FromClause | null;\r\n returningClause: ReturningClause | null;\r\n\r\n /**\r\n * @param params.source SourceExpression (table or subquery with optional alias)\r\n * @param params.setClause SetClause instance or array of {column, value} pairs\r\n * @param params.where WHERE clause (optional)\r\n * @param params.from FROM clause (optional)\r\n * @param params.returning RETURNING clause (optional)\r\n */\r\n\r\n constructor(params: {\r\n withClause?: WithClause | null;\r\n updateClause: UpdateClause;\r\n setClause: SetClause | { column: string | IdentifierString, value: ValueComponent }[];\r\n whereClause?: WhereClause | null;\r\n fromClause?: FromClause | null;\r\n returning?: ReturningClause | null;\r\n }) {\r\n super();\r\n this.withClause = params.withClause ?? null;\r\n this.updateClause = params.updateClause;\r\n this.setClause = params.setClause instanceof SetClause ? params.setClause : new SetClause(params.setClause);\r\n this.whereClause = params.whereClause ?? null;\r\n this.fromClause = params.fromClause ?? null;\r\n this.returningClause = params.returning ?? null;\r\n }\r\n}\r\n", "import { CommonTable, FromClause, JoinClause, ParenSource, SelectClause, SelectItem, SourceExpression, SubQuerySource, TableSource } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, SelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { ColumnReference, InlineQuery, LiteralValue, ValueComponent } from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableColumnResolver } from \"./TableColumnResolver\";\r\n\r\n/**\r\n * A visitor that collects all SelectItem instances from a SQL query structure.\r\n * This visitor scans through select clauses and collects all the SelectItem objects.\r\n * It can also resolve wildcard selectors (table.* or *) using a provided table column resolver.\r\n */\r\nexport class SelectValueCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private selectValues: { name: string, value: ValueComponent }[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n private tableColumnResolver: TableColumnResolver | null;\r\n private commonTableCollector: CTECollector;\r\n private commonTables: CommonTable[];\r\n public initialCommonTables: CommonTable[] | null;\r\n\r\n constructor(tableColumnResolver: TableColumnResolver | null = null, initialCommonTables: CommonTable[] | null = null) {\r\n this.tableColumnResolver = tableColumnResolver ?? null;\r\n this.commonTableCollector = new CTECollector();\r\n this.commonTables = [];\r\n this.initialCommonTables = initialCommonTables;\r\n\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n }\r\n\r\n /**\r\n * Get all collected SelectItems as an array of objects with name and value properties\r\n * @returns An array of objects with name (string) and value (ValueComponent) properties\r\n */\r\n public getValues(): { name: string, value: ValueComponent }[] {\r\n return this.selectValues;\r\n }\r\n\r\n /**\r\n * Reset the collection of SelectItems\r\n */\r\n private reset(): void {\r\n this.selectValues = [];\r\n this.visitedNodes.clear();\r\n if (this.initialCommonTables) {\r\n this.commonTables = this.initialCommonTables;\r\n } else {\r\n this.commonTables = [];\r\n }\r\n }\r\n\r\n public collect(arg: SqlComponent): { name: string, value: ValueComponent }[] {\r\n // Visit the component and return the collected select items\r\n this.visit(arg);\r\n const items = this.getValues();\r\n this.reset(); // Reset after collection\r\n return items;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n }\r\n\r\n /**\r\n * Process a SimpleSelectQuery to collect data and store the current context\r\n */\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n if (this.commonTables.length === 0 && this.initialCommonTables === null) {\r\n this.commonTables = this.commonTableCollector.collect(query);\r\n }\r\n\r\n if (query.selectClause) {\r\n query.selectClause.accept(this);\r\n }\r\n\r\n // no wildcard \r\n const wildcards = this.selectValues.filter(item => item.name === '*');\r\n if (wildcards.length === 0) {\r\n return;\r\n }\r\n\r\n // full wildcard\r\n if (this.selectValues.some(item => item.value instanceof ColumnReference && item.value.namespaces === null)) {\r\n if (query.fromClause) {\r\n this.processFromClause(query.fromClause, true);\r\n }\r\n // remove wildcard\r\n this.selectValues = this.selectValues.filter(item => item.name !== '*');\r\n return;\r\n };\r\n\r\n // table wildcard\r\n const wildSourceNames = wildcards.filter(item => item.value instanceof ColumnReference && item.value.namespaces)\r\n .map(item => (item.value as ColumnReference).getNamespace());\r\n\r\n if (query.fromClause) {\r\n const fromSourceName = query.fromClause.getSourceAliasName();\r\n if (fromSourceName && wildSourceNames.includes(fromSourceName)) {\r\n this.processFromClause(query.fromClause, false);\r\n }\r\n if (query.fromClause.joins) {\r\n for (const join of query.fromClause.joins) {\r\n const joinSourceName = join.getSourceAliasName();\r\n if (joinSourceName && wildSourceNames.includes(joinSourceName)) {\r\n this.processJoinClause(join);\r\n }\r\n }\r\n }\r\n }\r\n // remove wildcard\r\n this.selectValues = this.selectValues.filter(item => item.name !== '*');\r\n return;\r\n }\r\n\r\n private processFromClause(clause: FromClause, joinCascade: boolean): void {\r\n if (clause) {\r\n const fromSourceName = clause.getSourceAliasName();\r\n this.processSourceExpression(fromSourceName, clause.source);\r\n\r\n if (clause.joins && joinCascade) {\r\n for (const join of clause.joins) {\r\n this.processJoinClause(join);\r\n }\r\n }\r\n }\r\n return;\r\n }\r\n\r\n private processJoinClause(clause: JoinClause): void {\r\n const sourceName = clause.getSourceAliasName();\r\n this.processSourceExpression(sourceName, clause.source);\r\n }\r\n\r\n private processSourceExpression(sourceName: string | null, source: SourceExpression) {\r\n // check common table\r\n const commonTable = this.commonTables.find(item => item.aliasExpression.table.name === sourceName);\r\n if (commonTable) {\r\n // Exclude this CTE from consideration to prevent self-reference\r\n const innerCommonTables = this.commonTables.filter(item => item.aliasExpression.table.name !== sourceName);\r\n\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, innerCommonTables);\r\n const innerSelected = innerCollector.collect(commonTable.query);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n } else {\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const innerSelected = innerCollector.collect(source);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n }\r\n }\r\n\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n this.processSelectItem(item);\r\n }\r\n }\r\n\r\n private processSelectItem(item: SelectItem): void {\r\n if (item.identifier) {\r\n this.addSelectValueAsUnique(item.identifier.name, item.value);\r\n }\r\n else if (item.value instanceof ColumnReference) { // Handle column reference\r\n // columnName can be '*'\r\n const columnName = item.value.column.name;\r\n if (columnName === '*') {\r\n // Force add without checking duplicates\r\n this.selectValues.push({ name: columnName, value: item.value });\r\n }\r\n else {\r\n // Add with duplicate checking\r\n this.addSelectValueAsUnique(columnName, item.value);\r\n }\r\n }\r\n }\r\n\r\n private visitSourceExpression(source: SourceExpression): void {\r\n // Column aliases have the highest priority if present\r\n // For physical tables, use external function to get column names\r\n // For subqueries, instantiate a new collector and get column names from the subquery\r\n // For parenthesized expressions, treat them the same as subqueries\r\n\r\n if (source.aliasExpression && source.aliasExpression.columns) {\r\n const sourceName = source.getAliasName();\r\n source.aliasExpression.columns.forEach(column => {\r\n this.addSelectValueAsUnique(column.name, new ColumnReference(sourceName ? [sourceName] : null, column.name));\r\n });\r\n return;\r\n } else if (source.datasource instanceof TableSource) {\r\n if (this.tableColumnResolver) {\r\n const sourceName = source.datasource.getSourceName();\r\n this.tableColumnResolver(sourceName).forEach(column => {\r\n this.addSelectValueAsUnique(column, new ColumnReference([sourceName], column));\r\n });\r\n }\r\n return;\r\n } else if (source.datasource instanceof SubQuerySource) {\r\n const sourceName = source.getAliasName();\r\n const innerCollector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const innerSelected = innerCollector.collect(source.datasource.query);\r\n innerSelected.forEach(item => {\r\n this.addSelectValueAsUnique(item.name, new ColumnReference(sourceName ? [sourceName] : null, item.name));\r\n });\r\n return;\r\n } else if (source.datasource instanceof ParenSource) {\r\n return this.visit(source.datasource.source);\r\n }\r\n }\r\n\r\n private visitFromClause(clause: FromClause): void {\r\n if (clause) {\r\n this.processFromClause(clause, true);\r\n }\r\n }\r\n\r\n private addSelectValueAsUnique(name: string, value: ValueComponent): void {\r\n // Check if a select value with the same name already exists before adding\r\n if (!this.selectValues.some(item => item.name === name)) {\r\n this.selectValues.push({ name, value });\r\n }\r\n }\r\n}\r\n", "import { SqlComponent } from \"./SqlComponent\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { ColumnReference, FunctionCall, IdentifierString, RawString } from \"./ValueComponent\";\r\nimport { SimpleSelectQuery } from \"./SimpleSelectQuery\";\r\nimport { SelectClause, SelectItem, FromClause, TableSource, SourceExpression } from \"./Clause\";\r\nimport { SelectValueCollector } from \"../transformers/SelectValueCollector\";\r\n\r\n// Represents a CREATE TABLE query model\r\n// Supports temporary tables and AS SELECT ...\r\nexport class CreateTableQuery extends SqlComponent {\r\n /** SqlComponent kind symbol for visitor pattern */\r\n static kind = Symbol(\"CreateTableQuery\");\r\n /** Table name (with optional schema) */\r\n tableName: IdentifierString;\r\n /** If true, this is a temporary table */\r\n isTemporary: boolean;\r\n /** Optional: SELECT query for AS SELECT ... */\r\n asSelectQuery?: SelectQuery;\r\n\r\n constructor(params: {\r\n tableName: string;\r\n isTemporary?: boolean;\r\n asSelectQuery?: SelectQuery;\r\n }) {\r\n super();\r\n this.tableName = new IdentifierString(params.tableName);\r\n this.isTemporary = params.isTemporary ?? false;\r\n this.asSelectQuery = params.asSelectQuery;\r\n }\r\n\r\n /**\r\n * Returns a SelectQuery that selects all columns from this table.\r\n */\r\n getSelectQuery(): SimpleSelectQuery {\r\n let selectItems: SelectItem[];\r\n if (this.asSelectQuery) {\r\n // Use SelectValueCollector to get columns from asSelectQuery\r\n const collector = new SelectValueCollector();\r\n const values = collector.collect(this.asSelectQuery);\r\n selectItems = values.map(val => new SelectItem(val.value, val.name));\r\n } else {\r\n // fallback: wildcard\r\n selectItems = [new SelectItem(new RawString(\"*\"))];\r\n }\r\n return new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, this.tableName.name),\r\n null\r\n ),\r\n null // joins\r\n ),\r\n });\r\n }\r\n\r\n /**\r\n * Returns a SelectQuery that counts all rows in this table.\r\n */\r\n getCountQuery(): SimpleSelectQuery {\r\n return new SimpleSelectQuery({\r\n selectClause: new SelectClause([\r\n new SelectItem(new FunctionCall(null, \"count\", new ColumnReference(null, \"*\"), null))\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, this.tableName.name),\r\n null\r\n ),\r\n null // joins\r\n ),\r\n });\r\n }\r\n}\r\n", "import { PartitionByClause, OrderByClause, OrderByItem, SelectClause, SelectItem, Distinct, DistinctOn, SortDirection, NullsSortDirection, TableSource, SourceExpression, FromClause, JoinClause, JoinOnClause, JoinUsingClause, FunctionSource, SourceAliasExpression, WhereClause, GroupByClause, HavingClause, SubQuerySource, WindowFrameClause, LimitClause, ForClause, OffsetClause, WindowsClause as WindowClause, CommonTable, WithClause, FetchClause, FetchExpression, InsertClause, UpdateClause, SetClause, ReturningClause, SetClauseItem } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { SqlPrintToken, SqlPrintTokenType, SqlPrintTokenContainerType } from \"../models/SqlPrintToken\";\r\nimport {\r\n ValueList,\r\n ColumnReference,\r\n FunctionCall,\r\n UnaryExpression,\r\n BinaryExpression,\r\n LiteralValue,\r\n ParameterExpression,\r\n SwitchCaseArgument,\r\n CaseKeyValuePair,\r\n RawString,\r\n IdentifierString,\r\n ParenExpression,\r\n CastExpression,\r\n CaseExpression,\r\n ArrayExpression,\r\n ArrayQueryExpression,\r\n BetweenExpression,\r\n StringSpecifierExpression,\r\n TypeValue,\r\n TupleExpression,\r\n WindowFrameExpression,\r\n QualifiedName,\r\n InlineQuery,\r\n WindowFrameSpec,\r\n WindowFrameBoundStatic,\r\n WindowFrameBoundaryValue\r\n} from \"../models/ValueComponent\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { IdentifierDecorator } from \"./IdentifierDecorator\";\r\nimport { ParameterDecorator } from \"./ParameterDecorator\";\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { UpdateQuery } from \"../models/UpdateQuery\";\r\nimport { CreateTableQuery } from \"../models/CreateTableQuery\";\r\n\r\nexport enum ParameterStyle {\r\n Anonymous = 'anonymous',\r\n Indexed = 'indexed',\r\n Named = 'named'\r\n}\r\n\r\nexport interface FormatterConfig {\r\n identifierEscape?: {\r\n start: string;\r\n end: string;\r\n };\r\n parameterSymbol?: string | { start: string; end: string };\r\n /**\r\n * Parameter style: anonymous (?), indexed ($1), or named (:name)\r\n */\r\n parameterStyle?: ParameterStyle;\r\n}\r\n\r\nexport const PRESETS: Record<string, FormatterConfig> = {\r\n mysql: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n postgres: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n postgresWithNamedParams: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n sqlserver: {\r\n identifierEscape: { start: '[', end: ']' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n sqlite: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n oracle: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n clickhouse: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n firebird: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n db2: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n snowflake: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n cloudspanner: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n duckdb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n cockroachdb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n athena: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n bigquery: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '@',\r\n parameterStyle: ParameterStyle.Named,\r\n },\r\n hive: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n mariadb: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n redshift: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '$',\r\n parameterStyle: ParameterStyle.Indexed,\r\n },\r\n flinksql: {\r\n identifierEscape: { start: '`', end: '`' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n mongodb: {\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: '?',\r\n parameterStyle: ParameterStyle.Anonymous,\r\n },\r\n};\r\n\r\nexport class SqlPrintTokenParser implements SqlComponentVisitor<SqlPrintToken> {\r\n // Static tokens for common symbols\r\n private static readonly SPACE_TOKEN = new SqlPrintToken(SqlPrintTokenType.space, ' ');\r\n private static readonly COMMA_TOKEN = new SqlPrintToken(SqlPrintTokenType.comma, ',');\r\n private static readonly ARGUMENT_SPLIT_COMMA_TOKEN = new SqlPrintToken(SqlPrintTokenType.argumentSplitter, ',');\r\n private static readonly PAREN_OPEN_TOKEN = new SqlPrintToken(SqlPrintTokenType.parenthesis, '(');\r\n private static readonly PAREN_CLOSE_TOKEN = new SqlPrintToken(SqlPrintTokenType.parenthesis, ')');\r\n private static readonly DOT_TOKEN = new SqlPrintToken(SqlPrintTokenType.dot, '.');\r\n\r\n private handlers: Map<symbol, (arg: any) => SqlPrintToken> = new Map();\r\n parameterDecorator: ParameterDecorator;\r\n identifierDecorator: IdentifierDecorator;\r\n index: number = 1;\r\n\r\n constructor(options?: {\r\n preset?: FormatterConfig,\r\n identifierEscape?: { start: string; end: string },\r\n parameterSymbol?: string | { start: string; end: string },\r\n parameterStyle?: 'anonymous' | 'indexed' | 'named'\r\n }) {\r\n if (options?.preset) {\r\n const preset = options.preset\r\n options = { ...preset, ...options };\r\n }\r\n\r\n this.parameterDecorator = new ParameterDecorator({\r\n prefix: typeof options?.parameterSymbol === 'string' ? options.parameterSymbol : options?.parameterSymbol?.start ?? ':',\r\n suffix: typeof options?.parameterSymbol === 'object' ? options.parameterSymbol.end : '',\r\n style: options?.parameterStyle ?? 'named'\r\n });\r\n\r\n this.identifierDecorator = new IdentifierDecorator({\r\n start: options?.identifierEscape?.start ?? '\"',\r\n end: options?.identifierEscape?.end ?? '\"'\r\n });\r\n\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(QualifiedName.kind, (expr) => this.visitQualifiedName(expr as QualifiedName));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(LiteralValue.kind, (expr) => this.visitLiteralValue(expr as LiteralValue));\r\n this.handlers.set(ParameterExpression.kind, (expr) => this.visitParameterExpression(expr as ParameterExpression));\r\n this.handlers.set(SwitchCaseArgument.kind, (expr) => this.visitSwitchCaseArgument(expr as SwitchCaseArgument));\r\n this.handlers.set(CaseKeyValuePair.kind, (expr) => this.visitCaseKeyValuePair(expr as CaseKeyValuePair));\r\n this.handlers.set(RawString.kind, (expr) => this.visitRawString(expr as RawString));\r\n this.handlers.set(IdentifierString.kind, (expr) => this.visitIdentifierString(expr as IdentifierString));\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(StringSpecifierExpression.kind, (expr) => this.visitStringSpecifierExpression(expr as StringSpecifierExpression));\r\n this.handlers.set(TypeValue.kind, (expr) => this.visitTypeValue(expr as TypeValue));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n this.handlers.set(InlineQuery.kind, (expr) => this.visitInlineQuery(expr as InlineQuery));\r\n\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(WindowFrameSpec.kind, (expr) => this.visitWindowFrameSpec(expr as WindowFrameSpec));\r\n this.handlers.set(WindowFrameBoundStatic.kind, (expr) => this.visitWindowFrameBoundStatic(expr as WindowFrameBoundStatic));\r\n this.handlers.set(WindowFrameBoundaryValue.kind, (expr) => this.visitWindowFrameBoundaryValue(expr as WindowFrameBoundaryValue));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(OrderByItem.kind, (expr) => this.visitOrderByItem(expr));\r\n\r\n // select\r\n this.handlers.set(SelectItem.kind, (expr) => this.visitSelectItem(expr as SelectItem));\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(Distinct.kind, (expr) => this.visitDistinct(expr as Distinct));\r\n this.handlers.set(DistinctOn.kind, (expr) => this.visitDistinctOn(expr as DistinctOn));\r\n\r\n // from\r\n this.handlers.set(TableSource.kind, (expr) => this.visitTableSource(expr as TableSource));\r\n this.handlers.set(FunctionSource.kind, (expr) => this.visitFunctionSource(expr as FunctionSource));\r\n this.handlers.set(SourceExpression.kind, (expr) => this.visitSourceExpression(expr as SourceExpression));\r\n this.handlers.set(SourceAliasExpression.kind, (expr) => this.visitSourceAliasExpression(expr as SourceAliasExpression));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(JoinClause.kind, (expr) => this.visitJoinClause(expr as JoinClause));\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // where\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n\r\n // group\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n\r\n this.handlers.set(WindowClause.kind, (expr) => this.visitWindowClause(expr as WindowClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.visitOffsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n this.handlers.set(FetchExpression.kind, (expr) => this.visitFetchExpression(expr as FetchExpression));\r\n this.handlers.set(ForClause.kind, (expr) => this.visitForClause(expr as ForClause));\r\n\r\n // With\r\n this.handlers.set(WithClause.kind, (expr) => this.visitWithClause(expr as WithClause));\r\n this.handlers.set(CommonTable.kind, (expr) => this.visitCommonTable(expr as CommonTable));\r\n\r\n // Query\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(SubQuerySource.kind, (expr) => this.visitSubQuerySource(expr as SubQuerySource));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr));\r\n this.handlers.set(ValuesQuery.kind, (expr) => this.visitValuesQuery(expr as ValuesQuery));\r\n this.handlers.set(TupleExpression.kind, (expr) => this.visitTupleExpression(expr as TupleExpression));\r\n\r\n this.handlers.set(InsertQuery.kind, (expr) => this.visitInsertQuery(expr as InsertQuery));\r\n this.handlers.set(InsertClause.kind, (expr) => this.visitInsertClause(expr as InsertClause));\r\n this.handlers.set(UpdateQuery.kind, (expr) => this.visitUpdateQuery(expr as UpdateQuery));\r\n this.handlers.set(UpdateClause.kind, (expr) => this.visitUpdateClause(expr as UpdateClause));\r\n this.handlers.set(SetClause.kind, (expr) => this.visitSetClause(expr as SetClause));\r\n this.handlers.set(SetClauseItem.kind, (expr) => this.visitSetClauseItem(expr as SetClauseItem));\r\n this.handlers.set(ReturningClause.kind, (expr) => this.visitReturningClause(expr as ReturningClause));\r\n this.handlers.set(CreateTableQuery.kind, (expr) => this.visitCreateTableQuery(expr as CreateTableQuery));\r\n }\r\n\r\n /**\r\n * Pretty-prints a BinarySelectQuery (e.g., UNION, INTERSECT, EXCEPT).\r\n * This will recursively print left and right queries, separated by the operator.\r\n * @param arg BinarySelectQuery\r\n */\r\n private visitBinarySelectQuery(arg: BinarySelectQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(this.visit(arg.left));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.operator.value, SqlPrintTokenContainerType.BinarySelectQueryOperator));\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.right));\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Returns an array of tokens representing a comma followed by a space.\r\n * This is a common pattern in SQL pretty-printing.\r\n */\r\n private static commaSpaceTokens(): SqlPrintToken[] {\r\n return [SqlPrintTokenParser.COMMA_TOKEN, SqlPrintTokenParser.SPACE_TOKEN];\r\n }\r\n\r\n private static argumentCommaSpaceTokens(): SqlPrintToken[] {\r\n return [SqlPrintTokenParser.ARGUMENT_SPLIT_COMMA_TOKEN, SqlPrintTokenParser.SPACE_TOKEN];\r\n }\r\n\r\n\r\n private visitQualifiedName(arg: QualifiedName): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.QualifiedName);\r\n\r\n if (arg.namespaces) {\r\n for (let i = 0; i < arg.namespaces.length; i++) {\r\n token.innerTokens.push(arg.namespaces[i].accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.DOT_TOKEN);\r\n }\r\n }\r\n token.innerTokens.push(arg.name.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n private visitPartitionByClause(arg: PartitionByClause): SqlPrintToken {\r\n // Print as: partition by ...\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'partition by', SqlPrintTokenContainerType.PartitionByClause);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n return token;\r\n }\r\n\r\n private visitOrderByClause(arg: OrderByClause): SqlPrintToken {\r\n // Print as: order by ...\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'order by', SqlPrintTokenContainerType.OrderByClause);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.order.length; i++) {\r\n if (i > 0) token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n token.innerTokens.push(this.visit(arg.order[i]));\r\n }\r\n return token;\r\n }\r\n\r\n /**\r\n * Print an OrderByItem (expression [asc|desc] [nulls first|last])\r\n */\r\n private visitOrderByItem(arg: OrderByItem): SqlPrintToken {\r\n // arg: OrderByItem\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.OrderByItem);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n if (arg.sortDirection && arg.sortDirection !== SortDirection.Ascending) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'desc'));\r\n }\r\n\r\n if (arg.nullsPosition) {\r\n if (arg.nullsPosition === NullsSortDirection.First) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'nulls first'));\r\n } else if (arg.nullsPosition === NullsSortDirection.Last) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'nulls last'));\r\n }\r\n }\r\n return token;\r\n }\r\n\r\n public parse(arg: SqlComponent): { token: SqlPrintToken, params: any[] | Record<string, any>[] | Record<string, any> } {\r\n // reset parameter index before parsing\r\n this.index = 1;\r\n\r\n const token = this.visit(arg);\r\n const paramsRaw = ParameterCollector.collect(arg).sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\r\n\r\n const style = this.parameterDecorator.style;\r\n if (style === ParameterStyle.Named) {\r\n // Named: { name: value, ... }\r\n const paramsObj: Record<string, any> = {};\r\n for (const p of paramsRaw) {\r\n const key = p.name.value;\r\n if (paramsObj.hasOwnProperty(key)) {\r\n if (paramsObj[key] !== p.value) {\r\n throw new Error(`Duplicate parameter name '${key}' with different values detected during query composition.`);\r\n }\r\n // If value is the same, skip (already set)\r\n continue;\r\n }\r\n paramsObj[key] = p.value;\r\n }\r\n return { token, params: paramsObj };\r\n } else if (style === ParameterStyle.Indexed) {\r\n // Indexed: [value1, value2, ...] (sorted by index)\r\n const paramsArr = paramsRaw.map(p => p.value);\r\n return { token, params: paramsArr };\r\n } else if (style === ParameterStyle.Anonymous) {\r\n // Anonymous: [value1, value2, ...] (sorted by index, name is empty)\r\n const paramsArr = paramsRaw.map(p => p.value);\r\n return { token, params: paramsArr };\r\n }\r\n\r\n // Fallback (just in case)\r\n return { token, params: [] };\r\n }\r\n\r\n public visit(arg: SqlComponent): SqlPrintToken {\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n return handler(arg);\r\n }\r\n throw new Error(`[SqlPrintTokenParser] No handler for kind: ${arg.getKind().toString()}`);\r\n }\r\n\r\n private visitValueList(arg: ValueList): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ValueList);\r\n for (let i = 0; i < arg.values.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.values[i]));\r\n }\r\n return token;\r\n }\r\n\r\n private visitColumnReference(arg: ColumnReference): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ColumnReference);\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n return token;\r\n }\r\n\r\n private visitFunctionCall(arg: FunctionCall): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FunctionCall);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n if (arg.argument) {\r\n token.innerTokens.push(this.visit(arg.argument));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n if (arg.over) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'over'));\r\n\r\n if (arg.over instanceof IdentifierString) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.over.accept(this));\r\n }\r\n else {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.over));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitUnaryExpression(arg: UnaryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.UnaryExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.operator));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n\r\n return token;\r\n }\r\n\r\n private visitBinaryExpression(arg: BinaryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.BinaryExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.left));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, arg.operator.value));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.right));\r\n\r\n return token;\r\n }\r\n\r\n private visitLiteralValue(arg: LiteralValue): SqlPrintToken {\r\n let text;\r\n if (typeof arg.value === \"string\") {\r\n text = `'${arg.value.replace(/'/g, \"''\")}'`;\r\n } else if (arg.value === null) {\r\n text = \"null\";\r\n } else {\r\n text = arg.value.toString();\r\n }\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n text,\r\n SqlPrintTokenContainerType.LiteralValue\r\n );\r\n }\r\n\r\n private visitParameterExpression(arg: ParameterExpression): SqlPrintToken {\r\n // Create a parameter token and decorate it using the parameterDecorator\r\n arg.index = this.index;\r\n const text = this.parameterDecorator.decorate(arg.name.value, arg.index)\r\n const token = new SqlPrintToken(SqlPrintTokenType.parameter, text);\r\n\r\n this.index++;\r\n return token;\r\n }\r\n\r\n private visitSwitchCaseArgument(arg: SwitchCaseArgument): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SwitchCaseArgument);\r\n\r\n // Add each WHEN/THEN clause\r\n for (const kv of arg.cases) {\r\n // Create a new line for each WHEN clause\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(kv.accept(this));\r\n }\r\n\r\n // Add ELSE clause if present\r\n if (arg.elseValue) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.createElseToken(arg.elseValue));\r\n }\r\n return token;\r\n }\r\n\r\n private createElseToken(elseValue: SqlComponent): SqlPrintToken {\r\n // Creates a token for the ELSE clause in a CASE expression.\r\n const elseToken = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ElseClause); // Add the ELSE keyword\r\n elseToken.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'else'));\r\n\r\n // Create a container for the ELSE value to enable proper indentation\r\n elseToken.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n const elseValueContainer = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseElseValue);\r\n elseValueContainer.innerTokens.push(this.visit(elseValue));\r\n elseToken.innerTokens.push(elseValueContainer);\r\n\r\n return elseToken;\r\n }\r\n\r\n private visitCaseKeyValuePair(arg: CaseKeyValuePair): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseKeyValuePair);\r\n\r\n // Create WHEN clause\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'when'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.key)); // Create THEN clause\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'then'));\r\n\r\n // Create a container for the THEN value to enable proper indentation\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n const thenValueContainer = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseThenValue);\r\n thenValueContainer.innerTokens.push(this.visit(arg.value));\r\n token.innerTokens.push(thenValueContainer);\r\n\r\n return token;\r\n }\r\n\r\n private visitRawString(arg: RawString): SqlPrintToken {\r\n // Even for non-container tokens, set the container type for context\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n arg.value,\r\n SqlPrintTokenContainerType.RawString\r\n );\r\n }\r\n\r\n private visitIdentifierString(arg: IdentifierString): SqlPrintToken {\r\n // Create an identifier token and decorate it using the identifierDecorator\r\n const text = arg.name === \"*\" ? arg.name : this.identifierDecorator.decorate(arg.name)\r\n const token = new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n text,\r\n SqlPrintTokenContainerType.IdentifierString\r\n );\r\n return token;\r\n }\r\n\r\n private visitParenExpression(arg: ParenExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ParenExpression);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitCastExpression(arg: CastExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CastExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.input));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, '::'));\r\n token.innerTokens.push(this.visit(arg.castType));\r\n\r\n return token;\r\n }\r\n\r\n private visitCaseExpression(arg: CaseExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CaseExpression);\r\n\r\n // Add the CASE keyword\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'case'));\r\n\r\n // Add the condition if exists\r\n if (arg.condition) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n }\r\n\r\n // Add the WHEN/THEN pairs and ELSE\r\n token.innerTokens.push(this.visit(arg.switchCase));\r\n\r\n // Add the END keyword\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'end'));\r\n\r\n return token;\r\n }\r\n\r\n private visitArrayExpression(arg: ArrayExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ArrayExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'array'));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, '['));\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, ']'));\r\n\r\n return token;\r\n }\r\n\r\n private visitArrayQueryExpression(arg: ArrayQueryExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.ArrayExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'array'));\r\n // ARRAY(SELECT ...)\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, '('));\r\n token.innerTokens.push(this.visit(arg.query));\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.parenthesis, ')'));\r\n\r\n return token;\r\n }\r\n\r\n private visitBetweenExpression(arg: BetweenExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.BetweenExpression);\r\n\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n if (arg.negated) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'not'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'between'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.lower));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'and'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.upper));\r\n\r\n return token;\r\n }\r\n\r\n private visitStringSpecifierExpression(arg: StringSpecifierExpression): SqlPrintToken {\r\n // Combine specifier and value into a single token\r\n const specifier = arg.specifier.accept(this).text;\r\n const value = arg.value.accept(this).text;\r\n return new SqlPrintToken(\r\n SqlPrintTokenType.value,\r\n specifier + value,\r\n SqlPrintTokenContainerType.StringSpecifierExpression\r\n );\r\n }\r\n\r\n private visitTypeValue(arg: TypeValue): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.TypeValue);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n if (arg.argument) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.argument));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitTupleExpression(arg: TupleExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.TupleExpression);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.values.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.values[i]));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitWindowFrameExpression(arg: WindowFrameExpression): SqlPrintToken {\r\n // Compose window frame expression: over(partition by ... order by ... rows ...)\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameExpression);\r\n\r\n let first = true;\r\n if (arg.partition) {\r\n token.innerTokens.push(this.visit(arg.partition));\r\n first = false;\r\n }\r\n if (arg.order) {\r\n if (!first) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n } else {\r\n first = false;\r\n }\r\n token.innerTokens.push(this.visit(arg.order));\r\n }\r\n if (arg.frameSpec) {\r\n if (!first) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n } else {\r\n first = false;\r\n }\r\n token.innerTokens.push(this.visit(arg.frameSpec));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitWindowFrameSpec(arg: WindowFrameSpec): SqlPrintToken {\r\n // This method prints a window frame specification, such as \"rows between ... and ...\" or \"range ...\".\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameSpec);\r\n\r\n // Add frame type (e.g., \"rows\", \"range\", \"groups\")\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.frameType));\r\n\r\n if (arg.endBound === null) {\r\n // Only start bound: e.g., \"rows unbounded preceding\"\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.startBound.accept(this));\r\n } else {\r\n // Between: e.g., \"rows between unbounded preceding and current row\"\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'between'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.startBound.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'and'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.endBound.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Prints a window frame boundary value, such as \"5 preceding\" or \"3 following\".\r\n * @param arg WindowFrameBoundaryValue\r\n */\r\n private visitWindowFrameBoundaryValue(arg: WindowFrameBoundaryValue): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameBoundaryValue);\r\n\r\n token.innerTokens.push(arg.value.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // true for \"FOLLOWING\", false for \"PRECEDING\"\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.isFollowing ? 'following' : 'preceding'));\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * Prints a static window frame bound, such as \"unbounded preceding\", \"current row\", or \"unbounded following\".\r\n * @param arg WindowFrameBoundStatic\r\n */\r\n private visitWindowFrameBoundStatic(arg: WindowFrameBoundStatic): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, arg.bound);\r\n return token;\r\n }\r\n\r\n private visitSelectItem(arg: SelectItem): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SelectItem);\r\n\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n if (!arg.identifier) {\r\n return token;\r\n }\r\n\r\n // No alias needed if it matches the default name\r\n if (arg.value instanceof ColumnReference) {\r\n const defaultName = arg.value.column.name;\r\n if (arg.identifier.name === defaultName) {\r\n return token;\r\n }\r\n }\r\n\r\n // Add alias if it is different from the default name\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.identifier));\r\n return token;\r\n }\r\n\r\n private visitSelectClause(arg: SelectClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'select', SqlPrintTokenContainerType.SelectClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n if (arg.distinct) {\r\n token.keywordTokens = [];\r\n token.keywordTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.keywordTokens.push(arg.distinct.accept(this));\r\n }\r\n\r\n for (let i = 0; i < arg.items.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.items[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitDistinct(arg: Distinct): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'distinct');\r\n return token;\r\n }\r\n\r\n private visitDistinctOn(arg: DistinctOn): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.DistinctOn);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'distinct on'));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(arg.value.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitTableSource(arg: TableSource): SqlPrintToken {\r\n // Print table name with optional namespaces and alias\r\n let fullName = '';\r\n if (Array.isArray(arg.namespaces) && arg.namespaces.length > 0) {\r\n fullName = arg.namespaces.map(ns => ns.accept(this).text).join('.') + '.';\r\n }\r\n fullName += arg.table.accept(this).text;\r\n const token = new SqlPrintToken(SqlPrintTokenType.value, fullName);\r\n // alias (if present and different from table name)\r\n if (arg.identifier && arg.identifier.name !== arg.table.name) {\r\n\r\n }\r\n return token;\r\n }\r\n\r\n private visitSourceExpression(arg: SourceExpression): SqlPrintToken {\r\n // Print source expression (e.g. \"table\", \"table as t\", \"schema.table t\")\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SourceExpression);\r\n token.innerTokens.push(arg.datasource.accept(this));\r\n\r\n if (!arg.aliasExpression) {\r\n return token;\r\n }\r\n\r\n if (arg.datasource instanceof TableSource) {\r\n // No alias needed if it matches the default name\r\n const defaultName = arg.datasource.table.name;\r\n if (arg.aliasExpression.table.name === defaultName) {\r\n return token;\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // exclude column aliases\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n return token;\r\n } else {\r\n // For other source types, just print the alias\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n // included column aliases\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n return token;\r\n }\r\n }\r\n\r\n public visitFromClause(arg: FromClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'from', SqlPrintTokenContainerType.FromClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.source));\r\n\r\n if (arg.joins) {\r\n for (let i = 0; i < arg.joins.length; i++) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.joins[i]));\r\n }\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinClause(arg: JoinClause): SqlPrintToken {\r\n // Print join clause: [joinType] [lateral] [source] [on/using ...]\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinClause);\r\n\r\n // join type (e.g. inner join, left join, etc)\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.joinType.value));\r\n if (arg.lateral) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'lateral'));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.source));\r\n\r\n if (arg.condition) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinOnClause(arg: JoinOnClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinOnClause);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'on'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitJoinUsingClause(arg: JoinUsingClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.JoinUsingClause);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'using'));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitFunctionSource(arg: FunctionSource): SqlPrintToken {\r\n // Print function source: [functionName]([args])\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FunctionSource);\r\n\r\n token.innerTokens.push(arg.qualifiedName.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n if (arg.argument) {\r\n token.innerTokens.push(this.visit(arg.argument));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n return token;\r\n }\r\n\r\n public visitSourceAliasExpression(arg: SourceAliasExpression): SqlPrintToken {\r\n // Print source alias expression: [source] as [alias]\r\n const token = new SqlPrintToken(\r\n SqlPrintTokenType.container,\r\n '',\r\n SqlPrintTokenContainerType.SourceAliasExpression\r\n );\r\n\r\n token.innerTokens.push(this.visit(arg.table));\r\n\r\n if (arg.columns) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.argumentCommaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.columns[i]));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitWhereClause(arg: WhereClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'where', SqlPrintTokenContainerType.WhereClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitGroupByClause(arg: GroupByClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'group by', SqlPrintTokenContainerType.GroupByClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.grouping.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.grouping[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitHavingClause(arg: HavingClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'having', SqlPrintTokenContainerType.HavingClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.condition));\r\n\r\n return token;\r\n }\r\n\r\n public visitWindowClause(arg: WindowClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'window', SqlPrintTokenContainerType.WindowClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.windows.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.windows[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitWindowFrameClause(arg: WindowFrameClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.WindowFrameClause);\r\n\r\n token.innerTokens.push(arg.name.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitLimitClause(arg: LimitClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'limit', SqlPrintTokenContainerType.LimitClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n return token;\r\n }\r\n\r\n public visitOffsetClause(arg: OffsetClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'offset', SqlPrintTokenContainerType.OffsetClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.value));\r\n\r\n return token;\r\n }\r\n\r\n public visitFetchClause(arg: FetchClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'fetch', SqlPrintTokenContainerType.FetchClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.expression));\r\n\r\n return token;\r\n }\r\n\r\n public visitFetchExpression(arg: FetchExpression): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.FetchExpression);\r\n\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.type));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.count.accept(this));\r\n\r\n if (arg.unit) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.unit));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitForClause(arg: ForClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'for', SqlPrintTokenContainerType.ForClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, arg.lockMode));\r\n\r\n return token;\r\n }\r\n\r\n public visitWithClause(arg: WithClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'with', SqlPrintTokenContainerType.WithClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n if (arg.recursive) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'recursive'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n\r\n for (let i = 0; i < arg.tables.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(arg.tables[i].accept(this));\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n return token;\r\n }\r\n\r\n public visitCommonTable(arg: CommonTable): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.CommonTable);\r\n\r\n token.innerTokens.push(arg.aliasExpression.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n if (arg.materialized !== null) {\r\n if (arg.materialized) {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'materialized'));\r\n } else {\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'not materialized'));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const query = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SubQuerySource);\r\n query.innerTokens.push(arg.query.accept(this));\r\n\r\n token.innerTokens.push(query);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n // query\r\n public visitSimpleQuery(arg: SimpleSelectQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SimpleSelectQuery);\r\n\r\n if (arg.withClause) {\r\n token.innerTokens.push(arg.withClause.accept(this));\r\n }\r\n\r\n token.innerTokens.push(arg.selectClause.accept(this));\r\n\r\n if (!arg.fromClause) {\r\n return token;\r\n }\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fromClause.accept(this));\r\n\r\n if (arg.whereClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.whereClause.accept(this));\r\n }\r\n\r\n if (arg.groupByClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.groupByClause.accept(this));\r\n }\r\n\r\n if (arg.havingClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.havingClause.accept(this));\r\n }\r\n\r\n if (arg.orderByClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.orderByClause.accept(this));\r\n }\r\n\r\n if (arg.windowClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.windowClause.accept(this));\r\n }\r\n\r\n if (arg.limitClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.limitClause.accept(this));\r\n }\r\n\r\n if (arg.offsetClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.offsetClause.accept(this));\r\n }\r\n\r\n if (arg.fetchClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fetchClause.accept(this));\r\n }\r\n\r\n if (arg.forClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.forClause.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitSubQuerySource(arg: SubQuerySource): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const subQuery = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SubQuerySource);\r\n subQuery.innerTokens.push(arg.query.accept(this));\r\n\r\n token.innerTokens.push(subQuery);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n public visitValuesQuery(arg: ValuesQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'values', SqlPrintTokenContainerType.ValuesQuery);\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n\r\n const values = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.Values);\r\n for (let i = 0; i < arg.tuples.length; i++) {\r\n if (i > 0) {\r\n values.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n values.innerTokens.push(arg.tuples[i].accept(this));\r\n }\r\n\r\n token.innerTokens.push(values);\r\n return token;\r\n }\r\n\r\n public visitInlineQuery(arg: InlineQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n\r\n const queryToken = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.InlineQuery);\r\n queryToken.innerTokens.push(arg.selectQuery.accept(this));\r\n\r\n token.innerTokens.push(queryToken);\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n\r\n return token;\r\n }\r\n\r\n private visitInsertQuery(arg: InsertQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.InsertQuery);\r\n\r\n // Process the insert clause\r\n token.innerTokens.push(this.visit(arg.insertClause));\r\n\r\n // Process the select query if present\r\n if (arg.selectQuery) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(this.visit(arg.selectQuery));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitInsertClause(arg: InsertClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '');\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'insert into'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.source.accept(this));\r\n\r\n if (arg.columns.length > 0) {\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(arg.columns[i].accept(this));\r\n }\r\n token.innerTokens.push(SqlPrintTokenParser.PAREN_CLOSE_TOKEN);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private visitUpdateQuery(arg: UpdateQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.UpdateQuery);\r\n\r\n if (arg.withClause) {\r\n token.innerTokens.push(arg.withClause.accept(this));\r\n }\r\n\r\n token.innerTokens.push(arg.updateClause.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.setClause.accept(this));\r\n\r\n if (arg.fromClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.fromClause.accept(this));\r\n }\r\n\r\n if (arg.whereClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.whereClause.accept(this));\r\n }\r\n\r\n if (arg.returningClause) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.returningClause.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitUpdateClause(arg: UpdateClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'update', SqlPrintTokenContainerType.UpdateClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.source.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n public visitSetClause(arg: SetClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'set', SqlPrintTokenContainerType.SelectClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.items.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.items[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitSetClauseItem(arg: SetClauseItem): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.container, '', SqlPrintTokenContainerType.SetClauseItem);\r\n\r\n token.innerTokens.push(arg.column.accept(this));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.operator, '='));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.value.accept(this));\r\n\r\n return token;\r\n }\r\n\r\n public visitReturningClause(arg: ReturningClause): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, 'returning', SqlPrintTokenContainerType.ReturningClause);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n for (let i = 0; i < arg.columns.length; i++) {\r\n if (i > 0) {\r\n token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());\r\n }\r\n token.innerTokens.push(this.visit(arg.columns[i]));\r\n }\r\n\r\n return token;\r\n }\r\n\r\n public visitCreateTableQuery(arg: CreateTableQuery): SqlPrintToken {\r\n const token = new SqlPrintToken(SqlPrintTokenType.keyword, arg.isTemporary ? 'create temporary table' : 'create table', SqlPrintTokenContainerType.CreateTableQuery);\r\n\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.tableName.accept(this));\r\n\r\n if (arg.asSelectQuery) {\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(new SqlPrintToken(SqlPrintTokenType.keyword, 'as'));\r\n token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);\r\n token.innerTokens.push(arg.asSelectQuery.accept(this));\r\n }\r\n\r\n return token;\r\n }\r\n}\r\n", "// Define the allowed newline options\r\nexport type NewlineOption = ' ' | '\\n' | '\\r\\n';\r\n\r\n// Define the allowed indent character options\r\nexport type IndentCharOption = '' | ' ' | '\\t';\r\n\r\n/**\r\n * SqlPrintHelper provides utility methods for SQL pretty printing.\r\n */\r\nexport class LinePrinter {\r\n indentChar: IndentCharOption; // Changed type to IndentCharOption\r\n indentSize: number;\r\n newline: NewlineOption; // Changed type to NewlineOption\r\n lines: PrintLine[];\r\n /**\r\n * @param indentChar Character used for indentation (default: ' ') // Updated comment to reflect options\r\n * @param indentSize Number of indentChar per level (default: 0)\r\n * @param newline Newline string (default: '\\r\\n') // Changed type and default value\r\n */\r\n constructor(indentChar: IndentCharOption = ' ', indentSize: number = 0, newline: NewlineOption = '\\r\\n') { // Changed type for indentChar\r\n this.indentChar = indentChar;\r\n this.indentSize = indentSize;\r\n this.newline = newline;\r\n this.lines = [];\r\n this.appendNewline(0);\r\n }\r\n\r\n public print(): string {\r\n let result = '';\r\n for (const line of this.lines) {\r\n if (line.text !== '') {\r\n // append indent and text\r\n result += this.indent(line.level) + line.text;\r\n }\r\n }\r\n return result.trimEnd();\r\n }\r\n\r\n /**\r\n * Returns the indent string for a given level.\r\n * @param level Indentation level\r\n */\r\n private indent(level: number): string {\r\n return this.indentChar.repeat(this.indentSize * level);\r\n }\r\n\r\n /**\r\n * Appends a newline token to the given tokens array if newline is set, or adds an empty line if tokens is empty.\r\n * @param tokens Array of token objects with 'level' and 'text' property\r\n * @param level Indentation level\r\n */\r\n appendNewline(level: number): void {\r\n if (this.lines.length > 0) {\r\n const current = this.lines[this.lines.length - 1];\r\n if (current.text !== '') {\r\n current.text = current.text.trimEnd() + this.newline;\r\n }\r\n }\r\n this.lines.push(new PrintLine(level, ''));\r\n }\r\n\r\n /**\r\n * Appends text to the last element of tokens array.\r\n * @param tokens Array of token objects with 'text' property\r\n * @param text Text to append\r\n */\r\n appendText(text: string): void {\r\n if (this.lines.length > 0) {\r\n const workingIndex = this.lines.length - 1;\r\n const workLine = this.lines[workingIndex]\r\n // Leading space is not needed\r\n if (!(text === ' ' && workLine.text === '')) {\r\n workLine.text += text;\r\n }\r\n } else {\r\n throw new Error('No tokens to append to.');\r\n }\r\n }\r\n\r\n getCurrentLine(): PrintLine {\r\n if (this.lines.length > 0) {\r\n return this.lines[this.lines.length - 1];\r\n } else {\r\n throw new Error('No tokens to get current line from.');\r\n }\r\n }\r\n}\r\n\r\nexport class PrintLine {\r\n level: number;\r\n text: string;\r\n\r\n constructor(level: number, text: string) {\r\n this.level = level;\r\n this.text = text;\r\n }\r\n}", "import { SqlPrintToken, SqlPrintTokenType, SqlPrintTokenContainerType } from \"../models/SqlPrintToken\";\r\nimport { IndentCharOption, LinePrinter, NewlineOption } from \"./LinePrinter\";\r\n\r\n/**\r\n * CommaBreakStyle determines how commas are placed in formatted SQL output.\r\n * - 'none': No line break for commas\r\n * - 'before': Line break before comma\r\n * - 'after': Line break after comma\r\n */\r\nexport type CommaBreakStyle = 'none' | 'before' | 'after';\r\n\r\n/**\r\n * AndBreakStyle determines how AND operators are placed in formatted SQL output.\r\n * - 'none': No line break for AND\r\n * - 'before': Line break before AND\r\n * - 'after': Line break after AND\r\n */\r\nexport type AndBreakStyle = 'none' | 'before' | 'after';\r\n\r\n/**\r\n * SqlPrinter formats a SqlPrintToken tree into a SQL string with flexible style options.\r\n */\r\nexport class SqlPrinter {\r\n /** Indent character (e.g., ' ' or '\\\\t') */\r\n indentChar: IndentCharOption; // Changed type from string\r\n /** Indent size (number of indentChar repetitions per level) */\r\n indentSize: number;\r\n /** Newline character (e.g., '\\\\n' or '\\\\r\\\\n') */\r\n newline: NewlineOption; // Changed type from string\r\n /** Comma break style: 'none', 'before', or 'after' */\r\n commaBreak: CommaBreakStyle;\r\n /** AND break style: 'none', 'before', or 'after' */\r\n andBreak: AndBreakStyle;\r\n\r\n /** Keyword case style: 'none', 'upper' | 'lower' */\r\n keywordCase: 'none' | 'upper' | 'lower';\r\n\r\n private linePrinter: LinePrinter;\r\n private indentIncrementContainers: Set<SqlPrintTokenContainerType>;\r\n\r\n /**\r\n * @param options Optional style settings for pretty printing\r\n */\r\n constructor(options?: {\r\n indentChar?: IndentCharOption;\r\n indentSize?: number;\r\n newline?: NewlineOption;\r\n commaBreak?: CommaBreakStyle;\r\n andBreak?: AndBreakStyle;\r\n keywordCase?: 'none' | 'upper' | 'lower';\r\n indentIncrementContainerTypes?: string[]; // Option to customize\r\n }) {\r\n this.indentChar = options?.indentChar ?? '';\r\n this.indentSize = options?.indentSize ?? 0;\r\n\r\n // The default newline character is set to a blank space (' ') to enable one-liner formatting.\r\n // This is intentional and differs from the LinePrinter default of '\\r\\n'.\r\n this.newline = options?.newline ?? ' ';\r\n\r\n this.commaBreak = options?.commaBreak ?? 'none';\r\n this.andBreak = options?.andBreak ?? 'none';\r\n this.keywordCase = options?.keywordCase ?? 'none';\r\n this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline);\r\n\r\n // Initialize\r\n this.indentIncrementContainers = new Set(\r\n (options?.indentIncrementContainerTypes as SqlPrintTokenContainerType[] | undefined) ?? [\r\n SqlPrintTokenContainerType.SelectClause,\r\n SqlPrintTokenContainerType.FromClause,\r\n SqlPrintTokenContainerType.WhereClause,\r\n SqlPrintTokenContainerType.GroupByClause,\r\n SqlPrintTokenContainerType.HavingClause,\r\n SqlPrintTokenContainerType.WindowFrameExpression,\r\n SqlPrintTokenContainerType.PartitionByClause,\r\n SqlPrintTokenContainerType.OrderByClause,\r\n SqlPrintTokenContainerType.WindowClause,\r\n SqlPrintTokenContainerType.LimitClause,\r\n SqlPrintTokenContainerType.OffsetClause,\r\n SqlPrintTokenContainerType.SubQuerySource,\r\n SqlPrintTokenContainerType.BinarySelectQueryOperator, SqlPrintTokenContainerType.Values,\r\n SqlPrintTokenContainerType.WithClause,\r\n SqlPrintTokenContainerType.SwitchCaseArgument,\r\n SqlPrintTokenContainerType.CaseKeyValuePair,\r\n SqlPrintTokenContainerType.CaseThenValue,\r\n SqlPrintTokenContainerType.ElseClause,\r\n SqlPrintTokenContainerType.CaseElseValue\r\n // CaseExpression, SwitchCaseArgument, CaseKeyValuePair, and ElseClause\r\n // are not included by default to maintain backward compatibility with tests\r\n //SqlPrintTokenContainerType.CommonTable\r\n ]\r\n );\r\n }\r\n\r\n /**\r\n * Converts a SqlPrintToken tree to a formatted SQL string.\r\n * @param token The root SqlPrintToken\r\n * @param level Indentation level (default: 0)\r\n */\r\n print(token: SqlPrintToken, level: number = 0): string {\r\n // initialize\r\n this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline);\r\n if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {\r\n this.linePrinter.lines[0].level = level;\r\n }\r\n\r\n this.appendToken(token, level);\r\n\r\n return this.linePrinter.print();\r\n }\r\n\r\n private appendToken(token: SqlPrintToken, level: number) {\r\n if (!token.innerTokens || token.innerTokens.length === 0) {\r\n if (token.text === '') {\r\n return;\r\n }\r\n }\r\n\r\n const current = this.linePrinter.getCurrentLine();\r\n\r\n if (token.type === SqlPrintTokenType.keyword) {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n this.linePrinter.appendText(text);\r\n } else if (token.type === SqlPrintTokenType.comma) {\r\n let text = token.text;\r\n if (this.commaBreak === 'before') {\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else if (this.commaBreak === 'after') {\r\n this.linePrinter.appendText(text);\r\n this.linePrinter.appendNewline(level);\r\n } else {\r\n this.linePrinter.appendText(text);\r\n }\r\n } else if (token.type === SqlPrintTokenType.operator && token.text.toLowerCase() === 'and') {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n\r\n if (this.andBreak === 'before') {\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else if (this.andBreak === 'after') {\r\n this.linePrinter.appendText(text);\r\n this.linePrinter.appendNewline(level);\r\n } else {\r\n this.linePrinter.appendText(text);\r\n }\r\n } else if (token.containerType === \"JoinClause\") {\r\n let text = token.text;\r\n if (this.keywordCase === 'upper') {\r\n text = text.toUpperCase();\r\n } else if (this.keywordCase === 'lower') {\r\n text = text.toLowerCase();\r\n }\r\n // before join clause, add newline\r\n this.linePrinter.appendNewline(level);\r\n this.linePrinter.appendText(text);\r\n } else {\r\n this.linePrinter.appendText(token.text);\r\n }\r\n\r\n // append keyword tokens(not indented)\r\n if (token.keywordTokens && token.keywordTokens.length > 0) {\r\n for (let i = 0; i < token.keywordTokens.length; i++) {\r\n const keywordToken = token.keywordTokens[i];\r\n this.appendToken(keywordToken, level);\r\n }\r\n }\r\n\r\n let innerLevel = level;\r\n\r\n // indent level up\r\n if (this.newline !== ' ' && current.text !== '' && this.indentIncrementContainers.has(token.containerType)) { // Changed condition\r\n innerLevel++;\r\n this.linePrinter.appendNewline(innerLevel);\r\n }\r\n\r\n for (let i = 0; i < token.innerTokens.length; i++) {\r\n const child = token.innerTokens[i];\r\n this.appendToken(child, innerLevel);\r\n }\r\n\r\n // indent level down\r\n if (innerLevel !== level) {\r\n this.linePrinter.appendNewline(level);\r\n }\r\n }\r\n}", "import { SqlPrintTokenParser, FormatterConfig, PRESETS } from '../parsers/SqlPrintTokenParser';\r\nimport { SqlPrinter, CommaBreakStyle, AndBreakStyle } from './SqlPrinter';\r\nimport { IndentCharOption, NewlineOption } from './LinePrinter'; // Import types for compatibility\r\nimport { SelectQuery } from '../models/SelectQuery';\r\nimport { SqlComponent } from '../models/SqlComponent';\r\n\r\n// Define valid preset names as a union type\r\nexport const VALID_PRESETS = ['mysql', 'postgres', 'sqlserver', 'sqlite'] as const;\r\nexport type PresetName = (typeof VALID_PRESETS)[number];\r\n\r\n/**\r\n * SqlFormatter class combines parsing and printing of SQL queries into a single interface.\r\n */\r\nexport class SqlFormatter {\r\n private parser: SqlPrintTokenParser;\r\n private printer: SqlPrinter;\r\n\r\n constructor(options: {\r\n preset?: PresetName; // Restrict preset to specific strings\r\n identifierEscape?: { start: string; end: string }; // Allow custom identifier escape\r\n parameterSymbol?: string | { start: string; end: string }; // Allow custom parameter symbol\r\n parameterStyle?: 'anonymous' | 'indexed' | 'named'; // Allow custom parameter style\r\n indentSize?: number;\r\n indentChar?: IndentCharOption; // Updated type\r\n newline?: NewlineOption; // Updated type\r\n keywordCase?: 'none' | 'upper' | 'lower'; // Updated type\r\n commaBreak?: CommaBreakStyle; // Updated type\r\n andBreak?: AndBreakStyle; // Updated type\r\n } = {}) { // Default to 'sqlserver' if options is empty\r\n\r\n const presetConfig = options.preset ? PRESETS[options.preset] : undefined;\r\n\r\n if (options.preset && !presetConfig) {\r\n throw new Error(`Invalid preset: ${options.preset}`); // Throw error for invalid preset\r\n }\r\n\r\n const parserOptions = {\r\n ...presetConfig, // Apply preset configuration\r\n identifierEscape: options.identifierEscape ?? presetConfig?.identifierEscape,\r\n parameterSymbol: options.parameterSymbol ?? presetConfig?.parameterSymbol,\r\n parameterStyle: options.parameterStyle ?? presetConfig?.parameterStyle,\r\n };\r\n\r\n this.parser = new SqlPrintTokenParser(parserOptions);\r\n this.printer = new SqlPrinter(options);\r\n }\r\n\r\n /**\r\n * Formats a SQL query string with the given parameters.\r\n * @param sqlText The SQL query string to format.\r\n * @param parameters A dictionary of parameters to replace in the query.\r\n * @returns An object containing the formatted SQL string and the parameters.\r\n */\r\n format(sql: SqlComponent): { formattedSql: string; params: Record<string, any> } {\r\n const { token, params } = this.parser.parse(sql);\r\n const formattedSql = this.printer.print(token);\r\n\r\n return { formattedSql, params };\r\n }\r\n}\r\n", "import { SqlFormatter } from './SqlFormatter';\r\nimport { SelectQuery } from '../models/SelectQuery';\r\nimport { SqlComponent, SqlComponentVisitor } from '../models/SqlComponent';\r\nimport { FormatterConfig } from '../parsers/SqlPrintTokenParser';\r\n\r\n/**\r\n * @deprecated The Formatter class is deprecated. Use SqlFormatter instead.\r\n */\r\nexport class Formatter implements SqlComponentVisitor<string> {\r\n private sqlFormatter: SqlFormatter;\r\n\r\n constructor() {\r\n this.sqlFormatter = new SqlFormatter({\r\n identifierEscape: { start: '\"', end: '\"' },\r\n parameterSymbol: ':',\r\n parameterStyle: 'named' // Default to 'named' for backward compatibility\r\n });\r\n }\r\n\r\n public format(arg: SqlComponent, config: FormatterConfig | null = null): string {\r\n // Use the sqlFormatter instance to format the SQL component\r\n if (config) {\r\n this.sqlFormatter = new SqlFormatter(config);\r\n }\r\n const result = this.sqlFormatter.format(arg);\r\n return result.formattedSql;\r\n }\r\n\r\n public formatWithParameters(arg: SqlComponent, config: FormatterConfig | null = null): { sql: string, params: any[] | Record<string, any>[] | Record<string, any> } {\r\n // Use the sqlFormatter instance to format the SQL component with parameters\r\n if (config) {\r\n this.sqlFormatter = new SqlFormatter(config);\r\n }\r\n const result = this.sqlFormatter.format(arg);\r\n return { sql: result.formattedSql, params: result.params };\r\n }\r\n\r\n public visit(arg: SqlComponent): string {\r\n return this.format(arg);\r\n }\r\n}\r\n\r\nexport { SqlFormatter };", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableSourceCollector } from \"./TableSourceCollector\";\r\nimport { Formatter } from \"./Formatter\";\r\n\r\n/**\r\n * CTENameConflictResolver is responsible for resolving name conflicts among Common Table Expressions (CTEs).\r\n * It also sorts the tables in the proper order based on dependencies and recursiveness.\r\n */\r\nexport class CTEBuilder {\r\n private sourceCollector: TableSourceCollector;\r\n private cteCollector: CTECollector;\r\n private formatter: Formatter;\r\n\r\n constructor() {\r\n this.sourceCollector = new TableSourceCollector(true);\r\n this.cteCollector = new CTECollector();\r\n this.formatter = new Formatter();\r\n }\r\n\r\n /**\r\n * Resolves name conflicts among CommonTables.\r\n * If there are duplicate CTE names, they must have identical definitions.\r\n * Also sorts the tables so that:\r\n * 1. Recursive CTEs come first (CTEs that reference themselves)\r\n * 2. Then remaining tables are sorted so inner (deeper) CTEs come before outer CTEs\r\n * \r\n * @param commonTables The list of CommonTables to check for name conflicts\r\n * @returns An object containing:\r\n * - needRecursive: boolean indicating if any recursive CTEs are present\r\n * - commonTables: A new list of CommonTables with resolved name conflicts and proper order\r\n * @throws Error if there are duplicate CTE names with different definitions\r\n */\r\n public build(commonTables: CommonTable[]): WithClause {\r\n // Early return for empty CTEs\r\n // Note:\r\n // Although it may seem reasonable to return early when there is only one element,\r\n // the 'recursive' property is determined dynamically. Therefore, if there is at least one element,\r\n // the CTEs must be rebuilt to ensure correct recursive detection.\r\n if (commonTables.length === 0) {\r\n return new WithClause(\r\n false,\r\n commonTables\r\n );\r\n }\r\n\r\n // Step 1: Resolve name conflicts\r\n const resolvedTables = this.resolveDuplicateNames(commonTables);\r\n\r\n // Step 2: Identify recursive CTEs and build dependency graph\r\n const { tableMap, recursiveCTEs, dependencies } = this.buildDependencyGraph(resolvedTables);\r\n\r\n // Step 3: Sort tables according to dependencies and recursiveness\r\n const sortedTables = this.sortCommonTables(resolvedTables, tableMap, recursiveCTEs, dependencies);\r\n\r\n return new WithClause(\r\n recursiveCTEs.size > 0,\r\n sortedTables\r\n );\r\n }\r\n\r\n /**\r\n * Resolves duplicate CTE names by checking if they have identical definitions.\r\n * If definitions differ, throws an error.\r\n * \r\n * @param commonTables The list of CTEs to check for duplicates\r\n * @returns A list of CTEs with duplicates removed\r\n * @throws Error if there are duplicate CTE names with different definitions\r\n */\r\n private resolveDuplicateNames(commonTables: CommonTable[]): CommonTable[] {\r\n // Group CTEs by their names\r\n const ctesByName = new Map<string, CommonTable[]>();\r\n for (const table of commonTables) {\r\n const tableName = table.aliasExpression.table.name;\r\n if (!ctesByName.has(tableName)) {\r\n ctesByName.set(tableName, []);\r\n }\r\n ctesByName.get(tableName)!.push(table);\r\n }\r\n\r\n // Resolve name duplications\r\n const resolvedTables: CommonTable[] = [];\r\n for (const [name, tables] of ctesByName.entries()) {\r\n if (tables.length === 1) {\r\n // No duplication\r\n resolvedTables.push(tables[0]);\r\n continue;\r\n }\r\n\r\n // For duplicate names, check if definitions are identical\r\n const definitions = tables.map(table => this.formatter.format(table.query));\r\n const uniqueDefinitions = new Set(definitions);\r\n\r\n if (uniqueDefinitions.size === 1) {\r\n // If all definitions are identical, use only the first one\r\n resolvedTables.push(tables[0]);\r\n } else {\r\n // Error if definitions differ\r\n throw new Error(`CTE name conflict detected: '${name}' has multiple different definitions`);\r\n }\r\n }\r\n\r\n return resolvedTables;\r\n }\r\n\r\n /**\r\n * Builds a dependency graph of CTEs and identifies recursive CTEs.\r\n * \r\n * @param tables The list of CTEs to analyze\r\n * @returns Object containing the table map, set of recursive CTEs, and dependency map\r\n */\r\n private buildDependencyGraph(tables: CommonTable[]): {\r\n tableMap: Map<string, CommonTable>,\r\n recursiveCTEs: Set<string>,\r\n dependencies: Map<string, Set<string>>\r\n } {\r\n // Create a map of table names for quick lookup\r\n const tableMap = new Map<string, CommonTable>();\r\n for (const table of tables) {\r\n tableMap.set(table.aliasExpression.table.name, table);\r\n }\r\n\r\n // Identify recursive CTEs (those that reference themselves)\r\n const recursiveCTEs = new Set<string>();\r\n\r\n // Build dependency graph: which tables reference which other tables\r\n const dependencies = new Map<string, Set<string>>();\r\n const referencedBy = new Map<string, Set<string>>();\r\n\r\n for (const table of tables) {\r\n const tableName = table.aliasExpression.table.name;\r\n\r\n // Check for self-references (recursive CTEs)\r\n const referencedTables = this.sourceCollector.collect(table.query);\r\n\r\n // Check if this CTE references itself\r\n for (const referencedTable of referencedTables) {\r\n if (referencedTable.table.name === tableName) {\r\n recursiveCTEs.add(tableName);\r\n break;\r\n }\r\n }\r\n\r\n // Setup dependencies\r\n if (!dependencies.has(tableName)) {\r\n dependencies.set(tableName, new Set<string>());\r\n }\r\n\r\n // Find any references to other CTEs in this table's query\r\n const referencedCTEs = this.cteCollector.collect(table.query);\r\n\r\n for (const referencedCTE of referencedCTEs) {\r\n const referencedName = referencedCTE.aliasExpression.table.name;\r\n\r\n // Only consider references to tables in our collection\r\n if (tableMap.has(referencedName)) {\r\n dependencies.get(tableName)!.add(referencedName);\r\n\r\n // Add the reverse relationship\r\n if (!referencedBy.has(referencedName)) {\r\n referencedBy.set(referencedName, new Set<string>());\r\n }\r\n referencedBy.get(referencedName)!.add(tableName);\r\n }\r\n }\r\n }\r\n\r\n return { tableMap, recursiveCTEs, dependencies };\r\n }\r\n\r\n /**\r\n * Sorts the CTEs using topological sort, with recursive CTEs coming first.\r\n * \r\n * @param tables The list of CTEs to sort\r\n * @param tableMap Map of table names to their CommonTable objects\r\n * @param recursiveCTEs Set of table names that are recursive (self-referential)\r\n * @param dependencies Map of table dependencies\r\n * @returns Sorted list of CTEs\r\n * @throws Error if a circular reference is detected\r\n */\r\n private sortCommonTables(\r\n tables: CommonTable[],\r\n tableMap: Map<string, CommonTable>,\r\n recursiveCTEs: Set<string>,\r\n dependencies: Map<string, Set<string>>\r\n ): CommonTable[] {\r\n const recursiveResult: CommonTable[] = [];\r\n const nonRecursiveResult: CommonTable[] = [];\r\n const visited = new Set<string>();\r\n const visiting = new Set<string>();\r\n\r\n // Topological sort function\r\n const visit = (tableName: string) => {\r\n if (visited.has(tableName)) return;\r\n if (visiting.has(tableName)) {\r\n throw new Error(`Circular reference detected in CTE: ${tableName}`);\r\n }\r\n\r\n visiting.add(tableName);\r\n\r\n // Process dependencies first (inner CTEs)\r\n const deps = dependencies.get(tableName) || new Set<string>();\r\n for (const dep of deps) {\r\n visit(dep);\r\n }\r\n\r\n visiting.delete(tableName);\r\n visited.add(tableName);\r\n\r\n // Add this table after its dependencies\r\n // Recursive CTEs go to recursiveResult, others to nonRecursiveResult\r\n if (recursiveCTEs.has(tableName)) {\r\n recursiveResult.push(tableMap.get(tableName)!);\r\n } else {\r\n nonRecursiveResult.push(tableMap.get(tableName)!);\r\n }\r\n };\r\n\r\n // Process all tables\r\n for (const table of tables) {\r\n const tableName = table.aliasExpression.table.name;\r\n if (!visited.has(tableName)) {\r\n visit(tableName);\r\n }\r\n }\r\n\r\n // Combine the results: recursive CTEs first, then non-recursive CTEs\r\n return [...recursiveResult, ...nonRecursiveResult];\r\n }\r\n}\r\n", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { CTEBuilder } from \"./CTEBuilder\";\r\n\r\n/**\r\n * CTEInjector accepts a SelectQuery object and an array of CommonTables,\r\n * and inserts Common Table Expressions into the query.\r\n * For BinarySelectQuery, CTEs are inserted into the left query.\r\n * \r\n * Uses CTENameConflictResolver to resolve naming conflicts between CTEs.\r\n */\r\nexport class CTEInjector {\r\n private nameConflictResolver: CTEBuilder;\r\n private cteCollector: CTECollector;\r\n\r\n constructor() {\r\n this.nameConflictResolver = new CTEBuilder();\r\n this.cteCollector = new CTECollector();\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into a SelectQuery object.\r\n * \r\n * @param query The query to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @returns A new query with the injected CTEs\r\n */\r\n public inject(query: SelectQuery, commonTables: CommonTable[]): SelectQuery {\r\n // If the array is empty, return the query as is\r\n if (commonTables.length === 0) {\r\n return query;\r\n }\r\n\r\n // Collect CTEs from the query\r\n commonTables.push(...this.cteCollector.collect(query));\r\n\r\n // Use CTENameConflictResolver to resolve duplicates and sort in appropriate order\r\n const resolvedWithCaluse = this.nameConflictResolver.build(commonTables);\r\n\r\n // Process based on query type\r\n if (query instanceof SimpleSelectQuery) {\r\n return this.injectIntoSimpleQuery(query, resolvedWithCaluse);\r\n } else if (query instanceof BinarySelectQuery) {\r\n return this.injectIntoBinaryQuery(query, resolvedWithCaluse);\r\n }\r\n\r\n // Unsupported query type\r\n throw new Error(\"Unsupported query type\");\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into a SimpleSelectQuery.\r\n * \r\n * @param query The SimpleSelectQuery to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @param needRecursive Boolean indicating if recursive WITH clause is needed\r\n * @returns A new SimpleSelectQuery with the injected CTEs\r\n */\r\n private injectIntoSimpleQuery(query: SimpleSelectQuery, withClause: WithClause): SimpleSelectQuery {\r\n if (query.withClause) {\r\n throw new Error(\"The query already has a WITH clause. Please remove it before injecting new CTEs.\");\r\n }\r\n // If the query doesn't have a WITH clause, set the new one\r\n query.withClause = withClause;\r\n return query;\r\n }\r\n\r\n /**\r\n * Inserts Common Table Expressions into the left query of a BinarySelectQuery.\r\n * \r\n * @param query The BinarySelectQuery to inject CTEs into\r\n * @param commonTables Array of CommonTables to be inserted\r\n * @param needRecursive Boolean indicating if recursive WITH clause is needed\r\n * @returns A new BinarySelectQuery with the injected CTEs\r\n */\r\n private injectIntoBinaryQuery(query: BinarySelectQuery, withClause: WithClause): BinarySelectQuery {\r\n // Insert CTEs into the left query\r\n if (query.left instanceof SimpleSelectQuery) {\r\n this.injectIntoSimpleQuery(query.left, withClause);\r\n return query;\r\n } else if (query.left instanceof BinarySelectQuery) {\r\n this.injectIntoBinaryQuery(query.left, withClause);\r\n return query;\r\n }\r\n throw new Error(\"Unsupported query type for BinarySelectQuery left side\");\r\n }\r\n}\r\n", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { TableSourceCollector } from \"./TableSourceCollector\";\r\nimport { CTEDisabler } from \"./CTEDisabler\";\r\nimport { Formatter } from \"./Formatter\";\r\nimport { CTEBuilder } from \"./CTEBuilder\";\r\nimport { CTEInjector } from \"./CTEInjector\";\r\n\r\n/**\r\n * CTENormalizer is responsible for normalizing Common Table Expressions (CTEs) within SQL queries.\r\n * It collects all CTEs from various parts of the query and consolidates them into a single WITH clause\r\n * at the root level of the query.\r\n * \r\n * This implementation uses:\r\n * 1. CommonTableCollector - to gather all CTEs from the query structure\r\n * 2. WithClauseDisabler - to remove all original WITH clauses from the query\r\n * 3. CTENameConflictResolver - to resolve name conflicts among CTEs and sort them properly\r\n */\r\nexport class CTENormalizer {\r\n /**\r\n * Private constructor to prevent instantiation of this utility class.\r\n */\r\n private constructor() {\r\n // This class is not meant to be instantiated.\r\n }\r\n /**\r\n * Normalizes a SQL query by consolidating all CTEs into a single WITH clause\r\n * at the root level of the query.\r\n * \r\n * @param query The query to normalize\r\n * @returns A new normalized query with all CTEs at the root level\r\n */\r\n public static normalize(query: SelectQuery): SelectQuery {\r\n // No need to normalize if the query doesn't have any CTEs\r\n const cteCollector = new CTECollector();\r\n const allCommonTables = cteCollector.collect(query);\r\n\r\n if (allCommonTables.length === 0) {\r\n return query;\r\n }\r\n\r\n // Remove all WITH clauses from the original query\r\n const cteDisabler = new CTEDisabler();\r\n cteDisabler.execute(query);\r\n\r\n const injector = new CTEInjector();\r\n return injector.inject(query, allCommonTables);\r\n }\r\n}", "/**\r\n * Enum for duplicate detection modes in SelectableColumnCollector.\r\n * Determines how duplicates are identified during column collection.\r\n */\r\nexport enum DuplicateDetectionMode {\r\n /**\r\n * Detect duplicates based only on column names.\r\n * This mode ignores the table name, so columns with the same name\r\n * from different tables are considered duplicates.\r\n */\r\n ColumnNameOnly = 'columnNameOnly',\r\n /**\r\n * Detect duplicates based on both table and column names.\r\n * This mode ensures that columns with the same name from different\r\n * tables are treated as distinct.\r\n */\r\n FullName = 'fullName',\r\n}\r\nimport { CommonTable, ForClause, FromClause, GroupByClause, HavingClause, LimitClause, OrderByClause, SelectClause, WhereClause, WindowFrameClause, WindowsClause, JoinClause, JoinOnClause, JoinUsingClause, TableSource, SubQuerySource, SourceExpression, SelectItem, PartitionByClause, FetchClause, OffsetClause } from \"../models/Clause\";\r\nimport { SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SqlComponent, SqlComponentVisitor } from \"../models/SqlComponent\";\r\nimport { ArrayExpression, ArrayQueryExpression, BetweenExpression, BinaryExpression, CaseExpression, CastExpression, ColumnReference, FunctionCall, InlineQuery, ParenExpression, UnaryExpression, ValueComponent, ValueList, WindowFrameExpression } from \"../models/ValueComponent\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { SelectValueCollector } from \"./SelectValueCollector\";\r\nimport { TableColumnResolver } from \"./TableColumnResolver\";\r\n\r\n/**\r\n * A visitor that collects all ColumnReference instances from a SQL query structure.\r\n * This visitor scans through all clauses and collects all unique ColumnReference objects.\r\n * It does not scan Common Table Expressions (CTEs) or subqueries.\r\n * \r\n * Important: Only collects column references to tables defined in the root FROM/JOIN clauses,\r\n * as these are the only columns that can be directly referenced in the query.\r\n */\r\nexport class SelectableColumnCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n private selectValues: { name: string, value: ValueComponent }[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private isRootVisit: boolean = true;\r\n private tableColumnResolver: TableColumnResolver | null = null;\r\n private commonTableCollector: CTECollector;\r\n private commonTables: CommonTable[] = [];\r\n private includeWildCard: boolean; // This option controls whether wildcard columns are included in the collection.\r\n private duplicateDetection: DuplicateDetectionMode;\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n\r\n /**\r\n * Creates a new instance of SelectableColumnCollector.\r\n *\r\n * @param {TableColumnResolver | null} [tableColumnResolver=null] - The resolver used to resolve column references to their respective tables.\r\n * @param {boolean} [includeWildCard=false] - If true, wildcard columns (e.g., `*`) are included in the collection.\r\n * @param {DuplicateDetectionMode} [duplicateDetection=DuplicateDetectionMode.ColumnNameOnly] - Specifies the duplicate detection mode: 'columnNameOnly' (default, only column name is used), or 'fullName' (table name + column name).\r\n * @param {Object} [options={}] - Additional options for the collector.\r\n * @param {boolean} [options.ignoreCaseAndUnderscore=false] - If true, column names are compared without considering case and underscores.\r\n */\r\n constructor(\r\n tableColumnResolver?: TableColumnResolver | null,\r\n includeWildCard: boolean = false,\r\n duplicateDetection: DuplicateDetectionMode = DuplicateDetectionMode.ColumnNameOnly,\r\n options?: { ignoreCaseAndUnderscore?: boolean }\r\n ) {\r\n this.tableColumnResolver = tableColumnResolver ?? null;\r\n this.includeWildCard = includeWildCard;\r\n this.commonTableCollector = new CTECollector();\r\n this.commonTables = [];\r\n this.duplicateDetection = duplicateDetection;\r\n this.options = options || {};\r\n\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Main entry point is the SimpleSelectQuery\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n\r\n // Handlers for each clause type that might contain column references\r\n this.handlers.set(SelectClause.kind, (expr) => this.visitSelectClause(expr as SelectClause));\r\n this.handlers.set(FromClause.kind, (expr) => this.visitFromClause(expr as FromClause));\r\n this.handlers.set(WhereClause.kind, (expr) => this.visitWhereClause(expr as WhereClause));\r\n this.handlers.set(GroupByClause.kind, (expr) => this.visitGroupByClause(expr as GroupByClause));\r\n this.handlers.set(HavingClause.kind, (expr) => this.visitHavingClause(expr as HavingClause));\r\n this.handlers.set(OrderByClause.kind, (expr) => this.visitOrderByClause(expr as OrderByClause));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(LimitClause.kind, (expr) => this.visitLimitClause(expr as LimitClause));\r\n this.handlers.set(OffsetClause.kind, (expr) => this.offsetClause(expr as OffsetClause));\r\n this.handlers.set(FetchClause.kind, (expr) => this.visitFetchClause(expr as FetchClause));\r\n\r\n // Add handlers for JOIN conditions\r\n this.handlers.set(JoinOnClause.kind, (expr) => this.visitJoinOnClause(expr as JoinOnClause));\r\n this.handlers.set(JoinUsingClause.kind, (expr) => this.visitJoinUsingClause(expr as JoinUsingClause));\r\n\r\n // For value components that might contain column references\r\n this.handlers.set(ColumnReference.kind, (expr) => this.visitColumnReference(expr as ColumnReference));\r\n this.handlers.set(BinaryExpression.kind, (expr) => this.visitBinaryExpression(expr as BinaryExpression));\r\n this.handlers.set(UnaryExpression.kind, (expr) => this.visitUnaryExpression(expr as UnaryExpression));\r\n this.handlers.set(FunctionCall.kind, (expr) => this.visitFunctionCall(expr as FunctionCall));\r\n this.handlers.set(ParenExpression.kind, (expr) => this.visitParenExpression(expr as ParenExpression));\r\n this.handlers.set(CaseExpression.kind, (expr) => this.visitCaseExpression(expr as CaseExpression));\r\n this.handlers.set(CastExpression.kind, (expr) => this.visitCastExpression(expr as CastExpression));\r\n this.handlers.set(BetweenExpression.kind, (expr) => this.visitBetweenExpression(expr as BetweenExpression));\r\n this.handlers.set(ArrayExpression.kind, (expr) => this.visitArrayExpression(expr as ArrayExpression));\r\n this.handlers.set(ArrayQueryExpression.kind, (expr) => this.visitArrayQueryExpression(expr as ArrayQueryExpression));\r\n this.handlers.set(ValueList.kind, (expr) => this.visitValueList(expr as ValueList));\r\n this.handlers.set(WindowFrameClause.kind, (expr) => this.visitWindowFrameClause(expr as WindowFrameClause));\r\n this.handlers.set(WindowFrameExpression.kind, (expr) => this.visitWindowFrameExpression(expr as WindowFrameExpression));\r\n this.handlers.set(PartitionByClause.kind, (expr) => this.visitPartitionByClause(expr as PartitionByClause));\r\n }\r\n\r\n public getValues(): { name: string, value: ValueComponent }[] {\r\n return this.selectValues;\r\n }\r\n\r\n public collect(arg: SqlComponent): { name: string, value: ValueComponent }[] {\r\n // Visit the component and return the collected select items\r\n this.visit(arg);\r\n const items = this.getValues();\r\n this.reset(); // Reset after collection\r\n return items;\r\n }\r\n\r\n /**\r\n * Reset the collection of ColumnReferences\r\n */\r\n private reset(): void {\r\n this.selectValues = []\r\n this.visitedNodes.clear();\r\n this.commonTables = [];\r\n }\r\n\r\n /**\r\n * Add a select value as unique, according to the duplicate detection option.\r\n * If duplicateDetection is 'columnNameOnly', only column name is checked.\r\n * If duplicateDetection is 'fullName', both table and column name are checked.\r\n */\r\n private addSelectValueAsUnique(name: string, value: ValueComponent): void {\r\n if (this.duplicateDetection === DuplicateDetectionMode.ColumnNameOnly) {\r\n if (!this.selectValues.some(item => item.name === name)) {\r\n this.selectValues.push({ name, value });\r\n }\r\n } else if (this.duplicateDetection === DuplicateDetectionMode.FullName) {\r\n // Try to get table name from ValueComponent if possible\r\n let tableName = '';\r\n if (value && typeof (value as any).getNamespace === 'function') {\r\n tableName = (value as any).getNamespace() || '';\r\n }\r\n const key = tableName ? tableName + '.' + name : name;\r\n if (!this.selectValues.some(item => {\r\n let itemTable = '';\r\n if (item.value && typeof (item.value as any).getNamespace === 'function') {\r\n itemTable = (item.value as any).getNamespace() || '';\r\n }\r\n const itemKey = itemTable ? itemTable + '.' + item.name : item.name;\r\n return itemKey === key;\r\n })) {\r\n this.selectValues.push({ name, value });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (!this.isRootVisit) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n if (!(arg instanceof SimpleSelectQuery)) {\r\n throw new Error(\"Root visit must be a SimpleSelectQuery\");\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.isRootVisit = false;\r\n this.commonTables = this.commonTableCollector.collect(arg);\r\n\r\n try {\r\n this.visitNode(arg);\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.isRootVisit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // For any other component types, we don't need to do anything\r\n }\r\n\r\n /**\r\n * Process a SimpleSelectQuery to collect ColumnReferences from all its clauses\r\n */\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n // Visit all clauses that might contain column references\r\n if (query.selectClause) {\r\n query.selectClause.accept(this);\r\n }\r\n\r\n if (query.fromClause) {\r\n query.fromClause.accept(this);\r\n }\r\n\r\n if (query.whereClause) {\r\n query.whereClause.accept(this);\r\n }\r\n\r\n if (query.groupByClause) {\r\n query.groupByClause.accept(this);\r\n }\r\n\r\n if (query.havingClause) {\r\n query.havingClause.accept(this);\r\n }\r\n\r\n if (query.windowClause) {\r\n for (const win of query.windowClause.windows) {\r\n win.accept(this);\r\n }\r\n }\r\n\r\n if (query.orderByClause) {\r\n query.orderByClause.accept(this);\r\n }\r\n\r\n if (query.limitClause) {\r\n query.limitClause.accept(this);\r\n }\r\n\r\n if (query.offsetClause) {\r\n query.offsetClause.accept(this);\r\n }\r\n\r\n if (query.fetchClause) {\r\n query.fetchClause.accept(this);\r\n }\r\n\r\n if (query.forClause) {\r\n query.forClause.accept(this);\r\n }\r\n\r\n // Explicitly NOT processing query.WithClause to avoid scanning CTEs\r\n }\r\n\r\n // Clause handlers\r\n private visitSelectClause(clause: SelectClause): void {\r\n for (const item of clause.items) {\r\n if (item.identifier) {\r\n this.addSelectValueAsUnique(item.identifier.name, item.value);\r\n }\r\n item.value.accept(this);\r\n }\r\n }\r\n\r\n private visitFromClause(clause: FromClause): void {\r\n // import source values\r\n const collector = new SelectValueCollector(this.tableColumnResolver, this.commonTables);\r\n const sourceValues = collector.collect(clause);\r\n for (const item of sourceValues) {\r\n // Add the select value as unique to avoid duplicates\r\n this.addSelectValueAsUnique(item.name, item.value);\r\n }\r\n\r\n if (clause.joins) {\r\n for (const join of clause.joins) {\r\n if (join.condition) {\r\n join.condition.accept(this);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private visitWhereClause(clause: WhereClause): void {\r\n if (clause.condition) {\r\n clause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitGroupByClause(clause: GroupByClause): void {\r\n if (clause.grouping) {\r\n for (const item of clause.grouping) {\r\n item.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitHavingClause(clause: HavingClause): void {\r\n if (clause.condition) {\r\n clause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitOrderByClause(clause: OrderByClause): void {\r\n if (clause.order) {\r\n for (const item of clause.order) {\r\n item.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitWindowFrameClause(clause: WindowFrameClause): void {\r\n clause.expression.accept(this);\r\n }\r\n\r\n private visitWindowFrameExpression(expr: WindowFrameExpression): void {\r\n if (expr.partition) {\r\n expr.partition.accept(this);\r\n }\r\n if (expr.order) {\r\n expr.order.accept(this);\r\n }\r\n if (expr.frameSpec) {\r\n expr.frameSpec.accept(this);\r\n }\r\n }\r\n\r\n private visitLimitClause(clause: LimitClause): void {\r\n if (clause.value) {\r\n clause.value.accept(this);\r\n }\r\n }\r\n\r\n private offsetClause(clause: OffsetClause): void {\r\n if (clause.value) {\r\n clause.value.accept(this);\r\n }\r\n }\r\n\r\n private visitFetchClause(clause: FetchClause): void {\r\n if (clause.expression) {\r\n clause.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinOnClause(joinOnClause: JoinOnClause): void {\r\n // Visit the join condition\r\n if (joinOnClause.condition) {\r\n joinOnClause.condition.accept(this);\r\n }\r\n }\r\n\r\n private visitJoinUsingClause(joinUsingClause: JoinUsingClause): void {\r\n // Visit the columns in the USING clause\r\n if (joinUsingClause.condition) {\r\n joinUsingClause.condition.accept(this);\r\n }\r\n }\r\n\r\n // Value component handlers\r\n private visitColumnReference(columnRef: ColumnReference): void {\r\n if (columnRef.column.name !== \"*\") {\r\n this.addSelectValueAsUnique(columnRef.column.name, columnRef);\r\n } else if (!this.includeWildCard) {\r\n return;\r\n } else {\r\n this.addSelectValueAsUnique(columnRef.column.name, columnRef);\r\n }\r\n }\r\n\r\n private visitBinaryExpression(expr: BinaryExpression): void {\r\n // Visit both sides of the expression\r\n if (expr.left) {\r\n expr.left.accept(this);\r\n }\r\n if (expr.right) {\r\n expr.right.accept(this);\r\n }\r\n }\r\n\r\n private visitUnaryExpression(expr: UnaryExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitFunctionCall(func: FunctionCall): void {\r\n if (func.argument) {\r\n func.argument.accept(this);\r\n }\r\n if (func.over) {\r\n func.over.accept(this);\r\n }\r\n }\r\n\r\n private visitParenExpression(expr: ParenExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitCaseExpression(expr: CaseExpression): void {\r\n if (expr.condition) {\r\n expr.condition.accept(this);\r\n }\r\n\r\n if (expr.switchCase) {\r\n expr.switchCase.accept(this);\r\n }\r\n }\r\n\r\n private visitCastExpression(expr: CastExpression): void {\r\n if (expr.input) {\r\n expr.input.accept(this);\r\n }\r\n }\r\n\r\n private visitBetweenExpression(expr: BetweenExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n\r\n if (expr.lower) {\r\n expr.lower.accept(this);\r\n }\r\n\r\n if (expr.upper) {\r\n expr.upper.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayExpression(expr: ArrayExpression): void {\r\n if (expr.expression) {\r\n expr.expression.accept(this);\r\n }\r\n }\r\n\r\n private visitArrayQueryExpression(expr: ArrayQueryExpression): void {\r\n expr.query.accept(this);\r\n }\r\n\r\n private visitValueList(expr: ValueList): void {\r\n if (expr.values) {\r\n for (const value of expr.values) {\r\n value.accept(this);\r\n }\r\n }\r\n }\r\n\r\n private visitPartitionByClause(clause: PartitionByClause): void {\r\n clause.value.accept(this);\r\n }\r\n}", "import { FullNameParser } from \"./FullNameParser\";\r\nimport { FunctionSource, SourceComponent, SubQuerySource, TableSource } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class SourceParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SourceComponent {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The source component is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parses only a TableSource from the given lexemes, regardless of the presence of parentheses after the identifier.\r\n * This method is specifically used for cases like INSERT queries (e.g., \"insert into table_name (col1, col2)\")\r\n * where a parenthesis immediately following the table name could otherwise be misinterpreted as a function call.\r\n * By using this method, the parser forcibly treats the source as a TableSource.\r\n *\r\n * @param lexemes The array of lexemes to parse.\r\n * @param index The starting index in the lexeme array.\r\n * @returns An object containing the parsed TableSource and the new index.\r\n */\r\n public static parseTableSourceFromLexemes(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, index);\r\n return this.parseTableSource(fullNameResult);\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n let idx = index;\r\n\r\n // Handle subquery\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n return this.parseParenSource(lexemes, idx);\r\n }\r\n\r\n // Retrieve the full name only once and reuse the result\r\n const fullNameResult = FullNameParser.parseFromLexeme(lexemes, idx);\r\n\r\n // Handle function-based source (determine by lastTokenType)\r\n if (fullNameResult.lastTokenType & TokenType.Function) {\r\n // Also use fullNameResult as argument for parseFunctionSource\r\n return SourceParser.parseFunctionSource(lexemes, fullNameResult);\r\n }\r\n\r\n // Handle table source (regular table, potentially schema-qualified)\r\n return SourceParser.parseTableSource(fullNameResult);\r\n }\r\n\r\n private static parseTableSource(fullNameResult: { namespaces: string[] | null, name: any, newIndex: number }): { value: TableSource; newIndex: number } {\r\n const { namespaces, name, newIndex } = fullNameResult;\r\n const value = new TableSource(namespaces, name.name);\r\n return { value, newIndex };\r\n }\r\n\r\n private static parseFunctionSource(\r\n lexemes: Lexeme[],\r\n fullNameResult: { namespaces: string[] | null, name: any, newIndex: number }\r\n ): { value: FunctionSource; newIndex: number } {\r\n let idx = fullNameResult.newIndex;\r\n const { namespaces, name } = fullNameResult;\r\n\r\n const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n idx = argument.newIndex;\r\n\r\n const functionName = name.name;\r\n const result = new FunctionSource({ namespaces: namespaces, name: functionName }, argument.value);\r\n return { value: result, newIndex: idx };\r\n }\r\n\r\n private static parseParenSource(lexemes: Lexeme[], index: number): { value: SourceComponent; newIndex: number } {\r\n let idx = index;\r\n // skip the open parenthesis\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input at position ${idx}. Expected a subquery or nested expression after opening parenthesis.`);\r\n }\r\n\r\n // Support both SELECT and VALUES in subqueries\r\n const keyword = lexemes[idx].value;\r\n if (keyword === \"select\" || keyword === \"values\" || keyword === \"with\") {\r\n const result = this.parseSubQuerySource(lexemes, idx);\r\n idx = result.newIndex;\r\n if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {\r\n // skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n return { value: result.value, newIndex: idx };\r\n } else if (lexemes[idx].type == TokenType.OpenParen) {\r\n const result = this.parseParenSource(lexemes, idx);\r\n idx = result.newIndex;\r\n if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {\r\n // skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n return { value: result.value, newIndex: idx };\r\n }\r\n\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword, 'VALUES' keyword, or opening parenthesis '(' but found \"${lexemes[idx].value}\".`);\r\n }\r\n\r\n private static parseSubQuerySource(lexemes: Lexeme[], index: number): { value: SubQuerySource; newIndex: number } {\r\n let idx = index;\r\n\r\n // Use the new parseFromLexeme method and destructure the result\r\n const { value: selectQuery, newIndex } = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = newIndex;\r\n\r\n const subQuerySource = new SubQuerySource(selectQuery);\r\n return { value: subQuerySource, newIndex: idx };\r\n }\r\n}\r\n", "import { SelectQuery, SimpleSelectQuery, BinarySelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CommonTable, SubQuerySource, TableSource, WithClause } from \"../models/Clause\";\r\nimport { SelectableColumnCollector } from \"./SelectableColumnCollector\";\r\nimport { CTECollector } from \"./CTECollector\";\r\n\r\n/**\r\n * UpstreamSelectQueryFinder searches upstream queries for the specified columns.\r\n * If a query (including its upstream CTEs or subqueries) contains all columns,\r\n * it returns the highest such SelectQuery. Otherwise, it searches downstream.\r\n * For UNION queries, it checks each branch independently.\r\n */\r\nexport class UpstreamSelectQueryFinder {\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n private tableColumnResolver?: (tableName: string) => string[];\r\n private columnCollector: SelectableColumnCollector;\r\n\r\n constructor(tableColumnResolver?: (tableName: string) => string[], options?: { ignoreCaseAndUnderscore?: boolean }) {\r\n this.options = options || {};\r\n this.tableColumnResolver = tableColumnResolver;\r\n // Pass the tableColumnResolver instead of options to fix type mismatch.\r\n this.columnCollector = new SelectableColumnCollector(this.tableColumnResolver);\r\n }\r\n\r\n /**\r\n * Finds the highest SelectQuery containing all specified columns.\r\n * @param query The root SelectQuery to search.\r\n * @param columnNames A column name or array of column names to check for.\r\n * @returns An array of SelectQuery objects, or an empty array if not found.\r\n */\r\n public find(query: SelectQuery, columnNames: string | string[]): SimpleSelectQuery[] {\r\n // Normalize columnNames to array\r\n const namesArray = typeof columnNames === 'string' ? [columnNames] : columnNames;\r\n // Use CTECollector to collect CTEs from the root query only once and reuse\r\n const cteCollector = new CTECollector();\r\n const ctes = cteCollector.collect(query);\r\n const cteMap: Map<string, CommonTable> = new Map();\r\n for (const cte of ctes) {\r\n cteMap.set(cte.getSourceAliasName(), cte);\r\n }\r\n return this.findUpstream(query, namesArray, cteMap);\r\n }\r\n\r\n private handleTableSource(src: TableSource, columnNames: string[], cteMap: Map<string, CommonTable>): SimpleSelectQuery[] | null {\r\n // Handles the logic for TableSource in findUpstream\r\n const cte = cteMap.get(src.table.name);\r\n if (cte) {\r\n // Remove the current CTE name from the map to prevent infinite recursion\r\n const nextCteMap = new Map(cteMap);\r\n nextCteMap.delete(src.table.name);\r\n const result = this.findUpstream(cte.query, columnNames, nextCteMap);\r\n if (result.length === 0) {\r\n return null;\r\n }\r\n return result;\r\n }\r\n return null;\r\n }\r\n\r\n private handleSubQuerySource(src: SubQuerySource, columnNames: string[], cteMap: Map<string, WithClause[\"tables\"][number]>): SimpleSelectQuery[] | null {\r\n // Handles the logic for SubQuerySource in findUpstream\r\n const result = this.findUpstream(src.query, columnNames, cteMap);\r\n if (result.length === 0) {\r\n return null;\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Processes all source branches in a FROM clause and checks if all upstream queries contain the specified columns.\r\n * Returns a flat array of SelectQuery if all branches are valid, otherwise null.\r\n */\r\n private processFromClauseBranches(\r\n fromClause: any,\r\n columnNames: string[],\r\n cteMap: Map<string, CommonTable>\r\n ): SimpleSelectQuery[] | null {\r\n const sources = fromClause.getSources();\r\n if (sources.length === 0) return null;\r\n\r\n let allBranchResults: SimpleSelectQuery[][] = [];\r\n let allBranchesOk = true;\r\n let validBranchCount = 0; // Count only filterable branches\r\n\r\n for (const sourceExpr of sources) {\r\n const src = sourceExpr.datasource;\r\n let branchResult: SimpleSelectQuery[] | null = null;\r\n if (src instanceof TableSource) {\r\n branchResult = this.handleTableSource(src, columnNames, cteMap);\r\n validBranchCount++;\r\n } else if (src instanceof SubQuerySource) {\r\n branchResult = this.handleSubQuerySource(src, columnNames, cteMap);\r\n validBranchCount++;\r\n } else if (src instanceof ValuesQuery) {\r\n // Skip ValuesQuery: not filterable, do not count as a valid branch\r\n continue;\r\n } else {\r\n allBranchesOk = false;\r\n break;\r\n }\r\n\r\n // If the branch result is null, \r\n // it means it didn't find the required columns in this branch\r\n if (branchResult === null) {\r\n allBranchesOk = false;\r\n break;\r\n }\r\n allBranchResults.push(branchResult);\r\n }\r\n\r\n // Check if all valid (filterable) branches are valid and contain the required columns\r\n if (allBranchesOk && allBranchResults.length === validBranchCount) {\r\n return allBranchResults.flat();\r\n }\r\n return null;\r\n }\r\n\r\n private findUpstream(query: SelectQuery, columnNames: string[], cteMap: Map<string, CommonTable>): SimpleSelectQuery[] {\r\n if (query instanceof SimpleSelectQuery) {\r\n const fromClause = query.fromClause;\r\n if (fromClause) {\r\n const branchResult = this.processFromClauseBranches(fromClause, columnNames, cteMap);\r\n if (branchResult) {\r\n return branchResult;\r\n }\r\n }\r\n const columns = this.columnCollector.collect(query).map(col => col.name);\r\n const normalize = (s: string) =>\r\n this.options.ignoreCaseAndUnderscore ? s.toLowerCase().replace(/_/g, '') : s;\r\n // Normalize both the columns and the required names for comparison.\r\n const hasAll = columnNames.every(name => columns.some(col => normalize(col) === normalize(name)));\r\n if (hasAll) {\r\n return [query];\r\n }\r\n return [];\r\n } else if (query instanceof BinarySelectQuery) {\r\n const left = this.findUpstream(query.left, columnNames, cteMap);\r\n const right = this.findUpstream(query.right, columnNames, cteMap);\r\n return [...left, ...right];\r\n }\r\n return [];\r\n }\r\n}\r\n", "import { SourceAliasExpression } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\n\r\n\r\nexport class SourceAliasExpressionParser {\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceAliasExpression; newIndex: number; } {\r\n let idx = index;\r\n\r\n // If there is a column alias, it may be detected as a function, so functions are also processed.\r\n if (idx < lexemes.length && ((lexemes[idx].type & TokenType.Identifier) || (lexemes[idx].type & TokenType.Function))) {\r\n // Check for alias\r\n const table = lexemes[idx].value;\r\n idx++;\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.OpenParen)) {\r\n // Check for column alias\r\n const columns: string[] = [];\r\n\r\n // Skip the open parenthesis\r\n idx++;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Identifier)) {\r\n columns.push(lexemes[idx].value);\r\n idx++;\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n } else {\r\n break; // Exit loop if not a comma\r\n }\r\n }\r\n\r\n if (lexemes[idx].type & TokenType.CloseParen) {\r\n // Skip the closing parenthesis\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for column alias list. Each opening parenthesis must have a matching closing parenthesis.`);\r\n }\r\n if (columns.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No column aliases found. Column alias declarations must contain at least one column name.`);\r\n }\r\n\r\n return { value: new SourceAliasExpression(table, columns), newIndex: idx };\r\n }\r\n\r\n return { value: new SourceAliasExpression(table, null), newIndex: idx };\r\n }\r\n\r\n throw new Error(`Syntax error at position ${index}: Expected an identifier for table alias but found \"${lexemes[index]?.value || 'end of input'}\".`);\r\n }\r\n}\r\n", "import { SourceAliasExpression, SourceExpression, TableSource } from \"../models/Clause\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SourceParser } from \"./SourceParser\";\r\nimport { SourceAliasExpressionParser } from \"./SourceAliasExpressionParser\";\r\n\r\nexport class SourceExpressionParser {\r\n /**\r\n * Parse SQL string to SourceExpression (e.g. \"table\", \"table as t\", \"schema.table t\")\r\n */\r\n public static parse(query: string): SourceExpression {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The source expression is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n public static parseTableSourceFromLexemes(lexemes: Lexeme[], index: number): { value: SourceExpression; newIndex: number } {\r\n const result = SourceParser.parseTableSourceFromLexemes(lexemes, index);\r\n // No alias for table source\r\n const sourceExpr = new SourceExpression(result.value, null);\r\n return { value: sourceExpr, newIndex: result.newIndex };\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SourceExpression; newIndex: number; } {\r\n let idx = index;\r\n\r\n const sourceResult = SourceParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n if (idx < lexemes.length) {\r\n if (lexemes[idx].value === \"as\") {\r\n idx++;\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);\r\n return { value: sourceExpr, newIndex: idx };\r\n }\r\n\r\n /**\r\n * Explanation:\r\n * Source aliases are typically identified as TokenType.Identifier.\r\n * However, when the 'AS' keyword is omitted and column alias names are specified,\r\n * they may sometimes be classified as TokenType.Function.\r\n * Since the TokenReader's responsibility is to perform coarse-grained classification,\r\n * the parser must interpret subsequent 'Function' tokens as source alias expressions\r\n * when they follow a source definition.\r\n * Example:\r\n * SQL: select t.* from (values(1)) t(id)\r\n * Explanation: The alias 't' and its column alias 'id' are parsed as a source alias expression.\r\n */\r\n if (idx < lexemes.length && this.isTokenTypeAliasCandidate(lexemes[idx].type)) {\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);\r\n return { value: sourceExpr, newIndex: idx };\r\n }\r\n }\r\n\r\n // no alias\r\n const expr = new SourceExpression(sourceResult.value, null);\r\n return { value: expr, newIndex: idx };\r\n }\r\n\r\n private static isTokenTypeAliasCandidate(type: number): boolean {\r\n return (type & TokenType.Identifier) !== 0 || (type & TokenType.Function) !== 0;\r\n }\r\n}\r\n", "import { SetClause, SetClauseItem, FromClause, WhereClause, SelectClause, SelectItem, SourceAliasExpression, SourceExpression, SubQuerySource, WithClause, TableSource, UpdateClause, InsertClause } from '../models/Clause';\r\nimport { UpdateQuery } from '../models/UpdateQuery';\r\nimport { BinaryExpression, ColumnReference } from '../models/ValueComponent';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery, ValuesQuery } from \"../models/SelectQuery\";\r\nimport { CTECollector } from \"./CTECollector\";\r\nimport { CTENormalizer } from \"./CTENormalizer\";\r\nimport { CreateTableQuery } from \"../models/CreateTableQuery\";\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { CTEDisabler } from './CTEDisabler';\r\nimport { SourceExpressionParser } from '../parsers/SourceExpressionParser';\r\n\r\n/**\r\n * QueryBuilder provides static methods to build or convert various SQL query objects.\r\n */\r\nexport class QueryBuilder {\r\n /**\r\n * Builds a BinarySelectQuery by combining an array of SelectQuery using the specified operator.\r\n * Throws if less than two queries are provided.\r\n * @param queries Array of SelectQuery to combine\r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @returns BinarySelectQuery\r\n */\r\n public static buildBinaryQuery(queries: SelectQuery[], operator: string): BinarySelectQuery {\r\n if (!queries || queries.length === 0) {\r\n throw new Error(\"No queries provided to combine.\");\r\n }\r\n if (queries.length === 1) {\r\n throw new Error(\"At least two queries are required to create a BinarySelectQuery.\");\r\n }\r\n\r\n // Always create a new BinarySelectQuery instance (never mutate input)\r\n const wrap = (q: SelectQuery) => q instanceof ValuesQuery ? QueryBuilder.buildSimpleQuery(q) : q;\r\n let result: BinarySelectQuery = new BinarySelectQuery(wrap(queries[0]), operator, wrap(queries[1]));\r\n CTENormalizer.normalize(result);\r\n\r\n for (let i = 2; i < queries.length; i++) {\r\n result.appendSelectQuery(operator, wrap(queries[i]));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private constructor() {\r\n // This class is not meant to be instantiated.\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to a standard SimpleSelectQuery form.\r\n * @param query The query to convert\r\n * @returns A SimpleSelectQuery\r\n */\r\n public static buildSimpleQuery(query: SelectQuery): SimpleSelectQuery {\r\n if (query instanceof SimpleSelectQuery) {\r\n return query;\r\n }\r\n else if (query instanceof BinarySelectQuery) {\r\n return QueryBuilder.buildSimpleBinaryQuery(query);\r\n }\r\n else if (query instanceof ValuesQuery) {\r\n return QueryBuilder.buildSimpleValuesQuery(query);\r\n }\r\n throw new Error(\"Unsupported query type for buildSimpleQuery\");\r\n }\r\n\r\n private static buildSimpleBinaryQuery(query: BinarySelectQuery): SimpleSelectQuery {\r\n // Create a subquery source from the binary query\r\n const subQuerySource = new SubQuerySource(query);\r\n\r\n // Create a source expression with alias\r\n const sourceExpr = new SourceExpression(\r\n subQuerySource,\r\n new SourceAliasExpression(\"bq\", null)\r\n );\r\n\r\n // Create FROM clause with the source expression\r\n const fromClause = new FromClause(sourceExpr, null);\r\n\r\n // Create SELECT clause with * (all columns)\r\n const selectClause = QueryBuilder.createSelectAllClause();\r\n\r\n // Create the final simple select query\r\n const q = new SimpleSelectQuery(\r\n {\r\n selectClause,\r\n fromClause\r\n }\r\n );\r\n\r\n return CTENormalizer.normalize(q) as SimpleSelectQuery;\r\n }\r\n\r\n /**\r\n * Converts a ValuesQuery to a SimpleSelectQuery with sequentially numbered columns or user-specified columns\r\n * \r\n * @param query The VALUES query to convert\r\n * @param columns Optional: column names\r\n * @returns A SimpleSelectQuery\r\n */\r\n private static buildSimpleValuesQuery(query: ValuesQuery): SimpleSelectQuery {\r\n // Figure out how many columns are in the VALUES clause\r\n const columnCount = query.tuples.length > 0 ? query.tuples[0].values.length : 0;\r\n if (query.tuples.length === 0) {\r\n throw new Error(\"Empty VALUES clause cannot be converted to a SimpleSelectQuery\");\r\n }\r\n if (!query.columnAliases) {\r\n throw new Error(\"Column aliases are required to convert a VALUES clause to SimpleSelectQuery. Please specify column aliases.\");\r\n }\r\n if (query.columnAliases.length !== columnCount) {\r\n throw new Error(`The number of column aliases (${query.columnAliases.length}) does not match the number of columns in the first tuple (${columnCount}).`);\r\n }\r\n\r\n // Create a subquery source from the VALUES query\r\n const subQuerySource = new SubQuerySource(query);\r\n const sourceExpr = new SourceExpression(\r\n subQuerySource,\r\n new SourceAliasExpression(\"vq\", query.columnAliases)\r\n );\r\n\r\n // Create FROM clause with the source expression\r\n const fromClause = new FromClause(sourceExpr, null);\r\n\r\n // Create SELECT clause with all columns\r\n const selectItems = query.columnAliases.map(name => new SelectItem(new ColumnReference(\"vq\", name), name));\r\n const selectClause = new SelectClause(selectItems, null);\r\n\r\n // Create the final simple select query\r\n return new SimpleSelectQuery(\r\n {\r\n selectClause,\r\n fromClause\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Creates a SELECT clause with a single * (all columns) item\r\n * \r\n * @returns A SELECT clause with *\r\n */\r\n private static createSelectAllClause(): SelectClause {\r\n // Create a column reference for *\r\n const columnRef = new ColumnReference(null, \"*\");\r\n\r\n // Create a SelectItem with the column reference\r\n const selectItem = new SelectItem(columnRef, \"*\");\r\n\r\n // Create and return a SelectClause with the item\r\n return new SelectClause([selectItem], null);\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to a CREATE TABLE query (CREATE [TEMPORARY] TABLE ... AS SELECT ...)\r\n * @param query The SELECT query to use as the source\r\n * @param tableName The name of the table to create\r\n * @param isTemporary If true, creates a temporary table\r\n * @returns A CreateTableQuery instance\r\n */\r\n public static buildCreateTableQuery(query: SelectQuery, tableName: string, isTemporary: boolean = false): CreateTableQuery {\r\n return new CreateTableQuery({\r\n tableName,\r\n isTemporary,\r\n asSelectQuery: query\r\n });\r\n }\r\n\r\n /**\r\n * Converts a SELECT query to an INSERT query (INSERT INTO ... SELECT ...)\r\n * @param selectQuery The SELECT query to use as the source\r\n * @param tableName The name of the table to insert into\r\n * @param columns Optional: array of column names. If omitted, columns are inferred from the selectQuery\r\n * @returns An InsertQuery instance\r\n */\r\n public static buildInsertQuery(selectQuery: SimpleSelectQuery, tableName: string): InsertQuery {\r\n let cols: string[];\r\n\r\n const count = selectQuery.selectClause.items.length;\r\n\r\n // Try to infer columns from the selectQuery\r\n const collector = new SelectValueCollector();\r\n const items = collector.collect(selectQuery);\r\n cols = items.map(item => item.name);\r\n if (!cols.length || count !== cols.length) {\r\n throw new Error(\r\n `Columns cannot be inferred from the selectQuery. ` +\r\n `Make sure you are not using wildcards or unnamed columns.\\n` +\r\n `Select clause column count: ${count}, ` +\r\n `Columns with valid names: ${cols.length}\\n` +\r\n `Detected column names: [${cols.join(\", \")}]`\r\n );\r\n }\r\n\r\n // Generate SourceExpression (supports only table name, does not support alias or schema)\r\n const sourceExpr = SourceExpressionParser.parse(tableName);\r\n return new InsertQuery({\r\n insertClause: new InsertClause(sourceExpr, cols),\r\n selectQuery: selectQuery\r\n });\r\n }\r\n\r\n /**\r\n * Builds an UPDATE query from a SELECT query, table name, and primary key(s).\r\n * @param selectQuery The SELECT query providing new values (must select all columns to update and PKs)\r\n * @param updateTableExprRaw The table name to update\r\n * @param primaryKeys The primary key column name(s)\r\n * @returns UpdateQuery instance\r\n */\r\n public static buildUpdateQuery(selectQuery: SimpleSelectQuery, selectSourceName: string, updateTableExprRaw: string, primaryKeys: string | string[]) {\r\n const updateClause = new UpdateClause(SourceExpressionParser.parse(updateTableExprRaw));\r\n\r\n const pkArray = Array.isArray(primaryKeys) ? primaryKeys : [primaryKeys];\r\n const selectCollector = new SelectValueCollector();\r\n const selectItems = selectCollector.collect(selectQuery);\r\n\r\n const cteCollector = new CTECollector();\r\n const collectedCTEs = cteCollector.collect(selectQuery);\r\n const cteDisabler = new CTEDisabler();\r\n cteDisabler.execute(selectQuery);\r\n\r\n for (const pk of pkArray) {\r\n if (!selectItems.some(item => item.name === pk)) {\r\n throw new Error(`Primary key column '${pk}' is not present in selectQuery select list.`);\r\n }\r\n }\r\n\r\n const updateSourceName = updateClause.getSourceAliasName();\r\n if (!updateSourceName) {\r\n throw new Error(`Source expression does not have an alias. Please provide an alias for the source expression.`);\r\n }\r\n\r\n const setColumns = selectItems.filter(item => !pkArray.includes(item.name));\r\n const setItems = setColumns.map(col => new SetClauseItem(col.name, new ColumnReference(updateSourceName, col.name)));\r\n const setClause = new SetClause(setItems);\r\n\r\n const from = new FromClause(selectQuery.toSource(selectSourceName), null);\r\n\r\n let where: BinaryExpression | null = null;\r\n for (const pk of pkArray) {\r\n const cond = new BinaryExpression(\r\n new ColumnReference(updateSourceName, pk),\r\n '=',\r\n new ColumnReference(selectSourceName, pk)\r\n );\r\n where = where ? new BinaryExpression(where, 'and', cond) : cond;\r\n }\r\n const whereClause = new WhereClause(where!);\r\n\r\n const updateQuery = new UpdateQuery({\r\n updateClause: updateClause,\r\n setClause: setClause,\r\n fromClause: from,\r\n whereClause: whereClause,\r\n withClause: collectedCTEs.length > 0 ? new WithClause(false, collectedCTEs) : undefined,\r\n });\r\n return updateQuery;\r\n }\r\n}\r\n", "import { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { SqlComponent } from \"../models/SqlComponent\";\r\n\r\n/**\r\n * Utility class for parameter operations on SQL queries.\r\n */\r\nexport class ParameterHelper {\r\n /**\r\n * Sets the value of a parameter by name in the given query.\r\n * Throws an error if the parameter is not found.\r\n * @param query The query object (must be a SqlComponent)\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public static set(query: SqlComponent, name: string, value: any): void {\r\n const params = ParameterCollector.collect(query);\r\n\r\n let found = false;\r\n for (const p of params) {\r\n if (p.name.value === name) {\r\n p.value = value;\r\n found = true;\r\n }\r\n }\r\n\r\n if (!found) {\r\n throw new Error(`Parameter '${name}' not found in query.`);\r\n }\r\n }\r\n}\r\n", "import { SqlComponent } from \"./SqlComponent\";\r\nimport { ForClause, FromClause, GroupByClause, HavingClause, JoinClause, JoinOnClause, LimitClause, OrderByClause, SelectClause, SourceExpression, SubQuerySource, SourceAliasExpression, WhereClause, WindowsClause as WindowClause, WithClause, CommonTable, OffsetClause, FetchClause } from \"./Clause\";\r\nimport { BinaryExpression, ColumnReference, ValueComponent } from \"./ValueComponent\";\r\nimport { ValueParser } from \"../parsers/ValueParser\";\r\nimport { CTENormalizer } from \"../transformers/CTENormalizer\";\r\nimport { SelectableColumnCollector } from \"../transformers/SelectableColumnCollector\";\r\nimport { SourceParser } from \"../parsers/SourceParser\";\r\nimport { BinarySelectQuery } from \"./BinarySelectQuery\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\nimport { Formatter } from \"../transformers/Formatter\";\r\nimport { TableColumnResolver } from \"../transformers/TableColumnResolver\";\r\nimport { UpstreamSelectQueryFinder } from \"../transformers/UpstreamSelectQueryFinder\";\r\nimport { QueryBuilder } from \"../transformers/QueryBuilder\";\r\nimport { ParameterHelper } from \"../utils/ParameterHelper\";\r\n\r\n/**\r\n * Represents a simple SELECT query in SQL.\r\n */\r\nexport class SimpleSelectQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"SelectQuery\");\r\n withClause: WithClause | null;\r\n selectClause: SelectClause;\r\n fromClause: FromClause | null;\r\n whereClause: WhereClause | null;\r\n groupByClause: GroupByClause | null;\r\n havingClause: HavingClause | null;\r\n orderByClause: OrderByClause | null;\r\n windowClause: WindowClause | null;\r\n limitClause: LimitClause | null;\r\n offsetClause: OffsetClause | null;\r\n fetchClause: FetchClause | null;\r\n forClause: ForClause | null;\r\n\r\n constructor(params: {\r\n selectClause: SelectClause,\r\n fromClause?: FromClause | null,\r\n whereClause?: WhereClause | null,\r\n groupByClause?: GroupByClause | null,\r\n havingClause?: HavingClause | null,\r\n orderByClause?: OrderByClause | null,\r\n windowClause?: WindowClause | null,\r\n limitClause?: LimitClause | null,\r\n offsetClause?: OffsetClause | null,\r\n fetchClause?: FetchClause | null,\r\n forClause?: ForClause | null,\r\n withClause?: WithClause | null,\r\n }) {\r\n super();\r\n this.withClause = params.withClause ?? null;\r\n this.selectClause = params.selectClause;\r\n this.fromClause = params.fromClause ?? null;\r\n this.whereClause = params.whereClause ?? null;\r\n this.groupByClause = params.groupByClause ?? null;\r\n this.havingClause = params.havingClause ?? null;\r\n this.orderByClause = params.orderByClause ?? null;\r\n this.windowClause = params.windowClause ?? null;\r\n this.limitClause = params.limitClause ?? null;\r\n this.offsetClause = params.offsetClause ?? null;\r\n this.fetchClause = params.fetchClause ?? null;\r\n this.forClause = params.forClause ?? null;\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using UNION as the operator.\r\n * \r\n * @param rightQuery The right side of the UNION\r\n * @returns A new BinarySelectQuery representing \"this UNION rightQuery\"\r\n */\r\n public toUnion(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('union', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using UNION ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the UNION ALL\r\n * @returns A new BinarySelectQuery representing \"this UNION ALL rightQuery\"\r\n */\r\n public toUnionAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('union all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using INTERSECT as the operator.\r\n * \r\n * @param rightQuery The right side of the INTERSECT\r\n * @returns A new BinarySelectQuery representing \"this INTERSECT rightQuery\"\r\n */\r\n public toIntersect(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('intersect', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using INTERSECT ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the INTERSECT ALL\r\n * @returns A new BinarySelectQuery representing \"this INTERSECT ALL rightQuery\"\r\n */\r\n public toIntersectAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('intersect all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using EXCEPT as the operator.\r\n * \r\n * @param rightQuery The right side of the EXCEPT\r\n * @returns A new BinarySelectQuery representing \"this EXCEPT rightQuery\"\r\n */\r\n public toExcept(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('except', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using EXCEPT ALL as the operator.\r\n * \r\n * @param rightQuery The right side of the EXCEPT ALL\r\n * @returns A new BinarySelectQuery representing \"this EXCEPT ALL rightQuery\"\r\n */\r\n public toExceptAll(rightQuery: SelectQuery): BinarySelectQuery {\r\n return this.toBinaryQuery('except all', rightQuery);\r\n }\r\n\r\n /**\r\n * Creates a new BinarySelectQuery with this query as the left side and the provided query as the right side,\r\n * using the specified operator.\r\n * \r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @param rightQuery The right side of the binary operation\r\n * @returns A new BinarySelectQuery representing \"this [operator] rightQuery\"\r\n */\r\n public toBinaryQuery(operator: string, rightQuery: SelectQuery): BinarySelectQuery {\r\n return QueryBuilder.buildBinaryQuery([this, rightQuery], operator);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's WHERE clause using AND logic.\r\n * The condition is provided as a raw SQL string which is parsed internally.\r\n * \r\n * @param rawCondition Raw SQL string representing the condition (e.g. \"status = 'active'\")\r\n */\r\n public appendWhereRaw(rawCondition: string): void {\r\n const parsedCondition = ValueParser.parse(rawCondition);\r\n this.appendWhere(parsedCondition);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's WHERE clause using AND logic.\r\n * The condition is provided as a ValueComponent object.\r\n * \r\n * @param condition ValueComponent representing the condition\r\n */\r\n public appendWhere(condition: ValueComponent): void {\r\n if (!this.whereClause) {\r\n this.whereClause = new WhereClause(condition);\r\n } else {\r\n this.whereClause.condition = new BinaryExpression(\r\n this.whereClause.condition,\r\n 'and',\r\n condition\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's HAVING clause using AND logic.\r\n * The condition is provided as a raw SQL string which is parsed internally.\r\n * \r\n * @param rawCondition Raw SQL string representing the condition (e.g. \"count(*) > 5\")\r\n */\r\n public appendHavingRaw(rawCondition: string): void {\r\n const parsedCondition = ValueParser.parse(rawCondition);\r\n this.appendHaving(parsedCondition);\r\n }\r\n\r\n /**\r\n * Appends a new condition to the query's HAVING clause using AND logic.\r\n * The condition is provided as a ValueComponent object.\r\n * \r\n * @param condition ValueComponent representing the condition\r\n */\r\n public appendHaving(condition: ValueComponent): void {\r\n if (!this.havingClause) {\r\n this.havingClause = new HavingClause(condition);\r\n } else {\r\n this.havingClause.condition = new BinaryExpression(\r\n this.havingClause.condition,\r\n 'and',\r\n condition\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Appends an INNER JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join (e.g., \"my_table\", \"schema.my_table\")\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition (e.g. [\"user_id\"] or \"user_id\")\r\n */\r\n public innerJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('inner join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a LEFT JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition\r\n */\r\n public leftJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('left join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a RIGHT JOIN clause to the query.\r\n * @param joinSourceRawText The table source text to join\r\n * @param alias The alias for the joined table\r\n * @param columns The columns to use for the join condition\r\n */\r\n public rightJoinRaw(joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSourceRaw('right join', joinSourceRawText, alias, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends an INNER JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public innerJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('inner join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a LEFT JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public leftJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('left join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Appends a RIGHT JOIN clause to the query using a SourceExpression.\r\n * @param sourceExpr The source expression to join\r\n * @param columns The columns to use for the join condition\r\n */\r\n public rightJoin(sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n this.joinSource('right join', sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Internal helper to append a JOIN clause.\r\n * Parses the table source, finds the corresponding columns in the existing query context,\r\n * and builds the JOIN condition.\r\n * @param joinType Type of join (e.g., 'inner join', 'left join')\r\n * @param joinSourceRawText Raw text for the table/source to join (e.g., \"my_table\", \"schema.another_table\")\r\n * @param alias Alias for the table/source being joined\r\n * @param columns Array or string of column names to join on\r\n */\r\n private joinSourceRaw(joinType: string, joinSourceRawText: string, alias: string, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n const tableSource = SourceParser.parse(joinSourceRawText);\r\n const sourceExpr = new SourceExpression(tableSource, new SourceAliasExpression(alias, null));\r\n this.joinSource(joinType, sourceExpr, columns, resolver);\r\n }\r\n\r\n /**\r\n * Internal helper to append a JOIN clause using a SourceExpression.\r\n * @param joinType Type of join (e.g., 'inner join', 'left join')\r\n * @param sourceExpr The source expression to join\r\n * @param columns Array or string of column names to join on\r\n */\r\n private joinSource(joinType: string, sourceExpr: SourceExpression, columns: string | string[], resolver: TableColumnResolver | null = null): void {\r\n if (!this.fromClause) {\r\n throw new Error('A FROM clause is required to add a JOIN condition.');\r\n }\r\n\r\n // Always treat columns as array\r\n const columnsArr = Array.isArray(columns) ? columns : [columns];\r\n\r\n const collector = new SelectableColumnCollector(resolver);\r\n const valueSets = collector.collect(this);\r\n let joinCondition: ValueComponent | null = null;\r\n let count = 0;\r\n\r\n const sourceAlias = sourceExpr.getAliasName();\r\n if (!sourceAlias) {\r\n throw new Error('An alias is required for the source expression to add a JOIN condition.');\r\n }\r\n\r\n for (const valueSet of valueSets) {\r\n if (columnsArr.some(col => col == valueSet.name)) {\r\n const expr = new BinaryExpression(\r\n valueSet.value,\r\n '=',\r\n new ColumnReference([sourceAlias], valueSet.name)\r\n );\r\n if (joinCondition) {\r\n joinCondition = new BinaryExpression(\r\n joinCondition,\r\n 'and',\r\n expr\r\n );\r\n } else {\r\n joinCondition = expr;\r\n }\r\n count++;\r\n }\r\n }\r\n\r\n if (!joinCondition || count !== columnsArr.length) {\r\n throw new Error(`Invalid JOIN condition. The specified columns were not found: ${columnsArr.join(', ')}`);\r\n }\r\n\r\n const joinOnClause = new JoinOnClause(joinCondition);\r\n const joinClause = new JoinClause(joinType, sourceExpr, joinOnClause, false);\r\n\r\n if (this.fromClause) {\r\n if (this.fromClause.joins) {\r\n this.fromClause.joins.push(joinClause);\r\n } else {\r\n this.fromClause.joins = [joinClause];\r\n }\r\n }\r\n\r\n CTENormalizer.normalize(this);\r\n }\r\n\r\n // Returns a SourceExpression wrapping this query as a subquery source.\r\n // Alias is required for correct SQL generation and join logic.\r\n public toSource(alias: string): SourceExpression {\r\n if (!alias || alias.trim() === \"\") {\r\n throw new Error(\"Alias is required for toSource(). Please specify a non-empty alias name.\");\r\n }\r\n return new SourceExpression(\r\n new SubQuerySource(this),\r\n new SourceAliasExpression(alias, null)\r\n );\r\n }\r\n\r\n public appendWith(commonTable: CommonTable | CommonTable[]): void {\r\n // Always treat as array for simplicity\r\n const tables = Array.isArray(commonTable) ? commonTable : [commonTable];\r\n if (!this.withClause) {\r\n this.withClause = new WithClause(false, tables);\r\n } else {\r\n this.withClause.tables.push(...tables);\r\n }\r\n\r\n CTENormalizer.normalize(this);\r\n }\r\n\r\n /**\r\n * Appends a CommonTable (CTE) to the WITH clause from raw SQL text and alias.\r\n * If alias is provided, it will be used as the CTE name.\r\n *\r\n * @param rawText Raw SQL string representing the CTE body (e.g. '(SELECT ...)')\r\n * @param alias Optional alias for the CTE (e.g. 'cte_name')\r\n */\r\n public appendWithRaw(rawText: string, alias: string): void {\r\n const query = SelectQueryParser.parse(rawText);\r\n const commonTable = new CommonTable(query, alias, null);\r\n this.appendWith(commonTable);\r\n }\r\n\r\n /**\r\n * Overrides a select item using a template literal function.\r\n * The callback receives the SQL string of the original expression and must return a new SQL string.\r\n * The result is parsed and set as the new select item value.\r\n *\r\n * Example usage:\r\n * query.overrideSelectItemRaw(\"journal_date\", expr => `greatest(${expr}, DATE '2025-01-01')`)\r\n *\r\n * @param columnName The name of the column to override\r\n * @param fn Callback that receives the SQL string of the original expression and returns a new SQL string\r\n */\r\n public overrideSelectItemExpr(columnName: string, fn: (expr: string) => string): void {\r\n const items = this.selectClause.items.filter(item => item.identifier?.name === columnName);\r\n if (items.length === 0) {\r\n throw new Error(`Column ${columnName} not found in the query`);\r\n }\r\n if (items.length > 1) {\r\n throw new Error(`Duplicate column name ${columnName} found in the query`);\r\n }\r\n const item = items[0];\r\n const formatter = new Formatter();\r\n const exprSql = formatter.visit(item.value);\r\n const newValue = fn(exprSql);\r\n item.value = ValueParser.parse(newValue);\r\n }\r\n\r\n /**\r\n * Appends a WHERE clause using the expression for the specified column.\r\n * If `options.upstream` is true, applies to all upstream queries containing the column.\r\n * If false or omitted, applies only to the current query.\r\n *\r\n * @param columnName The name of the column to target.\r\n * @param exprBuilder Function that receives the column expression as a string and returns the WHERE condition string.\r\n * @param options Optional settings. If `upstream` is true, applies to upstream queries.\r\n */\r\n public appendWhereExpr(\r\n columnName: string,\r\n exprBuilder: (expr: string) => string,\r\n options?: { upstream?: boolean }\r\n ): void {\r\n // If upstream option is true, find all upstream queries containing the column\r\n if (options && options.upstream) {\r\n // Use UpstreamSelectQueryFinder to find all relevant queries\r\n // (Assume UpstreamSelectQueryFinder is imported)\r\n const finder = new UpstreamSelectQueryFinder();\r\n const queries = finder.find(this, [columnName]);\r\n const collector = new SelectableColumnCollector();\r\n const formatter = new Formatter();\r\n for (const q of queries) {\r\n const exprs = collector.collect(q).filter(item => item.name === columnName).map(item => item.value);\r\n if (exprs.length !== 1) {\r\n throw new Error(`Expected exactly one expression for column '${columnName}'`);\r\n }\r\n const exprStr = formatter.format(exprs[0]);\r\n q.appendWhereRaw(exprBuilder(exprStr));\r\n }\r\n } else {\r\n // Only apply to the current query\r\n const collector = new SelectableColumnCollector();\r\n const formatter = new Formatter();\r\n const exprs = collector.collect(this).filter(item => item.name === columnName).map(item => item.value);\r\n if (exprs.length !== 1) {\r\n throw new Error(`Expected exactly one expression for column '${columnName}'`);\r\n }\r\n const exprStr = formatter.format(exprs[0]);\r\n this.appendWhereRaw(exprBuilder(exprStr));\r\n }\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { SourceExpression, SubQuerySource, SourceAliasExpression } from \"./Clause\";\r\nimport type { SelectQuery } from \"./SelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { RawString } from \"./ValueComponent\";\r\nimport { CTENormalizer } from \"../transformers/CTENormalizer\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { ParameterHelper } from \"../utils/ParameterHelper\";\r\n\r\n/**\r\n * Represents a binary SELECT query (e.g., UNION, INTERSECT, EXCEPT).\r\n */\r\nexport class BinarySelectQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"BinarySelectQuery\");\r\n left: SelectQuery;\r\n operator: RawString;\r\n right: SelectQuery;\r\n\r\n constructor(left: SelectQuery, operator: string, right: SelectQuery) {\r\n super();\r\n this.left = left;\r\n this.operator = new RawString(operator);\r\n this.right = right;\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with UNION\r\n * @returns A new BinarySelectQuery representing \"(this) UNION query\"\r\n */\r\n public union(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('union', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with UNION ALL\r\n * @returns A new BinarySelectQuery representing \"(this) UNION ALL query\"\r\n */\r\n public unionAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('union all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using INTERSECT as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with INTERSECT\r\n * @returns A new BinarySelectQuery representing \"(this) INTERSECT query\"\r\n */\r\n public intersect(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('intersect', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using INTERSECT ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with INTERSECT ALL\r\n * @returns A new BinarySelectQuery representing \"(this) INTERSECT ALL query\"\r\n */\r\n public intersectAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('intersect all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using EXCEPT as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with EXCEPT\r\n * @returns A new BinarySelectQuery representing \"(this) EXCEPT query\"\r\n */\r\n public except(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('except', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using EXCEPT ALL as the operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param query The query to append with EXCEPT ALL\r\n * @returns A new BinarySelectQuery representing \"(this) EXCEPT ALL query\"\r\n */\r\n public exceptAll(query: SelectQuery): BinarySelectQuery {\r\n return this.appendSelectQuery('except all', query);\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using the specified operator.\r\n * This creates a new BinarySelectQuery where the left side is this binary query\r\n * and the right side is the provided query.\r\n * \r\n * @param operator SQL operator to use (e.g. 'union', 'union all', 'intersect', 'except')\r\n * @param query The query to append with the specified operator\r\n * @returns A new BinarySelectQuery representing \"(this) [operator] query\"\r\n */\r\n public appendSelectQuery(operator: string, query: SelectQuery): BinarySelectQuery {\r\n this.left = new BinarySelectQuery(this.left, this.operator.value, this.right);\r\n this.operator = new RawString(operator);\r\n this.right = query;\r\n\r\n CTENormalizer.normalize(this);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Appends another query to this binary query using UNION as the operator, accepting a raw SQL string.\r\n * This method parses the SQL string and appends the resulting query using UNION.\r\n * @param sql The SQL string to parse and union\r\n * @returns A new BinarySelectQuery representing \"(this) UNION (parsed query)\"\r\n */\r\n public unionRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.union(parsedQuery);\r\n }\r\n public unionAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.unionAll(parsedQuery);\r\n }\r\n public intersectRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.intersect(parsedQuery);\r\n }\r\n public intersectAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.intersectAll(parsedQuery);\r\n }\r\n public exceptRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.except(parsedQuery);\r\n }\r\n public exceptAllRaw(sql: string): BinarySelectQuery {\r\n const parsedQuery = SelectQueryParser.parse(sql);\r\n return this.exceptAll(parsedQuery);\r\n }\r\n\r\n // Returns a SourceExpression wrapping this query as a subquery source.\r\n // Optionally takes an alias name (default: \"subq\")\r\n public toSource(alias: string = \"subq\"): SourceExpression {\r\n return new SourceExpression(\r\n new SubQuerySource(this),\r\n new SourceAliasExpression(alias, null)\r\n );\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { ParameterHelper } from \"../utils/ParameterHelper\";\r\nimport { ParameterCollector } from \"../transformers/ParameterCollector\";\r\nimport { QueryBuilder } from \"../transformers/QueryBuilder\";\r\nimport { SelectQuery } from \"./SelectQuery\";\r\nimport { SimpleSelectQuery } from \"./SimpleSelectQuery\";\r\nimport { SqlComponent } from \"./SqlComponent\";\r\nimport { TupleExpression } from \"./ValueComponent\";\r\n\r\n/**\r\n * Represents a VALUES query in SQL.\r\n */\r\nexport class ValuesQuery extends SqlComponent implements SelectQuery {\r\n static kind = Symbol(\"ValuesQuery\");\r\n tuples: TupleExpression[];\r\n /**\r\n * Column aliases for the VALUES query.\r\n * These represent the logical column names for each value tuple.\r\n * Note: This property is optional and is not referenced during SQL output, but is used when converting to a SimpleSelectQuery.\r\n */\r\n columnAliases: string[] | null;\r\n\r\n constructor(tuples: TupleExpression[], columnAliases: string[] | null = null) {\r\n super();\r\n this.tuples = tuples;\r\n this.columnAliases = columnAliases;\r\n }\r\n\r\n public toSimpleSelectQuery(): SimpleSelectQuery {\r\n return QueryBuilder.buildSimpleQuery(this);\r\n }\r\n\r\n /**\r\n * Sets the value of a parameter by name in this query.\r\n * @param name Parameter name\r\n * @param value Value to set\r\n */\r\n public setParameter(name: string, value: any): this {\r\n ParameterHelper.set(this, name, value);\r\n return this;\r\n }\r\n}\r\n", "import { Distinct, DistinctComponent, DistinctOn, SelectClause, SelectItem } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ColumnReference } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class SelectClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SelectClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The SELECT clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SelectClause; newIndex: number } {\r\n let idx = index;\r\n let distinct: DistinctComponent | null = null;\r\n\r\n if (lexemes[idx].value !== 'select') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found \"${lexemes[idx].value}\". SELECT clauses must start with the SELECT keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'distinct') {\r\n idx++;\r\n distinct = new Distinct();\r\n } else if (idx < lexemes.length && lexemes[idx].value === 'distinct on') {\r\n idx++;\r\n const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n distinct = new DistinctOn(argument.value);\r\n idx = argument.newIndex;\r\n }\r\n\r\n const items: SelectItem[] = [];\r\n const item = SelectItemParser.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = SelectItemParser.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No select items found. The SELECT clause requires at least one expression to select.`);\r\n } else {\r\n const clause = new SelectClause(items, distinct);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n}\r\n\r\n// Extracted SelectItemParser for parsing individual select items\r\nexport class SelectItemParser {\r\n /**\r\n * Parses a single select item from a SQL string.\r\n * @param query The SQL string representing a select item (e.g. 'id as user_id').\r\n * @returns The parsed SelectItem instance.\r\n */\r\n public static parse(query: string): SelectItem {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseItem(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The select item is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parses a single select item from lexemes.\r\n * @param lexemes The array of lexemes.\r\n * @param index The starting index.\r\n * @returns An object containing the SelectItem and the new index.\r\n */\r\n public static parseItem(lexemes: Lexeme[], index: number): { value: SelectItem; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'as') {\r\n // Skip 'AS' keyword\r\n idx++;\r\n }\r\n\r\n if (idx < lexemes.length && (lexemes[idx].type & TokenType.Identifier)) {\r\n const alias = lexemes[idx].value;\r\n idx++;\r\n return {\r\n value: new SelectItem(value, alias),\r\n newIndex: idx,\r\n };\r\n } else if (value instanceof ColumnReference && value.column.name !== \"*\") {\r\n // nameless select item\r\n return {\r\n value: new SelectItem(value, value.column.name),\r\n newIndex: idx,\r\n };\r\n }\r\n // nameless select item\r\n return {\r\n value: new SelectItem(value),\r\n newIndex: idx,\r\n };\r\n }\r\n}", "import { JoinOnClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class JoinOnClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinOnClause; newIndex: number } | null {\r\n let idx = index;\r\n if (idx < lexemes.length && lexemes[idx].value === 'on') {\r\n idx++; // Skip 'on' keyword\r\n // Parse the condition expression\r\n const condition = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = condition.newIndex;\r\n const joinOn = new JoinOnClause(condition.value);\r\n return { value: joinOn, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n}\r\n", "import { JoinUsingClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class JoinUsingClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinUsingClause; newIndex: number } | null {\r\n let idx = index;\r\n if (idx < lexemes.length && lexemes[idx].value === 'using') {\r\n idx++; // Skip 'using' keyword\r\n // Parse the columns in parentheses\r\n const result = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);\r\n const usingColumns = result.value;\r\n idx = result.newIndex;\r\n const joinUsing = new JoinUsingClause(usingColumns);\r\n return { value: joinUsing, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n}\r\n", "import { JoinClause, SourceExpression } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { joinkeywordParser } from \"../tokenReaders/CommandTokenReader\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\nimport { JoinOnClauseParser } from \"./JoinOnClauseParser\";\r\nimport { JoinUsingClauseParser } from \"./JoinUsingClauseParser\";\r\n\r\nexport class JoinClauseParser {\r\n public static tryParse(lexemes: Lexeme[], index: number): { value: JoinClause[]; newIndex: number } | null {\r\n let idx = index;\r\n const joins: JoinClause[] = [];\r\n\r\n while (this.isJoinCommand(lexemes, idx)) {\r\n const joinClause = this.parseJoinClause(lexemes, idx);\r\n joins.push(joinClause.value);\r\n idx = joinClause.newIndex;\r\n }\r\n\r\n if (joins.length > 0) {\r\n return { value: joins, newIndex: idx };\r\n }\r\n return null;\r\n }\r\n\r\n private static isJoinKeyword(value: string): boolean {\r\n // Although performance is not ideal,\r\n // we use keyword token reader to centralize keyword management\r\n const result = joinkeywordParser.parse(value, 0);\r\n if (result) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n private static parseLateral(lexemes: Lexeme[], index: number): { value: boolean; newIndex: number } {\r\n let idx = index;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value === 'lateral') {\r\n // Skip 'lateral' keyword\r\n idx++;\r\n return { value: true, newIndex: idx };\r\n }\r\n\r\n return { value: false, newIndex: idx };\r\n }\r\n\r\n private static isJoinCommand(lexemes: Lexeme[], index: number): boolean {\r\n if (index >= lexemes.length) {\r\n return false;\r\n }\r\n\r\n if (lexemes[index].type & TokenType.Comma || this.isJoinKeyword(lexemes[index].value) === true) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n private static parseJoinClause(lexemes: Lexeme[], index: number): { value: JoinClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Get the join type\r\n const joinType = lexemes[idx].value === \",\" ? \"cross join\" : lexemes[idx].value;\r\n idx++;\r\n\r\n // Check for lateral join\r\n const lateralResult = this.parseLateral(lexemes, idx);\r\n const lateral = lateralResult.value;\r\n idx = lateralResult.newIndex;\r\n\r\n // Parse the source expression to join with\r\n const sourceResult = SourceExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n\r\n if (idx < lexemes.length) {\r\n // JoinOnClauseParser\r\n const onResult = JoinOnClauseParser.tryParse(lexemes, idx);\r\n if (onResult) {\r\n const joinClause = new JoinClause(joinType, sourceResult.value, onResult.value, lateral);\r\n return { value: joinClause, newIndex: onResult.newIndex };\r\n }\r\n // JoinUsingClauseParser\r\n const usingResult = JoinUsingClauseParser.tryParse(lexemes, idx);\r\n if (usingResult) {\r\n const joinClause = new JoinClause(joinType, sourceResult.value, usingResult.value, lateral);\r\n return { value: joinClause, newIndex: usingResult.newIndex };\r\n }\r\n }\r\n\r\n // If we reach the end of the input, we can treat it as a natural join\r\n const joinClause = new JoinClause(joinType, sourceResult.value, null, lateral);\r\n return { value: joinClause, newIndex: idx };\r\n }\r\n}", "import { FromClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { JoinClauseParser } from \"./JoinClauseParser\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\n\r\nexport class FromClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): FromClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The FROM clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FromClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'from') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FROM' keyword but found \"${lexemes[idx].value}\". FROM clauses must start with the FROM keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FROM' keyword. The FROM clause requires a table reference.`);\r\n }\r\n\r\n // Parse the main source expression\r\n const sourceExpression = SourceExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = sourceExpression.newIndex;\r\n\r\n const join = JoinClauseParser.tryParse(lexemes, idx);\r\n idx = join?.newIndex || idx;\r\n\r\n if (join !== null) {\r\n const clause = new FromClause(sourceExpression.value, join.value);\r\n return { value: clause, newIndex: idx };\r\n } else {\r\n const clause = new FromClause(sourceExpression.value, null);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n}", "import { WhereClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class WhereClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WhereClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WHERE clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WhereClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'where') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'WHERE' keyword but found \"${lexemes[idx].value}\". WHERE clauses must start with the WHERE keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'WHERE' keyword. The WHERE clause requires a condition expression.`);\r\n }\r\n\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n const clause = new WhereClause(item.value);\r\n\r\n return { value: clause, newIndex: item.newIndex };\r\n }\r\n}", "import { GroupByClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValueComponent } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class GroupByClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): GroupByClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The GROUP BY clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: GroupByClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'group by') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'GROUP BY' keyword but found \"${lexemes[idx].value}\". GROUP BY clauses must start with the GROUP BY keywords.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'GROUP BY' keyword. The GROUP BY clause requires at least one expression to group by.`);\r\n }\r\n\r\n const items: ValueComponent[] = [];\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++;\r\n const item = this.parseItem(lexemes, idx);\r\n items.push(item.value);\r\n idx = item.newIndex;\r\n }\r\n\r\n if (items.length === 0) {\r\n throw new Error(`Syntax error at position ${index}: No grouping expressions found. The GROUP BY clause requires at least one expression to group by.`);\r\n } else {\r\n const clause = new GroupByClause(items);\r\n return { value: clause, newIndex: idx };\r\n }\r\n }\r\n\r\n private static parseItem(lexemes: Lexeme[], index: number): { value: ValueComponent; newIndex: number } {\r\n let idx = index;\r\n const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n const value = parsedValue.value;\r\n idx = parsedValue.newIndex;\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { HavingClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class HavingClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): HavingClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The HAVING clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: HavingClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'having') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'HAVING' keyword but found \"${lexemes[idx].value}\". HAVING clauses must start with the HAVING keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'HAVING' keyword. The HAVING clause requires a condition expression.`);\r\n }\r\n\r\n const item = ValueParser.parseFromLexeme(lexemes, idx);\r\n const clause = new HavingClause(item.value);\r\n\r\n return { value: clause, newIndex: item.newIndex };\r\n }\r\n}", "import { WindowFrameClause, WindowsClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WindowExpressionParser } from \"./WindowExpressionParser\";\r\n\r\nexport class WindowClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WindowsClause {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WINDOW clause is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WindowsClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'window') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'WINDOW' keyword but found \"${lexemes[idx].value}\". WINDOW clauses must start with the WINDOW keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'WINDOW' keyword. The WINDOW clause requires at least one window definition.`);\r\n }\r\n\r\n const windows: WindowFrameClause[] = [];\r\n while (idx < lexemes.length) {\r\n\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Identifier) {\r\n throw new Error(`Syntax error: Expected window name after 'WINDOW' keyword.`);\r\n }\r\n const name = lexemes[idx].value;\r\n idx++;\r\n if (idx >= lexemes.length || lexemes[idx].value !== 'as') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after window name.`);\r\n }\r\n idx++;\r\n const expr = WindowExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = expr.newIndex;\r\n windows.push(new WindowFrameClause(name, expr.value));\r\n\r\n if (idx < lexemes.length && lexemes[idx].type & TokenType.Comma) {\r\n idx++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n if (windows.length === 0) {\r\n throw new Error('At least one WINDOW clause is required after WINDOW keyword.');\r\n }\r\n return { value: new WindowsClause(windows), newIndex: idx };\r\n }\r\n}", "import { LimitClause as LimitClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class LimitClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): LimitClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The LIMIT clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: LimitClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'limit') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'LIMIT' keyword but found \"${lexemes[idx].value}\". LIMIT clauses must start with the LIMIT keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'LIMIT' keyword. The LIMIT clause requires a numeric expression.`);\r\n }\r\n\r\n // Parse LIMIT value\r\n const limitItem = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = limitItem.newIndex;\r\n\r\n const clause = new LimitClause(limitItem.value);\r\n\r\n return { value: clause, newIndex: idx };\r\n }\r\n}", "import { ForClause, LockMode } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\n\r\nexport class ForClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): ForClause {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The FOR clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ForClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check for FOR keyword\r\n if (lexemes[idx].value.toLowerCase() !== 'for') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FOR' keyword but found \"${lexemes[idx].value}\". FOR clauses must start with the FOR keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FOR' keyword. The FOR clause requires a lock mode specification.`);\r\n }\r\n\r\n // Parse lock mode\r\n const lockModeValue = lexemes[idx].value;\r\n let lockMode: LockMode;\r\n\r\n switch (lockModeValue) {\r\n case 'update':\r\n lockMode = LockMode.Update;\r\n idx++;\r\n break;\r\n case 'share':\r\n lockMode = LockMode.Share;\r\n idx++;\r\n break;\r\n case 'key share':\r\n lockMode = LockMode.KeyShare;\r\n idx++;\r\n break;\r\n case 'no key update':\r\n lockMode = LockMode.NokeyUpdate;\r\n idx++;\r\n break;\r\n default:\r\n throw new Error(`Syntax error at position ${idx}: Invalid lock mode \"${lockModeValue}\". Valid lock modes are: UPDATE, SHARE, KEY SHARE, NO KEY UPDATE.`);\r\n }\r\n\r\n const clause = new ForClause(lockMode);\r\n return { value: clause, newIndex: idx };\r\n }\r\n}", "import { CommonTable } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { SourceAliasExpressionParser } from \"./SourceAliasExpressionParser\";\r\n\r\nexport class CommonTableParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): CommonTable {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The CommonTable definition is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: CommonTable; newIndex: number } {\r\n let idx = index;\r\n\r\n // Parse alias and optional column aliases\r\n // SourceAliasExpressionParser already handles column aliases if present\r\n const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);\r\n idx = aliasResult.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].value !== \"as\") {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after CTE name but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip 'AS' keyword\r\n\r\n // Materialized flag\r\n let materialized: boolean | null = null;\r\n\r\n // Parse optional MATERIALIZED or NOT MATERIALIZED keywords\r\n if (idx < lexemes.length) {\r\n const currentValue = lexemes[idx].value;\r\n if (currentValue === \"materialized\") {\r\n materialized = true;\r\n idx++;\r\n } else if (currentValue === \"not materialized\") {\r\n materialized = false;\r\n idx++;\r\n }\r\n }\r\n\r\n if (idx < lexemes.length && lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected '(' after CTE name but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip opening parenthesis\r\n\r\n const queryResult = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n idx = queryResult.newIndex;\r\n\r\n if (idx < lexemes.length && lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected ')' after CTE query but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++; // Skip closing parenthesis\r\n\r\n const value = new CommonTable(queryResult.value, aliasResult.value, materialized);\r\n return { value, newIndex: idx };\r\n }\r\n}", "import { CommonTable, WithClause } from \"../models/Clause\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { CommonTableParser } from \"./CommonTableParser\";\r\n\r\nexport class WithClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): WithClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The WITH clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: WithClause; newIndex: number } {\r\n let idx = index;\r\n\r\n // Expect WITH keyword\r\n if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === \"with\") {\r\n idx++;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected WITH keyword.`);\r\n }\r\n\r\n // Check for RECURSIVE keyword\r\n const recursive = idx < lexemes.length && lexemes[idx].value.toLowerCase() === \"recursive\";\r\n if (recursive) {\r\n idx++;\r\n }\r\n\r\n // Parse CTEs\r\n const tables: CommonTable[] = [];\r\n\r\n // Parse first CTE (required)\r\n const firstCte = CommonTableParser.parseFromLexeme(lexemes, idx);\r\n tables.push(firstCte.value);\r\n idx = firstCte.newIndex;\r\n\r\n // Parse additional CTEs (optional)\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n const cteResult = CommonTableParser.parseFromLexeme(lexemes, idx);\r\n tables.push(cteResult.value);\r\n idx = cteResult.newIndex;\r\n }\r\n\r\n // Create WITH clause\r\n return {\r\n value: new WithClause(recursive, tables),\r\n newIndex: idx\r\n };\r\n }\r\n}", "import { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { ValuesQuery } from \"../models/SelectQuery\";\r\nimport { TupleExpression, ValueComponent } from \"../models/ValueComponent\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class ValuesQueryParser {\r\n public static parse(query: string): ValuesQuery {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The VALUES clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: ValuesQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value.toLowerCase() !== 'values') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'VALUES' keyword but found \"${lexemes[idx].value}\". VALUES clauses must start with the VALUES keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'VALUES' keyword. The VALUES clause requires at least one tuple expression.`);\r\n }\r\n\r\n const tuples: TupleExpression[] = [];\r\n\r\n // Parse the first tuple\r\n const firstTuple = this.parseTuple(lexemes, idx);\r\n tuples.push(firstTuple.value);\r\n idx = firstTuple.newIndex;\r\n\r\n // Parse additional tuples if they exist\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n const tuple = this.parseTuple(lexemes, idx);\r\n tuples.push(tuple.value);\r\n idx = tuple.newIndex;\r\n }\r\n\r\n const query = new ValuesQuery(tuples);\r\n return { value: query, newIndex: idx };\r\n }\r\n\r\n private static parseTuple(lexemes: Lexeme[], index: number): { value: TupleExpression; newIndex: number } {\r\n let idx = index;\r\n\r\n // Check for opening parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.OpenParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis but found \"${idx < lexemes.length ? lexemes[idx].value : \"end of input\"}\". Tuple expressions in VALUES clause must be enclosed in parentheses.`);\r\n }\r\n idx++;\r\n\r\n // Parse values inside the tuple\r\n const values: ValueComponent[] = [];\r\n\r\n // Parse first value\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after opening parenthesis in tuple expression.`);\r\n }\r\n\r\n // Check for empty tuple case\r\n if (lexemes[idx].type & TokenType.CloseParen) {\r\n idx++; // Skip closing parenthesis\r\n return { value: new TupleExpression([]), newIndex: idx };\r\n }\r\n\r\n // Parse the first value\r\n const firstValue = ValueParser.parseFromLexeme(lexemes, idx);\r\n values.push(firstValue.value);\r\n idx = firstValue.newIndex;\r\n\r\n // Parse additional values\r\n while (idx < lexemes.length && (lexemes[idx].type & TokenType.Comma)) {\r\n idx++; // Skip comma\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after comma in tuple expression.`);\r\n }\r\n\r\n const value = ValueParser.parseFromLexeme(lexemes, idx);\r\n values.push(value.value);\r\n idx = value.newIndex;\r\n }\r\n\r\n // Check for closing parenthesis\r\n if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected closing parenthesis but found \"${idx < lexemes.length ? lexemes[idx].value : \"end of input\"}\". Tuple expressions in VALUES clause must be enclosed in parentheses.`);\r\n }\r\n idx++; // Skip closing parenthesis\r\n\r\n return { value: new TupleExpression(values), newIndex: idx };\r\n }\r\n}", "import { FetchClause, FetchType, FetchUnit, FetchExpression } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { LiteralValue, ValueComponent } from \"../models/ValueComponent\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class FetchClauseParser {\r\n /**\r\n * Parses a FETCH clause from a lexeme array starting at the given index.\r\n * Supports syntax like: FETCH [FIRST|NEXT] <count> ROWS ONLY\r\n * @param lexemes The array of lexemes\r\n * @param index The starting index\r\n * @returns { value: FetchSpecification, newIndex: number }\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FetchClause; newIndex: number } {\r\n let idx = index;\r\n if (lexemes[idx].value !== 'fetch') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FETCH' keyword but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH' keyword.`);\r\n }\r\n\r\n const fetchExprResult = FetchExpressionParser.parseFromLexeme(lexemes, idx);\r\n const fetchExpr = fetchExprResult.value;\r\n idx = fetchExprResult.newIndex;\r\n\r\n return { value: new FetchClause(fetchExpr), newIndex: idx };\r\n }\r\n}\r\n\r\n// FetchExpressionParser: parses FETCH [FIRST|NEXT] <count> ROWS ONLY ...\r\nexport class FetchExpressionParser {\r\n /**\r\n * Parses a FETCH expression (not the whole clause, just the fetch part)\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: FetchExpression; newIndex: number } {\r\n let idx = index;\r\n let type: FetchType;\r\n const typeToken = lexemes[idx].value;\r\n if (typeToken === 'first') {\r\n type = FetchType.First;\r\n } else if (typeToken === 'next') {\r\n type = FetchType.Next;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'FIRST' or 'NEXT' after 'FETCH' but found \"${lexemes[idx].value}\".`);\r\n }\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT'.`);\r\n }\r\n\r\n let count: ValueComponent | null = null;\r\n let unit: FetchUnit | null = null;\r\n\r\n // Omitted count notation\r\n if (lexemes[idx].value === 'row only' || lexemes[idx].value === 'rows only') {\r\n count = new LiteralValue(1);\r\n unit = FetchUnit.RowsOnly;\r\n idx++;\r\n return { value: new FetchExpression(type, count, unit), newIndex: idx };\r\n }\r\n\r\n // <count>\r\n const countResult = ValueParser.parseFromLexeme(lexemes, idx);\r\n count = countResult.value;\r\n idx = countResult.newIndex;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT <count>'.`);\r\n }\r\n // ROWS ONLY (or other unit)\r\n\r\n if (lexemes[idx].value === 'rows only') {\r\n unit = FetchUnit.RowsOnly;\r\n idx++;\r\n } else if (lexemes[idx].value === 'percent') {\r\n unit = FetchUnit.Percent;\r\n idx++;\r\n } else if (lexemes[idx].value === 'percent with ties') {\r\n unit = FetchUnit.PercentWithTies;\r\n idx++;\r\n }\r\n if (!unit) {\r\n throw new Error(`Syntax error: Expected 'ROWS ONLY', 'PERCENT', or 'PERCENT WITH TIES' after 'FETCH FIRST|NEXT <count>'.`);\r\n }\r\n return { value: new FetchExpression(type, count, unit), newIndex: idx };\r\n }\r\n}\r\n", "import { OffsetClause } from \"../models/Clause\";\r\nimport { Lexeme } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { ValueParser } from \"./ValueParser\";\r\n\r\nexport class OffsetClauseParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): OffsetClause {\r\n const tokenizer = new SqlTokenizer(query); // Initialize tokenizer\r\n const lexemes = tokenizer.readLexmes(); // Get tokens\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The OFFSET clause is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: OffsetClause; newIndex: number } {\r\n let idx = index;\r\n\r\n if (lexemes[idx].value !== 'offset') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'OFFSET' keyword but found \"${lexemes[idx].value}\". OFFSET clauses must start with the OFFSET keyword.`);\r\n }\r\n idx++;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input after 'OFFSET' keyword. The OFFSET clause requires a numeric expression.`);\r\n }\r\n\r\n // Parse OFFSET value\r\n const offsetItem = ValueParser.parseFromLexeme(lexemes, idx);\r\n idx = offsetItem.newIndex;\r\n\r\n // If there is a \"row\" or \"rows\" command, skip it\r\n if (idx < lexemes.length && (lexemes[idx].value === 'row' || lexemes[idx].value === 'rows')) {\r\n idx++;\r\n }\r\n\r\n const clause = new OffsetClause(offsetItem.value);\r\n\r\n return { value: clause, newIndex: idx };\r\n }\r\n}\r\n", "import { Lexeme } from \"../models/Lexeme\";\r\nimport { BinarySelectQuery, SelectQuery, SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SelectClauseParser } from \"./SelectClauseParser\";\r\nimport { FromClauseParser } from \"./FromClauseParser\";\r\nimport { WhereClauseParser } from \"./WhereClauseParser\";\r\nimport { GroupByClauseParser } from \"./GroupByParser\";\r\nimport { HavingClauseParser } from \"./HavingParser\";\r\nimport { OrderByClauseParser } from \"./OrderByClauseParser\";\r\nimport { WindowClauseParser } from \"./WindowClauseParser\";\r\nimport { LimitClauseParser } from \"./LimitClauseParser\";\r\nimport { ForClauseParser } from \"./ForClauseParser\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { WithClauseParser } from \"./WithClauseParser\";\r\nimport { ValuesQueryParser } from \"./ValuesQueryParser\";\r\nimport { FetchClauseParser } from \"./FetchClauseParser\";\r\nimport { OffsetClauseParser } from \"./OffsetClauseParser\";\r\n\r\nexport class SelectQueryParser {\r\n // Parse SQL string to AST (was: parse)\r\n public static parse(query: string): SelectQuery {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n\r\n // Parse\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n\r\n // Error if there are remaining tokens\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`[SelectQueryParser] Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The SELECT query is complete but there are additional tokens.`);\r\n }\r\n\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Asynchronously parse SQL string to AST.\r\n * This method wraps the synchronous parse logic in a Promise for future extensibility.\r\n * @param query SQL string to parse\r\n * @returns Promise<SelectQuery>\r\n */\r\n public static async parseAsync(query: string): Promise<SelectQuery> {\r\n // For now, just wrap the sync parse in a resolved Promise\r\n return Promise.resolve(this.parse(query));\r\n }\r\n\r\n private static unionCommandSet = new Set<string>([\r\n \"union\",\r\n \"union all\",\r\n \"intersect\",\r\n \"intersect all\",\r\n \"except\",\r\n \"except all\",\r\n ]);\r\n private static selectCommandSet = new Set<string>([\"with\", \"select\"]);\r\n\r\n // Parse from lexeme array (was: parse)\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: SelectQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected end of input at position ${index}.`);\r\n }\r\n\r\n // Check if the first token is a SELECT keyword or VALUES\r\n const firstToken = lexemes[idx].value;\r\n if (!this.selectCommandSet.has(firstToken) && firstToken !== 'values') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' keyword but found \"${lexemes[idx].value}\".`);\r\n }\r\n\r\n let firstResult = this.selectCommandSet.has(firstToken)\r\n ? this.parseSimpleSelectQuery(lexemes, idx)\r\n : this.parseValuesQuery(lexemes, idx);\r\n\r\n let query: SelectQuery = firstResult.value;\r\n idx = firstResult.newIndex;\r\n\r\n // check 'union'\r\n while (idx < lexemes.length && this.unionCommandSet.has(lexemes[idx].value.toLowerCase())) {\r\n const operator = lexemes[idx].value.toLowerCase();\r\n idx++;\r\n if (idx >= lexemes.length) {\r\n throw new Error(`Syntax error at position ${idx}: Expected a query after '${operator.toUpperCase()}' but found end of input.`);\r\n }\r\n\r\n const nextToken = lexemes[idx].value.toLowerCase();\r\n if (this.selectCommandSet.has(nextToken)) {\r\n const result = this.parseSimpleSelectQuery(lexemes, idx);\r\n query = new BinarySelectQuery(query, operator, result.value);\r\n idx = result.newIndex;\r\n } else if (nextToken === 'values') {\r\n const result = this.parseValuesQuery(lexemes, idx);\r\n query = new BinarySelectQuery(query, operator, result.value);\r\n idx = result.newIndex;\r\n } else {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' after '${operator.toUpperCase()}' but found \"${lexemes[idx].value}\".`);\r\n }\r\n }\r\n\r\n return { value: query, newIndex: idx };\r\n }\r\n\r\n private static parseSimpleSelectQuery(lexemes: Lexeme[], index: number): { value: SimpleSelectQuery; newIndex: number } {\r\n let idx = index;\r\n let withClauseResult = null;\r\n\r\n // Parse optional WITH clause\r\n if (idx < lexemes.length && lexemes[idx].value === 'with') {\r\n withClauseResult = WithClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = withClauseResult.newIndex;\r\n }\r\n\r\n // Parse SELECT clause (required)\r\n if (idx >= lexemes.length || lexemes[idx].value !== 'select') {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found \"${idx < lexemes.length ? lexemes[idx].value : 'end of input'}\". SELECT queries must start with the SELECT keyword.`);\r\n }\r\n\r\n const selectClauseResult = SelectClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = selectClauseResult.newIndex;\r\n\r\n // Parse FROM clause (optional)\r\n let fromClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'from') {\r\n fromClauseResult = FromClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = fromClauseResult.newIndex;\r\n }\r\n\r\n // Parse WHERE clause (optional)\r\n let whereClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'where') {\r\n whereClauseResult = WhereClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = whereClauseResult.newIndex;\r\n }\r\n\r\n // Parse GROUP BY clause (optional)\r\n let groupByClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'group by') {\r\n groupByClauseResult = GroupByClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = groupByClauseResult.newIndex;\r\n }\r\n\r\n // Parse HAVING clause (optional)\r\n let havingClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'having') {\r\n havingClauseResult = HavingClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = havingClauseResult.newIndex;\r\n }\r\n\r\n // Parse WINDOW clause (optional)\r\n let windowClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'window') {\r\n windowClauseResult = WindowClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = windowClauseResult.newIndex;\r\n }\r\n\r\n // Parse ORDER BY clause (optional)\r\n let orderByClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'order by') {\r\n orderByClauseResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = orderByClauseResult.newIndex;\r\n }\r\n\r\n // Parse LIMIT clause (optional)\r\n let limitClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'limit') {\r\n limitClauseResult = LimitClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = limitClauseResult.newIndex;\r\n }\r\n\r\n // Parse OFFSET clause (optional)\r\n let offsetClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'offset') {\r\n offsetClauseResult = OffsetClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = offsetClauseResult.newIndex;\r\n }\r\n\r\n // Parse FETCH clause (optional)\r\n let fetchClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value === 'fetch') {\r\n fetchClauseResult = FetchClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = fetchClauseResult.newIndex;\r\n }\r\n\r\n // Parse FOR clause (optional)\r\n let forClauseResult = null;\r\n if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'for') {\r\n forClauseResult = ForClauseParser.parseFromLexeme(lexemes, idx);\r\n idx = forClauseResult.newIndex;\r\n }\r\n\r\n // Create and return the SelectQuery object\r\n const selectQuery = new SimpleSelectQuery({\r\n withClause: withClauseResult ? withClauseResult.value : null,\r\n selectClause: selectClauseResult.value,\r\n fromClause: fromClauseResult ? fromClauseResult.value : null,\r\n whereClause: whereClauseResult ? whereClauseResult.value : null,\r\n groupByClause: groupByClauseResult ? groupByClauseResult.value : null,\r\n havingClause: havingClauseResult ? havingClauseResult.value : null,\r\n orderByClause: orderByClauseResult ? orderByClauseResult.value : null,\r\n windowClause: windowClauseResult ? windowClauseResult.value : null,\r\n limitClause: limitClauseResult ? limitClauseResult.value : null,\r\n offsetClause: offsetClauseResult ? offsetClauseResult.value : null,\r\n fetchClause: fetchClauseResult ? fetchClauseResult.value : null,\r\n forClause: forClauseResult ? forClauseResult.value : null\r\n });\r\n\r\n return { value: selectQuery, newIndex: idx };\r\n }\r\n\r\n private static parseValuesQuery(lexemes: Lexeme[], index: number): { value: SelectQuery; newIndex: number } {\r\n // Use ValuesQueryParser to parse VALUES clause\r\n const result = ValuesQueryParser.parseFromLexeme(lexemes, index);\r\n\r\n // Return the result from ValuesQueryParser directly\r\n return { value: result.value, newIndex: result.newIndex };\r\n }\r\n}", "// filepath: src/parsers/InsertQueryParser.ts\r\n// Provides parsing for INSERT queries, supporting optional columns and WITH/SELECT/VALUES structure.\r\nimport { InsertQuery } from \"../models/InsertQuery\";\r\nimport { Lexeme, TokenType } from \"../models/Lexeme\";\r\nimport { SqlTokenizer } from \"./SqlTokenizer\";\r\nimport { SelectQueryParser } from \"./SelectQueryParser\";\r\nimport { WithClause } from \"../models/Clause\";\r\nimport { WithClauseParser } from \"./WithClauseParser\";\r\nimport { SimpleSelectQuery } from \"../models/SimpleSelectQuery\";\r\nimport { SourceExpressionParser } from \"./SourceExpressionParser\";\r\nimport { InsertClause } from \"../models/Clause\";\r\n\r\nexport class InsertQueryParser {\r\n /**\r\n * Parse SQL string to InsertQuery AST.\r\n * @param query SQL string\r\n */\r\n public static parse(query: string): InsertQuery {\r\n const tokenizer = new SqlTokenizer(query);\r\n const lexemes = tokenizer.readLexmes();\r\n const result = this.parseFromLexeme(lexemes, 0);\r\n if (result.newIndex < lexemes.length) {\r\n throw new Error(`Syntax error: Unexpected token \"${lexemes[result.newIndex].value}\" at position ${result.newIndex}. The INSERT query is complete but there are additional tokens.`);\r\n }\r\n return result.value;\r\n }\r\n\r\n /**\r\n * Parse from lexeme array (for internal use and tests)\r\n */\r\n public static parseFromLexeme(lexemes: Lexeme[], index: number): { value: InsertQuery; newIndex: number } {\r\n let idx = index;\r\n\r\n let withclause: WithClause | null = null;\r\n if (lexemes[idx].value === \"with\") {\r\n const result = WithClauseParser.parseFromLexeme(lexemes, idx);\r\n withclause = result.value;\r\n idx = result.newIndex;\r\n }\r\n\r\n // Expect INSERT INTO\r\n if (lexemes[idx].value !== \"insert into\") {\r\n throw new Error(`Syntax error at position ${idx}: Expected 'INSERT INTO' but found '${lexemes[idx].value}'.`);\r\n }\r\n idx++;\r\n\r\n // Parse table and optional alias/schema using SourceExpressionParser\r\n const sourceResult = SourceExpressionParser.parseTableSourceFromLexemes(lexemes, idx);\r\n idx = sourceResult.newIndex;\r\n\r\n // Optional columns\r\n let columns: string[] = [];\r\n if (lexemes[idx]?.type === TokenType.OpenParen) {\r\n idx++;\r\n while (idx < lexemes.length && lexemes[idx].type === TokenType.Identifier) {\r\n columns.push(lexemes[idx].value);\r\n idx++;\r\n if (lexemes[idx]?.type === TokenType.Comma) {\r\n idx++;\r\n } else {\r\n break;\r\n }\r\n }\r\n if (lexemes[idx]?.type !== TokenType.CloseParen) {\r\n throw new Error(`Syntax error at position ${idx}: Expected ')' after column list.`);\r\n }\r\n idx++;\r\n }\r\n\r\n const selectResult = SelectQueryParser.parseFromLexeme(lexemes, idx);\r\n if (withclause) {\r\n if (selectResult.value instanceof SimpleSelectQuery) {\r\n selectResult.value.withClause = withclause;\r\n } else {\r\n throw new Error(`WITH clause is not supported in this context.`);\r\n }\r\n }\r\n\r\n idx = selectResult.newIndex;\r\n return {\r\n value: new InsertQuery({\r\n insertClause: new InsertClause(sourceResult.value, columns),\r\n selectQuery: selectResult.value\r\n }),\r\n newIndex: idx\r\n };\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, BinaryExpression, CaseExpression, SwitchCaseArgument, CaseKeyValuePair, RawString } from '../models/ValueComponent';\r\nimport { JsonMapping } from './PostgresJsonQueryBuilder';\r\n\r\n/**\r\n * Entity with processing metadata\r\n */\r\nexport interface ProcessableEntity {\r\n id: string;\r\n name: string;\r\n columns: { [jsonKey: string]: string };\r\n isRoot: boolean;\r\n propertyName: string;\r\n // For nested entities\r\n parentId?: string;\r\n relationshipType?: \"object\" | \"array\";\r\n}\r\n\r\n/**\r\n * Information for object entity processing\r\n */\r\ninterface ObjectEntityProcessingInfo {\r\n entity: ProcessableEntity;\r\n depth: number;\r\n}\r\n\r\n/**\r\n * PostgreSQL-specific builder for creating CTEs for object entities (object relationships).\r\n * This class handles the creation of CTEs that build JSON/JSONB objects for object entities,\r\n * processing them from the deepest level up to ensure proper dependency ordering.\r\n * \r\n * Features:\r\n * - Depth-based CTE naming (cte_object_depth_N)\r\n * - NULL handling for entity columns\r\n * - JSONB/JSON object construction\r\n * - Hierarchical processing of nested objects\r\n * \r\n * Why depth calculation is critical:\r\n * 1. Object entities can be nested at multiple levels. We must process the deepest\r\n * (most distant) objects first to ensure their JSON representations are available\r\n * when building their parent entities.\r\n * 2. Object entity processing is essentially a column compression operation. Entities\r\n * at the same depth level can be processed simultaneously since they don't depend\r\n * on each other.\r\n * \r\n * Example hierarchy:\r\n * Order (root, depth 0)\r\n * \u2514\u2500 Customer (depth 1)\r\n * \u2514\u2500 Address (depth 2)\r\n * \u2514\u2500 Shipping (depth 1)\r\n * \u2514\u2500 Carrier (depth 2)\r\n * \r\n * Processing order: depth 2 \u2192 depth 1 \u2192 depth 0\r\n */\r\nexport class PostgresObjectEntityCteBuilder { // Constants for consistent naming conventions\r\n private static readonly JSON_COLUMN_SUFFIX = '_json';\r\n private static readonly CTE_OBJECT_PREFIX = 'cte_object_depth_';\r\n private static readonly WILDCARD_COLUMN = '*'; /**\r\n * Build CTEs for all object entities in the correct dependency order\r\n * @param initialCte The starting CTE containing all raw data\r\n * @param allEntities Map of all entities in the mapping\r\n * @param mapping The JSON mapping configuration\r\n * @returns Array of CTEs and the alias of the last CTE created\r\n */\r\n public buildObjectEntityCtes(\r\n initialCte: CommonTable,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): { ctes: CommonTable[], lastCteAlias: string } {\r\n const ctes: CommonTable[] = [initialCte];\r\n let previousCteAlias = initialCte.aliasExpression.table.name; // Collect and sort object entities by depth\r\n const objectEntityInfos = this.collectAndSortObjectEntities(mapping, allEntities);\r\n\r\n // Group entities by depth\r\n const entitiesByDepth = this.groupEntitiesByDepth(objectEntityInfos);\r\n\r\n // Process each depth level, starting from the deepest\r\n const depths = Array.from(entitiesByDepth.keys()).sort((a, b) => b - a);\r\n\r\n for (const depth of depths) {\r\n const entitiesAtDepth = entitiesByDepth.get(depth)!;\r\n const cteAlias = `${PostgresObjectEntityCteBuilder.CTE_OBJECT_PREFIX}${depth}`;\r\n\r\n // Build CTE for all entities at this depth\r\n const cte = this.buildDepthCte(\r\n entitiesAtDepth,\r\n previousCteAlias,\r\n cteAlias,\r\n mapping,\r\n allEntities\r\n );\r\n\r\n ctes.push(cte);\r\n previousCteAlias = cteAlias;\r\n }\r\n\r\n return { ctes, lastCteAlias: previousCteAlias };\r\n } /**\r\n * Collect all object entities and calculate their depth from root.\r\n * \r\n * Depth calculation is crucial because:\r\n * - It determines the processing order (deepest first)\r\n * - It ensures dependencies are resolved before an entity is processed\r\n * - It allows parallel processing of entities at the same depth level\r\n * \r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n * @returns Array of object entity information with calculated depths\r\n */\r\n private collectAndSortObjectEntities(\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>): ObjectEntityProcessingInfo[] {\r\n const objectInfos: ObjectEntityProcessingInfo[] = [];\r\n\r\n // Helper function to calculate actual object nesting depth for a given OBJECT entity\r\n const calculateActualObjectNestingDepth = (entityIdOfObject: string): number => {\r\n const initialEntity = allEntities.get(entityIdOfObject);\r\n if (!initialEntity) {\r\n throw new Error(`Entity ${entityIdOfObject} not found for depth calculation.`);\r\n }\r\n // If the object itself is root, its depth is 0. (This function should ideally be called for nested entities, not the root itself as a \"parent CTE\" subject)\r\n if (initialEntity.isRoot) return 0;\r\n\r\n // If the object is not root and has no parentId, it's considered a top-level object, depth 1.\r\n if (!initialEntity.parentId) {\r\n return 1;\r\n }\r\n\r\n let currentParentIdInHierarchy: string | undefined = initialEntity.parentId;\r\n let calculatedObjectDepth = 0;\r\n const visitedInPath = new Set<string>();\r\n visitedInPath.add(entityIdOfObject); // Add the starting object itself to detect cycles\r\n\r\n while (currentParentIdInHierarchy) {\r\n if (visitedInPath.has(currentParentIdInHierarchy)) {\r\n throw new Error(`Circular dependency detected: ${currentParentIdInHierarchy} already visited in path for ${entityIdOfObject}`);\r\n }\r\n visitedInPath.add(currentParentIdInHierarchy);\r\n\r\n const parentEntityData = allEntities.get(currentParentIdInHierarchy);\r\n if (!parentEntityData) {\r\n throw new Error(`Parent entity ${currentParentIdInHierarchy} not found during depth calculation for ${entityIdOfObject}`);\r\n }\r\n\r\n let parentIsConsideredAnObjectForNesting = false;\r\n if (parentEntityData.isRoot) {\r\n parentIsConsideredAnObjectForNesting = true; // Root counts as an object ancestor\r\n } else {\r\n // For non-root parents, find their definition in nestedEntities to check their type\r\n const parentDefinition = mapping.nestedEntities.find(ne => ne.id === currentParentIdInHierarchy);\r\n if (parentDefinition) {\r\n if (parentDefinition.relationshipType === \"object\") {\r\n parentIsConsideredAnObjectForNesting = true;\r\n }\r\n // If parentDefinition.relationshipType === \"array\", it's not an object ancestor for depth counting\r\n } else {\r\n // This implies currentParentIdInHierarchy refers to an entity not defined as root or in nestedEntities\r\n // This should ideally not happen with a consistent mapping.\r\n throw new Error(`Parent entity ${currentParentIdInHierarchy} (ancestor of ${entityIdOfObject}) has no definition in mapping.nestedEntities and is not root.`);\r\n }\r\n }\r\n\r\n if (parentIsConsideredAnObjectForNesting) {\r\n calculatedObjectDepth++;\r\n }\r\n\r\n if (parentEntityData.isRoot) {\r\n break; // Stop when the root is processed as the highest object ancestor\r\n }\r\n currentParentIdInHierarchy = parentEntityData.parentId; // Move to the next ancestor\r\n }\r\n return calculatedObjectDepth;\r\n };\r\n\r\n mapping.nestedEntities.forEach(nestedEntity => {\r\n if (nestedEntity.relationshipType === \"object\") {\r\n const entity = allEntities.get(nestedEntity.id);\r\n // Ensure we don't process the root entity itself as a \"parent\" CTE,\r\n // and that the entity actually exists.\r\n if (entity && !entity.isRoot) {\r\n objectInfos.push({\r\n entity,\r\n depth: calculateActualObjectNestingDepth(nestedEntity.id)\r\n });\r\n }\r\n }\r\n });\r\n\r\n // The existing grouping and sorting by depth (b - a for descending) should still work correctly\r\n // as it processes deepest levels first, regardless of the absolute depth numbers.\r\n return objectInfos;\r\n }\r\n\r\n /**\r\n * Group entities by their depth level.\r\n * \r\n * Grouping by depth allows us to:\r\n * - Process all entities at the same level in a single CTE\r\n * - Optimize query performance by reducing the number of CTEs\r\n * - Maintain clear dependency ordering\r\n * \r\n * @param parentInfos Array of parent entity information with depths\r\n * @returns Map of depth level to entities at that depth\r\n */ private groupEntitiesByDepth(\r\n objectInfos: ObjectEntityProcessingInfo[]\r\n ): Map<number, ObjectEntityProcessingInfo[]> {\r\n const entitiesByDepth = new Map<number, ObjectEntityProcessingInfo[]>();\r\n\r\n objectInfos.forEach(info => {\r\n const depth = info.depth;\r\n if (!entitiesByDepth.has(depth)) {\r\n entitiesByDepth.set(depth, []);\r\n }\r\n entitiesByDepth.get(depth)!.push(info);\r\n });\r\n\r\n return entitiesByDepth;\r\n }\r\n\r\n /**\r\n * Build a CTE that processes all entities at a specific depth level\r\n */\r\n private buildDepthCte(\r\n entitiesAtDepth: ObjectEntityProcessingInfo[],\r\n previousCteAlias: string,\r\n cteAlias: string,\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): CommonTable {\r\n // Build SELECT items: * and JSON objects for all entities at this depth\r\n const selectItems: SelectItem[] = [\r\n // Select all columns from previous CTE\r\n new SelectItem(new ColumnReference(null, new IdentifierString(PostgresObjectEntityCteBuilder.WILDCARD_COLUMN)))\r\n ];\r\n\r\n // Process each entity at this depth\r\n for (const { entity } of entitiesAtDepth) {\r\n const jsonColumn = this.buildEntityJsonColumn(entity, mapping, allEntities);\r\n selectItems.push(jsonColumn);\r\n }\r\n\r\n // Create CTE that selects from previous CTE\r\n const cteSelect = new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(previousCteAlias)),\r\n null\r\n ),\r\n null\r\n )\r\n });\r\n\r\n return new CommonTable(cteSelect, new SourceAliasExpression(cteAlias, null), null);\r\n }\r\n\r\n /**\r\n * Build JSON column for a single entity with NULL handling\r\n */\r\n private buildEntityJsonColumn(\r\n entity: ProcessableEntity,\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): SelectItem {\r\n // Build JSON object arguments and NULL checks\r\n const { jsonObjectArgs, nullChecks } = this.prepareEntityColumns(entity);\r\n\r\n // Add child object relationships\r\n this.addChildObjectRelationships(entity, jsonObjectArgs, mapping, allEntities);\r\n\r\n // Create JSON object\r\n const jsonObject = this.createJsonObject(jsonObjectArgs, mapping.useJsonb);\r\n\r\n // Build NULL condition and CASE expression\r\n const nullCondition = this.buildNullCondition(nullChecks);\r\n const caseExpr = this.createCaseExpression(nullCondition, jsonObject);\r\n\r\n // Add JSON object as named column\r\n const jsonColumnName = `${entity.name.toLowerCase()}${PostgresObjectEntityCteBuilder.JSON_COLUMN_SUFFIX}`;\r\n return new SelectItem(caseExpr, jsonColumnName);\r\n }\r\n\r\n /**\r\n * Prepare entity columns and NULL checks.\r\n * \r\n * This method extracts column data and creates NULL checks for each column.\r\n * The NULL checking is essential for handling outer joins correctly.\r\n * \r\n * In outer join scenarios, when there's no matching row in the joined table,\r\n * all columns from that table will be NULL. Instead of creating an empty object\r\n * with all NULL properties (e.g., {id: null, name: null, email: null}),\r\n * we want to represent the absence of the entity as NULL itself.\r\n * \r\n * This ensures cleaner JSON output where missing relationships are represented\r\n * as NULL rather than objects with all NULL fields.\r\n * \r\n * @param entity The entity whose columns are being processed\r\n * @returns Object containing arrays of JSON object arguments and NULL check conditions\r\n */\r\n private prepareEntityColumns(entity: ProcessableEntity): {\r\n jsonObjectArgs: ValueComponent[],\r\n nullChecks: ValueComponent[]\r\n } {\r\n const jsonObjectArgs: ValueComponent[] = [];\r\n const nullChecks: ValueComponent[] = [];\r\n\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n jsonObjectArgs.push(new LiteralValue(jsonKey));\r\n jsonObjectArgs.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n\r\n // Collect NULL checks for each column\r\n nullChecks.push(\r\n new BinaryExpression(\r\n new ColumnReference(null, new IdentifierString(sqlColumn)),\r\n \"is\",\r\n new LiteralValue(null)\r\n )\r\n );\r\n });\r\n\r\n return { jsonObjectArgs, nullChecks };\r\n }\r\n\r\n /**\r\n * Add child object relationships to JSON object arguments.\r\n * \r\n * This method processes nested object-type entities that are direct children of the current entity.\r\n * For each child entity, it adds the property name and corresponding JSON column reference\r\n * to the arguments array that will be used to build the parent's JSON object.\r\n * \r\n * The child JSON columns are expected to already exist in the data source (created by deeper\r\n * level CTEs), as we process from the deepest level up to the root.\r\n * \r\n * Note: In this context, \"child\" refers to entities that have an object relationship (0..1)\r\n * with their parent. From a data perspective, these are typically entities referenced via\r\n * foreign keys, representing \"parent\" entities in traditional database terminology.\r\n * \r\n * @param entity The current entity being processed\r\n * @param jsonObjectArgs Array to which JSON object arguments will be added\r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n */\r\n private addChildObjectRelationships(\r\n entity: ProcessableEntity,\r\n jsonObjectArgs: ValueComponent[],\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): void {\r\n const childEntities = mapping.nestedEntities.filter(ne =>\r\n ne.parentId === entity.id && ne.relationshipType === \"object\"\r\n );\r\n\r\n childEntities.forEach(childEntity => {\r\n const child = allEntities.get(childEntity.id);\r\n if (child) {\r\n jsonObjectArgs.push(new LiteralValue(childEntity.propertyName));\r\n const jsonColumnName = `${child.name.toLowerCase()}${PostgresObjectEntityCteBuilder.JSON_COLUMN_SUFFIX}`;\r\n jsonObjectArgs.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Create JSON object function call\r\n */\r\n private createJsonObject(args: ValueComponent[], useJsonb: boolean = false): FunctionCall {\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n return new FunctionCall(\r\n null,\r\n new RawString(jsonBuildFunction),\r\n new ValueList(args),\r\n null\r\n );\r\n }\r\n\r\n /**\r\n * Build NULL condition from NULL checks\r\n */\r\n private buildNullCondition(nullChecks: ValueComponent[]): ValueComponent {\r\n return nullChecks.reduce((acc, check) =>\r\n acc ? new BinaryExpression(acc, \"and\", check) : check\r\n );\r\n }\r\n\r\n /**\r\n * Create CASE expression with NULL handling\r\n */\r\n private createCaseExpression(nullCondition: ValueComponent, jsonObject: ValueComponent): CaseExpression {\r\n return new CaseExpression(\r\n null,\r\n new SwitchCaseArgument(\r\n [new CaseKeyValuePair(nullCondition, new LiteralValue(null))],\r\n jsonObject // ELSE return the JSON object\r\n )\r\n );\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource, GroupByClause } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, RawString } from '../models/ValueComponent';\r\nimport { JsonMapping } from './PostgresJsonQueryBuilder';\r\nimport { ProcessableEntity } from './PostgresObjectEntityCteBuilder';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\n\r\n/**\r\n * Information for array entity processing\r\n */\r\ninterface ArrayEntityProcessingInfo {\r\n entity: ProcessableEntity;\r\n parentEntity: ProcessableEntity;\r\n parentIdColumnSqlName: string;\r\n depth: number;\r\n}\r\n\r\n/**\r\n * PostgreSQL-specific builder for creating CTEs for array entities (array relationships).\r\n * This class handles the creation of CTEs that build JSON/JSONB arrays for child entities,\r\n * processing them from the deepest level up to ensure proper dependency ordering.\r\n * \r\n * Features:\r\n * - Depth-based CTE naming (cte_array_depth_N)\r\n * - Row compression using GROUP BY operations\r\n * - JSONB/JSON array aggregation\r\n * - Hierarchical processing of nested arrays\r\n * - Column exclusion to avoid duplication\r\n * \r\n * Why depth calculation is critical:\r\n * 1. Array entities can be nested at multiple levels. We must process the deepest\r\n * (most distant) arrays first to ensure their JSON representations are available\r\n * when building their parent arrays.\r\n * 2. Array entity processing is essentially a row compression operation using GROUP BY.\r\n * Unlike parent entities which use column compression, arrays require grouping\r\n * to aggregate multiple rows into JSON arrays.\r\n * \r\n * Example hierarchy:\r\n * Order (root, depth 0)\r\n * \u2514\u2500 Items (array, depth 1)\r\n * \u2514\u2500 Details (array, depth 2)\r\n * \r\n * Processing order: depth 2 \u2192 depth 1 \u2192 depth 0\r\n */\r\nexport class PostgresArrayEntityCteBuilder {\r\n // Constants for consistent naming conventions\r\n private static readonly CTE_ARRAY_PREFIX = 'cte_array_depth_';\r\n\r\n /**\r\n * Build CTEs for all array entities in the correct dependency order\r\n * @param ctesSoFar Array of CTEs built so far (starts with the initial CTE)\r\n * @param aliasOfCteToBuildUpon Alias of the CTE from which the current array CTE will select\r\n * @param allEntities Map of all entities in the mapping\r\n * @param mapping The JSON mapping configuration\r\n * @returns Object containing the updated list of all CTEs and the alias of the last CTE created\r\n */\r\n public buildArrayEntityCtes(\r\n ctesSoFar: CommonTable[],\r\n aliasOfCteToBuildUpon: string,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): { updatedCtes: CommonTable[], lastCteAlias: string } {\r\n let currentCtes = [...ctesSoFar];\r\n let currentCteAlias = aliasOfCteToBuildUpon;\r\n\r\n // Collect and sort array entities by depth\r\n const sortedArrayInfos = this.collectAndSortArrayEntities(mapping, allEntities);\r\n\r\n if (sortedArrayInfos.length === 0) {\r\n return { updatedCtes: currentCtes, lastCteAlias: currentCteAlias };\r\n }\r\n\r\n // Group array entities by depth level for batch processing\r\n const entitiesByDepth = this.groupEntitiesByDepth(sortedArrayInfos);\r\n\r\n // Process from deepest to shallowest (depth-first)\r\n const depths = Array.from(entitiesByDepth.keys()).sort((a, b) => b - a);\r\n\r\n for (const depth of depths) {\r\n const infos = entitiesByDepth.get(depth)!;\r\n\r\n // Build CTE for all entities at this depth\r\n const { cte, newCteAlias } = this.buildDepthCte(\r\n infos,\r\n currentCteAlias,\r\n currentCtes,\r\n depth,\r\n mapping\r\n );\r\n\r\n currentCtes.push(cte);\r\n currentCteAlias = newCteAlias;\r\n }\r\n\r\n return { updatedCtes: currentCtes, lastCteAlias: currentCteAlias };\r\n }\r\n\r\n /**\r\n * Collect all array entities and calculate their depth from root.\r\n * \r\n * Depth calculation ensures proper processing order where deeper nested\r\n * arrays are processed first, making their aggregated data available\r\n * for parent array processing.\r\n * \r\n * @param mapping The JSON mapping configuration\r\n * @param allEntities Map of all entities in the mapping\r\n * @returns Array of array entity information with calculated depths, sorted deepest first\r\n */\r\n private collectAndSortArrayEntities(\r\n mapping: JsonMapping,\r\n allEntities: Map<string, ProcessableEntity>\r\n ): ArrayEntityProcessingInfo[] {\r\n const arrayEntityInfos: ArrayEntityProcessingInfo[] = [];\r\n\r\n // Helper function to calculate depth for an entity\r\n const getDepth = (entityId: string): number => {\r\n const entity = allEntities.get(entityId);\r\n if (!entity || entity.isRoot) return 0;\r\n if (!entity.parentId) return 1;\r\n return 1 + getDepth(entity.parentId);\r\n };\r\n\r\n // Collect all array-type nested entities\r\n mapping.nestedEntities.forEach(ne => {\r\n if (ne.relationshipType === \"array\") {\r\n const currentArrayEntity = allEntities.get(ne.id);\r\n const parentEntity = allEntities.get(ne.parentId!);\r\n\r\n if (!currentArrayEntity || !parentEntity) {\r\n throw new Error(`Configuration error: Array entity '${ne.id}' or its parent '${ne.parentId}' not found.`);\r\n }\r\n\r\n // Determine the linking column from parent entity\r\n // This assumes the first column of the parent is a suitable key for linking.\r\n // More robust linking might require explicit configuration in the mapping.\r\n const parentSqlColumns = Object.values(parentEntity.columns);\r\n if (parentSqlColumns.length === 0) {\r\n throw new Error(`Configuration error: Parent entity '${parentEntity.name}' (ID: ${parentEntity.id}) must have at least one column defined to serve as a linking key for child array '${ne.name}'.`);\r\n }\r\n const parentIdColumnSqlName = parentSqlColumns[0];\r\n\r\n arrayEntityInfos.push({\r\n entity: currentArrayEntity,\r\n parentEntity: parentEntity,\r\n parentIdColumnSqlName: parentIdColumnSqlName,\r\n depth: getDepth(ne.id)\r\n });\r\n }\r\n });\r\n\r\n // Sort by depth, deepest arrays (higher depth number) processed first (bottom-up for arrays)\r\n arrayEntityInfos.sort((a, b) => b.depth - a.depth);\r\n return arrayEntityInfos;\r\n }\r\n\r\n /**\r\n * Group array entities by their depth level.\r\n * \r\n * Grouping by depth allows us to:\r\n * - Process all entities at the same level in a single CTE\r\n * - Optimize query performance by reducing the number of CTEs\r\n * - Maintain clear dependency ordering\r\n * \r\n * @param arrayInfos Array of array entity information with depths\r\n * @returns Map of depth level to entities at that depth\r\n */\r\n private groupEntitiesByDepth(\r\n arrayInfos: ArrayEntityProcessingInfo[]\r\n ): Map<number, ArrayEntityProcessingInfo[]> {\r\n const entitiesByDepth = new Map<number, ArrayEntityProcessingInfo[]>();\r\n\r\n arrayInfos.forEach(info => {\r\n const depth = info.depth;\r\n if (!entitiesByDepth.has(depth)) {\r\n entitiesByDepth.set(depth, []);\r\n }\r\n entitiesByDepth.get(depth)!.push(info);\r\n });\r\n\r\n return entitiesByDepth;\r\n }\r\n\r\n /**\r\n * Build a CTE that processes all array entities at a specific depth level.\r\n * \r\n * This method creates a single CTE that aggregates multiple array entities\r\n * at the same depth, using GROUP BY to compress rows into JSON arrays.\r\n * \r\n * @param infos Array entities at this depth level\r\n * @param currentCteAlias Alias of the CTE to build upon\r\n * @param currentCtes All CTEs built so far\r\n * @param depth Current depth level being processed\r\n * @param mapping JSON mapping configuration\r\n * @returns The new CTE and its alias\r\n */\r\n private buildDepthCte(\r\n infos: ArrayEntityProcessingInfo[],\r\n currentCteAlias: string,\r\n currentCtes: CommonTable[],\r\n depth: number,\r\n mapping: JsonMapping\r\n ): { cte: CommonTable, newCteAlias: string } {\r\n // Collect columns that will be compressed into arrays\r\n const arrayColumns = new Set<string>();\r\n infos.forEach(info => {\r\n Object.values(info.entity.columns).forEach(col => arrayColumns.add(col));\r\n });\r\n\r\n // Get columns from previous CTE\r\n const prevCte = currentCtes.find(c => c.aliasExpression.table.name === currentCteAlias)?.query;\r\n if (!prevCte) {\r\n throw new Error(`CTE not found: ${currentCteAlias}`);\r\n }\r\n\r\n const prevSelects = new SelectValueCollector(null, currentCtes).collect(prevCte);\r\n\r\n // Build SELECT items: columns that are NOT being compressed (for GROUP BY)\r\n const groupByItems: ValueComponent[] = [];\r\n const selectItems: SelectItem[] = [];\r\n\r\n prevSelects.forEach(sv => {\r\n if (!arrayColumns.has(sv.name)) {\r\n selectItems.push(new SelectItem(new ColumnReference(null, new IdentifierString(sv.name)), sv.name));\r\n groupByItems.push(new ColumnReference(null, new IdentifierString(sv.name)));\r\n }\r\n });\r\n\r\n // Add JSON aggregation columns for each array entity at this depth\r\n for (const info of infos) {\r\n const agg = this.buildAggregationDetailsForArrayEntity(\r\n info.entity,\r\n mapping.nestedEntities,\r\n new Map(), // allEntities - not needed for array aggregation\r\n mapping.useJsonb\r\n );\r\n selectItems.push(new SelectItem(agg.jsonAgg, info.entity.propertyName));\r\n }\r\n\r\n // Create the new CTE\r\n const cteAlias = `${PostgresArrayEntityCteBuilder.CTE_ARRAY_PREFIX}${depth}`;\r\n const cteSelect = new SimpleSelectQuery({\r\n selectClause: new SelectClause(selectItems),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(currentCteAlias)),\r\n null\r\n ),\r\n null\r\n ),\r\n groupByClause: groupByItems.length > 0 ? new GroupByClause(groupByItems) : null,\r\n });\r\n\r\n const cte = new CommonTable(cteSelect, new SourceAliasExpression(cteAlias, null), null);\r\n\r\n return { cte, newCteAlias: cteAlias };\r\n }\r\n\r\n /**\r\n * Build JSON aggregation function for an array entity.\r\n * \r\n * This method creates a jsonb_agg or json_agg function call that aggregates\r\n * the entity's columns into a JSON array. It also handles nested relationships\r\n * by including child entity properties in the JSON object.\r\n * \r\n * @param entity The array entity being processed\r\n * @param nestedEntities All nested entities from the mapping\r\n * @param allEntities Map of all entities (not used in current implementation)\r\n * @param useJsonb Whether to use JSONB functions\r\n * @returns Object containing the JSON aggregation function\r\n */\r\n private buildAggregationDetailsForArrayEntity(\r\n entity: ProcessableEntity,\r\n nestedEntities: any[],\r\n allEntities: Map<string, ProcessableEntity>,\r\n useJsonb: boolean = false\r\n ): { jsonAgg: ValueComponent } {\r\n // Build JSON object for array elements\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n const args: ValueComponent[] = [];\r\n\r\n // Add the entity's own columns\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n args.push(new LiteralValue(jsonKey));\r\n args.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n });\r\n\r\n // Find and process child entities (both object and array types)\r\n const childEntities = nestedEntities.filter((ne) => ne.parentId === entity.id);\r\n\r\n childEntities.forEach((childEntity) => {\r\n args.push(new LiteralValue(childEntity.propertyName));\r\n\r\n if (childEntity.relationshipType === \"object\") {\r\n // For object relationships, use pre-computed JSON column\r\n const jsonColumnName = `${childEntity.name.toLowerCase()}_json`;\r\n args.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n } else if (childEntity.relationshipType === \"array\") {\r\n // For array relationships, use the column directly\r\n args.push(new ColumnReference(null, new IdentifierString(childEntity.propertyName)));\r\n }\r\n });\r\n\r\n // Create JSON object\r\n const jsonObject = new FunctionCall(null, new RawString(jsonBuildFunction), new ValueList(args), null);\r\n\r\n // Create JSON aggregation\r\n const jsonAggFunction = useJsonb ? \"jsonb_agg\" : \"json_agg\";\r\n const jsonAgg = new FunctionCall(\r\n null,\r\n new RawString(jsonAggFunction),\r\n new ValueList([jsonObject]),\r\n null\r\n );\r\n\r\n return { jsonAgg };\r\n }\r\n}\r\n", "import { CommonTable, SourceAliasExpression, SelectItem, SelectClause, FromClause, SourceExpression, TableSource, GroupByClause, WithClause, SubQuerySource, LimitClause } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { IdentifierString, ValueComponent, ColumnReference, FunctionCall, ValueList, LiteralValue, BinaryExpression, CaseExpression, SwitchCaseArgument, CaseKeyValuePair, RawString, UnaryExpression } from '../models/ValueComponent';\r\nimport { SelectValueCollector } from \"./SelectValueCollector\";\r\nimport { PostgresObjectEntityCteBuilder, ProcessableEntity } from './PostgresObjectEntityCteBuilder';\r\nimport { PostgresArrayEntityCteBuilder } from './PostgresArrayEntityCteBuilder';\r\n\r\n/**\r\n * Universal JSON mapping definition for creating any level of JSON structures.\r\n * Supports flat arrays, nested objects, and unlimited hierarchical structures.\r\n */\r\nexport interface JsonMapping {\r\n rootName: string;\r\n rootEntity: {\r\n id: string;\r\n name: string;\r\n columns: { [jsonKey: string]: string };\r\n };\r\n nestedEntities: Array<{\r\n id: string;\r\n name: string;\r\n parentId: string;\r\n propertyName: string;\r\n relationshipType?: \"object\" | \"array\";\r\n columns: { [jsonKey: string]: string };\r\n }>;\r\n useJsonb?: boolean;\r\n resultFormat?: \"array\" | \"single\";\r\n emptyResult?: string;\r\n}\r\n\r\n/**\r\n * PostgreSQL JSON query builder that transforms SimpleSelectQuery into queries\r\n * that return JSON arrays or single JSON objects using PostgreSQL JSON functions.\r\n */\r\nexport class PostgresJsonQueryBuilder {\r\n private selectValueCollector: SelectValueCollector;\r\n private objectEntityCteBuilder: PostgresObjectEntityCteBuilder;\r\n private arrayEntityCteBuilder: PostgresArrayEntityCteBuilder; constructor() {\r\n this.selectValueCollector = new SelectValueCollector(null);\r\n this.objectEntityCteBuilder = new PostgresObjectEntityCteBuilder();\r\n this.arrayEntityCteBuilder = new PostgresArrayEntityCteBuilder();\r\n }\r\n\r\n /**\r\n * Validates the JSON mapping and the original query.\r\n * @param query Original query to transform\r\n * @param mapping JSON mapping configuration\r\n */\r\n private validateMapping(query: SimpleSelectQuery, mapping: JsonMapping): void {\r\n const collector = new SelectValueCollector();\r\n const selectedValues = collector.collect(query);\r\n\r\n // sv.name is the alias or derived name\r\n const availableColumns = new Set(selectedValues.map(sv => sv.name));\r\n\r\n // Check root entity columns\r\n for (const jsonKey in mapping.rootEntity.columns) {\r\n const sourceColumn = mapping.rootEntity.columns[jsonKey];\r\n if (!availableColumns.has(sourceColumn)) {\r\n throw new Error(`Validation Error: Column \"${sourceColumn}\" for JSON key \"${jsonKey}\" in root entity \"${mapping.rootEntity.name}\" not found in the query's select list.`);\r\n }\r\n }\r\n\r\n // Check nested entity columns and parent-child relationships\r\n const entityIds = new Set<string>([mapping.rootEntity.id]);\r\n const parentToChildrenMap = new Map<string, string[]>();\r\n\r\n mapping.nestedEntities.forEach(ne => {\r\n entityIds.add(ne.id);\r\n if (!parentToChildrenMap.has(ne.parentId)) {\r\n parentToChildrenMap.set(ne.parentId, []);\r\n }\r\n parentToChildrenMap.get(ne.parentId)!.push(ne.id);\r\n });\r\n\r\n for (const entity of mapping.nestedEntities) {\r\n if (!entityIds.has(entity.parentId)) {\r\n throw new Error(`Validation Error: Parent entity with ID \"${entity.parentId}\" for nested entity \"${entity.name}\" (ID: ${entity.id}) not found.`);\r\n }\r\n for (const jsonKey in entity.columns) {\r\n const sourceColumn = entity.columns[jsonKey];\r\n if (!availableColumns.has(sourceColumn)) {\r\n throw new Error(`Validation Error: Column \"${sourceColumn}\" for JSON key \"${jsonKey}\" in nested entity \"${entity.name}\" (ID: ${entity.id}) not found in the query's select list.`);\r\n }\r\n }\r\n }\r\n\r\n // Validate: An entity should not have multiple direct array children.\r\n // Validate: Child propertyNames under a single parent must be unique.\r\n const allParentIds = new Set([mapping.rootEntity.id, ...mapping.nestedEntities.map(ne => ne.parentId)]);\r\n for (const parentId of allParentIds) {\r\n const directChildren = mapping.nestedEntities.filter(ne => ne.parentId === parentId);\r\n const directArrayChildrenCount = directChildren.filter(c => c.relationshipType === 'array').length;\r\n if (directArrayChildrenCount > 1) {\r\n const parentName = parentId === mapping.rootEntity.id ? mapping.rootEntity.name : mapping.nestedEntities.find(ne => ne.id === parentId)?.name;\r\n throw new Error(`Validation Error: Parent entity \"${parentName}\" (ID: ${parentId}) has multiple direct array children. This is not supported.`);\r\n }\r\n\r\n const propertyNames = new Set<string>();\r\n for (const child of directChildren) {\r\n if (propertyNames.has(child.propertyName)) {\r\n const parentName = parentId === mapping.rootEntity.id ? mapping.rootEntity.name : mapping.nestedEntities.find(ne => ne.id === parentId)?.name;\r\n throw new Error(`Validation Error: Parent entity \"${parentName}\" (ID: ${parentId}) has duplicate property name \"${child.propertyName}\" for its children.`);\r\n }\r\n propertyNames.add(child.propertyName);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Build JSON query from original query and mapping configuration.\r\n * @param originalQuery Original query to transform\r\n * @param mapping JSON mapping configuration\r\n * @returns Transformed query with JSON aggregation\r\n */\r\n public buildJsonQuery(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery {\r\n return this.buildJsonWithCteStrategy(originalQuery, mapping);\r\n }\r\n\r\n /**\r\n * Build JSON query from original query and mapping configuration.\r\n * @deprecated Use buildJsonQuery instead. This method will be removed in a future version.\r\n * @param originalQuery Original query to transform\r\n * @param mapping JSON mapping configuration\r\n * @returns Transformed query with JSON aggregation\r\n */\r\n public buildJson(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery {\r\n console.warn('buildJson is deprecated. Use buildJsonQuery instead.');\r\n return this.buildJsonQuery(originalQuery, mapping);\r\n }\r\n\r\n /**\r\n * Builds the JSON structure using a unified CTE-based strategy.\r\n * @param originalQuery Original query\r\n * @param mapping JSON mapping configuration\r\n * @returns Query with CTE-based JSON aggregation\r\n */\r\n private buildJsonWithCteStrategy(\r\n originalQuery: SimpleSelectQuery,\r\n mapping: JsonMapping,\r\n ): SimpleSelectQuery {\r\n this.validateMapping(originalQuery, mapping);\r\n\r\n // Step 1: Create the initial CTE from the original query\r\n const { initialCte, initialCteAlias } = this.createInitialCte(originalQuery);\r\n\r\n let ctesForProcessing: CommonTable[] = [initialCte];\r\n let currentAliasToBuildUpon = initialCteAlias;\r\n\r\n // Step 2: Prepare entity information\r\n const allEntities = new Map<string, ProcessableEntity>();\r\n allEntities.set(mapping.rootEntity.id, { ...mapping.rootEntity, isRoot: true, propertyName: mapping.rootName });\r\n mapping.nestedEntities.forEach(ne => allEntities.set(ne.id, { ...ne, isRoot: false, propertyName: ne.propertyName })); // Step 2.5: Build CTEs for object entities using dedicated builder\r\n const objectEntityResult = this.objectEntityCteBuilder.buildObjectEntityCtes(\r\n initialCte,\r\n allEntities,\r\n mapping\r\n );\r\n // Important: Replace the entire CTE list with the result from object entity builder\r\n // The object entity builder returns all CTEs including the initial one\r\n ctesForProcessing = objectEntityResult.ctes;\r\n currentAliasToBuildUpon = objectEntityResult.lastCteAlias;\r\n\r\n // Step 3: Build CTEs for array entities using dedicated builder\r\n const arrayCteBuildResult = this.arrayEntityCteBuilder.buildArrayEntityCtes(\r\n ctesForProcessing,\r\n currentAliasToBuildUpon,\r\n allEntities,\r\n mapping\r\n );\r\n ctesForProcessing = arrayCteBuildResult.updatedCtes;\r\n currentAliasToBuildUpon = arrayCteBuildResult.lastCteAlias;\r\n\r\n // Step 4: Build the final SELECT query using all generated CTEs\r\n return this.buildFinalSelectQuery(\r\n ctesForProcessing,\r\n currentAliasToBuildUpon,\r\n allEntities,\r\n mapping\r\n );\r\n }\r\n\r\n /**\r\n * Creates the initial Common Table Expression (CTE) from the original query.\r\n * @param originalQuery The base SimpleSelectQuery.\r\n * @returns An object containing the initial CTE and its alias.\r\n */\r\n private createInitialCte(originalQuery: SimpleSelectQuery): { initialCte: CommonTable, initialCteAlias: string } {\r\n const originCteAlias = \"origin_query\";\r\n const originCte = new CommonTable(\r\n originalQuery,\r\n new SourceAliasExpression(originCteAlias, null),\r\n null\r\n );\r\n return { initialCte: originCte, initialCteAlias: originCteAlias };\r\n }\r\n\r\n /**\r\n * Builds the final SELECT query that constructs the root JSON object (or array of objects).\r\n * This query uses all previously generated CTEs.\r\n * @param finalCtesList The complete list of all CTEs (initial and array CTEs).\r\n * @param lastCteAliasForFromClause Alias of the final CTE from which the root object will be built.\r\n * @param allEntities Map of all processable entities.\r\n * @param mapping JSON mapping configuration.\r\n * @returns The final SimpleSelectQuery.\r\n */\r\n private buildFinalSelectQuery(\r\n finalCtesList: CommonTable[],\r\n lastCteAliasForFromClause: string,\r\n allEntities: Map<string, ProcessableEntity>,\r\n mapping: JsonMapping\r\n ): SimpleSelectQuery {\r\n const currentCtes = [...finalCtesList];\r\n\r\n // Define rootObjectCteAlias outside of if block\r\n const rootObjectCteAlias = `cte_root_${mapping.rootName.toLowerCase().replace(/[^a-z0-9_]/g, '_')}`;\r\n const rootEntity = allEntities.get(mapping.rootEntity.id);\r\n if (!rootEntity) {\r\n throw new Error(`Root entity ${mapping.rootEntity.id} not found`);\r\n }\r\n\r\n if (mapping.resultFormat === \"array\" || !mapping.resultFormat) {\r\n // Step 4.1a: Create a CTE that wraps the final result as the root object\r\n // No alias needed for single table SELECT\r\n const rootObjectBuilderExpression = this.buildEntityJsonObject(\r\n rootEntity,\r\n null, // No source alias for single table\r\n mapping.nestedEntities,\r\n allEntities,\r\n mapping.useJsonb\r\n );\r\n\r\n const rootObjectSelectItem = new SelectItem(rootObjectBuilderExpression, mapping.rootName);\r\n const rootObjectCte = new CommonTable(\r\n new SimpleSelectQuery({\r\n selectClause: new SelectClause([rootObjectSelectItem]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(lastCteAliasForFromClause)),\r\n null // No alias\r\n ),\r\n null\r\n ),\r\n }),\r\n new SourceAliasExpression(rootObjectCteAlias, null),\r\n null\r\n );\r\n currentCtes.push(rootObjectCte);\r\n\r\n // Step 4.1b: Aggregate all the root objects\r\n const aggregationFunc = mapping.useJsonb ? \"jsonb_agg\" : \"json_agg\";\r\n const aggregateExpression = new FunctionCall(\r\n null,\r\n new RawString(aggregationFunc),\r\n new ValueList([new ColumnReference(null, new IdentifierString(mapping.rootName))]),\r\n null\r\n );\r\n\r\n return new SimpleSelectQuery({\r\n withClause: new WithClause(false, currentCtes),\r\n selectClause: new SelectClause([\r\n new SelectItem(aggregateExpression, `${mapping.rootName}_array`)\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(new TableSource(null, new IdentifierString(rootObjectCteAlias)), null),\r\n null\r\n ),\r\n });\r\n } else {\r\n // For a single object result, create root object CTE without alias\r\n const rootObjectBuilderExpression = this.buildEntityJsonObject(\r\n rootEntity,\r\n null, // No source alias for single table\r\n mapping.nestedEntities,\r\n allEntities,\r\n mapping.useJsonb\r\n );\r\n\r\n const rootObjectSelectItem = new SelectItem(rootObjectBuilderExpression, mapping.rootName);\r\n const rootObjectCte = new CommonTable(\r\n new SimpleSelectQuery({\r\n selectClause: new SelectClause([rootObjectSelectItem]),\r\n fromClause: new FromClause(\r\n new SourceExpression(\r\n new TableSource(null, new IdentifierString(lastCteAliasForFromClause)),\r\n null // No alias\r\n ),\r\n null\r\n ),\r\n }),\r\n new SourceAliasExpression(rootObjectCteAlias, null),\r\n null\r\n );\r\n currentCtes.push(rootObjectCte);\r\n\r\n // Select directly from the root_object_cte with LIMIT 1\r\n return new SimpleSelectQuery({\r\n withClause: new WithClause(false, currentCtes),\r\n selectClause: new SelectClause([\r\n new SelectItem(new ColumnReference(null, new IdentifierString(mapping.rootName)), mapping.rootName)\r\n ]),\r\n fromClause: new FromClause(\r\n new SourceExpression(new TableSource(null, new IdentifierString(rootObjectCteAlias)), null),\r\n null\r\n ),\r\n limitClause: new LimitClause(new LiteralValue(1)) // Correctly use LimitClause\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Build JSON object for entity, using parent JSON columns when available\r\n */\r\n private buildEntityJsonObject(\r\n entity: ProcessableEntity,\r\n sourceAlias: string | null,\r\n nestedEntities: JsonMapping['nestedEntities'],\r\n allEntities: Map<string, ProcessableEntity>,\r\n useJsonb: boolean = false\r\n ): ValueComponent {\r\n const jsonBuildFunction = useJsonb ? \"jsonb_build_object\" : \"json_build_object\";\r\n const args: ValueComponent[] = []; // Add the entity's own columns\r\n Object.entries(entity.columns).forEach(([jsonKey, sqlColumn]) => {\r\n args.push(new LiteralValue(jsonKey));\r\n args.push(new ColumnReference(null, new IdentifierString(sqlColumn)));\r\n });\r\n\r\n // Find and process child entities (both object and array types)\r\n const childEntities = nestedEntities.filter((ne) => ne.parentId === entity.id);\r\n\r\n childEntities.forEach((childEntity) => {\r\n const child = allEntities.get(childEntity.id);\r\n if (!child) return;\r\n\r\n args.push(new LiteralValue(childEntity.propertyName)); if (childEntity.relationshipType === \"object\") {\r\n // For object relationships, use pre-computed JSON column\r\n const jsonColumnName = `${child.name.toLowerCase()}_json`;\r\n args.push(new ColumnReference(null, new IdentifierString(jsonColumnName)));\r\n } else if (childEntity.relationshipType === \"array\") {\r\n // For array relationships, use the column directly\r\n args.push(new ColumnReference(null, new IdentifierString(childEntity.propertyName)));\r\n }\r\n });\r\n\r\n return new FunctionCall(null, new RawString(jsonBuildFunction), new ValueList(args), null);\r\n }\r\n}", "import { SqlComponent, SqlComponentVisitor } from '../models/SqlComponent';\r\nimport { CommonTable, SubQuerySource, TableSource } from '../models/Clause';\r\nimport { SelectClause, SelectItem } from '../models/Clause';\r\nimport { SimpleSelectQuery } from '../models/SimpleSelectQuery';\r\nimport { CTECollector } from './CTECollector';\r\nimport { SelectableColumnCollector, DuplicateDetectionMode } from './SelectableColumnCollector';\r\nimport { SelectValueCollector } from './SelectValueCollector';\r\nimport { ColumnReference } from '../models/ValueComponent';\r\nimport { BinarySelectQuery, SelectQuery } from '../models/SelectQuery';\r\nimport { SourceExpression } from '../models/Clause';\r\nimport { TableColumnResolver } from './TableColumnResolver';\r\n\r\nexport class TableSchema {\r\n public name: string;\r\n public columns: string[];\r\n\r\n constructor(name: string, columns: string[]) {\r\n this.name = name;\r\n this.columns = columns;\r\n }\r\n}\r\n\r\n/**\r\n * A visitor that collects schema information (table names and column names) from a SQL query structure.\r\n */\r\nexport class SchemaCollector implements SqlComponentVisitor<void> {\r\n private handlers: Map<symbol, (arg: any) => void>;\r\n\r\n private tableSchemas: TableSchema[] = [];\r\n private visitedNodes: Set<SqlComponent> = new Set();\r\n private commonTables: CommonTable[] = [];\r\n private running = false;\r\n\r\n constructor(private tableColumnResolver: TableColumnResolver | null = null) {\r\n this.handlers = new Map<symbol, (arg: any) => void>();\r\n\r\n // Setup handlers for query components\r\n this.handlers.set(SimpleSelectQuery.kind, (expr) => this.visitSimpleSelectQuery(expr as SimpleSelectQuery));\r\n this.handlers.set(BinarySelectQuery.kind, (expr) => this.visitBinarySelectQuery(expr as BinarySelectQuery));\r\n }\r\n\r\n /**\r\n * Collects schema information (table names and column names) from a SQL query structure.\r\n * This method ensures that the collected schema information is unique and sorted.\r\n * The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n *\r\n * @param arg The SQL query structure to analyze.\r\n */\r\n public collect(arg: SqlComponent): TableSchema[] {\r\n this.visit(arg);\r\n return this.tableSchemas;\r\n }\r\n\r\n /**\r\n * Main entry point for the visitor pattern.\r\n * Implements the shallow visit pattern to distinguish between root and recursive visits.\r\n *\r\n * This method ensures that schema information is collected uniquely and sorted.\r\n * The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n *\r\n * @param arg The SQL component to visit.\r\n */\r\n public visit(arg: SqlComponent): void {\r\n // If not a root visit, just visit the node and return\r\n if (this.running) {\r\n this.visitNode(arg);\r\n return;\r\n }\r\n\r\n // If this is a root visit, we need to reset the state\r\n this.reset();\r\n this.running = true;\r\n\r\n try {\r\n // Ensure the argument is a SelectQuery\r\n if (!(arg instanceof SimpleSelectQuery || arg instanceof BinarySelectQuery)) {\r\n throw new Error(`Unsupported SQL component type for schema collection. Received: ${arg.constructor.name}. Expected: SimpleSelectQuery or BinarySelectQuery.`);\r\n }\r\n\r\n // Collects Common Table Expressions (CTEs) using CTECollector\r\n const cteCollector = new CTECollector();\r\n this.commonTables = cteCollector.collect(arg);\r\n\r\n this.visitNode(arg);\r\n\r\n // Consolidate tableSchemas\r\n this.consolidateTableSchemas();\r\n } finally {\r\n // Regardless of success or failure, reset the root visit flag\r\n this.running = false;\r\n }\r\n }\r\n\r\n /**\r\n * Internal visit method used for all nodes.\r\n * This separates the visit flag management from the actual node visitation logic.\r\n */\r\n private visitNode(arg: SqlComponent): void {\r\n // Skip if we've already visited this node to prevent infinite recursion\r\n if (this.visitedNodes.has(arg)) {\r\n return;\r\n }\r\n\r\n // Mark as visited\r\n this.visitedNodes.add(arg);\r\n\r\n const handler = this.handlers.get(arg.getKind());\r\n if (handler) {\r\n handler(arg);\r\n return;\r\n }\r\n\r\n // If no handler found, that's ok - we only care about specific components\r\n }\r\n\r\n /**\r\n * Resets the state of the collector for a new root visit.\r\n */\r\n private reset(): void {\r\n this.tableSchemas = [];\r\n this.visitedNodes = new Set();\r\n this.commonTables = [];\r\n }\r\n\r\n /**\r\n * Consolidates table schemas by merging columns for tables with the same name.\r\n * This ensures that each table name appears only once in the final schema list,\r\n * with all its columns combined while removing duplicates.\r\n *\r\n * Note: The resulting schemas and columns are sorted alphabetically to ensure deterministic ordering.\r\n */\r\n private consolidateTableSchemas(): void {\r\n const consolidatedSchemas: Map<string, Set<string>> = new Map();\r\n\r\n for (const schema of this.tableSchemas) {\r\n if (!consolidatedSchemas.has(schema.name)) {\r\n consolidatedSchemas.set(schema.name, new Set(schema.columns));\r\n } else {\r\n const existingColumns = consolidatedSchemas.get(schema.name);\r\n schema.columns.forEach(column => existingColumns?.add(column));\r\n }\r\n }\r\n\r\n this.tableSchemas = Array.from(consolidatedSchemas.entries())\r\n .sort(([nameA], [nameB]) => nameA.localeCompare(nameB)) // Sort by table name\r\n .map(([name, columns]) => {\r\n return new TableSchema(name, Array.from(columns).sort()); // Sort columns alphabetically\r\n });\r\n }\r\n\r\n private handleTableSource(source: SourceExpression, queryColumns: { table: string, column: string }[], includeUnnamed: boolean): void {\r\n if (source.datasource instanceof TableSource) {\r\n const tableName = source.datasource.getSourceName();\r\n const cte = this.commonTables.filter((table) => table.getSourceAliasName() === tableName);\r\n if (cte.length > 0) {\r\n cte[0].query.accept(this);\r\n } else {\r\n const tableAlias = source.getAliasName() ?? tableName;\r\n this.processCollectTableSchema(tableName, tableAlias, queryColumns, includeUnnamed);\r\n }\r\n } else {\r\n throw new Error(\"Datasource is not an instance of TableSource\");\r\n }\r\n }\r\n\r\n private visitSimpleSelectQuery(query: SimpleSelectQuery): void {\r\n if (query.fromClause === null) {\r\n return;\r\n }\r\n\r\n // Collect columns used in the query\r\n const columnCollector = new SelectableColumnCollector(this.tableColumnResolver, true, DuplicateDetectionMode.FullName);\r\n const columns = columnCollector.collect(query);\r\n const queryColumns = columns.filter((column) => column.value instanceof ColumnReference)\r\n .map(column => column.value as ColumnReference)\r\n .map(columnRef => ({\r\n table: columnRef.getNamespace(),\r\n column: columnRef.column.name\r\n }));\r\n\r\n // Throw an error if there are columns without table names in queries with joins\r\n if (query.fromClause.joins !== null && query.fromClause.joins.length > 0) {\r\n const columnsWithoutTable = queryColumns.filter((columnRef) => columnRef.table === \"\").map((columnRef) => columnRef.column);\r\n if (columnsWithoutTable.length > 0) {\r\n throw new Error(`Column reference(s) without table name found in query: ${columnsWithoutTable.join(', ')}`);\r\n }\r\n }\r\n\r\n // Handle the main FROM clause table\r\n if (query.fromClause.source.datasource instanceof TableSource) {\r\n this.handleTableSource(query.fromClause.source, queryColumns, true);\r\n } else if (query.fromClause.source.datasource instanceof SubQuerySource) {\r\n query.fromClause.source.datasource.query.accept(this);\r\n }\r\n\r\n // Handle JOIN clause tables\r\n if (query.fromClause?.joins) {\r\n for (const join of query.fromClause.joins) {\r\n if (join.source.datasource instanceof TableSource) {\r\n this.handleTableSource(join.source, queryColumns, false);\r\n } else if (join.source.datasource instanceof SubQuerySource) {\r\n join.source.datasource.query.accept(this);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private visitBinarySelectQuery(query: BinarySelectQuery): void {\r\n // Visit the left and right queries\r\n this.visitNode(query.left);\r\n this.visitNode(query.right);\r\n }\r\n\r\n private processCollectTableSchema(tableName: string, tableAlias: string, queryColumns: { table: string, column: string }[], includeUnnamed: boolean = false): void {\r\n // If a wildcard is present and no resolver is provided, throw an error\r\n if (this.tableColumnResolver === null) {\r\n const hasWildcard = queryColumns\r\n .filter((columnRef) => columnRef.table === tableAlias || (includeUnnamed && columnRef.table === \"\"))\r\n .filter((columnRef) => columnRef.column === \"*\")\r\n .length > 0;\r\n if (hasWildcard) {\r\n const errorMessage = tableName\r\n ? `Wildcard (*) is used. A TableColumnResolver is required to resolve wildcards. Target table: ${tableName}`\r\n : \"Wildcard (*) is used. A TableColumnResolver is required to resolve wildcards.\";\r\n throw new Error(errorMessage);\r\n }\r\n }\r\n\r\n let tableColumns = queryColumns\r\n .filter((columnRef) => columnRef.column !== \"*\")\r\n .filter((columnRef) => columnRef.table === tableAlias || (includeUnnamed && columnRef.table === \"\"))\r\n .map((columnRef) => columnRef.column);\r\n\r\n const tableSchema = new TableSchema(tableName, tableColumns);\r\n this.tableSchemas.push(tableSchema);\r\n }\r\n}\r\n", "import { SelectQuery, SimpleSelectQuery } from \"../models/SelectQuery\";\r\nimport { SelectableColumnCollector } from \"./SelectableColumnCollector\";\r\nimport { BinaryExpression, FunctionCall, ParameterExpression, ParenExpression, ValueComponent, ValueList } from \"../models/ValueComponent\";\r\nimport { UpstreamSelectQueryFinder } from \"./UpstreamSelectQueryFinder\";\r\nimport { SelectQueryParser } from \"../parsers/SelectQueryParser\";\r\n\r\n/**\r\n * SqlParamInjector injects state parameters into a SelectQuery model,\r\n * creating WHERE conditions and setting parameter values.\r\n */\r\nexport class SqlParamInjector {\r\n private tableColumnResolver?: (tableName: string) => string[];\r\n private options: { ignoreCaseAndUnderscore?: boolean };\r\n\r\n constructor(optionsOrResolver?: { ignoreCaseAndUnderscore?: boolean } | ((tableName: string) => string[]), options?: { ignoreCaseAndUnderscore?: boolean }) {\r\n // Type-check to decide which argument was provided\r\n if (typeof optionsOrResolver === 'function') {\r\n this.tableColumnResolver = optionsOrResolver;\r\n this.options = options || {};\r\n } else {\r\n this.tableColumnResolver = undefined;\r\n this.options = optionsOrResolver || {};\r\n }\r\n }\r\n\r\n /**\r\n * Injects parameters as WHERE conditions into the given query model.\r\n * @param query The SelectQuery to modify\r\n * @param state A record of parameter names and values\r\n * @returns The modified SelectQuery\r\n */\r\n public inject(\r\n query: SimpleSelectQuery | string,\r\n state: Record<string, number | string | boolean | Date | null | undefined | Condition>\r\n ): SelectQuery {\r\n // Convert string query to SimpleSelectQuery using SelectQueryParser if needed\r\n if (typeof query === 'string') {\r\n query = SelectQueryParser.parse(query) as SimpleSelectQuery;\r\n }\r\n\r\n // Pass tableColumnResolver to finder and collector\r\n const finder = new UpstreamSelectQueryFinder(this.tableColumnResolver, this.options);\r\n const collector = new SelectableColumnCollector(this.tableColumnResolver);\r\n // Normalization is handled locally below.\r\n const normalize = (s: string) =>\r\n this.options.ignoreCaseAndUnderscore ? s.toLowerCase().replace(/_/g, '') : s;\r\n\r\n const allowedOps = ['min', 'max', 'like', 'ilike', 'in', 'any', '=', '<', '>', '!=', '<>', '<=', '>=', 'or', 'and', 'column'];\r\n\r\n for (const [name, stateValue] of Object.entries(state)) {\r\n // skip undefined values\r\n if (stateValue === undefined) continue;\r\n\r\n // Handle OR conditions specially - they don't need the main column to exist\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && 'or' in stateValue) {\r\n const orConditions = stateValue.or as SingleCondition[];\r\n if (orConditions && orConditions.length > 0) {\r\n // For OR conditions, we need to find a query that contains any of the referenced columns\r\n const referencedColumns = orConditions\r\n .map(cond => cond.column || name)\r\n .filter((col, index, arr) => arr.indexOf(col) === index); // unique columns\r\n\r\n let targetQuery: SimpleSelectQuery | null = null;\r\n for (const colName of referencedColumns) {\r\n const queries = finder.find(query, colName);\r\n if (queries.length > 0) {\r\n targetQuery = queries[0];\r\n break;\r\n }\r\n }\r\n\r\n if (!targetQuery) {\r\n throw new Error(`None of the OR condition columns [${referencedColumns.join(', ')}] found in query`);\r\n }\r\n\r\n const columns = collector.collect(targetQuery);\r\n injectOrConditions(targetQuery, name, orConditions, normalize, columns, collector);\r\n continue;\r\n }\r\n }\r\n\r\n // Handle AND conditions specially - they don't need the main column to exist\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && 'and' in stateValue) {\r\n const andConditions = stateValue.and as SingleCondition[];\r\n if (andConditions && andConditions.length > 0) {\r\n // For AND conditions, we need to find a query that contains any of the referenced columns\r\n const referencedColumns = andConditions\r\n .map(cond => cond.column || name)\r\n .filter((col, index, arr) => arr.indexOf(col) === index); // unique columns\r\n\r\n let targetQuery: SimpleSelectQuery | null = null;\r\n for (const colName of referencedColumns) {\r\n const queries = finder.find(query, colName);\r\n if (queries.length > 0) {\r\n targetQuery = queries[0];\r\n break;\r\n }\r\n }\r\n\r\n if (!targetQuery) {\r\n throw new Error(`None of the AND condition columns [${referencedColumns.join(', ')}] found in query`);\r\n }\r\n\r\n const columns = collector.collect(targetQuery);\r\n injectAndConditions(targetQuery, name, andConditions, normalize, columns, collector);\r\n continue;\r\n }\r\n }\r\n\r\n // Handle explicit column mapping without OR\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && 'column' in stateValue && !('or' in stateValue)) {\r\n const explicitColumnName = stateValue.column;\r\n if (explicitColumnName) {\r\n const queries = finder.find(query, explicitColumnName);\r\n if (queries.length === 0) {\r\n throw new Error(`Explicit column '${explicitColumnName}' not found in query`);\r\n }\r\n\r\n for (const q of queries) {\r\n const columns = collector.collect(q);\r\n const entry = columns.find(item => normalize(item.name) === normalize(explicitColumnName));\r\n if (!entry) {\r\n throw new Error(`Explicit column '${explicitColumnName}' not found in query`);\r\n }\r\n\r\n // if object, validate its keys\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && Object.getPrototypeOf(stateValue) === Object.prototype) {\r\n validateOperators(stateValue, allowedOps, name);\r\n }\r\n\r\n injectComplexConditions(q, entry.value, name, stateValue);\r\n }\r\n continue;\r\n }\r\n }\r\n\r\n const queries = finder.find(query, name);\r\n if (queries.length === 0) {\r\n throw new Error(`Column '${name}' not found in query`);\r\n }\r\n\r\n for (const q of queries) {\r\n const columns = collector.collect(q);\r\n const entry = columns.find(item => normalize(item.name) === normalize(name));\r\n if (!entry) {\r\n throw new Error(`Column '${name}' not found in query`);\r\n }\r\n const columnRef = entry.value; // if object, validate its keys\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && Object.getPrototypeOf(stateValue) === Object.prototype) {\r\n validateOperators(stateValue, allowedOps, name);\r\n }\r\n\r\n // Handle explicit column mapping\r\n let targetColumn = columnRef;\r\n let targetColumnName = name;\r\n if (stateValue !== null && typeof stateValue === 'object' && !Array.isArray(stateValue) && 'column' in stateValue) {\r\n const explicitColumnName = stateValue.column;\r\n if (explicitColumnName) {\r\n const explicitEntry = columns.find(item => normalize(item.name) === normalize(explicitColumnName));\r\n if (explicitEntry) {\r\n targetColumn = explicitEntry.value;\r\n targetColumnName = explicitColumnName;\r\n }\r\n }\r\n }\r\n\r\n if (\r\n stateValue === null ||\r\n typeof stateValue !== 'object' ||\r\n Array.isArray(stateValue) ||\r\n stateValue instanceof Date\r\n ) {\r\n injectSimpleCondition(q, targetColumn, targetColumnName, stateValue);\r\n } else {\r\n injectComplexConditions(q, targetColumn, targetColumnName, stateValue);\r\n }\r\n }\r\n } function injectAndConditions(\r\n q: SimpleSelectQuery,\r\n baseName: string,\r\n andConditions: SingleCondition[],\r\n normalize: (s: string) => string,\r\n availableColumns: { name: string; value: ValueComponent }[],\r\n collector: SelectableColumnCollector\r\n ): void {\r\n // For AND conditions, we process each condition and add them all with AND logic\r\n for (let i = 0; i < andConditions.length; i++) {\r\n const andCondition = andConditions[i];\r\n const columnName = andCondition.column || baseName;\r\n\r\n // Find the target column\r\n const entry = availableColumns.find(item => normalize(item.name) === normalize(columnName));\r\n if (!entry) {\r\n throw new Error(`Column '${columnName}' not found in query for AND condition`);\r\n }\r\n const columnRef = entry.value;\r\n\r\n // Process each operator in the AND condition\r\n if ('=' in andCondition && andCondition['='] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_eq`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", paramExpr));\r\n }\r\n if ('min' in andCondition && andCondition.min !== undefined) {\r\n const paramName = `${baseName}_and_${i}_min`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition.min);\r\n q.appendWhere(new BinaryExpression(columnRef, \">=\", paramExpr));\r\n }\r\n if ('max' in andCondition && andCondition.max !== undefined) {\r\n const paramName = `${baseName}_and_${i}_max`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition.max);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<=\", paramExpr));\r\n } if ('like' in andCondition && andCondition.like !== undefined) {\r\n const paramName = `${baseName}_and_${i}_like`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition.like);\r\n q.appendWhere(new BinaryExpression(columnRef, \"like\", paramExpr));\r\n }\r\n if ('ilike' in andCondition && andCondition.ilike !== undefined) {\r\n const paramName = `${baseName}_and_${i}_ilike`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition.ilike);\r\n q.appendWhere(new BinaryExpression(columnRef, \"ilike\", paramExpr));\r\n }\r\n if ('in' in andCondition && andCondition.in !== undefined) {\r\n const arr = andCondition.in as (number | string)[];\r\n const prms: ParameterExpression[] = arr.map((v, j) =>\r\n new ParameterExpression(`${baseName}_and_${i}_in_${j}`, v)\r\n );\r\n q.appendWhere(new BinaryExpression(columnRef, \"in\", new ParenExpression(new ValueList(prms))));\r\n }\r\n if ('any' in andCondition && andCondition.any !== undefined) {\r\n const paramName = `${baseName}_and_${i}_any`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition.any);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", new FunctionCall(null, \"any\", paramExpr, null)));\r\n }\r\n if ('<' in andCondition && andCondition['<'] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_lt`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['<']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<\", paramExpr));\r\n }\r\n if ('>' in andCondition && andCondition['>'] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_gt`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['>']);\r\n q.appendWhere(new BinaryExpression(columnRef, \">\", paramExpr));\r\n }\r\n if ('!=' in andCondition && andCondition['!='] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_neq`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['!=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"!=\", paramExpr));\r\n }\r\n if ('<>' in andCondition && andCondition['<>'] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_ne`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['<>']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<>\", paramExpr));\r\n }\r\n if ('<=' in andCondition && andCondition['<='] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_le`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['<=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \"<=\", paramExpr));\r\n }\r\n if ('>=' in andCondition && andCondition['>='] !== undefined) {\r\n const paramName = `${baseName}_and_${i}_ge`;\r\n const paramExpr = new ParameterExpression(paramName, andCondition['>=']);\r\n q.appendWhere(new BinaryExpression(columnRef, \">=\", paramExpr));\r\n }\r\n }\r\n }\r\n\r\n function injectOrConditions(\r\n q: SimpleSelectQuery,\r\n baseName: string,\r\n orConditions: SingleCondition[],\r\n normalize: (s: string) => string,\r\n availableColumns: { name: string; value: ValueComponent }[],\r\n collector: SelectableColumnCollector\r\n ): void {\r\n const orExpressions: ValueComponent[] = [];\r\n\r\n for (let i = 0; i < orConditions.length; i++) {\r\n const orCondition = orConditions[i];\r\n const columnName = orCondition.column || baseName;\r\n\r\n // Find the target column\r\n const entry = availableColumns.find(item => normalize(item.name) === normalize(columnName));\r\n if (!entry) {\r\n throw new Error(`Column '${columnName}' not found in query for OR condition`);\r\n }\r\n const columnRef = entry.value;\r\n\r\n // Create conditions for this OR branch\r\n const branchConditions: ValueComponent[] = [];\r\n\r\n // Process each operator in the OR condition\r\n if ('=' in orCondition && orCondition['='] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_eq`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['=']);\r\n branchConditions.push(new BinaryExpression(columnRef, \"=\", paramExpr));\r\n }\r\n if ('min' in orCondition && orCondition.min !== undefined) {\r\n const paramName = `${baseName}_or_${i}_min`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition.min);\r\n branchConditions.push(new BinaryExpression(columnRef, \">=\", paramExpr));\r\n }\r\n if ('max' in orCondition && orCondition.max !== undefined) {\r\n const paramName = `${baseName}_or_${i}_max`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition.max);\r\n branchConditions.push(new BinaryExpression(columnRef, \"<=\", paramExpr));\r\n } if ('like' in orCondition && orCondition.like !== undefined) {\r\n const paramName = `${baseName}_or_${i}_like`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition.like);\r\n branchConditions.push(new BinaryExpression(columnRef, \"like\", paramExpr));\r\n }\r\n if ('ilike' in orCondition && orCondition.ilike !== undefined) {\r\n const paramName = `${baseName}_or_${i}_ilike`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition.ilike);\r\n branchConditions.push(new BinaryExpression(columnRef, \"ilike\", paramExpr));\r\n }\r\n if ('in' in orCondition && orCondition.in !== undefined) {\r\n const arr = orCondition.in as (number | string)[];\r\n const prms: ParameterExpression[] = arr.map((v, j) =>\r\n new ParameterExpression(`${baseName}_or_${i}_in_${j}`, v)\r\n );\r\n branchConditions.push(new BinaryExpression(columnRef, \"in\", new ParenExpression(new ValueList(prms))));\r\n }\r\n if ('any' in orCondition && orCondition.any !== undefined) {\r\n const paramName = `${baseName}_or_${i}_any`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition.any);\r\n branchConditions.push(new BinaryExpression(columnRef, \"=\", new FunctionCall(null, \"any\", paramExpr, null)));\r\n }\r\n if ('<' in orCondition && orCondition['<'] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_lt`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['<']);\r\n branchConditions.push(new BinaryExpression(columnRef, \"<\", paramExpr));\r\n }\r\n if ('>' in orCondition && orCondition['>'] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_gt`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['>']);\r\n branchConditions.push(new BinaryExpression(columnRef, \">\", paramExpr));\r\n }\r\n if ('!=' in orCondition && orCondition['!='] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_neq`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['!=']);\r\n branchConditions.push(new BinaryExpression(columnRef, \"!=\", paramExpr));\r\n }\r\n if ('<>' in orCondition && orCondition['<>'] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_ne`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['<>']);\r\n branchConditions.push(new BinaryExpression(columnRef, \"<>\", paramExpr));\r\n }\r\n if ('<=' in orCondition && orCondition['<='] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_le`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['<=']);\r\n branchConditions.push(new BinaryExpression(columnRef, \"<=\", paramExpr));\r\n }\r\n if ('>=' in orCondition && orCondition['>='] !== undefined) {\r\n const paramName = `${baseName}_or_${i}_ge`;\r\n const paramExpr = new ParameterExpression(paramName, orCondition['>=']);\r\n branchConditions.push(new BinaryExpression(columnRef, \">=\", paramExpr));\r\n }\r\n\r\n // Combine branch conditions with AND if there are multiple\r\n if (branchConditions.length > 0) {\r\n let branchExpr = branchConditions[0];\r\n for (let j = 1; j < branchConditions.length; j++) {\r\n branchExpr = new BinaryExpression(branchExpr, \"and\", branchConditions[j]);\r\n }\r\n // Wrap in parentheses if multiple conditions within the OR branch\r\n if (branchConditions.length > 1) {\r\n orExpressions.push(new ParenExpression(branchExpr));\r\n } else {\r\n orExpressions.push(branchExpr);\r\n }\r\n }\r\n }\r\n\r\n // Combine OR expressions\r\n if (orExpressions.length > 0) {\r\n let finalOrExpr = orExpressions[0];\r\n for (let i = 1; i < orExpressions.length; i++) {\r\n finalOrExpr = new BinaryExpression(finalOrExpr, \"or\", orExpressions[i]);\r\n }\r\n\r\n // Wrap in parentheses and append to WHERE clause\r\n q.appendWhere(new ParenExpression(finalOrExpr));\r\n }\r\n }\r\n\r\n function validateOperators(stateValue: object, allowedOps: string[], name: string): void {\r\n Object.keys(stateValue).forEach(op => {\r\n if (!allowedOps.includes(op)) {\r\n throw new Error(`Unsupported operator '${op}' for state key '${name}'`);\r\n }\r\n });\r\n }\r\n\r\n function injectSimpleCondition(q: SimpleSelectQuery, columnRef: ValueComponent, name: string, stateValue: any): void {\r\n const paramExpr = new ParameterExpression(name, stateValue);\r\n q.appendWhere(new BinaryExpression(columnRef, \"=\", paramExpr));\r\n } function injectComplexConditions(q: SimpleSelectQuery, columnRef: ValueComponent, name: string, stateValue: Condition): void {\r\n const conditions: ValueComponent[] = [];\r\n\r\n if ('=' in stateValue) {\r\n const paramEq = new ParameterExpression(name, stateValue['=']);\r\n conditions.push(new BinaryExpression(columnRef, \"=\", paramEq));\r\n }\r\n if ('min' in stateValue) {\r\n const paramMin = new ParameterExpression(name + \"_min\", stateValue.min);\r\n conditions.push(new BinaryExpression(columnRef, \">=\", paramMin));\r\n }\r\n if ('max' in stateValue) {\r\n const paramMax = new ParameterExpression(name + \"_max\", stateValue.max);\r\n conditions.push(new BinaryExpression(columnRef, \"<=\", paramMax));\r\n } if ('like' in stateValue) {\r\n const paramLike = new ParameterExpression(name + \"_like\", stateValue.like);\r\n conditions.push(new BinaryExpression(columnRef, \"like\", paramLike));\r\n }\r\n if ('ilike' in stateValue) {\r\n const paramIlike = new ParameterExpression(name + \"_ilike\", stateValue.ilike);\r\n conditions.push(new BinaryExpression(columnRef, \"ilike\", paramIlike));\r\n }\r\n if ('in' in stateValue) {\r\n const arr = stateValue['in'] as (number | string)[];\r\n const prms: ParameterExpression[] = arr.map((v, i) =>\r\n new ParameterExpression(`${name}_in_${i}`, v)\r\n );\r\n conditions.push(new BinaryExpression(columnRef, \"in\", new ParenExpression(new ValueList(prms))));\r\n }\r\n if ('any' in stateValue) {\r\n const paramAny = new ParameterExpression(name + \"_any\", stateValue.any);\r\n conditions.push(new BinaryExpression(columnRef, \"=\", new FunctionCall(null, \"any\", paramAny, null)));\r\n }\r\n if ('<' in stateValue) {\r\n const paramLT = new ParameterExpression(name + \"_lt\", stateValue['<']);\r\n conditions.push(new BinaryExpression(columnRef, \"<\", paramLT));\r\n }\r\n if ('>' in stateValue) {\r\n const paramGT = new ParameterExpression(name + \"_gt\", stateValue['>']);\r\n conditions.push(new BinaryExpression(columnRef, \">\", paramGT));\r\n }\r\n if ('!=' in stateValue) {\r\n const paramNEQ = new ParameterExpression(name + \"_neq\", stateValue['!=']);\r\n conditions.push(new BinaryExpression(columnRef, \"!=\", paramNEQ));\r\n }\r\n if ('<>' in stateValue) {\r\n const paramNE = new ParameterExpression(name + \"_ne\", stateValue['<>']);\r\n conditions.push(new BinaryExpression(columnRef, \"<>\", paramNE));\r\n }\r\n if ('<=' in stateValue) {\r\n const paramLE = new ParameterExpression(name + \"_le\", stateValue['<=']);\r\n conditions.push(new BinaryExpression(columnRef, \"<=\", paramLE));\r\n }\r\n if ('>=' in stateValue) {\r\n const paramGE = new ParameterExpression(name + \"_ge\", stateValue['>=']);\r\n conditions.push(new BinaryExpression(columnRef, \">=\", paramGE));\r\n }\r\n\r\n // Combine conditions with AND and wrap in parentheses if multiple conditions for clarity\r\n if (conditions.length === 1) {\r\n // Single condition - no parentheses needed\r\n q.appendWhere(conditions[0]);\r\n } else if (conditions.length > 1) {\r\n // Multiple conditions - combine with AND and wrap in parentheses for clarity\r\n let combinedExpr = conditions[0];\r\n for (let i = 1; i < conditions.length; i++) {\r\n combinedExpr = new BinaryExpression(combinedExpr, \"and\", conditions[i]);\r\n }\r\n q.appendWhere(new ParenExpression(combinedExpr));\r\n }\r\n }\r\n\r\n return query;\r\n }\r\n}\r\n\r\n// Define allowed condition keywords for state values\r\ntype BaseCondition = {\r\n '='?: number | string | boolean | Date;\r\n min?: number | string | Date;\r\n max?: number | string | Date;\r\n like?: string;\r\n ilike?: string;\r\n in?: (number | string | Date)[];\r\n any?: (number | string | Date)[];\r\n '<'?: number | string | Date;\r\n '>'?: number | string | Date;\r\n '!='?: number | string | boolean | Date;\r\n '<>'?: number | string | boolean | Date;\r\n '<='?: number | string | Date;\r\n '>='?: number | string | Date;\r\n};\r\n\r\n// Single condition with optional column mapping\r\ntype SingleCondition = BaseCondition & {\r\n column?: string;\r\n};\r\n\r\n// Logical grouping conditions\r\ntype LogicalCondition = {\r\n column?: string;\r\n and?: SingleCondition[];\r\n or?: SingleCondition[];\r\n};\r\n\r\n// Main condition type supporting all patterns\r\ntype Condition = BaseCondition | SingleCondition | LogicalCondition;", "import { SchemaCollector, TableSchema } from '../transformers/SchemaCollector';\r\nimport { SqlComponent } from '../models/SqlComponent';\r\nimport { TableColumnResolver } from '../transformers/TableColumnResolver';\r\nimport { SelectQueryParser } from '../parsers/SelectQueryParser';\r\n\r\nexport class SqlSchemaValidator {\r\n /**\r\n * Validates a SQL query structure against a provided TableColumnResolver or TableSchema array.\r\n * @param sql The SQL query structure to validate, can be a SQL string or a SqlComponent.\r\n * @param tableResolver The TableColumnResolver or TableSchema array to validate against.\r\n * @throws Error if the query contains undefined tables or columns.\r\n */\r\n public static validate(\r\n sql: string | SqlComponent,\r\n tableResolver: TableColumnResolver | TableSchema[]\r\n ): void {\r\n const sqlComponent = typeof sql === 'string' ? SelectQueryParser.parse(sql) : sql;\r\n\r\n // Convert TableSchema[] to a resolver function if necessary\r\n const resolver = Array.isArray(tableResolver)\r\n ? (tableName: string) => {\r\n const schema = tableResolver.find((t) => t.name === tableName);\r\n return schema ? schema.columns : [];\r\n }\r\n : tableResolver;\r\n\r\n const schemaCollector = new SchemaCollector(resolver);\r\n const tableSchemas = schemaCollector.collect(sqlComponent);\r\n const errors: string[] = [];\r\n\r\n for (const tableSchema of tableSchemas) {\r\n const resolvedColumns = resolver(tableSchema.name);\r\n if (resolvedColumns.length === 0) {\r\n errors.push(`Table '${tableSchema.name}' is not defined.`);\r\n continue;\r\n }\r\n\r\n const undefinedColumns = tableSchema.columns.filter(column => !resolvedColumns.includes(column));\r\n if (undefinedColumns.length > 0) {\r\n errors.push(\r\n `Table '${tableSchema.name}' contains undefined columns: ${undefinedColumns.join(', ')}.`\r\n );\r\n }\r\n }\r\n\r\n if (errors.length > 0) {\r\n throw new Error(errors.join('\\n'));\r\n }\r\n }\r\n}\r\n", "/**\r\n * Schema Manager for rawsql-ts\r\n * Provides unified schema definition and automatic conversion to various formats\r\n * Eliminates code duplication and provides type-safe schema management\r\n */\r\n\r\n// Import JsonMapping interface for type safety\r\nimport type { JsonMapping } from '../transformers/PostgresJsonQueryBuilder';\r\n\r\n// === Core Types for User-defined Schemas ===\r\n\r\n/**\r\n * Database column metadata for schema mapping\r\n */\r\nexport interface ColumnDefinition {\r\n /** Column name in database */\r\n name: string;\r\n /** Primary key indicator - used for UPDATE/DELETE query WHERE conditions */\r\n isPrimaryKey?: boolean;\r\n /** Foreign key reference */\r\n foreignKey?: {\r\n table: string;\r\n column: string;\r\n };\r\n /** Alias for JSON output (useful for avoiding conflicts) */\r\n jsonAlias?: string;\r\n}\r\n\r\n/**\r\n * Table relationship definition\r\n */\r\nexport interface RelationshipDefinition {\r\n /** Type of relationship */\r\n type: 'object' | 'array';\r\n /** Target table name */\r\n table: string;\r\n /** Property name in JSON output */\r\n propertyName: string;\r\n /** Optional: Override target table's primary key */\r\n targetKey?: string;\r\n}\r\n\r\n/**\r\n * Complete table schema definition that users write\r\n */\r\nexport interface TableDefinition {\r\n /** Table name in database */\r\n name: string;\r\n /** Human-readable entity name */\r\n displayName?: string;\r\n /** Column definitions */\r\n columns: Record<string, ColumnDefinition>;\r\n /** Relationships with other tables */\r\n relationships?: RelationshipDefinition[];\r\n}\r\n\r\n/**\r\n * Schema registry containing all table definitions\r\n */\r\nexport interface SchemaRegistry {\r\n [tableName: string]: TableDefinition;\r\n}\r\n\r\n// === Schema Manager Class ===\r\n\r\n/**\r\n * Central schema management utility for rawsql-ts\r\n * Converts user-defined schemas to various internal formats\r\n */\r\nexport class SchemaManager {\r\n private schemas: SchemaRegistry;\r\n\r\n constructor(schemas: SchemaRegistry) {\r\n this.schemas = schemas;\r\n this.validateSchemas();\r\n }\r\n\r\n /**\r\n * Validate schema definitions for consistency\r\n * Ensures each table has a primary key (required for UPDATE/DELETE operations)\r\n * and validates relationship references\r\n */\r\n private validateSchemas(): void {\r\n const tableNames = Object.keys(this.schemas);\r\n const errors: string[] = [];\r\n\r\n // Validate each table\r\n Object.entries(this.schemas).forEach(([tableName, table]) => {\r\n // Check primary key exists (required for UPDATE/DELETE WHERE conditions)\r\n const primaryKeys = Object.entries(table.columns)\r\n .filter(([_, col]) => col.isPrimaryKey)\r\n .map(([name, _]) => name);\r\n\r\n if (primaryKeys.length === 0) {\r\n errors.push(`Table '${tableName}' has no primary key defined`);\r\n }\r\n\r\n // Validate foreign key references\r\n table.relationships?.forEach(rel => {\r\n if (!tableNames.includes(rel.table)) {\r\n errors.push(`Table '${tableName}' references unknown table '${rel.table}' in relationship`);\r\n }\r\n });\r\n });\r\n\r\n if (errors.length > 0) {\r\n throw new Error(`Schema validation failed:\\\\n${errors.join('\\\\n')}`);\r\n }\r\n }\r\n\r\n /**\r\n * Get table column names for SqlParamInjector TableColumnResolver\r\n * @param tableName Name of the table\r\n * @returns Array of column names\r\n */\r\n public getTableColumns(tableName: string): string[] {\r\n const table = this.schemas[tableName];\r\n if (!table) {\r\n return [];\r\n }\r\n return Object.keys(table.columns);\r\n }\r\n\r\n /**\r\n * Create TableColumnResolver function for SqlParamInjector\r\n * @returns Function compatible with SqlParamInjector\r\n */\r\n public createTableColumnResolver(): (tableName: string) => string[] {\r\n return (tableName: string) => this.getTableColumns(tableName);\r\n }\r\n\r\n /**\r\n * Generate JSON mapping configuration for PostgresJsonQueryBuilder\r\n * @param rootTableName Root table for the JSON structure\r\n * @returns JSON mapping configuration\r\n */\r\n public createJsonMapping(rootTableName: string): JsonMapping {\r\n const rootTable = this.schemas[rootTableName];\r\n if (!rootTable) {\r\n throw new Error(`Table '${rootTableName}' not found in schema registry`);\r\n }\r\n\r\n // Build root entity columns mapping\r\n const rootColumns: Record<string, string> = {};\r\n Object.entries(rootTable.columns).forEach(([columnName, column]) => {\r\n rootColumns[columnName] = column.jsonAlias || column.name;\r\n });\r\n\r\n // Build nested entities from relationships\r\n const nestedEntities: JsonMapping['nestedEntities'] = [];\r\n\r\n rootTable.relationships?.forEach(rel => {\r\n const relatedTable = this.schemas[rel.table];\r\n if (!relatedTable) {\r\n throw new Error(`Related table '${rel.table}' not found in schema registry`);\r\n }\r\n\r\n // Build columns mapping for related table\r\n const relatedColumns: Record<string, string> = {};\r\n Object.entries(relatedTable.columns).forEach(([columnName, column]) => {\r\n relatedColumns[columnName] = column.jsonAlias || column.name;\r\n });\r\n\r\n // Determine relationship type for JSON builder\r\n const relationshipType = rel.type;\r\n\r\n nestedEntities.push({\r\n id: rel.propertyName,\r\n name: relatedTable.displayName || rel.table,\r\n parentId: rootTableName,\r\n propertyName: rel.propertyName,\r\n relationshipType: relationshipType as 'object' | 'array',\r\n columns: relatedColumns\r\n });\r\n });\r\n\r\n return {\r\n rootName: rootTableName,\r\n rootEntity: {\r\n id: rootTableName,\r\n name: rootTable.displayName || rootTableName,\r\n columns: rootColumns\r\n },\r\n nestedEntities,\r\n useJsonb: true,\r\n resultFormat: \"single\" as const\r\n };\r\n }\r\n\r\n /**\r\n * Get all table names in the schema\r\n * @returns Array of table names\r\n */\r\n public getTableNames(): string[] {\r\n return Object.keys(this.schemas);\r\n }\r\n\r\n /**\r\n * Get table definition by name\r\n * @param tableName Name of the table\r\n * @returns Table definition or undefined\r\n */\r\n public getTable(tableName: string): TableDefinition | undefined {\r\n return this.schemas[tableName];\r\n }\r\n\r\n /**\r\n * Get primary key column name for a table\r\n * Used by QueryBuilder.buildUpdateQuery for WHERE clause conditions\r\n * @param tableName Name of the table\r\n * @returns Primary key column name or undefined\r\n */\r\n public getPrimaryKey(tableName: string): string | undefined {\r\n const table = this.schemas[tableName];\r\n if (!table) return undefined;\r\n\r\n const primaryKeyEntry = Object.entries(table.columns)\r\n .find(([_, col]) => col.isPrimaryKey);\r\n\r\n return primaryKeyEntry ? primaryKeyEntry[0] : undefined;\r\n }\r\n\r\n /**\r\n * Get foreign key relationships for a table\r\n * @param tableName Name of the table\r\n * @returns Array of foreign key relationships\r\n */\r\n public getForeignKeys(tableName: string): Array<{ column: string; referencedTable: string; referencedColumn: string }> {\r\n const table = this.schemas[tableName];\r\n if (!table) return [];\r\n\r\n const foreignKeys: Array<{ column: string; referencedTable: string; referencedColumn: string }> = [];\r\n\r\n Object.entries(table.columns).forEach(([columnName, column]) => {\r\n if (column.foreignKey) {\r\n foreignKeys.push({\r\n column: columnName,\r\n referencedTable: column.foreignKey.table,\r\n referencedColumn: column.foreignKey.column\r\n });\r\n }\r\n });\r\n\r\n return foreignKeys;\r\n }\r\n}\r\n\r\n// === Convenience Functions ===\r\n\r\n/**\r\n * Create a SchemaManager instance from schema definitions\r\n * @param schemas Schema registry object\r\n * @returns SchemaManager instance\r\n */\r\nexport function createSchemaManager(schemas: SchemaRegistry): SchemaManager {\r\n return new SchemaManager(schemas);\r\n}\r\n\r\n/**\r\n * Create TableColumnResolver function from schema definitions\r\n * @param schemas Schema registry object\r\n * @returns TableColumnResolver function for SqlParamInjector\r\n */\r\nexport function createTableColumnResolver(schemas: SchemaRegistry): (tableName: string) => string[] {\r\n const manager = new SchemaManager(schemas);\r\n return manager.createTableColumnResolver();\r\n}\r\n\r\n/**\r\n * Create JSON mapping from schema definitions\r\n * @param schemas Schema registry object\r\n * @param rootTableName Root table name\r\n * @returns JSON mapping for PostgresJsonQueryBuilder\r\n */\r\nexport function createJsonMappingFromSchema(schemas: SchemaRegistry, rootTableName: string): JsonMapping {\r\n const manager = new SchemaManager(schemas);\r\n return manager.createJsonMapping(rootTableName);\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["src_exports", "__export", "ArrayExpression", "ArrayQueryExpression", "BetweenExpression", "BinaryExpression", "BinarySelectQuery", "CTECollector", "CTENormalizer", "CaseExpression", "CaseKeyValuePair", "CastExpression", "ColumnReference", "DuplicateDetectionMode", "Formatter", "FunctionCall", "IdentifierString", "InlineQuery", "InsertQuery", "InsertQueryParser", "LiteralValue", "ParameterExpression", "ParenExpression", "PostgresJsonQueryBuilder", "QualifiedName", "QueryBuilder", "RawString", "SchemaCollector", "SchemaManager", "SelectQueryParser", "SelectValueCollector", "SelectableColumnCollector", "SimpleSelectQuery", "SqlFormatter", "SqlParamInjector", "SqlSchemaValidator", "StringSpecifierExpression", "SwitchCaseArgument", "TableSchema", "TableSourceCollector", "TupleExpression", "TypeValue", "UnaryExpression", "UpstreamSelectQueryFinder", "VALID_PRESETS", "ValueList", "ValuesQuery", "WindowFrameBound", "WindowFrameBoundStatic", "WindowFrameBoundaryValue", "WindowFrameExpression", "WindowFrameSpec", "WindowFrameType", "createJsonMappingFromSchema", "createSchemaManager", "createTableColumnResolver", "__toCommonJS", "SqlComponent", "visitor", "formatter", "InsertQuery", "SqlComponent", "params", "InlineQuery", "SqlComponent", "selectQuery", "ValueList", "values", "ColumnReference", "IdentifierString", "namespaces", "column", "col", "QualifiedName", "toIdentifierStringArray", "namespace", "FunctionCall", "name", "argument", "over", "WindowFrameType", "WindowFrameBound", "WindowFrameBoundStatic", "bound", "WindowFrameBoundaryValue", "value", "isFollowing", "WindowFrameSpec", "frameType", "startBound", "endBound", "WindowFrameExpression", "partition", "order", "frameSpec", "UnaryExpression", "operator", "expression", "RawString", "BinaryExpression", "left", "right", "LiteralValue", "ParameterExpression", "SwitchCaseArgument", "cases", "elseValue", "CaseKeyValuePair", "key", "alias", "ParenExpression", "CastExpression", "input", "castType", "CaseExpression", "condition", "switchCase", "ArrayExpression", "ArrayQueryExpression", "query", "BetweenExpression", "lower", "upper", "negated", "StringSpecifierExpression", "specifier", "TypeValue", "nameValue", "ns", "TupleExpression", "filteredStrings", "filteredIdentifiers", "SelectItem", "SqlComponent", "value", "name", "IdentifierString", "SelectClause", "items", "distinct", "Distinct", "DistinctOn", "WhereClause", "condition", "PartitionByClause", "WindowFrameClause", "expression", "WindowsClause", "windows", "OrderByClause", "SqlComponent", "items", "OrderByItem", "expression", "sortDirection", "nullsPosition", "GroupByClause", "HavingClause", "condition", "TableSource", "IdentifierString", "namespaces", "table", "tbl", "QualifiedName", "namespace", "RawString", "FunctionSource", "name", "argument", "nameObj", "ParenSource", "source", "SubQuerySource", "query", "SourceExpression", "datasource", "aliasExpression", "JoinOnClause", "JoinUsingClause", "JoinClause", "joinType", "lateral", "FromClause", "join", "sources", "CommonTable", "materialized", "SourceAliasExpression", "WithClause", "recursive", "tables", "LimitClause", "limit", "OffsetClause", "SqlComponent", "value", "FetchClause", "expression", "FetchExpression", "type", "count", "unit", "ForClause", "SqlComponent", "lockMode", "SourceAliasExpression", "alias", "columnAlias", "IdentifierString", "ReturningClause", "columns", "col", "SetClause", "items", "item", "SetClauseItem", "column", "value", "colObj", "QualifiedName", "UpdateClause", "source", "TableSource", "InsertClause", "TokenType", "CharLookupTable", "char", "code", "StringUtils", "_StringUtils", "input", "errPosition", "start", "end", "debugInfo", "caret", "position", "length", "charCode", "comment", "lines", "i", "oldPosition", "lineCommentResult", "blockCommentResult", "result", "CharLookupTable", "BaseTokenReader", "input", "position", "shift", "expectChar", "char", "type", "value", "comments", "errPosition", "StringUtils", "IdentifierTokenReader", "BaseTokenReader", "previous", "char", "result", "StringUtils", "KeywordParser", "trie", "input", "position", "shift", "result", "StringUtils", "matchResult", "lexeme", "previousMatchResult", "KeywordTrie", "keywords", "keyword", "node", "word", "lexeme", "keywords", "trie", "KeywordTrie", "literalKeywordParser", "KeywordParser", "LiteralTokenReader", "BaseTokenReader", "previous", "char", "keyword", "CharLookupTable", "value", "sign", "pos", "result", "start", "hasDot", "hasExponent", "prefixType", "isHex", "c", "includeSingleQuote", "closed", "ParameterTokenReader", "BaseTokenReader", "input", "previous", "start", "identifier", "char", "CharLookupTable", "SpecialSymbolTokenReader", "_SpecialSymbolTokenReader", "BaseTokenReader", "previous", "char", "TokenReaderManager", "input", "position", "reader", "readers", "previous", "lexeme", "maxPosition", "total", "ratio", "trie", "KeywordTrie", "operatorOrTypeTrie", "keywordParser", "KeywordParser", "operatorOrTypeParser", "OperatorTokenReader", "BaseTokenReader", "previous", "char", "CharLookupTable", "start", "current", "resut", "result", "operatorOrTypeParser", "keywordParser", "joinTrie", "KeywordTrie", "keywordTrie", "keywordParser", "KeywordParser", "joinkeywordParser", "CommandTokenReader", "BaseTokenReader", "previous", "keywordJoin", "keyword", "start", "STRING_SPECIFIERS", "UNICODE_STRING_SPECIFIERS", "StringSpecifierTokenReader", "BaseTokenReader", "previous", "start", "trie", "KeywordTrie", "keywordParser", "KeywordParser", "FunctionTokenReader", "BaseTokenReader", "previous", "keyword", "result", "StringUtils", "shift", "trie", "KeywordTrie", "typeParser", "KeywordParser", "TypeTokenReader", "BaseTokenReader", "previous", "keyword", "result", "StringUtils", "EscapedIdentifierTokenReader", "BaseTokenReader", "previous", "char", "identifier", "delimiter", "start", "SqlTokenizer", "input", "TokenReaderManager", "EscapedIdentifierTokenReader", "ParameterTokenReader", "StringSpecifierTokenReader", "LiteralTokenReader", "SpecialSymbolTokenReader", "CommandTokenReader", "OperatorTokenReader", "TypeTokenReader", "FunctionTokenReader", "IdentifierTokenReader", "shift", "estimatedTokens", "lexemes", "lexemeCount", "comment", "pendingComments", "previous", "lexeme", "currentComment", "lastToken", "prefixComments", "suffixComments", "StringUtils", "errPosition", "FullNameParser", "_FullNameParser", "lexemes", "index", "identifiers", "newIndex", "namespaces", "name", "lastTokenType", "IdentifierString", "str", "SqlTokenizer", "result", "idx", "IdentifierParser", "lexemes", "index", "namespaces", "name", "newIndex", "FullNameParser", "ColumnReference", "LiteralParser", "lexemes", "index", "idx", "valueText", "parsedValue", "lex", "literalKeywordParser", "value", "RawString", "LiteralValue", "ParenExpressionParser", "lexemes", "index", "idx", "result", "SelectQueryParser", "InlineQuery", "ValueParser", "ParenExpression", "UnaryExpressionParser", "lexemes", "index", "idx", "operator", "ColumnReference", "result", "ValueParser", "UnaryExpression", "ParameterExpressionParser", "lexemes", "index", "idx", "paramName", "value", "ParameterExpression", "StringSpecifierExpressionParser", "lexemes", "index", "idx", "specifer", "value", "StringSpecifierExpression", "CommandExpressionParser", "lexemes", "index", "idx", "current", "command", "result", "ValueParser", "UnaryExpression", "condition", "switchCaseResult", "CaseExpression", "casewhenResult", "caseWhenList", "initialWhenThenList", "whenThenList", "elseValue", "whenResult", "elseResult", "SwitchCaseArgument", "lexeme", "value", "CaseKeyValuePair", "OrderByClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "OrderByClause", "parsedValue", "ValueParser", "value", "sortDirection", "nullsSortDirection", "OrderByItem", "PartitionByParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "ValueParser", "PartitionByClause", "ValueList", "WindowExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "partition", "order", "frameSpec", "partitionResult", "PartitionByParser", "orderResult", "OrderByClauseParser", "frameSpecResult", "WindowFrameExpression", "value", "lowerValue", "frameTypeStr", "frameType", "startBoundResult", "startBound", "endBoundResult", "endBound", "WindowFrameSpec", "boundaryResult", "currentValue", "frameBound", "WindowFrameBoundStatic", "valueResult", "ValueParser", "direction", "isFollowing", "WindowFrameBoundaryValue", "OverExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "name", "IdentifierString", "WindowExpressionParser", "FunctionExpressionParser", "lexemes", "index", "idx", "arg", "ValueParser", "ArrayExpression", "SelectQueryParser", "ArrayQueryExpression", "current", "left", "allowAndOperator", "allowOrOperator", "operator", "typeValue", "CastExpression", "rightResult", "BinaryExpression", "value", "negated", "lower", "upper", "BetweenExpression", "fullNameResult", "FullNameParser", "namespaces", "name", "over", "OverExpressionParser", "FunctionCall", "keywords", "input", "key", "required", "right", "newIndex", "TypeValue", "RawString", "ParseError", "_ParseError", "message", "index", "context", "lexemes", "messagePrefix", "start", "end", "lexeme", "idx", "marker", "typeName", "TokenType", "OperatorPrecedence", "operator", "precedence", "operator1", "operator2", "op", "lowerOp", "ValueParser", "query", "lexemes", "SqlTokenizer", "result", "ParseError", "index", "allowAndOperator", "allowOrOperator", "minPrecedence", "idx", "comment", "left", "operator", "precedence", "OperatorPrecedence", "betweenResult", "FunctionExpressionParser", "typeValue", "CastExpression", "nextMinPrecedence", "rightResult", "BinaryExpression", "current", "first", "IdentifierParser", "second", "LiteralParser", "UnaryExpression", "namespaces", "name", "newIndex", "FullNameParser", "ColumnReference", "ParenExpressionParser", "UnaryExpressionParser", "ParameterExpressionParser", "StringSpecifierExpressionParser", "CommandExpressionParser", "TypeValue", "openToken", "closeToken", "args", "ValueList", "wildcard", "argResult", "CTECollector", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "WithClause", "CommonTable", "SelectItem", "IdentifierString", "RawString", "ColumnReference", "ParameterExpression", "LiteralValue", "SourceExpression", "TableSource", "FunctionSource", "ParenSource", "SubQuerySource", "InlineQuery", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "WindowFrameExpression", "WindowFrameSpec", "TypeValue", "ValueList", "StringSpecifierExpression", "SelectClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "ForClause", "OrderByItem", "PartitionByClause", "query", "arg", "handler", "kindSymbol", "constructor", "win", "tuple", "withClause", "i", "commonTable", "clause", "item", "fromClause", "join", "source", "subQuery", "inlineQuery", "joinClause", "joinOn", "joinUsing", "whereClause", "switchCase", "caseItem", "pair", "func", "value", "spec", "ident", "raw", "column", "param", "partitionBy", "valueList", "CTEDisabler", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "SelectItem", "IdentifierString", "RawString", "ColumnReference", "ParameterExpression", "LiteralValue", "SourceExpression", "TableSource", "ParenSource", "SubQuerySource", "InlineQuery", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "WindowFrameExpression", "WindowFrameSpec", "TypeValue", "SelectClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "ForClause", "OrderByItem", "arg", "handler", "kindSymbol", "constructor", "table", "WindowsClause", "w", "query", "newTuples", "tuple", "clause", "newItems", "item", "newSource", "newJoins", "join", "subQuery", "newQuery", "inlineQuery", "joinClause", "newCondition", "joinOn", "joinUsing", "whereClause", "newGrouping", "newOrder", "newExpression", "newLimit", "newLeft", "newRight", "newSwitchCase", "switchCase", "newCases", "caseItem", "newElseValue", "pair", "newKey", "newValue", "newLower", "newUpper", "func", "newArgument", "newOver", "newValues", "value", "newInput", "newCastType", "typeValue", "ident", "raw", "column", "source", "newAlias", "param", "newPartition", "newFrameSpec", "spec", "TableSourceCollector", "selectableOnly", "SimpleSelectQuery", "expr", "BinarySelectQuery", "ValuesQuery", "WithClause", "CommonTable", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "SourceExpression", "TableSource", "FunctionSource", "ParenSource", "SubQuerySource", "InlineQuery", "WhereClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "ForClause", "OrderByItem", "SelectClause", "SelectItem", "ParenExpression", "BinaryExpression", "UnaryExpression", "CaseExpression", "CaseKeyValuePair", "SwitchCaseArgument", "BetweenExpression", "FunctionCall", "ArrayExpression", "ArrayQueryExpression", "TupleExpression", "CastExpression", "ValueList", "StringSpecifierExpression", "source", "ns", "RawString", "query", "arg", "handler", "cteCollector", "CTECollector", "commonTables", "cte", "win", "tuple", "withClause", "table", "commonTable", "fromClause", "join", "identifier", "value", "tableName", "subQuery", "inlineQuery", "joinClause", "joinOn", "joinUsing", "whereClause", "clause", "item", "switchCase", "caseItem", "pair", "func", "valueList", "SqlPrintToken", "type", "text", "containerType", "ParameterCollector", "node", "result", "walk", "n", "ParameterExpression", "key", "v", "IdentifierDecorator", "identifierEscape", "text", "ParameterDecorator", "options", "text", "index", "paramText", "UpdateQuery", "SqlComponent", "params", "SetClause", "SelectValueCollector", "_SelectValueCollector", "tableColumnResolver", "initialCommonTables", "CTECollector", "SimpleSelectQuery", "expr", "SelectClause", "SourceExpression", "FromClause", "arg", "items", "handler", "query", "wildcards", "item", "ColumnReference", "wildSourceNames", "fromSourceName", "join", "joinSourceName", "clause", "joinCascade", "sourceName", "source", "commonTable", "innerCommonTables", "columnName", "column", "TableSource", "SubQuerySource", "ParenSource", "name", "value", "CreateTableQuery", "SqlComponent", "params", "IdentifierString", "selectItems", "SelectValueCollector", "val", "SelectItem", "RawString", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "FunctionCall", "ColumnReference", "PRESETS", "SqlPrintTokenParser", "_SqlPrintTokenParser", "options", "ParameterDecorator", "IdentifierDecorator", "ValueList", "expr", "ColumnReference", "QualifiedName", "FunctionCall", "UnaryExpression", "BinaryExpression", "LiteralValue", "ParameterExpression", "SwitchCaseArgument", "CaseKeyValuePair", "RawString", "IdentifierString", "ParenExpression", "CastExpression", "CaseExpression", "ArrayExpression", "ArrayQueryExpression", "BetweenExpression", "StringSpecifierExpression", "TypeValue", "TupleExpression", "InlineQuery", "WindowFrameExpression", "WindowFrameSpec", "WindowFrameBoundStatic", "WindowFrameBoundaryValue", "PartitionByClause", "OrderByClause", "OrderByItem", "SelectItem", "SelectClause", "Distinct", "DistinctOn", "TableSource", "FunctionSource", "SourceExpression", "SourceAliasExpression", "FromClause", "JoinClause", "JoinOnClause", "JoinUsingClause", "WhereClause", "GroupByClause", "HavingClause", "WindowsClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "FetchExpression", "ForClause", "WithClause", "CommonTable", "SimpleSelectQuery", "SubQuerySource", "BinarySelectQuery", "ValuesQuery", "InsertQuery", "InsertClause", "UpdateQuery", "UpdateClause", "SetClause", "SetClauseItem", "ReturningClause", "CreateTableQuery", "SqlPrintToken", "arg", "token", "i", "paramsRaw", "ParameterCollector", "a", "b", "style", "paramsObj", "p", "key", "paramsArr", "handler", "text", "kv", "elseValue", "elseToken", "elseValueContainer", "thenValueContainer", "specifier", "value", "first", "defaultName", "fullName", "ns", "query", "subQuery", "values", "queryToken", "LinePrinter", "indentChar", "indentSize", "newline", "result", "line", "level", "current", "PrintLine", "text", "workingIndex", "workLine", "SqlPrinter", "options", "LinePrinter", "token", "level", "current", "text", "i", "keywordToken", "innerLevel", "child", "VALID_PRESETS", "SqlFormatter", "options", "presetConfig", "PRESETS", "parserOptions", "SqlPrintTokenParser", "SqlPrinter", "sql", "token", "params", "Formatter", "SqlFormatter", "arg", "config", "result", "CTEBuilder", "TableSourceCollector", "CTECollector", "Formatter", "commonTables", "WithClause", "resolvedTables", "tableMap", "recursiveCTEs", "dependencies", "sortedTables", "ctesByName", "table", "tableName", "name", "tables", "definitions", "referencedBy", "referencedTables", "referencedTable", "referencedCTEs", "referencedCTE", "referencedName", "recursiveResult", "nonRecursiveResult", "visited", "visiting", "visit", "deps", "dep", "CTEInjector", "CTEBuilder", "CTECollector", "query", "commonTables", "resolvedWithCaluse", "SimpleSelectQuery", "BinarySelectQuery", "withClause", "CTENormalizer", "query", "allCommonTables", "CTECollector", "CTEDisabler", "CTEInjector", "DuplicateDetectionMode", "SelectableColumnCollector", "tableColumnResolver", "includeWildCard", "duplicateDetection", "options", "CTECollector", "SimpleSelectQuery", "expr", "SelectClause", "FromClause", "WhereClause", "GroupByClause", "HavingClause", "OrderByClause", "WindowFrameClause", "LimitClause", "OffsetClause", "FetchClause", "JoinOnClause", "JoinUsingClause", "ColumnReference", "BinaryExpression", "UnaryExpression", "FunctionCall", "ParenExpression", "CaseExpression", "CastExpression", "BetweenExpression", "ArrayExpression", "ArrayQueryExpression", "ValueList", "WindowFrameExpression", "PartitionByClause", "arg", "items", "name", "value", "item", "tableName", "key", "itemTable", "handler", "query", "win", "clause", "sourceValues", "SelectValueCollector", "join", "joinOnClause", "joinUsingClause", "columnRef", "func", "SourceParser", "_SourceParser", "query", "lexemes", "SqlTokenizer", "result", "index", "fullNameResult", "FullNameParser", "idx", "namespaces", "name", "newIndex", "TableSource", "argument", "ValueParser", "functionName", "FunctionSource", "keyword", "selectQuery", "SelectQueryParser", "SubQuerySource", "UpstreamSelectQueryFinder", "tableColumnResolver", "options", "SelectableColumnCollector", "query", "columnNames", "namesArray", "ctes", "CTECollector", "cteMap", "cte", "src", "nextCteMap", "result", "fromClause", "sources", "allBranchResults", "allBranchesOk", "validBranchCount", "sourceExpr", "branchResult", "TableSource", "SubQuerySource", "ValuesQuery", "SimpleSelectQuery", "columns", "col", "normalize", "s", "name", "BinarySelectQuery", "left", "right", "SourceAliasExpressionParser", "lexemes", "index", "idx", "table", "columns", "SourceAliasExpression", "SourceExpressionParser", "query", "lexemes", "SqlTokenizer", "result", "index", "SourceParser", "SourceExpression", "idx", "sourceResult", "aliasResult", "SourceAliasExpressionParser", "type", "QueryBuilder", "_QueryBuilder", "queries", "operator", "wrap", "q", "ValuesQuery", "result", "BinarySelectQuery", "CTENormalizer", "i", "query", "SimpleSelectQuery", "subQuerySource", "SubQuerySource", "sourceExpr", "SourceExpression", "SourceAliasExpression", "fromClause", "FromClause", "selectClause", "columnCount", "selectItems", "name", "SelectItem", "ColumnReference", "SelectClause", "columnRef", "selectItem", "tableName", "isTemporary", "CreateTableQuery", "selectQuery", "cols", "count", "SelectValueCollector", "item", "SourceExpressionParser", "InsertQuery", "InsertClause", "selectSourceName", "updateTableExprRaw", "primaryKeys", "updateClause", "UpdateClause", "pkArray", "collectedCTEs", "CTECollector", "CTEDisabler", "pk", "updateSourceName", "setItems", "col", "SetClauseItem", "setClause", "SetClause", "from", "where", "cond", "BinaryExpression", "whereClause", "WhereClause", "UpdateQuery", "WithClause", "ParameterHelper", "query", "name", "value", "params", "ParameterCollector", "found", "p", "SimpleSelectQuery", "SqlComponent", "params", "rightQuery", "operator", "QueryBuilder", "rawCondition", "parsedCondition", "ValueParser", "condition", "BinaryExpression", "WhereClause", "HavingClause", "joinSourceRawText", "alias", "columns", "resolver", "sourceExpr", "joinType", "tableSource", "SourceParser", "SourceExpression", "SourceAliasExpression", "columnsArr", "valueSets", "SelectableColumnCollector", "joinCondition", "count", "sourceAlias", "valueSet", "col", "expr", "ColumnReference", "joinOnClause", "JoinOnClause", "joinClause", "JoinClause", "CTENormalizer", "SubQuerySource", "commonTable", "tables", "WithClause", "rawText", "query", "SelectQueryParser", "CommonTable", "columnName", "fn", "items", "item", "exprSql", "Formatter", "newValue", "exprBuilder", "options", "queries", "UpstreamSelectQueryFinder", "collector", "formatter", "q", "exprs", "exprStr", "name", "value", "ParameterHelper", "BinarySelectQuery", "_BinarySelectQuery", "SqlComponent", "left", "operator", "right", "RawString", "query", "CTENormalizer", "sql", "parsedQuery", "SelectQueryParser", "alias", "SourceExpression", "SubQuerySource", "SourceAliasExpression", "name", "value", "ParameterHelper", "ValuesQuery", "SqlComponent", "tuples", "columnAliases", "QueryBuilder", "name", "value", "ParameterHelper", "SelectClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "distinct", "Distinct", "argument", "ValueParser", "DistinctOn", "items", "item", "SelectItemParser", "SelectClause", "parsedValue", "value", "alias", "SelectItem", "ColumnReference", "JoinOnClauseParser", "lexemes", "index", "idx", "condition", "ValueParser", "JoinOnClause", "JoinUsingClauseParser", "lexemes", "index", "idx", "result", "ValueParser", "usingColumns", "JoinUsingClause", "JoinClauseParser", "lexemes", "index", "idx", "joins", "joinClause", "value", "joinkeywordParser", "joinType", "lateralResult", "lateral", "sourceResult", "SourceExpressionParser", "onResult", "JoinOnClauseParser", "JoinClause", "usingResult", "JoinUsingClauseParser", "FromClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "sourceExpression", "SourceExpressionParser", "join", "JoinClauseParser", "FromClause", "WhereClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "item", "ValueParser", "WhereClause", "GroupByClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "items", "item", "GroupByClause", "parsedValue", "ValueParser", "value", "HavingClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "item", "ValueParser", "HavingClause", "WindowClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "windows", "name", "expr", "WindowExpressionParser", "WindowFrameClause", "WindowsClause", "LimitClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "limitItem", "ValueParser", "LimitClause", "ForClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "lockModeValue", "lockMode", "ForClause", "CommonTableParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "aliasResult", "SourceAliasExpressionParser", "materialized", "currentValue", "queryResult", "SelectQueryParser", "CommonTable", "WithClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "recursive", "tables", "firstCte", "CommonTableParser", "cteResult", "WithClause", "ValuesQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "tuples", "firstTuple", "tuple", "ValuesQuery", "values", "TupleExpression", "firstValue", "ValueParser", "value", "FetchClauseParser", "lexemes", "index", "idx", "fetchExprResult", "FetchExpressionParser", "fetchExpr", "FetchClause", "type", "typeToken", "count", "unit", "LiteralValue", "FetchExpression", "countResult", "ValueParser", "OffsetClauseParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "offsetItem", "ValueParser", "OffsetClause", "SelectQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "firstToken", "firstResult", "operator", "nextToken", "BinarySelectQuery", "withClauseResult", "WithClauseParser", "selectClauseResult", "SelectClauseParser", "fromClauseResult", "FromClauseParser", "whereClauseResult", "WhereClauseParser", "groupByClauseResult", "GroupByClauseParser", "havingClauseResult", "HavingClauseParser", "windowClauseResult", "WindowClauseParser", "orderByClauseResult", "OrderByClauseParser", "limitClauseResult", "LimitClauseParser", "offsetClauseResult", "OffsetClauseParser", "fetchClauseResult", "FetchClauseParser", "forClauseResult", "ForClauseParser", "SimpleSelectQuery", "ValuesQueryParser", "InsertQueryParser", "query", "lexemes", "SqlTokenizer", "result", "index", "idx", "withclause", "WithClauseParser", "sourceResult", "SourceExpressionParser", "columns", "selectResult", "SelectQueryParser", "SimpleSelectQuery", "InsertQuery", "InsertClause", "PostgresObjectEntityCteBuilder", "_PostgresObjectEntityCteBuilder", "initialCte", "allEntities", "mapping", "ctes", "previousCteAlias", "objectEntityInfos", "entitiesByDepth", "depths", "a", "b", "depth", "entitiesAtDepth", "cteAlias", "cte", "objectInfos", "calculateActualObjectNestingDepth", "entityIdOfObject", "initialEntity", "currentParentIdInHierarchy", "calculatedObjectDepth", "visitedInPath", "parentEntityData", "parentIsConsideredAnObjectForNesting", "parentDefinition", "ne", "nestedEntity", "entity", "info", "selectItems", "SelectItem", "ColumnReference", "IdentifierString", "jsonColumn", "cteSelect", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "CommonTable", "SourceAliasExpression", "jsonObjectArgs", "nullChecks", "jsonObject", "nullCondition", "caseExpr", "jsonColumnName", "jsonKey", "sqlColumn", "LiteralValue", "BinaryExpression", "childEntity", "child", "args", "useJsonb", "jsonBuildFunction", "FunctionCall", "RawString", "ValueList", "acc", "check", "CaseExpression", "SwitchCaseArgument", "CaseKeyValuePair", "PostgresArrayEntityCteBuilder", "_PostgresArrayEntityCteBuilder", "ctesSoFar", "aliasOfCteToBuildUpon", "allEntities", "mapping", "currentCtes", "currentCteAlias", "sortedArrayInfos", "entitiesByDepth", "depths", "a", "b", "depth", "infos", "cte", "newCteAlias", "arrayEntityInfos", "getDepth", "entityId", "entity", "ne", "currentArrayEntity", "parentEntity", "parentSqlColumns", "parentIdColumnSqlName", "arrayInfos", "info", "arrayColumns", "col", "prevCte", "c", "prevSelects", "SelectValueCollector", "groupByItems", "selectItems", "sv", "SelectItem", "ColumnReference", "IdentifierString", "agg", "cteAlias", "cteSelect", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "GroupByClause", "CommonTable", "SourceAliasExpression", "nestedEntities", "useJsonb", "jsonBuildFunction", "args", "jsonKey", "sqlColumn", "LiteralValue", "childEntity", "jsonColumnName", "jsonObject", "FunctionCall", "RawString", "ValueList", "jsonAggFunction", "PostgresJsonQueryBuilder", "SelectValueCollector", "PostgresObjectEntityCteBuilder", "PostgresArrayEntityCteBuilder", "query", "mapping", "selectedValues", "availableColumns", "sv", "jsonKey", "sourceColumn", "entityIds", "parentToChildrenMap", "ne", "entity", "allParentIds", "parentId", "directChildren", "c", "parentName", "propertyNames", "child", "originalQuery", "initialCte", "initialCteAlias", "ctesForProcessing", "currentAliasToBuildUpon", "allEntities", "objectEntityResult", "arrayCteBuildResult", "originCteAlias", "CommonTable", "SourceAliasExpression", "finalCtesList", "lastCteAliasForFromClause", "currentCtes", "rootObjectCteAlias", "rootEntity", "rootObjectBuilderExpression", "rootObjectSelectItem", "SelectItem", "rootObjectCte", "SimpleSelectQuery", "SelectClause", "FromClause", "SourceExpression", "TableSource", "IdentifierString", "aggregationFunc", "aggregateExpression", "FunctionCall", "RawString", "ValueList", "ColumnReference", "WithClause", "LimitClause", "LiteralValue", "sourceAlias", "nestedEntities", "useJsonb", "jsonBuildFunction", "args", "sqlColumn", "childEntity", "jsonColumnName", "TableSchema", "name", "columns", "SchemaCollector", "tableColumnResolver", "SimpleSelectQuery", "expr", "BinarySelectQuery", "arg", "cteCollector", "CTECollector", "handler", "consolidatedSchemas", "schema", "existingColumns", "column", "nameA", "nameB", "source", "queryColumns", "includeUnnamed", "TableSource", "tableName", "cte", "table", "tableAlias", "query", "SelectableColumnCollector", "ColumnReference", "columnRef", "columnsWithoutTable", "SubQuerySource", "join", "errorMessage", "tableColumns", "tableSchema", "SqlParamInjector", "optionsOrResolver", "options", "query", "state", "SelectQueryParser", "finder", "UpstreamSelectQueryFinder", "collector", "SelectableColumnCollector", "normalize", "s", "allowedOps", "name", "stateValue", "orConditions", "referencedColumns", "cond", "col", "index", "arr", "targetQuery", "colName", "queries", "columns", "injectOrConditions", "andConditions", "injectAndConditions", "explicitColumnName", "q", "entry", "item", "validateOperators", "injectComplexConditions", "columnRef", "targetColumn", "targetColumnName", "explicitEntry", "injectSimpleCondition", "baseName", "availableColumns", "i", "andCondition", "columnName", "paramName", "paramExpr", "ParameterExpression", "BinaryExpression", "prms", "v", "j", "ParenExpression", "ValueList", "FunctionCall", "orExpressions", "orCondition", "branchConditions", "branchExpr", "finalOrExpr", "op", "conditions", "paramEq", "paramMin", "paramMax", "paramLike", "paramIlike", "paramAny", "paramLT", "paramGT", "paramNEQ", "paramNE", "paramLE", "paramGE", "combinedExpr", "SqlSchemaValidator", "sql", "tableResolver", "sqlComponent", "SelectQueryParser", "resolver", "tableName", "schema", "t", "tableSchemas", "SchemaCollector", "errors", "tableSchema", "resolvedColumns", "undefinedColumns", "column", "SchemaManager", "schemas", "tableNames", "errors", "tableName", "table", "_", "col", "name", "rel", "rootTableName", "rootTable", "rootColumns", "columnName", "column", "nestedEntities", "relatedTable", "relatedColumns", "relationshipType", "primaryKeyEntry", "foreignKeys", "createSchemaManager", "createTableColumnResolver", "createJsonMappingFromSchema"]
7
7
  }