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