001package gudusoft.gsqlparser.parser; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.TBaseType; 005import gudusoft.gsqlparser.TGSqlParser; 006import gudusoft.gsqlparser.TSourceTokenList; 007import gudusoft.gsqlparser.TStatementList; 008 009/** 010 * Trino SQL parser implementation. 011 * 012 * <p><b>Implementation Status:</b> DELEGATION PHASE 013 * <ul> 014 * <li><b>Current:</b> Delegates to legacy TGSqlParser</li> 015 * <li><b>Future:</b> Will extract Trino-specific logic incrementally</li> 016 * </ul> 017 * 018 * @see SqlParser 019 * @see SqlParserFactory 020 * @since 3.2.0.0 021 */ 022public class TrinoSqlParser implements SqlParser { 023 024 private final EDbVendor vendor = EDbVendor.dbvtrino; 025 026 @Override 027 public EDbVendor getVendor() { 028 return vendor; 029 } 030 031 @Override 032 public SqlParseResult parse(ParserContext context) { 033 return delegateToLegacy(context, true); 034 } 035 036 @Override 037 public SqlParseResult tokenize(ParserContext context) { 038 return delegateToLegacy(context, false); 039 } 040 041 private SqlParseResult delegateToLegacy(ParserContext context, boolean fullParse) { 042 SqlParseResult.Builder resultBuilder = new SqlParseResult.Builder(); 043 044 try { 045 // CRITICAL: Use dbvpresto (not dbvtrino) to avoid infinite recursion. 046 // TGSqlParser(dbvtrino) -> TrinoSqlParser.tokenize() -> delegateToLegacy() 047 // would create another TGSqlParser(dbvtrino), causing StackOverflowError. 048 // Presto has the actual parser implementation that Trino delegates to. 049 TGSqlParser legacyParser = new TGSqlParser(EDbVendor.dbvpresto); 050 transferContext(legacyParser, context); 051 052 long tokenStart = System.currentTimeMillis(); 053 legacyParser.tokenizeSqltext(); 054 resultBuilder.tokenizationTimeMs(System.currentTimeMillis() - tokenStart); 055 056 if (fullParse) { 057 long parseStart = System.currentTimeMillis(); 058 int result = legacyParser.parse(); 059 resultBuilder.parsingTimeMs(System.currentTimeMillis() - parseStart); 060 061 if (result != 0) { 062 resultBuilder.errorCode(result); 063 resultBuilder.errorMessage("Parsing failed: " + legacyParser.getErrormessage()); 064 } else { 065 resultBuilder.errorCode(0); 066 resultBuilder.errorMessage(""); 067 } 068 } else { 069 int result = legacyParser.getrawsqlstatements(); 070 if (result != 0) { 071 resultBuilder.errorCode(result); 072 resultBuilder.errorMessage("Tokenization failed: " + legacyParser.getErrormessage()); 073 } else { 074 resultBuilder.errorCode(0); 075 resultBuilder.errorMessage(""); 076 } 077 } 078 079 resultBuilder.sourceTokenList(legacyParser.sourcetokenlist); 080 resultBuilder.sqlStatements(legacyParser.sqlstatements); 081 resultBuilder.lexer(legacyParser.getFlexer()); 082 083 } catch (Exception e) { 084 resultBuilder.errorCode(1); 085 resultBuilder.errorMessage("Operation failed: " + e.getMessage()); 086 } 087 088 return resultBuilder.build(); 089 } 090 091 private void transferContext(TGSqlParser legacyParser, ParserContext context) { 092 if (context.getSqlText() != null && !context.getSqlText().isEmpty()) { 093 legacyParser.sqltext = context.getSqlText(); 094 } 095 if (context.getSqlFilename() != null && !context.getSqlFilename().isEmpty()) { 096 legacyParser.sqlfilename = context.getSqlFilename(); 097 } 098 099 legacyParser.setEnablePartialParsing(context.isEnablePartialParsing()); 100 legacyParser.setSinglePLBlock(context.isSinglePLBlock()); 101 legacyParser.setOnlyNeedRawParseTree(context.isOnlyNeedRawParseTree()); 102 103 if (context.getTeradataUtilityType() != null) { 104 legacyParser.setTeradataUtilityType(context.getTeradataUtilityType()); 105 } 106 if (context.getMetaDatabase() != null) { 107 legacyParser.setMetaDatabase(context.getMetaDatabase()); 108 } 109 if (context.getSqlEnv() != null) { 110 legacyParser.setSqlEnv(context.getSqlEnv()); 111 } 112 if (context.isDumpResolverLog()) { 113 TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE = true; 114 } 115 } 116 117 @Override 118 public String toString() { 119 return "TrinoSqlParser{vendor=" + vendor + "}"; 120 } 121}