001package gudusoft.gsqlparser.nodes; 002 003import java.util.ArrayList; 004import java.util.Arrays; 005import java.util.List; 006import java.util.regex.Matcher; 007import java.util.regex.Pattern; 008 009import gudusoft.gsqlparser.*; 010import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement; 011import gudusoft.gsqlparser.stmt.snowflake.TSnowflakeCopyIntoStmt; 012import gudusoft.gsqlparser.stmt.snowflake.TCreateStageStmt; 013 014public class TCreateTableOption extends TParseTreeNode { 015 016 private TDistributeBy distributeBy; 017 018 public TDistributeBy getDistributeBy() { 019 return distributeBy; 020 } 021 022 private TBaseTablePartition partitionSpec; 023 024 public TBaseTablePartition getPartitionSpec() { 025 return partitionSpec; 026 } 027 028 public TObjectName getComment() { 029 return comment; 030 } 031 032 private TObjectName comment; 033 034 /* 035 * BigQuery external_table_option_list 036 * 037 * @see https://cloud.google.com/bigquery/docs/reference/standard-sql/data- 038 * definition-language#external_table_option_list 039 */ 040 private Boolean allowJaggedRows; 041 private Boolean allowQuotedNewlines; 042 private String compression; 043 private String description; 044 private Boolean enableLogicalTypes; 045 private String encoding; 046 private String expirationTimestamp; 047 private String fieldDelimiter; 048 private String format; 049 private List<String> decimalTargetTypes; 050 private String hivePartitionUriPrefix; 051 private Boolean ignoreUnknownValues; 052 private Long maxBadRecords; 053 private String nullMarker; 054 private String projectionFields; 055 private String quote; 056 private Boolean requireHivePartitionFilter; 057 private String sheetRange; 058 private Long skipLeadingRows; 059 private List<String> uris; 060 061 private TObjectNameList columnNamelist; 062 063 public TObjectNameList getColumnNamelist() { 064 return columnNamelist; 065 } 066 067 private String awsSnsTopic = null; 068 private TObjectNameList partitionColumnList; 069 private TExpression partitionByExpr; 070 071 /** 072 * Bigquery partition by expr 073 * @return expr 074 */ 075 public TExpression getPartitionByExpr() { 076 return partitionByExpr; 077 } 078 079 private String fileFormatName = null; 080 private String fileFormatType = null; 081 private ArrayList<TNameValuePair> fileFormatProperties = null; 082 083 public void setFileFormatName(TSourceToken fileFormatName) { 084 this.fileFormatName = fileFormatName.toString(); 085 } 086 public void setFileFormatName(TObjectName fileFormatName) { 087 this.fileFormatName = fileFormatName.toString(); 088 } 089 090 public void setFileFormatType(TSourceToken fileFormatType) { 091 this.fileFormatType = fileFormatType.toString(); 092 } 093 094 public String getFileFormatName() { 095 return fileFormatName; 096 } 097 098 public String getFileFormatType() { 099 return fileFormatType; 100 } 101 102 /** 103 * Get file format properties list (e.g., TYPE=CSV, FIELD_DELIMITER='|', SKIP_HEADER=1) 104 * Used in Snowflake external table file_format option 105 * @return list of name-value pairs representing file format properties 106 */ 107 public ArrayList<TNameValuePair> getFileFormatProperties() { 108 return fileFormatProperties; 109 } 110 111 /** 112 * Set file format properties list 113 * @param fileFormatProperties list of name-value pairs for file format options 114 */ 115 public void setFileFormatProperties(ArrayList<TNameValuePair> fileFormatProperties) { 116 this.fileFormatProperties = fileFormatProperties; 117 } 118 119 /** 120 * Parse file format string and create name-value pair list 121 * 122 * <p>Parses file format options in formats like:</p> 123 * <ul> 124 * <li>Single line: file_format=(TYPE=CSV FIELD_DELIMITER='|' SKIP_HEADER=1)</li> 125 * <li>Multi-line: FILE_FORMAT = (TYPE = CSV, FIELD_DELIMITER = ',', SKIP_HEADER = 1)</li> 126 * </ul> 127 * 128 * @param fileFormatString the file_format string to parse 129 * @return ArrayList of TNameValuePair objects representing the properties 130 */ 131 public ArrayList<TNameValuePair> parseFileFormatProperties(String fileFormatString) { 132 if (fileFormatString == null || fileFormatString.trim().isEmpty()) { 133 return null; 134 } 135 136 ArrayList<TNameValuePair> properties = new ArrayList<TNameValuePair>(); 137 138 // Normalize the input: remove line breaks and extra spaces 139 String normalized = fileFormatString.replaceAll("\\s+", " ").trim(); 140 141 // Extract content within parentheses 142 // Match pattern: file_format=(...) or FILE_FORMAT = (...) 143 Pattern outerPattern = Pattern.compile("(?i)file_format\\s*=\\s*\\((.+)\\)", Pattern.DOTALL); 144 Matcher outerMatcher = outerPattern.matcher(normalized); 145 146 String content; 147 if (outerMatcher.find()) { 148 content = outerMatcher.group(1).trim(); 149 } else { 150 // Try to match just the content in parentheses (...) 151 Pattern parenthesesPattern = Pattern.compile("\\((.+)\\)", Pattern.DOTALL); 152 Matcher parenthesesMatcher = parenthesesPattern.matcher(normalized); 153 if (parenthesesMatcher.find()) { 154 content = parenthesesMatcher.group(1).trim(); 155 } else { 156 // No parentheses found, assume the whole string is the content 157 content = normalized; 158 } 159 } 160 161 // Split by comma or space, but respect quoted strings and parentheses 162 ArrayList<String> pairs; 163 if (hasUnquotedComma(content)) { 164 // Comma-separated format 165 pairs = splitByComma(content); 166 } else { 167 // Space-separated format 168 pairs = splitBySpace(content); 169 } 170 171 // Parse each name=value pair 172 for (String pair : pairs) { 173 pair = pair.trim(); 174 if (pair.isEmpty()) { 175 continue; 176 } 177 178 // Split by '=' to get name and value 179 int equalsIndex = findEqualsIndex(pair); 180 if (equalsIndex > 0) { 181 String name = pair.substring(0, equalsIndex).trim(); 182 String value = pair.substring(equalsIndex + 1).trim(); 183 184 TNameValuePair nvPair = new TNameValuePair(); 185 nvPair.init(name, value); 186 properties.add(nvPair); 187 } 188 } 189 190 // Store in the field and return 191 this.fileFormatProperties = properties; 192 return properties; 193 } 194 195 /** 196 * Check if the content has any unquoted comma 197 * Helper method for parseFileFormatProperties 198 */ 199 private boolean hasUnquotedComma(String content) { 200 boolean inSingleQuote = false; 201 boolean inDoubleQuote = false; 202 203 for (int i = 0; i < content.length(); i++) { 204 char ch = content.charAt(i); 205 206 if (ch == '\'' && !inDoubleQuote) { 207 inSingleQuote = !inSingleQuote; 208 } else if (ch == '"' && !inSingleQuote) { 209 inDoubleQuote = !inDoubleQuote; 210 } else if (ch == ',' && !inSingleQuote && !inDoubleQuote) { 211 return true; // Found an unquoted comma 212 } 213 } 214 215 return false; 216 } 217 218 /** 219 * Split string by comma, but respect quoted strings and parentheses 220 * Helper method for parseFileFormatProperties 221 */ 222 private ArrayList<String> splitByComma(String content) { 223 ArrayList<String> parts = new ArrayList<String>(); 224 StringBuilder current = new StringBuilder(); 225 boolean inSingleQuote = false; 226 boolean inDoubleQuote = false; 227 int parenthesesDepth = 0; 228 229 for (int i = 0; i < content.length(); i++) { 230 char ch = content.charAt(i); 231 232 if (ch == '\'' && !inDoubleQuote) { 233 inSingleQuote = !inSingleQuote; 234 current.append(ch); 235 } else if (ch == '"' && !inSingleQuote) { 236 inDoubleQuote = !inDoubleQuote; 237 current.append(ch); 238 } else if (ch == '(' && !inSingleQuote && !inDoubleQuote) { 239 parenthesesDepth++; 240 current.append(ch); 241 } else if (ch == ')' && !inSingleQuote && !inDoubleQuote) { 242 parenthesesDepth--; 243 current.append(ch); 244 } else if (ch == ',' && !inSingleQuote && !inDoubleQuote && parenthesesDepth == 0) { 245 // Found a separator comma 246 parts.add(current.toString()); 247 current.setLength(0); // Clear StringBuilder 248 } else { 249 current.append(ch); 250 } 251 } 252 253 // Add the last part 254 if (current.length() > 0) { 255 parts.add(current.toString()); 256 } 257 258 return parts; 259 } 260 261 /** 262 * Split string by space, but respect quoted strings 263 * Helper method for parseFileFormatProperties (for space-separated format) 264 */ 265 private ArrayList<String> splitBySpace(String content) { 266 ArrayList<String> parts = new ArrayList<String>(); 267 StringBuilder current = new StringBuilder(); 268 boolean inSingleQuote = false; 269 boolean inDoubleQuote = false; 270 boolean inValue = false; // Track if we're currently building a value after '=' 271 272 for (int i = 0; i < content.length(); i++) { 273 char ch = content.charAt(i); 274 275 if (ch == '\'' && !inDoubleQuote) { 276 inSingleQuote = !inSingleQuote; 277 current.append(ch); 278 } else if (ch == '"' && !inSingleQuote) { 279 inDoubleQuote = !inDoubleQuote; 280 current.append(ch); 281 } else if (ch == '=' && !inSingleQuote && !inDoubleQuote) { 282 current.append(ch); 283 inValue = true; // After '=', we're in the value part 284 } else if (ch == ' ' && !inSingleQuote && !inDoubleQuote && inValue) { 285 // Space after a value - end current pair 286 parts.add(current.toString()); 287 current.setLength(0); 288 inValue = false; 289 } else if (ch == ' ' && !inSingleQuote && !inDoubleQuote && !inValue) { 290 // Space before '=' - just skip it 291 if (current.length() > 0) { 292 current.append(ch); 293 } 294 } else { 295 current.append(ch); 296 } 297 } 298 299 // Add the last part 300 if (current.length() > 0) { 301 parts.add(current.toString()); 302 } 303 304 return parts; 305 } 306 307 /** 308 * Find the index of the first '=' that is not inside quotes 309 * Helper method for parseFileFormatProperties 310 */ 311 private int findEqualsIndex(String pair) { 312 boolean inSingleQuote = false; 313 boolean inDoubleQuote = false; 314 315 for (int i = 0; i < pair.length(); i++) { 316 char ch = pair.charAt(i); 317 318 if (ch == '\'' && !inDoubleQuote) { 319 inSingleQuote = !inSingleQuote; 320 } else if (ch == '"' && !inSingleQuote) { 321 inDoubleQuote = !inDoubleQuote; 322 } else if (ch == '=' && !inSingleQuote && !inDoubleQuote) { 323 return i; 324 } 325 } 326 327 return -1; // No equals sign found 328 } 329 330 private TStageLocation stageLocation; 331 332 public void setStageLocation(TStageLocation stageLocation) { 333 this.stageLocation = stageLocation; 334 } 335 336 public TStageLocation getStageLocation() { 337 return stageLocation; 338 } 339 340 341 342 public String getAwsSnsTopic() { 343 return awsSnsTopic; 344 } 345 346 public void setAwsSnsTopic(String awsSnsTopic) { 347 this.awsSnsTopic = awsSnsTopic; 348 } 349 350 public TObjectNameList getPartitionColumnList() { 351 return partitionColumnList; 352 } 353 354 public void setPartitionColumnList(TObjectNameList partitionColumnList) { 355 this.partitionColumnList = partitionColumnList; 356 } 357 358 public String getCompression() { 359 return compression; 360 } 361 362 public void setCompression(String compression) { 363 this.compression = compression; 364 } 365 366 public String getDescription() { 367 return description; 368 } 369 370 public void setDescription(String description) { 371 this.description = description; 372 } 373 374 public String getExpirationTimestamp() { 375 return expirationTimestamp; 376 } 377 378 public void setExpirationTimestamp(String expirationTimestamp) { 379 this.expirationTimestamp = expirationTimestamp; 380 } 381 382 public String getFieldDelimiter() { 383 return fieldDelimiter; 384 } 385 386 public void setFieldDelimiter(String fieldDelimiter) { 387 this.fieldDelimiter = fieldDelimiter; 388 } 389 390 public String getFormat() { 391 return format; 392 } 393 394 public void setFormat(String format) { 395 this.format = format; 396 } 397 398 public List<String> getDecimalTargetTypes() { 399 return decimalTargetTypes; 400 } 401 402 public void setDecimalTargetTypes(List<String> decimalTargetTypes) { 403 this.decimalTargetTypes = decimalTargetTypes; 404 } 405 406 public String getHivePartitionUriPrefix() { 407 return hivePartitionUriPrefix; 408 } 409 410 public void setHivePartitionUriPrefix(String hivePartitionUriPrefix) { 411 this.hivePartitionUriPrefix = hivePartitionUriPrefix; 412 } 413 414 public Boolean getIgnoreUnknownValues() { 415 return ignoreUnknownValues; 416 } 417 418 public void setIgnoreUnknownValues(Boolean ignoreUnknownValues) { 419 this.ignoreUnknownValues = ignoreUnknownValues; 420 } 421 422 public Long getMaxBadRecords() { 423 return maxBadRecords; 424 } 425 426 public void setMaxBadRecords(Long maxBadRecords) { 427 this.maxBadRecords = maxBadRecords; 428 } 429 430 public void setRequireHivePartitionFilter(Boolean requireHivePartitionFilter) { 431 this.requireHivePartitionFilter = requireHivePartitionFilter; 432 } 433 434 public String getNullMarker() { 435 return nullMarker; 436 } 437 438 public void setNullMarker(String nullMarker) { 439 this.nullMarker = nullMarker; 440 } 441 442 public String getProjectionFields() { 443 return projectionFields; 444 } 445 446 public void setProjectionFields(String projectionFields) { 447 this.projectionFields = projectionFields; 448 } 449 450 public String getQuote() { 451 return quote; 452 } 453 454 public void setQuote(String quote) { 455 this.quote = quote; 456 } 457 458 public Boolean getRequireHivePartitionFilter() { 459 return requireHivePartitionFilter; 460 } 461 462 public String getSheetRange() { 463 return sheetRange; 464 } 465 466 public void setSheetRange(String sheetRange) { 467 this.sheetRange = sheetRange; 468 } 469 470 public Long getSkipLeadingRows() { 471 return skipLeadingRows; 472 } 473 474 public void setSkipLeadingRows(Long skipLeadingRows) { 475 this.skipLeadingRows = skipLeadingRows; 476 } 477 478 public List<String> getUris() { 479 return uris; 480 } 481 482 public void setUris(List<String> uris) { 483 this.uris = uris; 484 } 485 486 public Boolean getAllowJaggedRows() { 487 return allowJaggedRows; 488 } 489 490 public void setAllowJaggedRows(Boolean allowJaggedRows) { 491 this.allowJaggedRows = allowJaggedRows; 492 } 493 494 public Boolean getAllowQuotedNewlines() { 495 return allowQuotedNewlines; 496 } 497 498 public void setAllowQuotedNewlines(Boolean allowQuotedNewlines) { 499 this.allowQuotedNewlines = allowQuotedNewlines; 500 } 501 502 public Boolean getEnableLogicalTypes() { 503 return enableLogicalTypes; 504 } 505 506 public void setEnableLogicalTypes(Boolean enableLogicalTypes) { 507 this.enableLogicalTypes = enableLogicalTypes; 508 } 509 510 public String getEncoding() { 511 return encoding; 512 } 513 514 public void setEncoding(String encoding) { 515 this.encoding = encoding; 516 } 517 public void setEncoding(TSourceToken encoding) { 518 this.encoding = encoding.toString(); 519 } // added by baffle 520 521 public String getExternalStageURL() { 522 return externalStageURL; 523 } 524 525 public void setExternalStageURL(String externalStageURL) { 526 this.externalStageURL = externalStageURL; 527 } 528 529 public void setPartitionByExpr(TExpression partitionByExpr) { 530 this.partitionByExpr = partitionByExpr; 531 } 532 533 public void setFileFormatName(String fileFormatName) { 534 this.fileFormatName = fileFormatName; 535 } 536 537 public void setFileFormatType(String fileFormatType) { 538 this.fileFormatType = fileFormatType; 539 } 540 541 public void setDateRetentionInDays(TSourceToken dateRetentionInDays) { 542 this.dateRetentionInDays = dateRetentionInDays; 543 } 544 545 public void setCommentToken(TSourceToken commentToken) { 546 this.commentToken = commentToken; 547 } 548 549 public void setStageFileFormat(TDummy stageFileFormat) { 550 this.stageFileFormat = stageFileFormat; 551 } 552 553 public void setCopyOptions(TDummy copyOptions) { 554 this.copyOptions = copyOptions; 555 } 556 557 public void setExpressionList(TExpressionList expressionList) { 558 this.expressionList = expressionList; 559 } 560 561 private TSourceToken dateRetentionInDays; 562 563 public TSourceToken getDateRetentionInDays() { 564 return dateRetentionInDays; 565 } 566 567 private TSourceToken commentToken; 568 569 /** 570 * @deprecated since v 2.8.1.1, please use {@link #getComment()} instead 571 * @return 572 */ 573 public TSourceToken getCommentToken() { 574 return commentToken; 575 } 576 577 private TDummy stageFileFormat; 578 579 private TDummy copyOptions; 580 581 public TDummy getCopyOptions() { 582 return copyOptions; 583 } 584 585 protected ECreateTableOption createTableOptionType; 586 587 public void setCreateTableOptionType(ECreateTableOption createTableOptionType) { 588 this.createTableOptionType = createTableOptionType; 589 } 590 591 public ECreateTableOption getCreateTableOptionType() { 592 return createTableOptionType; 593 } 594 595 public void init(Object arg1){ 596 createTableOptionType = (ECreateTableOption)arg1; 597 } 598 599 private TExpressionList expressionList; 600 601 public TExpressionList getExpressionList() { 602 return expressionList; 603 } 604 605 public TDummy getStageFileFormat() { 606 return stageFileFormat; 607 } 608 609 private String externalStageURL=null; 610 611 public void init(Object arg1, Object arg2){ 612 init(arg1); 613 switch(createTableOptionType){ 614 case etoClusterBy: 615 this.expressionList = (TExpressionList)arg2; 616 break; 617 case etoStageCopyOptions: 618 this.copyOptions = (TDummy)arg2; 619 break; 620 case etoStageFileFormat: 621 this.stageFileFormat = (TDummy)arg2; 622 break; 623 case etoComment: 624 //this.commentToken = (TSourceToken)arg2; 625 this.comment = (TObjectName) arg2; 626 break; 627 case etoDateRetentionTimeInDays: 628 this.dateRetentionInDays = (TSourceToken)arg2; 629 break; 630 case etoPartitionBy: 631 if (arg2 instanceof TObjectNameList){ 632 this.partitionColumnList = (TObjectNameList)arg2; 633 }else if (arg2 instanceof TExpression){ 634 this.partitionByExpr = (TExpression)arg2; 635 } 636 break; 637 case etoAWSSnsTopic: 638 awsSnsTopic = ((TSourceToken)arg2).toString(); 639 break; 640 case etoStageURL: 641 externalStageURL = ((TSourceToken)arg2).toString(); 642 break; 643 case etoFiles: 644 this.expressionList = (TExpressionList)arg2; 645 break; 646 case etoDistributeOn: 647 case etoOrganizeOn: 648 this.columnNamelist =(TObjectNameList)arg2; 649 break; 650 case etoReloptions: 651 this.attributeOptions = (ArrayList<TAttributeOption>)arg2; 652 break; 653 case etoPartitionSpec: 654 this.partitionSpec = (TBaseTablePartition)arg2; 655 break; 656 case etoDistributeBy: 657 this.distributeBy = (TDistributeBy)arg2; 658 break; 659 case etoDistributeByHash: 660 this.columnNamelist = (TObjectNameList)arg2; 661 break; 662 case etoPartitioningKey: 663 this.columnNamelist = (TObjectNameList)arg2; 664 break; 665 case etoOrganizeBy: 666 case etoOrganizeByDimensions: 667 this.valueRowItemList = (TMultiTargetList)arg2; 668 break; 669 } 670 } 671 672 private TMultiTargetList valueRowItemList; 673 674 public TMultiTargetList getValueRowItemList() { 675 return valueRowItemList; 676 } 677 678 public ArrayList<TAttributeOption> getAttributeOptions() { 679 return attributeOptions; 680 } 681 682 private ArrayList<TAttributeOption> attributeOptions ; 683 684 private void parseBigQueryTableOption() { 685 String options = this.toString().trim(); 686 if (!options.toUpperCase().startsWith("OPTIONS")) 687 return; 688 options = options.replaceFirst("(?i)OPTIONS", "").trim(); 689 options = options.substring(1, options.length() - 1).trim(); 690 if (!options.endsWith(",")) { 691 options = options + ","; 692 } 693 694 this.allowJaggedRows = getPatternBoolean(options, "allow_jagged_rows"); 695 this.allowQuotedNewlines = getPatternBoolean(options, "allow_quoted_newlines"); 696 this.compression = getPatternString(options, "compression"); 697 this.description = getPatternString(options, "description"); 698 this.enableLogicalTypes = getPatternBoolean(options, "enable_logical_types"); 699 this.encoding = getPatternString(options, "encoding"); 700 this.expirationTimestamp = getTimestampString(options, "expiration_timestamp"); 701 this.fieldDelimiter = getPatternString(options, "field_delimiter"); 702 this.format = getPatternString(options, "format"); 703 this.decimalTargetTypes = getPatternArray(options, "decimal_target_types"); 704 this.hivePartitionUriPrefix = getPatternString(options, "hive_partition_uri_prefix"); 705 this.ignoreUnknownValues = getPatternBoolean(options, "ignore_unknown_values"); 706 this.maxBadRecords = getPatternLong(options, "max_bad_records"); 707 this.nullMarker = getPatternString(options, "null_marker"); 708 this.projectionFields = getPatternString(options, "projection_fields"); 709 this.quote = getPatternString(options, "quote"); 710 this.requireHivePartitionFilter = getPatternBoolean(options, "require_hive_partition_filter"); 711 this.sheetRange = getPatternString(options, "sheet_range"); 712 this.skipLeadingRows = getPatternLong(options, "skip_leading_rows"); 713 this.uris = getPatternArray(options, "uris"); 714 } 715 716 private String getTimestampString(String content, String field) { 717 content = content.replaceAll("(\\s*,)+", ","); 718 if (content.matches("(?is).*" + field + "\\s*=(.+?)=.+")) { 719 String patternExp = "(?is)" + field + "\\s*=(.+?)="; 720 Pattern pattern = Pattern.compile(patternExp); 721 Matcher matcher = pattern.matcher(content); 722 if (matcher.find()) { 723 String timestamp = matcher.group(1).trim(); 724 timestamp = timestamp.substring(0, timestamp.lastIndexOf(",")).trim(); 725 return timestamp; 726 } 727 } 728 else if(content.matches("(?is).*" + field + "\\s*=(.+),")){ 729 String patternExp = "(?is)" + field + "\\s*=(.+),"; 730 Pattern pattern = Pattern.compile(patternExp); 731 Matcher matcher = pattern.matcher(content); 732 if (matcher.find()) { 733 String timestamp = matcher.group(1).trim(); 734 return timestamp; 735 } 736 } 737 return null; 738 } 739 740 private String getPatternString(String content, String field) { 741 String patternExp = "(?is)" + field + "\\s*=\\s*(\".+?\"),"; 742 Pattern pattern = Pattern.compile(patternExp); 743 Matcher matcher = pattern.matcher(content); 744 if (matcher.find()) { 745 return matcher.group(1).trim(); 746 } 747 patternExp = "(?is)" + field + "\\s*=\\s*('.+?\'),"; 748 pattern = Pattern.compile(patternExp); 749 matcher = pattern.matcher(content); 750 if (matcher.find()) { 751 return matcher.group(1).trim(); 752 } 753 return null; 754 } 755 756 private Boolean getPatternBoolean(String content, String field) { 757 String patternExp = "(?is)" + field + "\\s*=(.+?),"; 758 Pattern pattern = Pattern.compile(patternExp); 759 Matcher matcher = pattern.matcher(content); 760 if (matcher.find()) { 761 return Boolean.parseBoolean(matcher.group(1).trim()); 762 } 763 return null; 764 } 765 766 private Long getPatternLong(String content, String field) { 767 String patternExp = "(?is)" + field + "\\s*=(.+?),"; 768 Pattern pattern = Pattern.compile(patternExp); 769 Matcher matcher = pattern.matcher(content); 770 if (matcher.find()) { 771 return Long.parseLong(matcher.group(1).trim()); 772 } 773 return null; 774 } 775 776 private List<String> getPatternArray(String content, String field) { 777 String patternExp = "(?is)" + field + "\\s*=\\s*\\[(.+?)\\]\\s*,"; 778 Pattern pattern = Pattern.compile(patternExp); 779 Matcher matcher = pattern.matcher(content); 780 if (matcher.find()) { 781 String arrayItems = matcher.group(1).trim(); 782 if (arrayItems.startsWith("(") && arrayItems.endsWith(")")) { 783 arrayItems = arrayItems.substring(1, arrayItems.length() - 1).trim(); 784 } 785 return Arrays.asList(arrayItems.split("\\s*,\\s*")); 786 } 787 return null; 788 } 789 790 public void doParse(TCustomSqlStatement psql, ESqlClause plocation) { 791 792 if (psql instanceof TCreateTableSqlStatement) { 793 TCreateTableSqlStatement c = (TCreateTableSqlStatement) psql; 794 795 switch (this.createTableOptionType){ 796 case etoPartitionBy: 797 if (this.partitionColumnList != null){ 798 c.setPartitionColumnList(this.partitionColumnList); 799 }else if (this.partitionByExpr != null){ 800 c.setPartitionByExpr(this.partitionByExpr); 801 this.partitionByExpr.doParse(c,ESqlClause.createTable); 802 } 803 break; 804 case etoPattern: 805 c.setRegex_pattern(this.getEndToken().toString()); 806 break; 807 case etoComment: 808 c.setTableComment(TObjectName.createObjectName (psql.dbvendor, EDbObjectType.comment, this.commentToken)); 809 break; 810 case etoWithLocation: 811 c.setStageLocation(this.getStageLocation()); 812 break; 813 case etoFileFormat: 814 c.setFileFormatName(this.fileFormatName); 815 c.setFileFormatType(this.fileFormatType); 816 fileFormatProperties = parseFileFormatProperties(this.toString()); 817 break; 818 case etoAWSSnsTopic: 819 c.setAwsSnsTopic(this.awsSnsTopic); 820 break; 821 case etoBigQueryExternal: 822 parseBigQueryTableOption(); 823 break; 824 case etoClusterBy: 825 if (expressionList != null){ 826 expressionList.doParse(psql,plocation); 827 } 828 break; 829 default: 830 break; 831 832 } 833 }else if(psql instanceof TCreateStageStmt){ 834 TCreateStageStmt c = (TCreateStageStmt)psql; 835 switch (this.createTableOptionType){ 836 case etoFileFormat: 837 c.setFileFormatName(this.fileFormatName); 838 c.setFileFormatType(this.fileFormatType); 839 break; 840 case etoStageURL: 841 c.setExternalStageURL(this.externalStageURL); 842 break; 843 default: 844 break; 845 } 846 }else if(psql instanceof TSnowflakeCopyIntoStmt){ 847 TSnowflakeCopyIntoStmt c = (TSnowflakeCopyIntoStmt)psql; 848 switch (this.createTableOptionType){ 849 case etoFileFormat: 850 c.setFileFormatName(this.fileFormatName); 851 c.setFileFormatType(this.fileFormatType); 852 break; 853 case etoStageURL: 854 break; 855 case etoPattern: 856 c.setRegex_pattern(this.getEndToken().toString()); 857 break; 858 case etoFiles: 859 for(TExpression e:this.expressionList){ 860 c.getFileList().add(e.toString()); 861 } 862 break; 863 default: 864 break; 865 } 866 } 867 } 868 869 public void accept(TParseTreeVisitor v){ 870 v.preVisit(this); 871 v.postVisit(this); 872 } 873 public void acceptChildren(TParseTreeVisitor v){ 874 v.preVisit(this); 875 v.postVisit(this); 876 } 877}