support clickhouse limit by, fix #4110

This commit is contained in:
高铁
2020-12-26 06:08:25 +08:00
parent f91508e36b
commit 58fa713694
3 changed files with 69 additions and 10 deletions
@@ -15,11 +15,9 @@
*/
package com.alibaba.druid.sql.ast;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.HashMap;
@@ -30,6 +28,7 @@ import java.util.HashMap;
public final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {
private SQLExpr rowCount;
private SQLExpr offset;
private List<SQLExpr> by;
public SQLLimit() {
@@ -79,20 +78,26 @@ public final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {
this.offset = offset;
}
public void merge(SQLLimit limit) {
if (limit == null) {
public void merge(SQLLimit other) {
if (other == null) {
return;
}
if (limit.offset != null) {
if (other.offset != null) {
if (this.offset == null) {
this.offset = limit.offset.clone();
this.offset = other.offset.clone();
}
}
if (limit.rowCount != null) {
if (other.rowCount != null) {
if (this.rowCount == null) {
this.rowCount = limit.rowCount.clone();
this.rowCount = other.rowCount.clone();
}
}
if (other.by != null) {
for (SQLExpr item : other.by) {
addBy(item.clone());
}
}
}
@@ -107,6 +112,12 @@ public final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {
if (rowCount != null) {
rowCount.accept(visitor);
}
if (by != null) {
for (SQLExpr item : by) {
item.accept(visitor);
}
}
}
visitor.endVisit(this);
}
@@ -122,6 +133,12 @@ public final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {
x.setRowCount(rowCount.clone());
}
if (by != null) {
for (SQLExpr item : by) {
x.addBy(item);
}
}
if (attributes != null) {
x.attributes = (HashMap) ((HashMap) attributes).clone();
}
@@ -129,6 +146,22 @@ public final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {
return x;
}
public void addBy(SQLExpr item) {
if (item == null) {
return;
}
if (by == null) {
by = new ArrayList<>(1);
}
by.add(item);
item.setParent(this);
}
public List<SQLExpr> getBy() {
return by;
}
@Override
public boolean replace(SQLExpr expr, SQLExpr target) {
if (rowCount == expr) {
@@ -5711,6 +5711,21 @@ public class SQLExprParser extends SQLParser {
} else {
limit.setRowCount(temp);
}
if (lexer.token == Token.BY && dbType == DbType.clickhouse) {
lexer.nextToken();
for (;;) {
SQLExpr item = this.expr();
limit.addBy(item);
if (lexer.token == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
return limit;
}
@@ -7950,6 +7950,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
printExpr(rowCount, parameterized);
}
final List<SQLExpr> by = x.getBy();
if (by != null) {
print0(ucase ? " BY " : " by ");
for (int i = 0; i < by.size(); i++) {
if (i != 0) {
print0(", ");
}
by.get(i).accept(this);
}
}
return false;
}