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 082 public void setFileFormatName(TSourceToken fileFormatName) { 083 this.fileFormatName = fileFormatName.toString(); 084 } 085 public void setFileFormatName(TObjectName fileFormatName) { 086 this.fileFormatName = fileFormatName.toString(); 087 } 088 089 public void setFileFormatType(TSourceToken fileFormatType) { 090 this.fileFormatType = fileFormatType.toString(); 091 } 092 093 public String getFileFormatName() { 094 return fileFormatName; 095 } 096 097 public String getFileFormatType() { 098 return fileFormatType; 099 } 100 101 private TStageLocation stageLocation; 102 103 public void setStageLocation(TStageLocation stageLocation) { 104 this.stageLocation = stageLocation; 105 } 106 107 public TStageLocation getStageLocation() { 108 return stageLocation; 109 } 110 111 112 113 public String getAwsSnsTopic() { 114 return awsSnsTopic; 115 } 116 117 public void setAwsSnsTopic(String awsSnsTopic) { 118 this.awsSnsTopic = awsSnsTopic; 119 } 120 121 public TObjectNameList getPartitionColumnList() { 122 return partitionColumnList; 123 } 124 125 public void setPartitionColumnList(TObjectNameList partitionColumnList) { 126 this.partitionColumnList = partitionColumnList; 127 } 128 129 public String getCompression() { 130 return compression; 131 } 132 133 public void setCompression(String compression) { 134 this.compression = compression; 135 } 136 137 public String getDescription() { 138 return description; 139 } 140 141 public void setDescription(String description) { 142 this.description = description; 143 } 144 145 public String getExpirationTimestamp() { 146 return expirationTimestamp; 147 } 148 149 public void setExpirationTimestamp(String expirationTimestamp) { 150 this.expirationTimestamp = expirationTimestamp; 151 } 152 153 public String getFieldDelimiter() { 154 return fieldDelimiter; 155 } 156 157 public void setFieldDelimiter(String fieldDelimiter) { 158 this.fieldDelimiter = fieldDelimiter; 159 } 160 161 public String getFormat() { 162 return format; 163 } 164 165 public void setFormat(String format) { 166 this.format = format; 167 } 168 169 public List<String> getDecimalTargetTypes() { 170 return decimalTargetTypes; 171 } 172 173 public void setDecimalTargetTypes(List<String> decimalTargetTypes) { 174 this.decimalTargetTypes = decimalTargetTypes; 175 } 176 177 public String getHivePartitionUriPrefix() { 178 return hivePartitionUriPrefix; 179 } 180 181 public void setHivePartitionUriPrefix(String hivePartitionUriPrefix) { 182 this.hivePartitionUriPrefix = hivePartitionUriPrefix; 183 } 184 185 public Boolean getIgnoreUnknownValues() { 186 return ignoreUnknownValues; 187 } 188 189 public void setIgnoreUnknownValues(Boolean ignoreUnknownValues) { 190 this.ignoreUnknownValues = ignoreUnknownValues; 191 } 192 193 public Long getMaxBadRecords() { 194 return maxBadRecords; 195 } 196 197 public void setMaxBadRecords(Long maxBadRecords) { 198 this.maxBadRecords = maxBadRecords; 199 } 200 201 public void setRequireHivePartitionFilter(Boolean requireHivePartitionFilter) { 202 this.requireHivePartitionFilter = requireHivePartitionFilter; 203 } 204 205 public String getNullMarker() { 206 return nullMarker; 207 } 208 209 public void setNullMarker(String nullMarker) { 210 this.nullMarker = nullMarker; 211 } 212 213 public String getProjectionFields() { 214 return projectionFields; 215 } 216 217 public void setProjectionFields(String projectionFields) { 218 this.projectionFields = projectionFields; 219 } 220 221 public String getQuote() { 222 return quote; 223 } 224 225 public void setQuote(String quote) { 226 this.quote = quote; 227 } 228 229 public Boolean getRequireHivePartitionFilter() { 230 return requireHivePartitionFilter; 231 } 232 233 public String getSheetRange() { 234 return sheetRange; 235 } 236 237 public void setSheetRange(String sheetRange) { 238 this.sheetRange = sheetRange; 239 } 240 241 public Long getSkipLeadingRows() { 242 return skipLeadingRows; 243 } 244 245 public void setSkipLeadingRows(Long skipLeadingRows) { 246 this.skipLeadingRows = skipLeadingRows; 247 } 248 249 public List<String> getUris() { 250 return uris; 251 } 252 253 public void setUris(List<String> uris) { 254 this.uris = uris; 255 } 256 257 public Boolean getAllowJaggedRows() { 258 return allowJaggedRows; 259 } 260 261 public void setAllowJaggedRows(Boolean allowJaggedRows) { 262 this.allowJaggedRows = allowJaggedRows; 263 } 264 265 public Boolean getAllowQuotedNewlines() { 266 return allowQuotedNewlines; 267 } 268 269 public void setAllowQuotedNewlines(Boolean allowQuotedNewlines) { 270 this.allowQuotedNewlines = allowQuotedNewlines; 271 } 272 273 public Boolean getEnableLogicalTypes() { 274 return enableLogicalTypes; 275 } 276 277 public void setEnableLogicalTypes(Boolean enableLogicalTypes) { 278 this.enableLogicalTypes = enableLogicalTypes; 279 } 280 281 public String getEncoding() { 282 return encoding; 283 } 284 285 public void setEncoding(String encoding) { 286 this.encoding = encoding; 287 } 288 public void setEncoding(TSourceToken encoding) { 289 this.encoding = encoding.toString(); 290 } // added by baffle 291 292 public String getExternalStageURL() { 293 return externalStageURL; 294 } 295 296 public void setExternalStageURL(String externalStageURL) { 297 this.externalStageURL = externalStageURL; 298 } 299 300 public void setPartitionByExpr(TExpression partitionByExpr) { 301 this.partitionByExpr = partitionByExpr; 302 } 303 304 public void setFileFormatName(String fileFormatName) { 305 this.fileFormatName = fileFormatName; 306 } 307 308 public void setFileFormatType(String fileFormatType) { 309 this.fileFormatType = fileFormatType; 310 } 311 312 public void setDateRetentionInDays(TSourceToken dateRetentionInDays) { 313 this.dateRetentionInDays = dateRetentionInDays; 314 } 315 316 public void setCommentToken(TSourceToken commentToken) { 317 this.commentToken = commentToken; 318 } 319 320 public void setStageFileFormat(TDummy stageFileFormat) { 321 this.stageFileFormat = stageFileFormat; 322 } 323 324 public void setCopyOptions(TDummy copyOptions) { 325 this.copyOptions = copyOptions; 326 } 327 328 public void setExpressionList(TExpressionList expressionList) { 329 this.expressionList = expressionList; 330 } 331 332 private TSourceToken dateRetentionInDays; 333 334 public TSourceToken getDateRetentionInDays() { 335 return dateRetentionInDays; 336 } 337 338 private TSourceToken commentToken; 339 340 /** 341 * @deprecated since v 2.8.1.1, please use {@link #getComment()} instead 342 * @return 343 */ 344 public TSourceToken getCommentToken() { 345 return commentToken; 346 } 347 348 private TDummy stageFileFormat; 349 350 private TDummy copyOptions; 351 352 public TDummy getCopyOptions() { 353 return copyOptions; 354 } 355 356 protected ECreateTableOption createTableOptionType; 357 358 public void setCreateTableOptionType(ECreateTableOption createTableOptionType) { 359 this.createTableOptionType = createTableOptionType; 360 } 361 362 public ECreateTableOption getCreateTableOptionType() { 363 return createTableOptionType; 364 } 365 366 public void init(Object arg1){ 367 createTableOptionType = (ECreateTableOption)arg1; 368 } 369 370 private TExpressionList expressionList; 371 372 public TExpressionList getExpressionList() { 373 return expressionList; 374 } 375 376 public TDummy getStageFileFormat() { 377 return stageFileFormat; 378 } 379 380 private String externalStageURL=null; 381 382 public void init(Object arg1, Object arg2){ 383 init(arg1); 384 switch(createTableOptionType){ 385 case etoClusterBy: 386 this.expressionList = (TExpressionList)arg2; 387 break; 388 case etoStageCopyOptions: 389 this.copyOptions = (TDummy)arg2; 390 break; 391 case etoStageFileFormat: 392 this.stageFileFormat = (TDummy)arg2; 393 break; 394 case etoComment: 395 //this.commentToken = (TSourceToken)arg2; 396 this.comment = (TObjectName) arg2; 397 break; 398 case etoDateRetentionTimeInDays: 399 this.dateRetentionInDays = (TSourceToken)arg2; 400 break; 401 case etoPartitionBy: 402 if (arg2 instanceof TObjectNameList){ 403 this.partitionColumnList = (TObjectNameList)arg2; 404 }else if (arg2 instanceof TExpression){ 405 this.partitionByExpr = (TExpression)arg2; 406 } 407 break; 408 case etoAWSSnsTopic: 409 awsSnsTopic = ((TSourceToken)arg2).toString(); 410 break; 411 case etoStageURL: 412 externalStageURL = ((TSourceToken)arg2).toString(); 413 break; 414 case etoFiles: 415 this.expressionList = (TExpressionList)arg2; 416 break; 417 case etoDistributeOn: 418 case etoOrganizeOn: 419 this.columnNamelist =(TObjectNameList)arg2; 420 break; 421 case etoReloptions: 422 this.attributeOptions = (ArrayList<TAttributeOption>)arg2; 423 break; 424 case etoPartitionSpec: 425 this.partitionSpec = (TBaseTablePartition)arg2; 426 break; 427 case etoDistributeBy: 428 this.distributeBy = (TDistributeBy)arg2; 429 break; 430 case etoDistributeByHash: 431 this.columnNamelist = (TObjectNameList)arg2; 432 break; 433 case etoPartitioningKey: 434 this.columnNamelist = (TObjectNameList)arg2; 435 break; 436 case etoOrganizeBy: 437 case etoOrganizeByDimensions: 438 this.valueRowItemList = (TMultiTargetList)arg2; 439 break; 440 } 441 } 442 443 private TMultiTargetList valueRowItemList; 444 445 public TMultiTargetList getValueRowItemList() { 446 return valueRowItemList; 447 } 448 449 public ArrayList<TAttributeOption> getAttributeOptions() { 450 return attributeOptions; 451 } 452 453 private ArrayList<TAttributeOption> attributeOptions ; 454 455 private void parseBigQueryTableOption() { 456 String options = this.toString().trim(); 457 if (!options.toUpperCase().startsWith("OPTIONS")) 458 return; 459 options = options.replaceFirst("(?i)OPTIONS", "").trim(); 460 options = options.substring(1, options.length() - 1).trim(); 461 if (!options.endsWith(",")) { 462 options = options + ","; 463 } 464 465 this.allowJaggedRows = getPatternBoolean(options, "allow_jagged_rows"); 466 this.allowQuotedNewlines = getPatternBoolean(options, "allow_quoted_newlines"); 467 this.compression = getPatternString(options, "compression"); 468 this.description = getPatternString(options, "description"); 469 this.enableLogicalTypes = getPatternBoolean(options, "enable_logical_types"); 470 this.encoding = getPatternString(options, "encoding"); 471 this.expirationTimestamp = getTimestampString(options, "expiration_timestamp"); 472 this.fieldDelimiter = getPatternString(options, "field_delimiter"); 473 this.format = getPatternString(options, "format"); 474 this.decimalTargetTypes = getPatternArray(options, "decimal_target_types"); 475 this.hivePartitionUriPrefix = getPatternString(options, "hive_partition_uri_prefix"); 476 this.ignoreUnknownValues = getPatternBoolean(options, "ignore_unknown_values"); 477 this.maxBadRecords = getPatternLong(options, "max_bad_records"); 478 this.nullMarker = getPatternString(options, "null_marker"); 479 this.projectionFields = getPatternString(options, "projection_fields"); 480 this.quote = getPatternString(options, "quote"); 481 this.requireHivePartitionFilter = getPatternBoolean(options, "require_hive_partition_filter"); 482 this.sheetRange = getPatternString(options, "sheet_range"); 483 this.skipLeadingRows = getPatternLong(options, "skip_leading_rows"); 484 this.uris = getPatternArray(options, "uris"); 485 } 486 487 private String getTimestampString(String content, String field) { 488 content = content.replaceAll("(\\s*,)+", ","); 489 if (content.matches("(?is).*" + field + "\\s*=(.+?)=.+")) { 490 String patternExp = "(?is)" + field + "\\s*=(.+?)="; 491 Pattern pattern = Pattern.compile(patternExp); 492 Matcher matcher = pattern.matcher(content); 493 if (matcher.find()) { 494 String timestamp = matcher.group(1).trim(); 495 timestamp = timestamp.substring(0, timestamp.lastIndexOf(",")).trim(); 496 return timestamp; 497 } 498 } 499 else if(content.matches("(?is).*" + field + "\\s*=(.+),")){ 500 String patternExp = "(?is)" + field + "\\s*=(.+),"; 501 Pattern pattern = Pattern.compile(patternExp); 502 Matcher matcher = pattern.matcher(content); 503 if (matcher.find()) { 504 String timestamp = matcher.group(1).trim(); 505 return timestamp; 506 } 507 } 508 return null; 509 } 510 511 private String getPatternString(String content, String field) { 512 String patternExp = "(?is)" + field + "\\s*=\\s*(\".+?\"),"; 513 Pattern pattern = Pattern.compile(patternExp); 514 Matcher matcher = pattern.matcher(content); 515 if (matcher.find()) { 516 return matcher.group(1).trim(); 517 } 518 patternExp = "(?is)" + field + "\\s*=\\s*('.+?\'),"; 519 pattern = Pattern.compile(patternExp); 520 matcher = pattern.matcher(content); 521 if (matcher.find()) { 522 return matcher.group(1).trim(); 523 } 524 return null; 525 } 526 527 private Boolean getPatternBoolean(String content, String field) { 528 String patternExp = "(?is)" + field + "\\s*=(.+?),"; 529 Pattern pattern = Pattern.compile(patternExp); 530 Matcher matcher = pattern.matcher(content); 531 if (matcher.find()) { 532 return Boolean.parseBoolean(matcher.group(1).trim()); 533 } 534 return null; 535 } 536 537 private Long getPatternLong(String content, String field) { 538 String patternExp = "(?is)" + field + "\\s*=(.+?),"; 539 Pattern pattern = Pattern.compile(patternExp); 540 Matcher matcher = pattern.matcher(content); 541 if (matcher.find()) { 542 return Long.parseLong(matcher.group(1).trim()); 543 } 544 return null; 545 } 546 547 private List<String> getPatternArray(String content, String field) { 548 String patternExp = "(?is)" + field + "\\s*=\\s*\\[(.+?)\\]\\s*,"; 549 Pattern pattern = Pattern.compile(patternExp); 550 Matcher matcher = pattern.matcher(content); 551 if (matcher.find()) { 552 String arrayItems = matcher.group(1).trim(); 553 if (arrayItems.startsWith("(") && arrayItems.endsWith(")")) { 554 arrayItems = arrayItems.substring(1, arrayItems.length() - 1).trim(); 555 } 556 return Arrays.asList(arrayItems.split("\\s*,\\s*")); 557 } 558 return null; 559 } 560 561 public void doParse(TCustomSqlStatement psql, ESqlClause plocation) { 562 563 if (psql instanceof TCreateTableSqlStatement) { 564 TCreateTableSqlStatement c = (TCreateTableSqlStatement) psql; 565 566 switch (this.createTableOptionType){ 567 case etoPartitionBy: 568 if (this.partitionColumnList != null){ 569 c.setPartitionColumnList(this.partitionColumnList); 570 }else if (this.partitionByExpr != null){ 571 c.setPartitionByExpr(this.partitionByExpr); 572 this.partitionByExpr.doParse(c,ESqlClause.createTable); 573 } 574 break; 575 case etoPattern: 576 c.setRegex_pattern(this.getEndToken().toString()); 577 break; 578 case etoComment: 579 c.setTableComment(TObjectName.createObjectName (psql.dbvendor, EDbObjectType.comment, this.commentToken)); 580 break; 581 case etoWithLocation: 582 c.setStageLocation(this.getStageLocation()); 583 break; 584 case etoFileFormat: 585 c.setFileFormatName(this.fileFormatName); 586 c.setFileFormatType(this.fileFormatType); 587 break; 588 case etoAWSSnsTopic: 589 c.setAwsSnsTopic(this.awsSnsTopic); 590 break; 591 case etoBigQueryExternal: 592 parseBigQueryTableOption(); 593 break; 594 case etoClusterBy: 595 if (expressionList != null){ 596 expressionList.doParse(psql,plocation); 597 } 598 break; 599 default: 600 break; 601 602 } 603 }else if(psql instanceof TCreateStageStmt){ 604 TCreateStageStmt c = (TCreateStageStmt)psql; 605 switch (this.createTableOptionType){ 606 case etoFileFormat: 607 c.setFileFormatName(this.fileFormatName); 608 c.setFileFormatType(this.fileFormatType); 609 break; 610 case etoStageURL: 611 c.setExternalStageURL(this.externalStageURL); 612 break; 613 default: 614 break; 615 } 616 }else if(psql instanceof TSnowflakeCopyIntoStmt){ 617 TSnowflakeCopyIntoStmt c = (TSnowflakeCopyIntoStmt)psql; 618 switch (this.createTableOptionType){ 619 case etoFileFormat: 620 c.setFileFormatName(this.fileFormatName); 621 c.setFileFormatType(this.fileFormatType); 622 break; 623 case etoStageURL: 624 break; 625 case etoPattern: 626 c.setRegex_pattern(this.getEndToken().toString()); 627 break; 628 case etoFiles: 629 for(TExpression e:this.expressionList){ 630 c.getFileList().add(e.toString()); 631 } 632 break; 633 default: 634 break; 635 } 636 } 637 } 638 639 public void accept(TParseTreeVisitor v){ 640 v.preVisit(this); 641 v.postVisit(this); 642 } 643 public void acceptChildren(TParseTreeVisitor v){ 644 v.preVisit(this); 645 v.postVisit(this); 646 } 647}