hive的sql解析

 

写了一个下午,实现了表级别的sql解析。但后来知道taobao那边已经有了完备的字段级别的sql解析工具,所以也就没必要在写下去了。不过还是要将表级别的sql解析介绍介绍,毕竟也写了几百行代码。

先把最后的解析结果贴出来:
hive> ?select * from sunwg;
0 TOK_QUERY sunwg QueryFromClause
Time taken: 0.0010 seconds

hive> ?create table sunwg (id int);
0 TOK_CREATETABLE sunwg CreateTableClause
Time taken: 0.0080 seconds

hive> ?create table sunwg like sunwg00;
0 TOK_CREATETABLE sunwg CreateTableClause
1 TOK_CREATETABLE sunwg00 CreateTableLikeClause
Time taken: 0.0020 seconds

hive> ?insert overwrite table sunwg select * from sunwg01;
0 TOK_QUERY sunwg01 QueryFromClause
1 TOK_QUERY sunwg QueryInsertClause
Time taken: 0.0050 seconds

hive> ?from sunwg
> insert overwrite table sunwg01 select *
> insert overwrite table sunwg02 select *;
0 TOK_QUERY sunwg QueryFromClause
1 TOK_QUERY sunwg01 QueryInsertClause
2 TOK_QUERY sunwg02 QueryInsertClause
Time taken: 0.0020 seconds

hive> ?select * from sunwg01 join sunwg02 join sunwg03;
0 TOK_QUERY sunwg01 QueryFromClause
1 TOK_QUERY sunwg02 QueryFromClause
2 TOK_QUERY sunwg03 QueryFromClause
Time taken: 0.0010 seconds

hive> ?select * from (select * from sunwg) r1;
0 TOK_QUERY sunwg QueryFromClause
Time taken: 0.0020 seconds

hive> ?select * from (select 1 from sunwg union all select 2 from sunwg01 union all select 3 from sunwg02) r1;
0 TOK_QUERY sunwg QueryFromClause
1 TOK_QUERY sunwg01 QueryFromClause
2 TOK_QUERY sunwg02 QueryFromClause
Time taken: 0.193 seconds

hive> ?select * from (select 1 from sunwg union all select 2 from sunwg01 union all select 3 from sunwg02) r1 join sunwg04;
0 TOK_QUERY sunwg QueryFromClause
1 TOK_QUERY sunwg01 QueryFromClause
2 TOK_QUERY sunwg02 QueryFromClause
3 TOK_QUERY sunwg04 QueryFromClause

实现的思路:
1,通过“?”标识该sql仅仅进行解析,而不真正的执行。
2,先对sql进行编译,而不执行,编译的结果传递给sql解析类HiveParseResult.java
3,在HiveParseResult中按照sql的类型进行解析
4,HiveParseResult的解析结果以string的格式传递给hive前台

代码比较长,就贴出具有代表性的吧:
switch (tree.getToken().getType()) {
case HiveParser.TOK_DROPTABLE:
ParseDropTable(tree);
break;
case HiveParser.TOK_DROPVIEW:
ParseDropView(tree);
break;
case HiveParser.TOK_CREATETABLE:
ParseCreateTable(tree);
break;
case HiveParser.TOK_ALTERTABLE_ADDPARTS:
ParseAlterTableAddParts(tree);
break;
case HiveParser.TOK_ALTERTABLE_DROPPARTS:
ParseAlterTableDropParts(tree);
break;
case HiveParser.TOK_ALTERTABLE_RENAME:
ParseAlterTableRename(tree);
break;
case HiveParser.TOK_ALTERTABLE_RENAMECOL:
ParseAlterTableRenameCol(tree);
break;
case HiveParser.TOK_ALTERTABLE_ADDCOLS:
ParseAlterTableAddCols(tree);
break;
case HiveParser.TOK_ALTERTABLE_REPLACECOLS:
ParseAlterTableReplaceCols(tree);
break;
case HiveParser.TOK_ALTERTABLE_PROPERTIES:
ParseAlterTableProperties(tree);
break;
case HiveParser.TOK_ALTERTABLE_SERIALIZER:
ParseAlterTableSerializer(tree);
break;
case HiveParser.TOK_ALTERTABLE_SERDEPROPERTIES:
ParseAlterTableSerdeProperties(tree);
break;
case HiveParser.TOK_ALTERTABLE_FILEFORMAT:
ParseAlterTableFileFormat(tree);
break;
case HiveParser.TOK_ALTERTABLE_CLUSTER_SORT:
ParseAlterTableClusterSort(tree);
break;
case HiveParser.TOK_ALTERTABLE_TOUCH:
ParseAlterTableTouch(tree);
break;
case HiveParser.TOK_ALTERVIEW_PROPERTIES:
ParseAlterViewProperties(tree);
break;
case HiveParser.TOK_QUERY:
ParseQuery(tree);
break;
case HiveParser.TOK_CREATEVIEW:
ParseCreateView(tree);
break;
}
根据不同的SQL类型来调用不同的解析方法。

public void ParseQuery(ASTNode ASTNodeParseQuery) {

int childcount = ASTNodeParseQuery.getChildCount();

for ( int childpos = 0; childpos < childcount; ++childpos) {
ASTNode ASTNodetmp01 = (ASTNode)ASTNodeParseQuery.getChild(childpos);

switch (ASTNodetmp01.getToken().getType()) {
case HiveParser.TOK_FROM:
ASTNode ASTNodetmp02 = (ASTNode)ASTNodetmp01.getChild(0);
ParseQueryFrom(tree,ASTNodetmp02);
break;
case HiveParser.TOK_INSERT:
ParseQueryInsert(tree,ASTNodetmp01);
break;
}
}
}
对于QUERY的解析,主要分析的是TOK_FROM和TOK_INSERT的部分。

public void SubParseQuery(ASTNode ASTNodeParseQuery, ASTNode ASTNodeParseSubQuery) {

int childcount = 0;
int childpos = 0;

switch (ASTNodeParseSubQuery.getToken().getType()) {
case HiveParser.TOK_QUERY:
childcount = ASTNodeParseSubQuery.getChildCount();

for ( childpos = 0; childpos < childcount; ++childpos) {
ASTNode ASTNodetmp01 = (ASTNode)ASTNodeParseSubQuery.getChild(childpos);

switch (ASTNodetmp01.getToken().getType()) {
case HiveParser.TOK_FROM:
ASTNode ASTNodetmp02 = (ASTNode)ASTNodetmp01.getChild(0);
ParseQueryFrom(tree,ASTNodetmp02);
break;
}
}
break;
case HiveParser.TOK_UNION:
childcount = ASTNodeParseSubQuery.getChildCount();

for ( childpos = 0; childpos < childcount; ++childpos) {
ASTNode ASTNodetmp02 = (ASTNode)ASTNodeParseSubQuery.getChild(childpos);
SubParseQuery(ASTNodeParseQuery,ASTNodetmp02);
}
break;
}
}
对于子查询的分析,主要分析TOK_FROM,TOK_UNION,TOK_QUERY的部分。

其他的SQL类型都比较简单了,比如DROP TABLE,如下
public void ParseDropTable(ASTNode ASTNodeDropTable) {
ASTNode ASTNodetmp01 = (ASTNode)ASTNodeDropTable.getChild(0);
ParseResultAppend(ASTNodeDropTable.toString(), ASTNodetmp01.toString(), “DropTableClause”);
}

原文地址:http://www.oratea.net/?p=666

### HiveSQL解析数组的方法及示例 在HiveSQL中,解析数组通常涉及使用内置函数如`array_contains()`、`size()`、`split()`以及结合`explode()`函数来实现。以下详细介绍这些函数的使用方法和示例。 #### 使用 `array_contains()` 函数 `array_contains()` 用于判断一个数组是否包含指定的值。此函数与 SQL 中的 `IN` 关键字类似,但适用于数组字段。如果需要检查数组中是否包含某个值,可以使用该函数[^2]。 ```sql SELECT array_contains(array('apple', 'banana', 'orange'), 'banana') AS contains_banana; ``` 上述代码将返回 `true`,因为数组中包含 `'banana'`。 #### 使用 `explode()` 函数 `explode()` 函数用于将数组或映射类型的列拆分为多行。这在需要对数组中的每个元素进行单独处理时非常有用[^3]。 假设有一张表 `example_table`,其中包含一个数组字段 `fruits`: | id | fruits | |-----|-------------------------| | 1 | ["apple", "banana"] | | 2 | ["orange", "grape"] | 可以通过以下查询将其展开为多行: ```sql SELECT id, explode(fruits) AS fruit FROM example_table; ``` 结果如下: | id | fruit | |-----|----------| | 1 | apple | | 1 | banana | | 2 | orange | | 2 | grape | #### 结合 `split()` 和 `explode()` 解析字符串数组 如果数组是以字符串形式存储的(例如 JSON 格式的数组),可以先使用 `split()` 将其转换为数组,然后使用 `explode()` 进行解析[^3]。 假设有一列 `json_array`,存储格式如下: | json_array | |---------------------------------------------------------------------------| | '[{"website":"www.baidu.com","name":"百度"},{"website":"www.taobao.com","name":"淘宝"}]' | 可以通过以下步骤解析: 1. 使用正则表达式替换掉多余的符号(如 `[`、`]` 和 `,`)。 2. 使用 `split()` 将字符串分割为数组。 3. 使用 `explode()` 将数组拆分为多行。 完整示例如下: ```sql SELECT explode( split( regexp_replace( regexp_replace(json_array, '\\}\\,\\{', '\\}\\;\\{'), '\\[|\\]', '' ), '\\;' ) ) AS parsed_item FROM example_table; ``` #### 使用 `size()` 函数 `size()` 函数用于获取数组的长度。如果需要验证数组是否为空或者统计数组中元素的数量,可以使用该函数[^2]。 ```sql SELECT size(array('apple', 'banana', 'orange')) AS array_size; ``` 上述代码将返回 `3`,因为数组中有三个元素。 --- ### 总结 HiveSQL 提供了多种解析数组的方法,包括但不限于 `array_contains()`、`explode()`、`split()` 和 `size()` 等函数。通过组合这些函数,可以灵活地处理复杂的数据结构,满足不同的业务需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值