001package gudusoft.gsqlparser.stmt.teradata; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.TCustomSqlStatement; 005import gudusoft.gsqlparser.nodes.TParseTreeVisitor; 006import gudusoft.gsqlparser.ESqlStatementType; 007 008public class TTeradataMultiLoadExport extends TCustomSqlStatement { 009 private CommandType commandType; 010 private String filePath; 011 private String delimiter = "|"; // default delimiter 012 private String quote = "\""; // default quote 013 private String encoding = "UTF8"; // default encoding 014 private boolean indicData = false; 015 private Integer width; 016 private String command; 017 018 public enum CommandType { 019 OUTFILE, 020 RESET, 021 UNKNOWN 022 } 023 024 public TTeradataMultiLoadExport(EDbVendor dbvendor, String exportCommand) { 025 super(dbvendor); 026 sqlstatementtype = ESqlStatementType.sstteradataMultiLoadExport; 027 this.command = exportCommand; 028 parse(exportCommand); 029 } 030 031 private void parse(String exportCommand) { 032 if (exportCommand == null || exportCommand.trim().isEmpty()) { 033 throw new IllegalArgumentException("Export command cannot be empty"); 034 } 035 036 String command = exportCommand.trim(); 037 038 if (!command.startsWith(".EXPORT")) { 039 throw new IllegalArgumentException("Invalid export command format. Must start with .EXPORT"); 040 } 041 042 if (command.equals(".EXPORT RESET")) { 043 this.commandType = CommandType.RESET; 044 return; 045 } 046 047 if (command.startsWith(".EXPORT OUTFILE")) { 048 this.commandType = CommandType.OUTFILE; 049 parseOutfileCommand(command); 050 } else { 051 this.commandType = CommandType.UNKNOWN; 052 throw new IllegalArgumentException("Unknown export command type"); 053 } 054 } 055 056 private void parseOutfileCommand(String command) { 057 // Remove .EXPORT OUTFILE from the start 058 String options = command.substring(".EXPORT OUTFILE".length()).trim(); 059 060 // Parse each option 061 String[] parts = options.split("\\s+(?=(?:[^'\"]*['\"][^'\"]*['\"])*[^'\"]*$)"); 062 063 for (int i = 0; i < parts.length; i++) { 064 String part = parts[i].trim(); 065 066 if (i == 0) { 067 // First part should be the file path 068 this.filePath = extractQuotedString(part); 069 continue; 070 } 071 072 switch (part.toUpperCase()) { 073 case "DELIMITER": 074 if (i + 1 < parts.length) { 075 this.delimiter = extractQuotedString(parts[++i]); 076 } 077 break; 078 case "QUOTE": 079 if (i + 1 < parts.length) { 080 this.quote = extractQuotedString(parts[++i]); 081 } 082 break; 083 case "ENCODING": 084 if (i + 1 < parts.length) { 085 this.encoding = extractQuotedString(parts[++i]); 086 } 087 break; 088 case "INDICDATA": 089 this.indicData = true; 090 break; 091 case "WIDTH": 092 if (i + 1 < parts.length) { 093 try { 094 this.width = Integer.parseInt(parts[++i].replace(";", "")); 095 } catch (NumberFormatException e) { 096 throw new IllegalArgumentException("Invalid WIDTH value"); 097 } 098 } 099 break; 100 } 101 } 102 103 if (this.filePath == null || this.filePath.isEmpty()) { 104 throw new IllegalArgumentException("File path is required for OUTFILE command"); 105 } 106 } 107 108 private String extractQuotedString(String input) { 109 input = input.replace(";", ""); // Remove trailing semicolon if present 110 if (input.startsWith("'") && input.endsWith("'")) { 111 return input.substring(1, input.length() - 1); 112 } 113 if (input.startsWith("\"") && input.endsWith("\"")) { 114 return input.substring(1, input.length() - 1); 115 } 116 return input; 117 } 118 119 public String toCommandString() { 120 if (commandType == CommandType.RESET) { 121 return ".EXPORT RESET;"; 122 } 123 124 if (commandType == CommandType.OUTFILE) { 125 StringBuilder command = new StringBuilder(); 126 command.append(".EXPORT OUTFILE '").append(filePath).append("'"); 127 128 if (!"|".equals(delimiter)) { 129 command.append(" DELIMITER '").append(delimiter).append("'"); 130 } 131 if (!"\"".equals(quote)) { 132 command.append(" QUOTE '").append(quote).append("'"); 133 } 134 if (!"UTF8".equals(encoding)) { 135 command.append(" ENCODING '").append(encoding).append("'"); 136 } 137 if (indicData) { 138 command.append(" INDICDATA"); 139 } 140 if (width != null) { 141 command.append(" WIDTH ").append(width); 142 } 143 command.append(";"); 144 145 return command.toString(); 146 } 147 148 return ""; 149 } 150 151 // Getters 152 public CommandType getCommandType() { return commandType; } 153 public String getFilePath() { return filePath; } 154 public String getDelimiter() { return delimiter; } 155 public String getQuote() { return quote; } 156 public String getEncoding() { return encoding; } 157 public boolean isIndicData() { return indicData; } 158 public Integer getWidth() { return width; } 159 160 // Setters 161 public void setFilePath(String filePath) { this.filePath = filePath; } 162 public void setDelimiter(String delimiter) { this.delimiter = delimiter; } 163 public void setQuote(String quote) { this.quote = quote; } 164 public void setEncoding(String encoding) { this.encoding = encoding; } 165 public void setIndicData(boolean indicData) { this.indicData = indicData; } 166 public void setWidth(Integer width) { this.width = width; } 167 168 public void accept(TParseTreeVisitor v){ 169 v.preVisit(this); 170 v.postVisit(this); 171 } 172 173 public void acceptChildren(TParseTreeVisitor v){ 174 v.preVisit(this); 175 v.postVisit(this); 176 } 177}