DataQL之语法-万能查询执行步骤

万能查询执行步骤

引用包

<dependency>
    <groupId>net.hasor</groupId>
    <artifactId>hasor-dataql</artifactId>
    <version>4.1.13</version>
    <!-- 查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-dataql -->
</dependency>

基于底层接口使用 DataQL

这种方式更加底层,依然是脱离了 Hasor 容器环境来执行 DataQL 查询。事实上无论是 Hasor 方式还是 JSR223 方式它们都是通过这个底层接口封装 DataQL 的。

DataQL 的运行基于三个步骤:

  • 解析DataQL查询
  • 编译查询
  • 执行查询

解析DataQL查询

解析 DataQL 查询就是把 DataQL 查询字符串通过解析器解码为 AST(抽象语法树)

QueryModel queryModel = QueryHelper.queryParser(query1);

编译查询

编译是指将DataQL 的 AST(抽象语法树) 编译为 QIL 指令序列。

QIL qil = QueryHelper.queryCompiler(queryModel, null, Finder.DEFAULT);

执行查询

根据 QIL 创建对应的 Query 接口即可。

Query dataQuery = QueryHelper.createQuery(qil, Finder.DEFAULT);

通过 Hasor 使用 DataQL

由于 AppContext 有自身的声明周期特性,因此需要做一个单例模式来创建 DataQL 接口。

public class DataQueryContext {
    private static AppContext appContext = null;
    private static DataQL     dataQL     = null;
    public static DataQL getDataQL() {
        if (appContext == null) {
            appContext = Hasor.create().build();
            dataQL = appContext.getInstance(DataQL.class);
        }
        return dataQL;
    }
}

运行代码


HashMap<String, Object> tempData = new HashMap<String, Object>() {{
    put("uid", "hello");
    put("sid", "world");
}};
 
DataQL dataQL = DataQueryContext.getDataQL();
Query dataQuery = dataQL.createQuery("return [${uid},${sid}]");
QueryResult queryResult = dataQuery.execute(tempData);
DataModel dataModel = queryResult.getData();

dataModel 的值就是 [‘hello’,‘world’]

通过 JSR223 使用 DataQL

JDK1.6开始 Java引入了 JSR223 规范,通过该规范可以用一致的形式在JVM上执行一些脚本语言。
DataQL 默认实现了这一规范的接入API,这就使得开发者可以脱离 Hasor 容器的特性独立的使用 DataQL 查询引擎。
这种方法无需考虑 Hasor 容器生命周期问题。

ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("dataql");
SimpleScriptContext params = new SimpleScriptContext();
params.setBindings(scriptEngine.createBindings(), ScriptContext.GLOBAL_SCOPE);
params.setBindings(scriptEngine.createBindings(), ScriptContext.ENGINE_SCOPE);
params.setAttribute("uid", "Hello", ScriptContext.ENGINE_SCOPE);
params.setAttribute("sid", "world", ScriptContext.GLOBAL_SCOPE);
 
Object eval = scriptEngine.eval("return [${uid},${sid}]", params);
DataModel dataModel = ((QueryResult) eval).getData();

dataModel 的值就是 [‘Hello’, ‘world’]
注意:在 JSR223 方式下:不提供 CustomizeScope 接口支持。三个Dim注解无效:@DimFragment、@DimUdf、@DimUdfSource

查询接口(Query)

以上无论使用的是何种方式查询都会通过 DataQL 的查询接口发出查询指令,查询接口的完整类名为 net.hasor.dataql.Query

/** 执行查询 */
public default QueryResult execute() throws InstructRuntimeException {
    return this.execute(symbol -> Collections.emptyMap());
}
 
/** 执行查询 */
public default QueryResult execute(Map<String, ?> envData) throws InstructRuntimeException {
    return this.execute(symbol -> envData);
}
 
/** 执行查询 */
public default QueryResult execute(Object[] envData) throws InstructRuntimeException {
    if (envData == null) {
        return this.execute(Collections.emptyMap());
    }
    Map<String, Object> objectMap = new HashMap<>();
    for (int i = 0; i < envData.length; i++) {
        objectMap.put("_" + i, envData[i]);
    }
    return this.execute(objectMap);
}
 
/** 执行查询 */
public QueryResult execute(CustomizeScope customizeScope) throws InstructRuntimeException;

查询结果(QueryResult)

发出DataQL查询后,如果顺利执行完查询,结果会以 QueryResult 接口形式返回。QueryResult 接口定义了四个方法来获取返回值相关信息。

/** 执行结果是否通过 EXIT 形式返回的 */
public boolean isExit();
 
/** 获得退出码。如果未指定退出码,则默认值为 0 */
public int getCode();
 
/** 获得返回值 */
public DataModel getData();
 
/** 获得本次执行耗时 */
public long executionTime();

总结

本次是DataQL万能查询执行步骤,同时支持多种查询方式,你可以试试
如有问题,欢迎有问题及时交流。谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值