001package gudusoft.gsqlparser.parser; 002 003import gudusoft.gsqlparser.EDbVendor; 004 005/** 006 * Strategy interface for vendor-specific SQL parsing. 007 * 008 * <p>This interface defines the contract for all database vendor-specific parsers. 009 * Each vendor (Oracle, MySQL, PostgreSQL, etc.) provides its own implementation 010 * that handles the vendor-specific tokenization, parsing, and semantic analysis. 011 * 012 * <p><b>Design Pattern:</b> Strategy Pattern 013 * <ul> 014 * <li>The strategy (SqlParser) is selected at runtime based on database vendor</li> 015 * <li>All inputs come from {@link ParserContext} (immutable)</li> 016 * <li>All outputs go to {@link SqlParseResult} (immutable)</li> 017 * </ul> 018 * 019 * <p><b>Usage Example:</b> 020 * <pre> 021 * // Get parser for specific vendor 022 * SqlParser parser = SqlParserFactory.get(EDbVendor.dbvoracle); 023 * 024 * // Build context with inputs 025 * ParserContext context = new ParserContext.Builder(EDbVendor.dbvoracle) 026 * .sqlText("SELECT * FROM employees") 027 * .build(); 028 * 029 * // Parse and get result 030 * SqlParseResult result = parser.parse(context); 031 * 032 * // Access outputs 033 * TStatementList statements = result.getSqlStatements(); 034 * </pre> 035 * 036 * @see ParserContext 037 * @see SqlParseResult 038 * @see AbstractSqlParser 039 * @since 3.2.0.0 040 */ 041public interface SqlParser { 042 043 /** 044 * Get the database vendor this parser handles. 045 * 046 * @return the database vendor (e.g., dbvoracle, dbvmysql) 047 */ 048 EDbVendor getVendor(); 049 050 /** 051 * Parse SQL from the given context. 052 * 053 * <p>This method performs full parsing including: 054 * <ul> 055 * <li>Tokenization (lexical analysis)</li> 056 * <li>Syntax analysis (building parse tree)</li> 057 * <li>Semantic analysis (resolving references)</li> 058 * </ul> 059 * 060 * <p>All inputs come from the context parameter, all outputs go to the result. 061 * This ensures clean separation of concerns and thread-safety. 062 * 063 * @param context immutable context containing all parser inputs 064 * (SQL text, options, callbacks, etc.) 065 * @return immutable result containing all parser outputs 066 * (statements, tokens, errors, etc.) 067 */ 068 SqlParseResult parse(ParserContext context); 069 070 /** 071 * Tokenize SQL without parsing or statement extraction. 072 * 073 * <p>This method performs only tokenization (lexical analysis): 074 * <ul> 075 * <li>Tokenization (lexical analysis)</li> 076 * </ul> 077 * 078 * <p>The result contains tokens but NO statements. Use this when you only 079 * need the token stream (e.g., for syntax highlighting, token analysis). 080 * 081 * <p>For statement boundaries without full parsing, use {@link #getrawsqlstatements(ParserContext)}. 082 * 083 * @param context immutable context containing all parser inputs 084 * @return immutable result containing tokens only (no statements) 085 */ 086 SqlParseResult tokenize(ParserContext context); 087 088 /** 089 * Vendor policy validation, run by {@code TGSqlParser} AFTER every statement 090 * has been parsed ("recognize then reject", Sybase family decomposition). 091 * 092 * <p>Runs post-parse on purpose: some statement objects are REPLACED during 093 * parsing (the refined statement is built from the parse-tree node), so an 094 * error attached at raw-extraction time can silently vanish with the old 095 * object. Post-parse, the statements are final. 096 * 097 * <p>Default is a no-op returning {@code null} — behaviour of every vendor 098 * that does not override this is untouched. 099 * 100 * @param statements the fully parsed statement list 101 * @return statements this vendor rejects (errors already attached), or null 102 */ 103 default java.util.List<gudusoft.gsqlparser.TCustomSqlStatement> 104 validateRecognizedStatements(gudusoft.gsqlparser.TStatementList statements) { 105 return null; 106 } 107 108 /** 109 * Extract raw SQL statements without full parsing. 110 * 111 * <p>This method performs: 112 * <ul> 113 * <li>Tokenization (lexical analysis)</li> 114 * <li>Raw statement extraction (statement boundary detection)</li> 115 * </ul> 116 * 117 * <p>This is faster than {@link #parse(ParserContext)} because it skips 118 * detailed syntax checking and semantic analysis. The statements returned 119 * have their tokens grouped correctly but no AST (parse tree) is built. 120 * 121 * <p><b>Use cases:</b> 122 * <ul> 123 * <li>Split a script into individual statements</li> 124 * <li>Determine statement types without full parsing</li> 125 * <li>Quick validation of statement boundaries</li> 126 * <li>Pre-processing before selective parsing</li> 127 * </ul> 128 * 129 * <p><b>Equivalent to legacy API:</b> {@code TGSqlParser.getrawsqlstatements()} 130 * 131 * <p><b>Default implementation:</b> For parsers still in delegation phase, 132 * this default implementation falls back to {@link #tokenize(ParserContext)}. 133 * Parsers extending AbstractSqlParser override this with proper implementation. 134 * 135 * @param context immutable context containing all parser inputs 136 * @return immutable result containing tokens and raw statements (no AST) 137 */ 138 default SqlParseResult getrawsqlstatements(ParserContext context) { 139 // Default implementation for parsers in delegation phase 140 // Just tokenize - subclasses should override with proper implementation 141 return tokenize(context); 142 } 143 144 /** 145 * Extract raw statements from already-tokenized source without re-tokenization. 146 * 147 * <p>This method is used when tokens are already available from a previous 148 * tokenization step (e.g., via {@code dosqltexttotokenlist()}). It performs 149 * only raw statement extraction without repeating tokenization. 150 * 151 * <p><b>Default implementation:</b> Falls back to tokenize() method for vendors 152 * that haven't implemented this optimization yet. 153 * 154 * @param context immutable context containing all parser inputs 155 * @param tokens already-tokenized source token list 156 * @return statement list containing extracted raw statements 157 * @since 3.2.0.0 158 * @deprecated As of 3.2.0.0, replaced by {@link #getrawsqlstatements(ParserContext)} 159 * which returns a richer {@link SqlParseResult} object containing statements, 160 * tokens, errors, timing information, and more. This method only returns 161 * {@link gudusoft.gsqlparser.TStatementList} without error information. 162 * <p> 163 * <b>Migration:</b> Use {@code vendorParser.getrawsqlstatements(context)} 164 * instead, which performs both tokenization and extraction in a single call 165 * and returns complete result information via {@link SqlParseResult}. 166 * <p> 167 * This method will be removed in a future major version. 168 */ 169 @Deprecated 170 default gudusoft.gsqlparser.TStatementList doExtractRawStatements(ParserContext context, gudusoft.gsqlparser.TSourceTokenList tokens) { 171 // Default implementation: fall back to tokenize() which does both tokenization and extraction 172 // Vendors that extend AbstractSqlParser will override this via the doExtractRawStatements() implementation 173// SqlParseResult result = tokenize(context); 174// return result.getSqlStatements(); 175 return null; // To be implemented by vendors, this method must be orerridden 176 } 177}