mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
support clickhouse limit by, fix #4110
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user