UNPKG

rawsql-ts

Version:

High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.

321 lines (320 loc) 12.9 kB
import { FromClause, JoinClause, JoinOnClause, JoinUsingClause, FunctionSource, SourceAliasExpression, WhereClause, GroupByClause, HavingClause, SubQuerySource, WindowFrameClause, LimitClause, ForClause, OffsetClause, WindowsClause as WindowClause, CommonTable, WithClause, FetchClause, FetchExpression, UpdateClause, DeleteClause, UsingClause, SetClause, ReturningClause, SetClauseItem } from "../models/Clause"; import { SimpleSelectQuery, ValuesQuery } from "../models/SelectQuery"; import { SqlComponent, SqlComponentVisitor } from "../models/SqlComponent"; import { SqlPrintToken } from "../models/SqlPrintToken"; import { InlineQuery } from "../models/ValueComponent"; import { IdentifierDecorator } from "./IdentifierDecorator"; import { ParameterDecorator } from "./ParameterDecorator"; import { CreateTableQuery } from "../models/CreateTableQuery"; export declare enum ParameterStyle { Anonymous = "anonymous", Indexed = "indexed", Named = "named" } export type CastStyle = 'postgres' | 'standard'; export type ConstraintStyle = 'postgres' | 'mysql'; export interface FormatterConfig { identifierEscape?: { start: string; end: string; }; parameterSymbol?: string | { start: string; end: string; }; /** * Parameter style: anonymous (?), indexed ($1), or named (:name) */ parameterStyle?: ParameterStyle; /** Controls how CAST expressions are rendered */ castStyle?: CastStyle; /** Controls how table/column constraints are rendered */ constraintStyle?: ConstraintStyle; } export declare const PRESETS: Record<string, FormatterConfig>; export declare class SqlPrintTokenParser implements SqlComponentVisitor<SqlPrintToken> { private static readonly SPACE_TOKEN; private static readonly COMMA_TOKEN; private static readonly ARGUMENT_SPLIT_COMMA_TOKEN; private static readonly PAREN_OPEN_TOKEN; private static readonly PAREN_CLOSE_TOKEN; private static readonly DOT_TOKEN; private static _selfHandlingComponentTypes; private static getSelfHandlingComponentTypes; private handlers; parameterDecorator: ParameterDecorator; identifierDecorator: IdentifierDecorator; index: number; private castStyle; private constraintStyle; private readonly normalizeJoinConditionOrder; private joinConditionContexts; constructor(options?: { preset?: FormatterConfig; identifierEscape?: { start: string; end: string; }; parameterSymbol?: string | { start: string; end: string; }; parameterStyle?: 'anonymous' | 'indexed' | 'named'; castStyle?: CastStyle; constraintStyle?: ConstraintStyle; joinConditionOrderByDeclaration?: boolean; }); /** * Pretty-prints a BinarySelectQuery (e.g., UNION, INTERSECT, EXCEPT). * This will recursively print left and right queries, separated by the operator. * @param arg BinarySelectQuery */ private visitBinarySelectQuery; /** * Returns an array of tokens representing a comma followed by a space. * This is a common pattern in SQL pretty-printing. */ private static commaSpaceTokens; private static argumentCommaSpaceTokens; private visitQualifiedName; private visitPartitionByClause; private visitOrderByClause; /** * Print an OrderByItem (expression [asc|desc] [nulls first|last]) */ private visitOrderByItem; parse(arg: SqlComponent): { token: SqlPrintToken; params: any[] | Record<string, any>[] | Record<string, any>; }; /** * Check if a component handles its own comments */ private componentHandlesOwnComments; visit(arg: SqlComponent): SqlPrintToken; /** * Check if a component has positioned comments */ private hasPositionedComments; /** * Check if a component has legacy comments */ private hasLegacyComments; /** * Centralized comment handling - checks positioned comments first, falls back to legacy */ private addComponentComments; /** * Adds positioned comment tokens to a SqlPrintToken for inline formatting */ private addPositionedCommentsToToken; /** * Adds comment tokens to a SqlPrintToken based on the comments array */ private addCommentsToToken; /** * Creates inline comment sequence for multiple comments without newlines */ private createInlineCommentSequence; /** * Creates CommentBlock containers for the given comments. * Each CommentBlock contains: Comment -> CommentNewline -> Space. * @param comments Raw comment strings to convert into CommentBlock tokens. * @param isHeaderComment Marks the generated blocks as originating from header comments when true. */ private createCommentBlocks; /** * Determines if a comment should be merged with consecutive comments */ private shouldMergeComment; /** * Creates a multi-line block comment structure from consecutive comments * Returns a CommentBlock containing multiple comment lines for proper LinePrinter integration */ /** * Creates a single CommentBlock with the standard structure: * Comment -> CommentNewline -> Space * * This structure supports both formatting modes: * - Multiline mode: Comment + newline (space is filtered as leading space) * - Oneliner mode: Comment + space (commentNewline is skipped) */ private createSingleCommentBlock; /** * Formats a comment, preserving line comment format for -- comments * and converting others to block format for safety */ private formatComment; /** * Inserts comment blocks into a token and handles spacing logic. * Adds separator spaces for clause-level containers and manages duplicate space removal. */ private insertCommentBlocksWithSpacing; /** * Handles positioned comments for ParenExpression with special spacing rules. * ParenExpression comments should be adjacent to parentheses without separator spaces. */ private addPositionedCommentsToParenExpression; /** * Determines whether a separator space should be added after comments for the given container type. * * Clause-level containers (SELECT, FROM, WHERE, etc.) need separator spaces because: * - Comments appear before the main clause content * - A space is needed to separate comment block from SQL tokens * * Item-level containers (SelectItem, etc.) don't need separator spaces because: * - Comments are inline with the item content * - Spacing is handled by existing token structure */ private shouldAddSeparatorSpace; /** * Checks if the container type represents a SQL clause (as opposed to an item within a clause). */ private isClauseLevelContainer; /** * Formats a comment string as a block comment with security sanitization. * Prevents SQL injection by removing dangerous comment sequences. */ private formatBlockComment; private shouldMergeHeaderComments; private createHeaderMultiLineCommentBlock; /** * Formats text as a single-line comment while sanitizing unsafe sequences. */ private formatLineComment; /** * Sanitizes content intended for a single-line comment. */ private sanitizeLineCommentContent; private escapeCommentDelimiters; private visitValueList; private visitColumnReference; private visitFunctionCall; private relocateGroupingSetComments; private isGroupingSetsFunction; private extractPositionedComments; private visitUnaryExpression; private visitBinaryExpression; private visitLiteralValue; private visitParameterExpression; private visitSwitchCaseArgument; private createElseToken; private visitCaseKeyValuePair; private visitRawString; private visitIdentifierString; private visitParenExpression; private visitCastExpression; private visitCaseExpression; private extractSwitchAfterComments; private collectCaseLeadingCommentsFromSwitch; private findCaseKeyToken; private collectCaseLeadingCommentBlocks; private collectCaseLeadingCommentBlocksRecursive; private isTransparentCaseWrapper; private commentBlockSignature; private visitArrayExpression; private visitArrayQueryExpression; private visitArraySliceExpression; private visitArrayIndexExpression; private visitBetweenExpression; private visitStringSpecifierExpression; private visitTypeValue; private visitTupleExpression; private tupleRequiresMultiline; private hasInlineComments; private hasLeadingComments; private visitWindowFrameExpression; private visitWindowFrameSpec; /** * Prints a window frame boundary value, such as "5 preceding" or "3 following". * @param arg WindowFrameBoundaryValue */ private visitWindowFrameBoundaryValue; /** * Prints a static window frame bound, such as "unbounded preceding", "current row", or "unbounded following". * @param arg WindowFrameBoundStatic */ private visitWindowFrameBoundStatic; private visitSelectItem; private visitSelectClause; private flattenTokenText; private visitHintClause; private visitDistinct; private visitDistinctOn; private visitTableSource; private visitSourceExpression; visitFromClause(arg: FromClause): SqlPrintToken; visitJoinClause(arg: JoinClause): SqlPrintToken; visitJoinOnClause(arg: JoinOnClause): SqlPrintToken; private getCurrentJoinAliasOrder; private buildJoinAliasOrder; private collectSourceIdentifiers; private normalizeJoinConditionValue; private normalizeBinaryEquality; private resolveColumnOwner; visitJoinUsingClause(arg: JoinUsingClause): SqlPrintToken; visitFunctionSource(arg: FunctionSource): SqlPrintToken; visitSourceAliasExpression(arg: SourceAliasExpression): SqlPrintToken; visitWhereClause(arg: WhereClause): SqlPrintToken; visitGroupByClause(arg: GroupByClause): SqlPrintToken; visitHavingClause(arg: HavingClause): SqlPrintToken; visitWindowClause(arg: WindowClause): SqlPrintToken; visitWindowFrameClause(arg: WindowFrameClause): SqlPrintToken; visitLimitClause(arg: LimitClause): SqlPrintToken; visitOffsetClause(arg: OffsetClause): SqlPrintToken; visitFetchClause(arg: FetchClause): SqlPrintToken; visitFetchExpression(arg: FetchExpression): SqlPrintToken; visitForClause(arg: ForClause): SqlPrintToken; visitWithClause(arg: WithClause): SqlPrintToken; visitCommonTable(arg: CommonTable): SqlPrintToken; visitSimpleQuery(arg: SimpleSelectQuery): SqlPrintToken; visitSubQuerySource(arg: SubQuerySource): SqlPrintToken; visitValuesQuery(arg: ValuesQuery): SqlPrintToken; visitInlineQuery(arg: InlineQuery): SqlPrintToken; private visitInsertQuery; private visitInsertClause; private visitDeleteQuery; visitDeleteClause(arg: DeleteClause): SqlPrintToken; visitUsingClause(arg: UsingClause): SqlPrintToken; private visitMergeQuery; private visitMergeWhenClause; private visitMergeUpdateAction; private visitMergeDeleteAction; private visitMergeInsertAction; private visitMergeDoNothingAction; private mergeMatchTypeToKeyword; private visitUpdateQuery; visitUpdateClause(arg: UpdateClause): SqlPrintToken; visitSetClause(arg: SetClause): SqlPrintToken; visitSetClauseItem(arg: SetClauseItem): SqlPrintToken; visitReturningClause(arg: ReturningClause): SqlPrintToken; visitCreateTableQuery(arg: CreateTableQuery): SqlPrintToken; private visitTableColumnDefinition; private visitColumnConstraintDefinition; private visitTableConstraintDefinition; private wrapWithParenExpression; private visitReferenceDefinition; private visitCreateIndexStatement; private visitCreateSequenceStatement; private visitAlterSequenceStatement; private visitSequenceClauses; private visitSequenceClause; private visitIndexColumnDefinition; private visitDropTableStatement; private visitDropIndexStatement; private visitAlterTableStatement; private visitAlterTableAddConstraint; private visitAlterTableDropConstraint; private visitAlterTableAddColumn; private visitAlterTableDropColumn; private visitAlterTableAlterColumnDefault; private visitDropConstraintStatement; private visitExplainStatement; private visitAnalyzeStatement; private renderExplainOption; private isExplainLegacyFlag; private isExplainBooleanTrue; private renderQualifiedNameInline; private renderIdentifierInline; private renderIdentifierText; }