Skip to content

Commit

Permalink
feat: SQL:2016 TABLESAMPLE clause
Browse files Browse the repository at this point in the history
- supports SQL:2016
- supports Oracle dialect
- fixes #1826
- fixes #1593

Signed-off-by: Andreas Reichel <andreas@manticore-projects.com>
  • Loading branch information
manticore-projects committed Jul 12, 2023
1 parent 52df32d commit 4d8a512
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ public static int getUnbalancedPosition(String text) {
return i; // Return position of unbalanced closing bracket
}
char top = stack.pop();
if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) {
if (c == ')' && top != '(' || c == ']' && top != '[' || c == '}' && top != '{') {
return i; // Return position of unbalanced closing bracket
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ public class ParserKeywordsUtils {
{"PIVOT", RESTRICTED_JSQLPARSER}, {"PROCEDURE", RESTRICTED_ALIAS},
{"PUBLIC", RESTRICTED_ALIAS}, {"RECURSIVE", RESTRICTED_SQL2016},
{"REGEXP", RESTRICTED_SQL2016}, {"RETURNING", RESTRICTED_JSQLPARSER},
{"RIGHT", RESTRICTED_SQL2016}, {"SEL", RESTRICTED_ALIAS}, {"SELECT", RESTRICTED_ALIAS},
{"RIGHT", RESTRICTED_SQL2016}, {"SAMPLE", RESTRICTED_ALIAS}, {"SEL", RESTRICTED_ALIAS},
{"SELECT", RESTRICTED_ALIAS},
{"SEMI", RESTRICTED_JSQLPARSER}, {"SET", RESTRICTED_JSQLPARSER},
{"SOME", RESTRICTED_JSQLPARSER}, {"START", RESTRICTED_JSQLPARSER},
{"TABLES", RESTRICTED_ALIAS}, {"TOP", RESTRICTED_SQL2016},
Expand All @@ -86,7 +87,8 @@ public class ParserKeywordsUtils {
{"UNPIVOT", RESTRICTED_JSQLPARSER}, {"USE", RESTRICTED_JSQLPARSER},
{"USING", RESTRICTED_SQL2016}, {"SQL_CACHE", RESTRICTED_JSQLPARSER},
{"SQL_CALC_FOUND_ROWS", RESTRICTED_JSQLPARSER}, {"SQL_NO_CACHE", RESTRICTED_JSQLPARSER},
{"STRAIGHT_JOIN", RESTRICTED_JSQLPARSER}, {"VALUE", RESTRICTED_JSQLPARSER},
{"STRAIGHT_JOIN", RESTRICTED_JSQLPARSER}, {"TABLESAMPLE", RESTRICTED_ALIAS},
{"VALUE", RESTRICTED_JSQLPARSER},
{"VALUES", RESTRICTED_SQL2016}, {"VARYING", RESTRICTED_JSQLPARSER},
{"WHEN", RESTRICTED_SQL2016}, {"WHERE", RESTRICTED_SQL2016},
{"WINDOW", RESTRICTED_SQL2016}, {"WITH", RESTRICTED_SQL2016},
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public enum Feature {
/**
* "RETURNING expr(, expr)*"
*
* @see SelectExpressionItem
* @see net.sf.jsqlparser.expression.operators.relational.ExpressionList
*/
insertReturningExpressionList,

Expand Down Expand Up @@ -326,7 +326,7 @@ public enum Feature {
/**
* "RETURNING expr(, expr)*"
*
* @see SelectExpressionItem
* @see net.sf.jsqlparser.statement.select.SelectItem
*/
updateReturning,
/**
Expand Down Expand Up @@ -354,7 +354,7 @@ public enum Feature {
/**
* "RETURNING expr(, expr)*"
*
* @see SelectExpressionItem
* @see net.sf.jsqlparser.statement.select.SelectItem
*/
deleteReturningExpressionList,

Expand Down Expand Up @@ -436,7 +436,6 @@ public enum Feature {
/**
* SQL "REPLACE" statement is allowed
*
* @see Replace
*/
@Deprecated
replace,
Expand Down Expand Up @@ -644,7 +643,7 @@ public enum Feature {

lateralSubSelect,
/**
* @see ValuesList
* @see net.sf.jsqlparser.statement.select.Values
*/
valuesList,
/**
Expand Down
60 changes: 48 additions & 12 deletions src/main/java/net/sf/jsqlparser/schema/Table.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.IntoTableVisitor;
import net.sf.jsqlparser.statement.select.Pivot;
import net.sf.jsqlparser.statement.select.SampleClause;
import net.sf.jsqlparser.statement.select.UnPivot;

/**
Expand All @@ -42,6 +43,8 @@ public class Table extends ASTNodeAccessImpl implements FromItem, MultiPartName

private Alias alias;

private SampleClause sampleClause;

private Pivot pivot;

private UnPivot unpivot;
Expand All @@ -50,8 +53,7 @@ public class Table extends ASTNodeAccessImpl implements FromItem, MultiPartName

private SQLServerHints sqlServerHints;

public Table() {
}
public Table() {}

public Table(String name) {
setName(name);
Expand Down Expand Up @@ -104,21 +106,21 @@ public void setSchemaName(String schemaName) {

public String getName() {
String name = getIndex(NAME_IDX);
if (name!=null && name.contains("@")) {
if (name != null && name.contains("@")) {
int pos = name.lastIndexOf('@');
if (pos>0) {
name = name.substring(0, pos );
if (pos > 0) {
name = name.substring(0, pos);
}
}
return name;
}

public String getDBLinkName() {
String name = getIndex(NAME_IDX);
if (name!=null && name.contains("@")) {
if (name != null && name.contains("@")) {
int pos = name.lastIndexOf('@');
if (pos>0 && name.length()>1) {
name = name.substring(pos+1);
if (pos > 0 && name.length() > 1) {
name = name.substring(pos + 1);
}
}
return name;
Expand Down Expand Up @@ -232,12 +234,46 @@ public void setSqlServerHints(SQLServerHints sqlServerHints) {
this.sqlServerHints = sqlServerHints;
}

public SampleClause getSampleClause() {
return sampleClause;
}

public Table setSampleClause(SampleClause sampleClause) {
this.sampleClause = sampleClause;
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append(getFullyQualifiedName());
if (alias != null) {
builder.append(alias);
}

if (sampleClause != null) {
sampleClause.appendTo(builder);
}

if (pivot != null) {
builder.append(" ").append(pivot);
}

if (unpivot != null) {
builder.append(" ").append(unpivot);
}

if (mysqlHints != null) {
builder.append(mysqlHints);
}

if (sqlServerHints != null) {
builder.append(sqlServerHints);
}
return builder;
}

@Override
public String toString() {
return getFullyQualifiedName() + ((alias != null) ? alias.toString() : "")
+ ((pivot != null) ? " " + pivot : "") + ((unpivot != null) ? " " + unpivot : "")
+ ((mysqlHints != null) ? mysqlHints.toString() : "")
+ ((sqlServerHints != null) ? sqlServerHints.toString() : "");
return appendTo(new StringBuilder()).toString();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
import java.util.List;

/**
* RETURNING clause according to
* {@see https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7
* } Part of UPDATE, INSERT, DELETE statements
* RETURNING clause according to <a href=
* "https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7"
* /> Part of UPDATE, INSERT, DELETE statements
*/

public class ReturningClause extends ArrayList<SelectItem<?>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ default FromItem withUnPivot(UnPivot unpivot) {

void setUnPivot(UnPivot unpivot);


}
8 changes: 4 additions & 4 deletions src/main/java/net/sf/jsqlparser/statement/select/Join.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Join withInner(boolean b) {

/**
*
* @return Sets the INNER keyword and switches off any contradicting qualifiers automatically.
* Sets the INNER keyword and switches off any contradicting qualifiers automatically.
*/
public void setInner(boolean b) {
if (b) {
Expand Down Expand Up @@ -128,7 +128,7 @@ public Join withOuter(boolean b) {

/**
*
* @return Sets the OUTER keyword and switches off any contradicting qualifiers automatically.
* Sets the OUTER keyword and switches off any contradicting qualifiers automatically.
*/
public void setOuter(boolean b) {
if (b) {
Expand Down Expand Up @@ -184,7 +184,7 @@ public Join withLeft(boolean b) {

/**
*
* @return Sets the LEFT keyword and switches off any contradicting qualifiers automatically.
* Sets the LEFT keyword and switches off any contradicting qualifiers automatically.
*/
public void setLeft(boolean b) {
if (b) {
Expand All @@ -210,7 +210,7 @@ public Join withRight(boolean b) {

/**
*
* @return Sets the RIGHT keyword and switches off any contradicting qualifiers automatically.
* Sets the RIGHT keyword and switches off any contradicting qualifiers automatically.
*/
public void setRight(boolean b) {
if (b) {
Expand Down
120 changes: 120 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package net.sf.jsqlparser.statement.select;

public class SampleClause {
public enum SampleKeyword {
SAMPLE, TABLESAMPLE;

public static SampleKeyword from(String sampleKeyword) {
return Enum.valueOf(SampleKeyword.class, sampleKeyword.toUpperCase());
}
}

public enum SampleMethod {
BERNOULLI, SYSTEM, BLOCK;

public static SampleMethod from(String sampleMethod) {
return Enum.valueOf(SampleMethod.class, sampleMethod.toUpperCase());
}
}

private SampleKeyword keyword;
private SampleMethod method;
private Number percentageArgument;
private Number repeatArgument;

// Oracle Specific
private Number seedArgument;

public SampleClause(String keyword, String method, Number percentageArgument,
Number repeatArgument, Number seedArgument) {
this.keyword = SampleKeyword.from(keyword);
this.method = method == null || method.length() == 0 ? null : SampleMethod.from(method);
this.percentageArgument = percentageArgument;
this.repeatArgument = repeatArgument;
this.seedArgument = seedArgument;
}

public SampleClause() {
this(SampleKeyword.TABLESAMPLE.toString(), null, null, null, null);
}

public SampleClause(String keyword) {
this(keyword, null, null, null, null);
}

public SampleKeyword getKeyword() {
return keyword;
}

public SampleClause setKeyword(SampleKeyword keyword) {
this.keyword = keyword;
return this;
}

public Number getPercentageArgument() {
return percentageArgument;
}

public SampleClause setPercentageArgument(Number percentageArgument) {
this.percentageArgument = percentageArgument;
return this;
}

public Number getRepeatArgument() {
return repeatArgument;
}

public SampleClause setRepeatArgument(Number repeatArgument) {
this.repeatArgument = repeatArgument;
return this;
}

public Number getSeedArgument() {
return seedArgument;
}

public SampleClause setSeedArgument(Number seedArgument) {
this.seedArgument = seedArgument;
return this;
}

public SampleMethod getMethod() {
return method;
}

public SampleClause setMethod(SampleMethod method) {
this.method = method;
return this;
}

public SampleClause setMethod(String method) {
this.method = method == null || method.length() == 0 ? null : SampleMethod.from(method);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {

builder.append(" ").append(keyword);
if (method != null) {
builder.append(" ").append(method);
}

if (percentageArgument != null) {
builder.append(" (").append(percentageArgument).append(")");
}

if (repeatArgument != null) {
builder.append(" REPEATABLE (").append(repeatArgument).append(")");
}

if (seedArgument != null) {
builder.append(" SEED (").append(seedArgument).append(")");
}

return builder;
}

public String toString() {
return appendTo(new StringBuilder()).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,13 @@ public void visit(PlainSelect plainSelect) {
if (plainSelect.getFromItem() != null) {
buffer.append(" FROM ");
plainSelect.getFromItem().accept(this);

if (plainSelect.getFromItem() instanceof Table) {
Table table = (Table) plainSelect.getFromItem();
if (table.getSampleClause() != null) {
table.getSampleClause().appendTo(buffer);
}
}
}

if (plainSelect.getLateralViews() != null) {
Expand Down
Loading

0 comments on commit 4d8a512

Please sign in to comment.