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