Skip to content

Commit

Permalink
feat(hive): add hive expression column
Browse files Browse the repository at this point in the history
  • Loading branch information
LuckyFBB committed Oct 15, 2024
1 parent 7b95431 commit 7fb4c56
Show file tree
Hide file tree
Showing 10 changed files with 6,491 additions and 5,644 deletions.
16 changes: 12 additions & 4 deletions src/grammar/hive/HiveSqlParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing permissions and limitations under the
Expand Down Expand Up @@ -758,6 +758,10 @@ columnName
| {this.shouldMatchEmpty()}?
;

columnNamePath
: poolPath
;

columnNameCreate
: id_
;
Expand Down Expand Up @@ -1437,7 +1441,7 @@ subQuerySource
Rules for parsing PTF clauses
*/
partitioningSpec
: KW_PARTITION KW_BY expressions orderByClause?
: partitionByClause orderByClause?
| orderByClause
| distributeByClause sortByClause?
| sortByClause
Expand Down Expand Up @@ -1613,6 +1617,10 @@ orderByClause
: KW_ORDER KW_BY columnRefOrder (COMMA columnRefOrder)*
;

partitionByClause
: KW_PARTITION KW_BY expressions
;

clusterByClause
: KW_CLUSTER KW_BY expressions
;
Expand Down Expand Up @@ -1714,7 +1722,7 @@ constant
| KW_FALSE
| KW_NULL
| p=QUESTION
| Identifier
| columnNamePath
;

intervalValue
Expand Down
4 changes: 3 additions & 1 deletion src/lib/hive/HiveSqlParser.interp

Large diffs are not rendered by default.

11,864 changes: 6,227 additions & 5,637 deletions src/lib/hive/HiveSqlParser.ts

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/lib/hive/HiveSqlParserListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ import { ColumnNameTypeOrConstraintListContext } from "./HiveSqlParser.js";
import { ColumnNameColonTypeListContext } from "./HiveSqlParser.js";
import { ColumnNameListContext } from "./HiveSqlParser.js";
import { ColumnNameContext } from "./HiveSqlParser.js";
import { ColumnNamePathContext } from "./HiveSqlParser.js";
import { ColumnNameCreateContext } from "./HiveSqlParser.js";
import { ExtColumnNameContext } from "./HiveSqlParser.js";
import { ColumnNameOrderListContext } from "./HiveSqlParser.js";
Expand Down Expand Up @@ -282,6 +283,7 @@ import { ExpressionsContext } from "./HiveSqlParser.js";
import { ExpressionsInParenthesisContext } from "./HiveSqlParser.js";
import { ExpressionsNotInParenthesisContext } from "./HiveSqlParser.js";
import { OrderByClauseContext } from "./HiveSqlParser.js";
import { PartitionByClauseContext } from "./HiveSqlParser.js";
import { ClusterByClauseContext } from "./HiveSqlParser.js";
import { DistributeByClauseContext } from "./HiveSqlParser.js";
import { SortByClauseContext } from "./HiveSqlParser.js";
Expand Down Expand Up @@ -1653,6 +1655,16 @@ export class HiveSqlParserListener implements ParseTreeListener {
* @param ctx the parse tree
*/
exitColumnName?: (ctx: ColumnNameContext) => void;
/**
* Enter a parse tree produced by `HiveSqlParser.columnNamePath`.
* @param ctx the parse tree
*/
enterColumnNamePath?: (ctx: ColumnNamePathContext) => void;
/**
* Exit a parse tree produced by `HiveSqlParser.columnNamePath`.
* @param ctx the parse tree
*/
exitColumnNamePath?: (ctx: ColumnNamePathContext) => void;
/**
* Enter a parse tree produced by `HiveSqlParser.columnNameCreate`.
* @param ctx the parse tree
Expand Down Expand Up @@ -3111,6 +3123,16 @@ export class HiveSqlParserListener implements ParseTreeListener {
* @param ctx the parse tree
*/
exitOrderByClause?: (ctx: OrderByClauseContext) => void;
/**
* Enter a parse tree produced by `HiveSqlParser.partitionByClause`.
* @param ctx the parse tree
*/
enterPartitionByClause?: (ctx: PartitionByClauseContext) => void;
/**
* Exit a parse tree produced by `HiveSqlParser.partitionByClause`.
* @param ctx the parse tree
*/
exitPartitionByClause?: (ctx: PartitionByClauseContext) => void;
/**
* Enter a parse tree produced by `HiveSqlParser.clusterByClause`.
* @param ctx the parse tree
Expand Down
14 changes: 14 additions & 0 deletions src/lib/hive/HiveSqlParserVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ import { ColumnNameTypeOrConstraintListContext } from "./HiveSqlParser.js";
import { ColumnNameColonTypeListContext } from "./HiveSqlParser.js";
import { ColumnNameListContext } from "./HiveSqlParser.js";
import { ColumnNameContext } from "./HiveSqlParser.js";
import { ColumnNamePathContext } from "./HiveSqlParser.js";
import { ColumnNameCreateContext } from "./HiveSqlParser.js";
import { ExtColumnNameContext } from "./HiveSqlParser.js";
import { ColumnNameOrderListContext } from "./HiveSqlParser.js";
Expand Down Expand Up @@ -282,6 +283,7 @@ import { ExpressionsContext } from "./HiveSqlParser.js";
import { ExpressionsInParenthesisContext } from "./HiveSqlParser.js";
import { ExpressionsNotInParenthesisContext } from "./HiveSqlParser.js";
import { OrderByClauseContext } from "./HiveSqlParser.js";
import { PartitionByClauseContext } from "./HiveSqlParser.js";
import { ClusterByClauseContext } from "./HiveSqlParser.js";
import { DistributeByClauseContext } from "./HiveSqlParser.js";
import { SortByClauseContext } from "./HiveSqlParser.js";
Expand Down Expand Up @@ -1140,6 +1142,12 @@ export class HiveSqlParserVisitor<Result> extends AbstractParseTreeVisitor<Resul
* @return the visitor result
*/
visitColumnName?: (ctx: ColumnNameContext) => Result;
/**
* Visit a parse tree produced by `HiveSqlParser.columnNamePath`.
* @param ctx the parse tree
* @return the visitor result
*/
visitColumnNamePath?: (ctx: ColumnNamePathContext) => Result;
/**
* Visit a parse tree produced by `HiveSqlParser.columnNameCreate`.
* @param ctx the parse tree
Expand Down Expand Up @@ -2014,6 +2022,12 @@ export class HiveSqlParserVisitor<Result> extends AbstractParseTreeVisitor<Resul
* @return the visitor result
*/
visitOrderByClause?: (ctx: OrderByClauseContext) => Result;
/**
* Visit a parse tree produced by `HiveSqlParser.partitionByClause`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPartitionByClause?: (ctx: PartitionByClauseContext) => Result;
/**
* Visit a parse tree produced by `HiveSqlParser.clusterByClause`.
* @param ctx the parse tree
Expand Down
4 changes: 3 additions & 1 deletion src/parser/hive/hiveErrorListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class HiveErrorListener extends ParseErrorListener {
[HiveSqlParser.RULE_functionNameCreate, 'function'],
[HiveSqlParser.RULE_columnName, 'column'],
[HiveSqlParser.RULE_columnNameCreate, 'column'],
[HiveSqlParser.RULE_columnNamePath, 'column'],
]);

constructor(errorListener: ErrorListener, preferredRules: Set<number>, locale: LOCALE_TYPE) {
Expand Down Expand Up @@ -50,7 +51,8 @@ export class HiveErrorListener extends ParseErrorListener {
case HiveSqlParser.RULE_viewName:
case HiveSqlParser.RULE_functionNameForDDL:
case HiveSqlParser.RULE_functionNameForInvoke:
case HiveSqlParser.RULE_columnName: {
case HiveSqlParser.RULE_columnName:
case HiveSqlParser.RULE_columnNamePath: {
result.push(`{existing}${name}`);
break;
}
Expand Down
17 changes: 17 additions & 0 deletions src/parser/hive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class HiveSQL extends BasicSQL<HiveSqlLexer, ProgramContext, HiveSqlParse
HiveSqlParser.RULE_functionNameForInvoke, // function name
HiveSqlParser.RULE_functionNameCreate, // function name that will be created
HiveSqlParser.RULE_columnName,
HiveSqlParser.RULE_columnNamePath,
HiveSqlParser.RULE_columnNameCreate,
]);

Expand Down Expand Up @@ -107,6 +108,22 @@ export class HiveSQL extends BasicSQL<HiveSqlLexer, ProgramContext, HiveSqlParse
syntaxContextType = EntityContextType.COLUMN_CREATE;
break;
}
case HiveSqlParser.RULE_columnNamePath: {
if (
candidateRule.ruleList.includes(HiveSqlParser.RULE_orderByClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_havingClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_groupByClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_sortByClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_whereClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_qualifyClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_clusterByClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_distributeByClause) ||
candidateRule.ruleList.includes(HiveSqlParser.RULE_selectClause)
) {
syntaxContextType = EntityContextType.COLUMN;
}
break;
}
default:
break;
}
Expand Down
23 changes: 23 additions & 0 deletions test/parser/hive/errorListener.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const sql2 = `SELECT * FROM `;
const sql3 = `DROP VIEW IF EXIsST aaa aaa`;
const sql4 = `SELECT * froma aaa`;
const sql5 = `CREATE TABLE `;
const sql6 = `SELECT col1 FROM t1 GROUP BY col1 HAVING SUM(col2 `;

describe('HiveSQL validate invalid sql and test msg', () => {
const hive = new HiveSQL();
Expand Down Expand Up @@ -55,6 +56,14 @@ describe('HiveSQL validate invalid sql and test msg', () => {
);
});

test('validate unComplete sql6', () => {
const errors = hive.validate(sql6);
expect(errors.length).toBe(1);
expect(errors[0].message).toBe(
`Statement is incomplete, expecting an existing function or an existing column or a keyword`
);
});

test('validate random text cn', () => {
hive.locale = 'zh_CN';
const errors = hive.validate(randomText);
Expand Down Expand Up @@ -88,4 +97,18 @@ describe('HiveSQL validate invalid sql and test msg', () => {
expect(errors.length).toBe(1);
expect(errors[0].message).toBe(`'froma' 在此位置无效,期望一个关键字`);
});

test('validate unComplete sql5', () => {
const errors = hive.validate(sql5);
expect(errors.length).toBe(1);
expect(errors[0].message).toBe(`语句不完整,期望一个新的table或者一个关键字`);
});

test('validate unComplete sql6 cn', () => {
const errors = hive.validate(sql6);
expect(errors.length).toBe(1);
expect(errors[0].message).toBe(
`语句不完整,期望一个存在的function或者一个存在的column或者一个关键字`
);
});
});
18 changes: 17 additions & 1 deletion test/parser/hive/suggestion/fixtures/syntaxSuggestion.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,20 @@ FROM table_name_1 SELECT col1, col2;

FROM a JOIN b ON (a.id = b.id AND a.department = b.department) SELECT a.*;

FROM page_view_stg INSERT;
FROM page_view_stg INSERT;

SELECT key FROM (SELECT key FROM src ORDER BY sum(a,b) LIMIT 10)subq1;

SELECT col1 FROM t1 GROUP BY col1 HAVING SUM(col2) > 10;

SELECT col1 FROM (SELECT col1, SUM(col2) AS col2sum FROM t1 GROUP BY col1 > 20) t2 WHERE t2.col2sum > 10;

SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC;

SELECT id, RANK() OVER (PARTITION BY customer_id ORDER BY sale_date) AS rank FROM sales QUALIFY rank = 1;

SELECT id, customer_id, amount FROM sales CLUSTER BY customer_id;

SELECT sum(t3.col), col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC;

SELECT a, COUNT(b) OVER (PARTITION BY c, d) FROM T;
Loading

0 comments on commit 7fb4c56

Please sign in to comment.