#gStore-weekly | SPARQL 解析(上)
1.1 简介
gStore 的 SPARQL 解析发生在发起查询时(包括使用 gquery 和 ghttp 来发起查询)。如使用 gquery 发起查询:
$ bin/gquery -db example -q example.sparql
则 gStore 会读入 SPARQL 查询文件 example.sparql ,对其进行解析,并交由查询执行器执行。
1.2 类层次结构
SPARQL 解析由 QueryParser 类完成。QueryParser 类继承了解析器生成器 ANTLR 由 SPARQL 语法自动生成的 SPARQLBaseVisitor 类,生成查询的语法树,并通过访问语法树的相关结点获取关键信息,填充到表征查询的 QueryTree 类对象中。
1.3 QueryTree 类
QueryTree 类用于表示查询结构、存储查询中的关键信息。
1.3.1 类成员变量
变量 | 类型 | 注释 |
---|---|---|
QueryForm | enum 公有 | 标识查询类型(SELECT或ASK) |
ProjectionModifier | enum 公有 | 标识查询投影变量是否有修饰符(目前支持无修饰符Modifier_None、DISTINCT修饰符Modifier_Distinct) |
UpdateType | enum 公有 | 标识更新语句的类型(若为查询,则值为Not_Update;暂未支持Modify_Clause) |
query_form | QueryForm 私有 | 查询类型 |
projection_modifier | ProjectionModifier 私有 | 查询投影变量的修饰符 |
projection | std::vector 私有 | 投影的变量/函数 |
projection_asterisk | bool 私有 | 是否投影查询中出现的所有变量(SELECT *) |
group_by | Varset 私有 | GROUP BY语句中出现的变量集合 |
order_by | std::vector 私有 | ORDER BY语句中的条件 |
offset | int 私有 | OFFSET语句中的数值,表示从第几行结果开始输出,一般与ORDER BY配合使用 |
limit | int 私有 | LIMIT语句中的数值,表示输出的结果数量上限 |
group_pattern | GroupPattern 私有 | 查询中最外层的组图模式(即最外层大括号括起的部分) |
singleBGP | bool 私有 | 查询中是否仅包含一个基本图模式(Basic Graph Pattern, BGP) |
update_type | UpdateType 私有 | 更新语句的类型 |
insert_patterns | GroupPattern 私有 | INSERT类更新语句中最外层的组图模式 |
delete_patterns | GroupPattern 私有 | DELETE类更新语句中最外层的组图模式 |
其中 group_pattern 为嵌套类 QueryTree::GroupPattern 对象,有成员变量 vector<QueryTree::GroupPattern::SubGroupPattern> sub_group_pattern ,表示组图模式中互为连接关系的子图模式。
1.3.2 关键嵌套类 QueryTree::GroupPattern::SubGroupPattern
这一嵌套类表示组图模式中的子图模式,分为以下类型:嵌套组图模式、三元组模式、UNION图模式、OPTIONAL图模式、MINUS图模式、FILTER结构/BIND结构。为某种类型时,相应的成员变量中存储其相关信息:如为三元组模式时,为 QueryTree::GroupPattern::Pattern 类对象的成员变量 pattern 中存储三元组的主语、谓词和宾语。
QueryTree::GroupPattern::SubGroupPattern 类的成员变量如下:
变量 | 类型 | 注释 |
---|---|---|
SubGroupPatternType | enum 公有 | 标识子模式类型(嵌套组图模式/三元组模式/UNION图模式/OPTIONAL图模式/MINUS图模式/FILTER结构/BIND结构) |
type | SubGroupPatternType 公有 | 当前子模式的类型 |
pattern | Pattern 公有 | 当前子模式为三元组模式时,给出其具体信息 |
group_pattern | GroupPattern 公有 | 当前子模式为嵌套组图模式时,给出其具体信息 |
unions | std::vector 公有 | 当前子模式为UNION图模式时,给出其具体信息 |
optional | GroupPattern 公有 | 当前子模式为OPTIONAL图模式时,给出其具体信息 |
filter | CompTreeNode 公有 | 当前子模式为FILTER结构时,给出其具体信息 |
bind | Bind 公有 | 当前子模式为BIND结构时,给出其具体信息 |
1.4 QueryParser::SPARQLParse
QueryParser::SPARQLParse 为 QueryParser 类中驱动 SPARQL 解析的成员函数。
函数原型:
void SPARQLParse(const std::string &query);
关键代码段说明如下。
函数整体为 try-catch 结构,尝试进行 SPARQL 解析,若其中遇到语法错误并抛出异常,则捕获异常并打印错误信息。
try{
...
}catch(const runtime_error& e1)
{
throw runtime_error(e1.what());
}
在 try 分支中,首先由输入参数 query 字符串创建 istringstream 类对象,并创建用于捕捉和报告语法错误的 SPARQLErrorListener 类对象:
istringstream ifs(query);
SPARQLErrorListener lstnr;
然后使用 ANTLR 自动生成的 SPARQL 词法解析器 SPARQLLexer ,对查询进行词法解析(将其原有的错误报告器替换为自定义配置过的 lstnr ):
antlr4::ANTLRInputStream input(ifs);
SPARQLLexer lexer(&input);
lexer.removeErrorListeners();
lexer.addErrorListener(&lstnr);
再使用 ANTLR 自动生成的 SPARQL 语法解析器 SPARQParser 对词法解析的结果进行语法解析(同样将其原有的错误报告器替换为 lstnr ):
antlr4::CommonTokenStream tokens(&lexer);
SPARQLParser parser(&tokens);
parser.removeErrorListeners();
parser.addErrorListener(&lstnr);
最后调用入口函数 QueryParser::visitEntry ,从语法解析树的根结点开始遍历之,收集关键信息填入 QueryTree:
SPARQLParser::EntryContext *tree = parser.entry();
visitEntry(tree);
1.5 小结
本篇介绍了 gStore 的 SPARQL 解析机制,主要详细分析了 QueryTree 类的结构和 QueryParser 类中的驱动函数 QueryParser::SPARQLParse,建议在阅读的同时结合源码 Query/QueryTree.h、Parser/QueryParser.cpp 一起分析,会更容易理解。在本章的下篇中,我们将继续介绍 QueryParser 类在遍历语法解析树的过程中调用的关键函数。
#gStore-weekly | SPARQL 解析(下)