Skip to content

Commit 4b4ae04

Browse files
feat: BigQuery Except(..) Replace(..) syntax
- supports `SELECT * Except(..) Replace(..)` - simplifies `AllColumns` and `AllTableColumns` Expressions - fixes #1700
1 parent d50807d commit 4b4ae04

File tree

8 files changed

+150
-26
lines changed

8 files changed

+150
-26
lines changed

src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,83 @@
1111

1212
import net.sf.jsqlparser.expression.Expression;
1313
import net.sf.jsqlparser.expression.ExpressionVisitor;
14+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
1415
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
16+
import net.sf.jsqlparser.schema.Column;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
1520

1621
public class AllColumns extends ASTNodeAccessImpl implements Expression {
22+
protected ExpressionList<Column> exceptColumns;
23+
protected List<SelectItem<?>> replaceExpressions;
24+
25+
public AllColumns(ExpressionList<Column> exceptColumns,
26+
List<SelectItem<?>> replaceExpressions) {
27+
this.exceptColumns = exceptColumns;
28+
this.replaceExpressions = replaceExpressions;
29+
}
30+
31+
public AllColumns() {
32+
this(null, null);
33+
}
34+
35+
public ExpressionList<Column> getExceptColumns() {
36+
return exceptColumns;
37+
}
38+
39+
public ExpressionList<Column> addExceptColumn(Column column) {
40+
if (exceptColumns == null) {
41+
exceptColumns = new ExpressionList<>();
42+
}
43+
exceptColumns.add(column);
44+
return exceptColumns;
45+
}
46+
47+
public AllColumns setExceptColumns(ExpressionList<Column> exceptColumns) {
48+
this.exceptColumns = exceptColumns;
49+
return this;
50+
}
51+
52+
public List<SelectItem<?>> getReplaceExpressions() {
53+
return replaceExpressions;
54+
}
55+
56+
public List<SelectItem<?>> addReplaceExpression(SelectItem<?> selectItem) {
57+
if (replaceExpressions == null) {
58+
replaceExpressions = new ArrayList<>();
59+
}
60+
replaceExpressions.add(selectItem);
61+
return replaceExpressions;
62+
}
63+
64+
public AllColumns setReplaceExpressions(List<SelectItem<?>> replaceExpressions) {
65+
this.replaceExpressions = replaceExpressions;
66+
return this;
67+
}
68+
69+
public StringBuilder appendTo(StringBuilder builder) {
70+
builder.append("*");
71+
if (exceptColumns != null && exceptColumns.size() > 0) {
72+
builder.append(" Except( ");
73+
exceptColumns.appendTo(builder);
74+
builder.append(" )");
75+
}
76+
if (replaceExpressions != null && replaceExpressions.size() > 0) {
77+
builder.append(" Replace(");
78+
int i = 0;
79+
for (SelectItem<?> selectItem : replaceExpressions) {
80+
builder.append(i++ > 0 ? ", " : " ");
81+
selectItem.appendTo(builder);
82+
}
83+
builder.append(" )");
84+
}
85+
return builder;
86+
}
87+
1788
@Override
1889
public String toString() {
19-
return "*";
90+
return appendTo(new StringBuilder()).toString();
2091
}
2192

2293
@Override

src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,28 @@
99
*/
1010
package net.sf.jsqlparser.statement.select;
1111

12-
import net.sf.jsqlparser.expression.Expression;
13-
import net.sf.jsqlparser.expression.ExpressionVisitor;
14-
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
15-
import net.sf.jsqlparser.schema.*;
12+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
13+
import net.sf.jsqlparser.schema.Column;
14+
import net.sf.jsqlparser.schema.Table;
1615

17-
public class AllTableColumns extends ASTNodeAccessImpl implements Expression {
16+
import java.util.List;
17+
18+
public class AllTableColumns extends AllColumns {
1819

1920
private Table table;
2021

21-
public AllTableColumns() {}
22+
public AllTableColumns(Table table, ExpressionList<Column> exceptColumns,
23+
List<SelectItem<?>> replaceExpressions) {
24+
super(exceptColumns, replaceExpressions);
25+
this.table = table;
26+
}
27+
28+
public AllTableColumns(Table table) {
29+
this(table, null, null);
30+
}
2231

23-
public AllTableColumns(Table tableName) {
24-
this.table = tableName;
32+
public AllTableColumns(Table table, AllColumns allColumns) {
33+
this(table, allColumns.exceptColumns, allColumns.replaceExpressions);
2534
}
2635

2736
public Table getTable() {
@@ -32,18 +41,13 @@ public void setTable(Table table) {
3241
this.table = table;
3342
}
3443

35-
@Override
36-
public String toString() {
37-
return table + ".*";
38-
}
39-
4044
public AllTableColumns withTable(Table table) {
4145
this.setTable(table);
4246
return this;
4347
}
4448

4549
@Override
46-
public void accept(ExpressionVisitor expressionVisitor) {
47-
expressionVisitor.visit(this);
50+
public StringBuilder appendTo(StringBuilder builder) {
51+
return super.appendTo(table.appendTo(builder).append("."));
4852
}
4953
}

src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ public SelectItem(T expression) {
3131
this(expression, null);
3232
}
3333

34-
public static SelectItem from(Expression expression, Alias alias) {
35-
return new SelectItem(expression, alias);
34+
public static SelectItem<?> from(Expression expression, Alias alias) {
35+
return new SelectItem<>(expression, alias);
3636
}
3737

38-
public static SelectItem from(Expression expression) {
38+
public static SelectItem<?> from(Expression expression) {
3939
return from(expression, null);
4040
}
4141

@@ -69,7 +69,7 @@ public SelectItem<T> withExpression(T expression) {
6969
return this;
7070
}
7171

72-
public SelectItem withAlias(Alias alias) {
72+
public SelectItem<?> withAlias(Alias alias) {
7373
this.setAlias(alias);
7474
return this;
7575
}

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,7 +2329,7 @@ SelectItem SelectItem() #SelectItem:
23292329
// @fixme: Oracle's SEQUENCE.nextval is parsed as COLUMN with a name part nextval
23302330
// @todo: parse a proper SEQUENCE instead of a COLUMN
23312331
(
2332-
"*" { expression = new AllColumns(); }
2332+
expression = AllColumns()
23332333
|
23342334
LOOKAHEAD(AllTableColumns()) expression = AllTableColumns()
23352335
|
@@ -2347,14 +2347,30 @@ SelectItem SelectItem() #SelectItem:
23472347
}
23482348
}
23492349

2350+
AllColumns AllColumns():
2351+
{
2352+
ParenthesedExpressionList<Column> exceptColumns = null;
2353+
List<SelectItem<?>> replaceExpressions = null;
2354+
}
2355+
{
2356+
"*"
2357+
[ LOOKAHEAD(2) <K_EXCEPT> exceptColumns = ParenthesedColumnList() ]
2358+
[ LOOKAHEAD(2) <K_REPLACE> "(" replaceExpressions = SelectItemsList() ")" ]
2359+
2360+
{
2361+
return new AllColumns(exceptColumns, replaceExpressions);
2362+
}
2363+
}
2364+
23502365
AllTableColumns AllTableColumns():
23512366
{
23522367
Table table = null;
2368+
AllColumns allColumns;
23532369
}
23542370
{
2355-
table=Table() "." "*"
2371+
table=Table() "." allColumns=AllColumns()
23562372
{
2357-
return new AllTableColumns(table);
2373+
return new AllTableColumns(table, allColumns);
23582374
}
23592375

23602376
}

src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public class ReflectionModelTest {
169169
new net.sf.jsqlparser.statement.merge.Merge(),
170170
new net.sf.jsqlparser.statement.merge.MergeUpdate(new ArrayList<UpdateSet>()),
171171
new net.sf.jsqlparser.statement.select.AllColumns(),
172-
new net.sf.jsqlparser.statement.select.AllTableColumns(),
172+
// new net.sf.jsqlparser.statement.select.AllTableColumns(new Table()),
173173
new net.sf.jsqlparser.statement.select.Distinct(),
174174
new net.sf.jsqlparser.statement.select.ExceptOp(),
175175
new net.sf.jsqlparser.statement.select.Fetch(),
@@ -190,7 +190,7 @@ public class ReflectionModelTest {
190190
new net.sf.jsqlparser.statement.select.PivotXml(),
191191
// new net.sf.jsqlparser.statement.select.PlainSelect(),
192192
// new net.sf.jsqlparser.statement.select.Select(),
193-
new net.sf.jsqlparser.statement.select.SelectItem(),
193+
new net.sf.jsqlparser.statement.select.SelectItem<>(),
194194
// new net.sf.jsqlparser.statement.select.SetOperationList(),
195195
new net.sf.jsqlparser.statement.select.Skip(),
196196
// new net.sf.jsqlparser.statement.select.ParenthesedSelect(),
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package net.sf.jsqlparser.statement.select;
2+
3+
import net.sf.jsqlparser.JSQLParserException;
4+
import net.sf.jsqlparser.test.TestUtils;
5+
import org.junit.jupiter.api.Test;
6+
7+
8+
class AllColumnsTest {
9+
10+
@Test
11+
void testBigQuerySyntax() throws JSQLParserException {
12+
String sqlStr =
13+
"SELECT * EXCEPT (order_id) REPLACE (\"widget\" AS item_name), \"more\" as more_fields\n"
14+
+ "FROM orders";
15+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
16+
}
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.sf.jsqlparser.statement.select;
2+
3+
import net.sf.jsqlparser.JSQLParserException;
4+
import net.sf.jsqlparser.test.TestUtils;
5+
import org.junit.jupiter.api.Test;
6+
7+
8+
class AllTableColumnsTest {
9+
@Test
10+
void testBigQuerySyntax() throws JSQLParserException {
11+
String sqlStr =
12+
"SELECT orders.* EXCEPT (order_id) REPLACE (\"widget\" AS item_name), \"more\" as more_fields\n"
13+
+ "FROM orders";
14+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
15+
}
16+
}

src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public void testAllColumnsFromTable() throws Exception {
270270
Table t = new Table("tableName");
271271
assertDeparse(
272272
new PlainSelect()
273-
.addSelectItems(new AllTableColumns().withTable(t)).withFromItem(t),
273+
.addSelectItems(new AllTableColumns(t)).withFromItem(t),
274274
statement);
275275
}
276276

0 commit comments

Comments
 (0)