odps sql parser support qualify clause

This commit is contained in:
shaojin.wensj
2022-10-06 02:27:21 +08:00
parent de95667be5
commit 37485e5e17
10 changed files with 64 additions and 54 deletions
@@ -46,6 +46,7 @@ public class SQLSelectQueryBlock extends SQLSelectQueryBase implements SQLReplac
protected SQLSelectGroupByClause groupBy;
protected List<SQLWindow> windows;
protected SQLExpr qualify;
protected SQLOrderBy orderBy;
protected boolean forUpdate;
protected boolean noWait;
@@ -113,6 +114,17 @@ public class SQLSelectQueryBlock extends SQLSelectQueryBase implements SQLReplac
this.windows.add(x);
}
public SQLExpr getQualify() {
return qualify;
}
public void setQualify(SQLExpr x) {
if (x != null) {
x.setParent(this);
}
this.qualify = x;
}
public SQLExpr getWhere() {
return this.where;
}
@@ -45,6 +45,7 @@ public class OdpsLexer extends Lexer {
map.put("RLIKE", Token.RLIKE);
map.put("DIV", Token.DIV);
map.put("LATERAL", Token.LATERAL);
map.put("QUALIFY", Token.QUALIFY);
map.put(";", Token.SEMI);
DEFAULT_ODPS_KEYWORDS = new Keywords(map);
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.odps.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
@@ -161,11 +162,17 @@ public class OdpsSelectParser extends SQLSelectParser {
parseGroupBy(queryBlock);
}
parseGroupBy(queryBlock);
if (lexer.identifierEquals(FnvHash.Constants.WINDOW)) {
parseWindow(queryBlock);
}
parseGroupBy(queryBlock);
if (lexer.token() == Token.QUALIFY) {
lexer.nextToken();
SQLExpr qualify = this.exprParser.expr();
queryBlock.setQualify(qualify);
}
queryBlock.setOrderBy(this.exprParser.parseOrderBy());
queryBlock.setZOrderBy(this.exprParser.parseZOrderBy());
@@ -473,6 +473,13 @@ public class OdpsOutputVisitor extends HiveOutputVisitor implements OdpsASTVisit
printAndAccept(windows, ", ");
}
SQLExpr qualify = x.getQualify();
if (qualify != null) {
println();
print0(ucase ? "QUALIFY " : "qualify ");
qualify.accept(this);
}
if (x.getOrderBy() != null) {
println();
x.getOrderBy().accept(this);
@@ -974,6 +974,7 @@ public final class FnvHash {
long RETURNS = fnv1a_64_lower("RETURNS");
long ROWTYPE = fnv1a_64_lower("ROWTYPE");
long WINDOW = fnv1a_64_lower("WINDOW");
long QUALIFY = fnv1a_64_lower("QUALIFY");
long MULTIVALUE = fnv1a_64_lower("MULTIVALUE");
long OPTIONALLY = fnv1a_64_lower("OPTIONALLY");
long ENCLOSED = fnv1a_64_lower("ENCLOSED");
@@ -70,7 +70,7 @@ public class TestUtil {
try (Reader reader = new InputStreamReader(
contextClassLoader
.getResourceAsStream(path), "UTF-8")
){
) {
return Utils.read(reader);
} catch (IOException ignored) {
return null;
@@ -15,37 +15,29 @@
*/
package com.alibaba.druid.bvt.sql.odps;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.TestUtil;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsSchemaStatVisitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.util.Utils;
public class OdpsResourceTest extends TestCase {
public void test_0() throws Exception {
exec_test("bvt/parser/odps-0.sql");
exec_test("bvt/parser/odps-0.txt");
}
public void test_9() throws Exception {
exec_test("bvt/parser/odps-9.txt");
}
public void exec_test(String resource) throws Exception {
// System.out.println(resource);
InputStream is = null;
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
Reader reader = new InputStreamReader(is, "UTF-8");
String input = Utils.read(reader);
JdbcUtils.close(reader);
String input = TestUtil.getResource(resource);
String[] items = input.split("---------------------------");
String sql = items[0].trim();
String expect = null;
@@ -63,29 +55,9 @@ public class OdpsResourceTest extends TestCase {
SchemaStatVisitor visitor = new OdpsSchemaStatVisitor();
stmt.accept(visitor);
// System.out.println(sql);
// System.out.println("Tables : " + visitor.getTables());
// System.out.println("fields : " + visitor.getColumns());
//
// System.out.println();
// System.out.println("---------------------------");
// System.out.println(SQLUtils.toOdpsString(stmt));
if (expect != null) {
String result = stmt.toString();
assertEquals(expect, result);
}
}
void mergValidate(String sql, String expect) {
MySqlStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement statemen = statementList.get(0);
Assert.assertEquals(1, statementList.size());
StringBuilder out = new StringBuilder();
MySqlOutputVisitor visitor = new MySqlOutputVisitor(out, true);
statemen.accept(visitor);
System.out.println(out.toString());
Assert.assertEquals(expect, out.toString());
}
}
@@ -35,7 +35,7 @@ import com.alibaba.druid.util.Utils;
public class OdpsFileTest extends TestCase {
public void test_0() throws Exception {
exec_test("bvt/parser/odps-0.sql");
exec_test("bvt/parser/odps-0.txt");
}
public void exec_test(String resource) throws Exception {
@@ -10,15 +10,17 @@ create table tt_xx
) comment 'xx comment xxx' partitioned by (pt string comment '按天分区字段', seg string comment '时间跨度')
;
---------------------------
create table tt_xx
(
f1 string,
f2 string comment 'xxx',
f3 string comment 'xxx',
gmt_first datetime comment '首次时间',
gmt_last datetime comment '末次时间',
pv_cnt bigint comment 'PV数量',
pv_day_cnt bigint comment 'PV天数'
) comment 'xx comment xxx'
partitioned by (pt string comment '按天分区字段', seg string comment '时间跨度')
;
CREATE TABLE tt_xx (
f1 STRING,
f2 STRING COMMENT 'xxx',
f3 STRING COMMENT 'xxx',
gmt_first DATETIME COMMENT '首次时间',
gmt_last DATETIME COMMENT '末次时间',
pv_cnt BIGINT COMMENT 'PV数量',
pv_day_cnt BIGINT COMMENT 'PV天数'
)
COMMENT 'xx comment xxx'
PARTITIONED BY (
pt STRING COMMENT '按天分区字段',
seg STRING COMMENT '时间跨度'
);
@@ -0,0 +1,8 @@
select i, p, o
from qt
qualify row_number() over (partition by p order by o) = 1
;
---------------------------
SELECT i, p, o
FROM qt
QUALIFY row_number() OVER (PARTITION BY p ORDER BY o) = 1;