Skip to content

Commit 6f2bdd6

Browse files
Merge branch 'master' into manticore
2 parents 15e58e9 + c9930e3 commit 6f2bdd6

31 files changed

Lines changed: 1417 additions & 70 deletions

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,14 @@ default void visit(JsonTableFunction jsonTableFunction) {
659659
this.visit(jsonTableFunction, null);
660660
}
661661

662+
default <S> T visit(XmlTableFunction xmlTableFunction, S context) {
663+
return visit((Function) xmlTableFunction, context);
664+
}
665+
666+
default void visit(XmlTableFunction xmlTableFunction) {
667+
this.visit(xmlTableFunction, null);
668+
}
669+
662670
<S> T visit(ConnectByRootOperator connectByRootOperator, S context);
663671

664672
default void visit(ConnectByRootOperator connectByRootOperator) {

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,11 @@ public <S> T visit(JsonTableFunction jsonTableFunction, S context) {
758758
return visitExpressions(jsonTableFunction, context, jsonTableFunction.getAllExpressions());
759759
}
760760

761+
@Override
762+
public <S> T visit(XmlTableFunction xmlTableFunction, S context) {
763+
return visitExpressions(xmlTableFunction, context, xmlTableFunction.getAllExpressions());
764+
}
765+
761766
@Override
762767
public <S> T visit(ConnectByRootOperator connectByRootOperator, S context) {
763768
return connectByRootOperator.getColumn().accept(this, context);

src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class IntervalExpression extends ASTNodeAccessImpl implements Expression
1818
private final boolean intervalKeyword;
1919
private String parameter = null;
2020
private String intervalType = null;
21+
private IntervalQualifier intervalQualifier = null;
2122
private Expression expression = null;
2223

2324
public IntervalExpression() {
@@ -47,12 +48,42 @@ public void setParameter(String parameter) {
4748
this.parameter = parameter;
4849
}
4950

51+
/**
52+
* Returns the non-standard single-identifier interval type (e.g. MySQL {@code INTERVAL 1 foo}),
53+
* or {@code null} when a structured {@link IntervalQualifier} is present.
54+
*
55+
* @deprecated the structured {@link #getIntervalQualifier()} is the canonical representation.
56+
* This legacy field is kept only for the non-standard single-identifier form.
57+
* @return the legacy interval type, or {@code null} if a qualifier is set
58+
*/
59+
@Deprecated
5060
public String getIntervalType() {
5161
return intervalType;
5262
}
5363

64+
/**
65+
* Sets the non-standard single-identifier interval type (e.g. MySQL {@code INTERVAL 1 foo}) and
66+
* clears any structured qualifier.
67+
*
68+
* @deprecated use {@link #setIntervalQualifier(IntervalQualifier)} for the standard form.
69+
* @param intervalType the legacy interval type
70+
*/
71+
@Deprecated
5472
public void setIntervalType(String intervalType) {
5573
this.intervalType = intervalType;
74+
this.intervalQualifier = null;
75+
}
76+
77+
public IntervalQualifier getIntervalQualifier() {
78+
return intervalQualifier;
79+
}
80+
81+
/**
82+
* Sets the structured interval qualifier and clears the legacy interval type.
83+
*/
84+
public void setIntervalQualifier(IntervalQualifier intervalQualifier) {
85+
this.intervalQualifier = intervalQualifier;
86+
this.intervalType = null;
5687
}
5788

5889
public Expression getExpression() {
@@ -67,7 +98,9 @@ public void setExpression(Expression expression) {
6798
public String toString() {
6899
return (intervalKeyword ? "INTERVAL " : "")
69100
+ Objects.toString(expression, parameter)
70-
+ (intervalType != null ? " " + intervalType : "");
101+
+ (intervalQualifier != null
102+
? " " + intervalQualifier.toString()
103+
: (intervalType != null ? " " + intervalType : ""));
71104
}
72105

73106
@Override
@@ -80,11 +113,22 @@ public IntervalExpression withParameter(String parameter) {
80113
return this;
81114
}
82115

116+
/**
117+
* @deprecated use {@link #withIntervalQualifier(IntervalQualifier)} for the standard form.
118+
* @param intervalType the legacy interval type
119+
* @return this instance
120+
*/
121+
@Deprecated
83122
public IntervalExpression withIntervalType(String intervalType) {
84123
this.setIntervalType(intervalType);
85124
return this;
86125
}
87126

127+
public IntervalExpression withIntervalQualifier(IntervalQualifier intervalQualifier) {
128+
this.setIntervalQualifier(intervalQualifier);
129+
return this;
130+
}
131+
88132
public IntervalExpression withExpression(Expression expression) {
89133
this.setExpression(expression);
90134
return this;
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression;
11+
12+
import java.io.Serializable;
13+
import java.util.Objects;
14+
15+
/**
16+
* Models an SQL interval qualifier as defined by the SQL standard (see
17+
* <a href="https://www.postgresql.org/docs/current/datatype-datetime.html">PostgreSQL: Interval
18+
* Input</a>), e.g. {@code YEAR}, {@code DAY TO SECOND}, {@code DAY(9) TO SECOND} or
19+
* {@code SECOND(2, 4)}.
20+
* <p>
21+
* It is shared by {@link IntervalExpression} (the {@code INTERVAL ...} expression literal, used in
22+
* DML) and by {@code net.sf.jsqlparser.statement.create.table.ColDataType} (the {@code INTERVAL}
23+
* column / cast target type, used in DDL), so the qualifier is represented once and round-trips
24+
* consistently across all contexts.
25+
*/
26+
public final class IntervalQualifier implements Serializable {
27+
28+
private final String leadingField;
29+
private final Integer leadingFieldPrecision;
30+
private final String trailingField;
31+
private final Integer fractionalSecondsPrecision;
32+
33+
public IntervalQualifier(
34+
String leadingField, Integer leadingFieldPrecision, String trailingField,
35+
Integer fractionalSecondsPrecision) {
36+
this.leadingField = leadingField;
37+
this.leadingFieldPrecision = leadingFieldPrecision;
38+
this.trailingField = trailingField;
39+
this.fractionalSecondsPrecision = fractionalSecondsPrecision;
40+
}
41+
42+
public String getLeadingField() {
43+
return leadingField;
44+
}
45+
46+
public Integer getLeadingFieldPrecision() {
47+
return leadingFieldPrecision;
48+
}
49+
50+
public String getTrailingField() {
51+
return trailingField;
52+
}
53+
54+
public Integer getFractionalSecondsPrecision() {
55+
return fractionalSecondsPrecision;
56+
}
57+
58+
public IntervalQualifier withLeadingField(String leadingField) {
59+
return new IntervalQualifier(
60+
leadingField, leadingFieldPrecision, trailingField, fractionalSecondsPrecision);
61+
}
62+
63+
public IntervalQualifier withLeadingFieldPrecision(Integer leadingFieldPrecision) {
64+
return new IntervalQualifier(
65+
leadingField, leadingFieldPrecision, trailingField, fractionalSecondsPrecision);
66+
}
67+
68+
public IntervalQualifier withTrailingField(String trailingField) {
69+
return new IntervalQualifier(
70+
leadingField, leadingFieldPrecision, trailingField, fractionalSecondsPrecision);
71+
}
72+
73+
public IntervalQualifier withFractionalSecondsPrecision(Integer fractionalSecondsPrecision) {
74+
return new IntervalQualifier(
75+
leadingField, leadingFieldPrecision, trailingField, fractionalSecondsPrecision);
76+
}
77+
78+
@Override
79+
public boolean equals(Object o) {
80+
if (this == o) {
81+
return true;
82+
}
83+
if (!(o instanceof IntervalQualifier)) {
84+
return false;
85+
}
86+
IntervalQualifier that = (IntervalQualifier) o;
87+
return Objects.equals(leadingField, that.leadingField)
88+
&& Objects.equals(leadingFieldPrecision, that.leadingFieldPrecision)
89+
&& Objects.equals(trailingField, that.trailingField)
90+
&& Objects.equals(fractionalSecondsPrecision, that.fractionalSecondsPrecision);
91+
}
92+
93+
@Override
94+
public int hashCode() {
95+
return Objects.hash(
96+
leadingField, leadingFieldPrecision, trailingField, fractionalSecondsPrecision);
97+
}
98+
99+
/**
100+
* Renders the qualifier back to SQL, e.g. {@code DAY}, {@code DAY TO SECOND},
101+
* {@code DAY(9) TO SECOND} or {@code SECOND(2, 4)}.
102+
*/
103+
@Override
104+
public String toString() {
105+
StringBuilder sb = new StringBuilder(Objects.toString(leadingField, ""));
106+
if (leadingFieldPrecision != null) {
107+
sb.append("(").append(leadingFieldPrecision);
108+
// For a single-field qualifier such as SECOND(2, 4), the fractional seconds
109+
// precision is rendered together with the leading precision.
110+
if (trailingField == null && fractionalSecondsPrecision != null) {
111+
sb.append(", ").append(fractionalSecondsPrecision);
112+
}
113+
sb.append(")");
114+
}
115+
if (trailingField != null) {
116+
sb.append(" TO ").append(trailingField);
117+
if (fractionalSecondsPrecision != null) {
118+
sb.append("(").append(fractionalSecondsPrecision).append(")");
119+
}
120+
}
121+
return sb.toString();
122+
}
123+
}

src/main/java/net/sf/jsqlparser/expression/WindowElement.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class WindowElement implements Serializable {
1717
private Type type;
1818
private WindowOffset offset;
1919
private WindowRange range;
20+
private Exclusion exclusion;
2021

2122
public Type getType() {
2223
return type;
@@ -42,6 +43,14 @@ public void setRange(WindowRange range) {
4243
this.range = range;
4344
}
4445

46+
public Exclusion getExclusion() {
47+
return exclusion;
48+
}
49+
50+
public void setExclusion(Exclusion exclusion) {
51+
this.exclusion = exclusion;
52+
}
53+
4554
@Override
4655
public String toString() {
4756
StringBuilder buffer = new StringBuilder(type.toString());
@@ -52,6 +61,10 @@ public String toString() {
5261
buffer.append(range.toString());
5362
}
5463

64+
if (exclusion != null) {
65+
buffer.append(" EXCLUDE ").append(exclusion);
66+
}
67+
5568
return buffer.toString();
5669
}
5770

@@ -70,12 +83,32 @@ public WindowElement withRange(WindowRange range) {
7083
return this;
7184
}
7285

86+
public WindowElement withExclusion(Exclusion exclusion) {
87+
this.setExclusion(exclusion);
88+
return this;
89+
}
90+
7391
public enum Type {
74-
ROWS, RANGE;
92+
ROWS, RANGE, GROUPS;
7593

7694
public static Type from(String type) {
7795
return Enum.valueOf(Type.class, type.toUpperCase(Locale.ROOT));
7896
}
7997
}
8098

99+
public enum Exclusion {
100+
CURRENT_ROW("CURRENT ROW"), GROUP("GROUP"), TIES("TIES"), NO_OTHERS("NO OTHERS");
101+
102+
private final String keyword;
103+
104+
Exclusion(String keyword) {
105+
this.keyword = keyword;
106+
}
107+
108+
@Override
109+
public String toString() {
110+
return keyword;
111+
}
112+
}
113+
81114
}

0 commit comments

Comments
 (0)