Skip to content

Commit 6f4c4fb

Browse files
feat: Snowflake time travel syntax
Signed-off-by: Andreas Reichel <[email protected]>
1 parent 7c37171 commit 6f4c4fb

File tree

5 files changed

+259
-19
lines changed

5 files changed

+259
-19
lines changed

src/main/java/net/sf/jsqlparser/schema/Table.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package net.sf.jsqlparser.schema;
1111

1212
import java.util.ArrayList;
13+
import java.util.Arrays;
1314
import java.util.Collections;
1415
import java.util.List;
1516

@@ -28,11 +29,9 @@
2829
/**
2930
* A table. It can have an alias and the schema name it belongs to.
3031
*/
31-
public class Table extends ASTNodeAccessImpl implements ErrorDestination, FromItem, MultiPartName {
32+
public class Table extends ASTNodeAccessImpl
33+
implements ErrorDestination, FromItem, MultiPartName, Cloneable {
3234

33-
// private Database database;
34-
// private String schemaName;
35-
// private String name;
3635
private static final int NAME_IDX = 0;
3736

3837
private static final int SCHEMA_IDX = 1;
@@ -45,6 +44,9 @@ public class Table extends ASTNodeAccessImpl implements ErrorDestination, FromIt
4544

4645
private List<String> partDelimiters = new ArrayList<>();
4746

47+
// holds the various `time travel` syntax for BigQuery, RedShift, Snowflake or RedShift
48+
private String timeTravelStr = null;
49+
4850
private Alias alias;
4951

5052
private SampleClause sampleClause;
@@ -74,6 +76,10 @@ public Table(String name) {
7476
setName(name);
7577
}
7678

79+
public Table(String name, boolean splitNamesOnDelimiter) {
80+
setName(name, splitNamesOnDelimiter);
81+
}
82+
7783
public Table(String schemaName, String name) {
7884
setSchemaName(schemaName);
7985
setName(name);
@@ -197,12 +203,20 @@ public void setName(String name) {
197203
.of("0", "N", "n", "FALSE", "false", "OFF", "off")
198204
.contains(System.getProperty("SPLIT_NAMES_ON_DELIMITER"));
199205

206+
setName(name, splitNamesOnDelimiter);
207+
}
208+
209+
public void setName(String name, boolean splitNamesOnDelimiter) {
200210
if (MultiPartName.isQuoted(name) && name.contains(".") && splitNamesOnDelimiter) {
201211
partItems.clear();
202212
for (String unquotedIdentifier : MultiPartName.unquote(name).split("\\.")) {
203213
partItems.add("\"" + unquotedIdentifier + "\"");
204214
}
205215
Collections.reverse(partItems);
216+
} else if (name.contains(".") && splitNamesOnDelimiter) {
217+
partItems.clear();
218+
partItems.addAll(Arrays.asList(MultiPartName.unquote(name).split("\\.")));
219+
Collections.reverse(partItems);
206220
} else {
207221
setIndex(NAME_IDX, name);
208222
}
@@ -294,6 +308,15 @@ public <T, S> T accept(IntoTableVisitor<T> intoTableVisitor, S context) {
294308
return intoTableVisitor.visit(this, context);
295309
}
296310

311+
public String getTimeTravel() {
312+
return timeTravelStr;
313+
}
314+
315+
public Table setTimeTravel(String timeTravelStr) {
316+
this.timeTravelStr = timeTravelStr;
317+
return this;
318+
}
319+
297320
@Override
298321
public Pivot getPivot() {
299322
return pivot;
@@ -346,6 +369,11 @@ public Table setSampleClause(SampleClause sampleClause) {
346369

347370
public StringBuilder appendTo(StringBuilder builder) {
348371
builder.append(getFullyQualifiedName());
372+
373+
if (timeTravelStr != null) {
374+
builder.append(" ").append(timeTravelStr);
375+
}
376+
349377
if (alias != null) {
350378
builder.append(alias);
351379
}
@@ -422,7 +450,9 @@ public Table getResolvedTable() {
422450
*/
423451
public Table setResolvedTable(Table resolvedTable) {
424452
// clone, not reference
425-
this.resolvedTable = new Table(resolvedTable.getFullyQualifiedName());
453+
if (resolvedTable != null) {
454+
this.resolvedTable = new Table(resolvedTable.getFullyQualifiedName());
455+
}
426456
return this;
427457
}
428458

@@ -465,4 +495,16 @@ public static Table[] setUnsetCatalogAndSchema(String currentCatalogName,
465495
}
466496
return tables;
467497
}
498+
499+
@Override
500+
public Table clone() {
501+
try {
502+
Table clone = (Table) super.clone();
503+
clone.setName(this.getFullyQualifiedName());
504+
clone.setResolvedTable(this.resolvedTable);
505+
return clone;
506+
} catch (CloneNotSupportedException e) {
507+
throw new AssertionError();
508+
}
509+
}
468510
}

src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -449,25 +449,28 @@ public <S> StringBuilder visit(SelectItem<?> selectItem, S context) {
449449

450450

451451
@Override
452-
public <S> StringBuilder visit(Table tableName, S context) {
453-
builder.append(tableName.getFullyQualifiedName());
454-
Alias alias = tableName.getAlias();
452+
public <S> StringBuilder visit(Table table, S context) {
453+
builder.append(table.getFullyQualifiedName());
454+
if (table.getTimeTravel() != null) {
455+
builder.append(" ").append(table.getTimeTravel());
456+
}
457+
Alias alias = table.getAlias();
455458
if (alias != null) {
456459
builder.append(alias);
457460
}
458-
Pivot pivot = tableName.getPivot();
461+
Pivot pivot = table.getPivot();
459462
if (pivot != null) {
460463
pivot.accept(this, context);
461464
}
462-
UnPivot unpivot = tableName.getUnPivot();
465+
UnPivot unpivot = table.getUnPivot();
463466
if (unpivot != null) {
464467
unpivot.accept(this, context);
465468
}
466-
MySQLIndexHint indexHint = tableName.getIndexHint();
469+
MySQLIndexHint indexHint = table.getIndexHint();
467470
if (indexHint != null) {
468471
builder.append(indexHint);
469472
}
470-
SQLServerHints sqlServerHints = tableName.getSqlServerHints();
473+
SQLServerHints sqlServerHints = table.getSqlServerHints();
471474
if (sqlServerHints != null) {
472475
builder.append(sqlServerHints);
473476
}

0 commit comments

Comments
 (0)