DQL 实践 —— WEB 界面

一、 部署DQL服务

DQL服务器的启动程序是{安装目录}/esProc/bin/startDQLSERVER.bat(linux下是……startDQLSERVER.sh),运行它之前,先把制作好的TPCH.glmd部署到DQL服务器上,服务器配置文件目录是{安装目录}/esProc/esproc-services/,其下每个文件夹对应一个DQL服务,复制默认的datalogic服务成一个新的服务,命名为TPCH

..

然后修改server.xml,增加TPCH服务,这里还配置了服务器地址及服务端口:

..

进入TPCH目录,把元数据文件TPCH.glmd复制到TPCH/conf/下,然后修改TPCH/service.xml,设置元数据文件:

..

配置完,运行startDQLSERVER.bat,点击Start,这时DQL服务器的TPCH服务就启动了:

..

二、 实现手写DQL查询

DQL JDBC

WEB系统中通常使用JDBC方式连接数据库,执行SQL获得数据。执行DQL也是一样,把DQL JDBC的驱动程序(esproc-ent-*.jar)放入WEB-INF/lib/下就可以用Java代码查询数据了:

Connection con = null;

try {

   String driverClass = "com.esproc.dql.jdbc.DQLDriver";

   String url = "jdbc:esproc:dql://127.0.0.1:3368/TPCH";

   String dql = "SELECT * FROM Orders";

   Class.forName(driverClass);

   con= DriverManager.getConnection(url,"root","root");

   ResultSet resultSet = con.createStatement().executeQuery(dql);

   while (resultSet.next()) {

      System.out.println(resultSet.getObject(1)

      +","+resultSet.getObject(2)

      +","+resultSet.getObject(3));

   }

} finally {

   if(con != null) con.close();

}

驱动类是com.esproc.dql.jdbc.DQLDriver

连接URLjdbc:esproc:dql://127.0.0.1:3368/TPCH,连接DQL服务器中的TPCH服务;

查询Orders表,在控制台打印出前三列的值:

..

查询页面

基于上面的代码,编写下面的/raqsoft/dql/jsp/manualDqlQuery.jsp,实现手写DQL查询,用Html form表单提交DQL服务名称及DQL语句,执行得到结果resultHtmlString,展示到页面上

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>

<%@ page import="com.scudata.web.dql.esprocdql.*" %>

<%@ page import="java.sql.*" %>

<%

String dataSource = request.getParameter("dataSource");

String dql = request.getParameter( "dql" );

String cp = request.getContextPath();

if (dataSource == null) dataSource = "TPCH";

if (dql == null) dql = "select * from orders";

Connection con = null;

String resultHtmlString = null;

try {

   String driverClass = "com.esproc.dql.jdbc.DQLDriver";

   String url = "jdbc:esproc:dql://127.0.0.1:3368/"+dataSource;

   Class.forName(driverClass);

   con= DriverManager.getConnection(url,"root","root");

   ResultSet rs = con.createStatement().executeQuery(dql);

   resultHtmlString = DqlUtil.resultSetToHTMLString(rs);

} finally {

   if(con != null)con.close();

}

%>

<html>

   <head>

      <link rel="stylesheet" href="<%=cp %>/raqsoft/dql/css/queryResult.css"type="text/css">

   </head>

   <body>

      <div>

            <form name="executeForm" method="post" accept-charset="UTF-8"

               target="_self" action="<%=cp%>/raqsoft/dql/jsp/manualDqlQuery.jsp">

               <span>Data Source&nbsp;&nbsp;</span><input name="dataSource" value="<%=dataSource%>" type="text">

               <br>

               <span>DQL&nbsp;&nbsp;</span><textarea name="dql"class="dql"><%=dql%></textarea>

               <input type="button" onclick="executeForm.submit();" value="Execute">

            </form>

         </div>

      <div><%=resultHtmlString %></div>

   </body>

</html>

尝试执行下DQL实践:元数据与语法中的示例2

..

尝试下示例5

..

三、可视化查询

如果查询涉及较多字段,以及有复杂关系的多表时,手写就不方便了。下面我们实现一个可视化界面,能把所有备选的表、字段展示出来,并且能用自动或可视的方法编辑多表之间的关联。

1、获取元数据

DQL提供了查询语句“metadata”,能返回完整的JSON格式元数据信息,用上面查询页面执行看一下:

..

返回表、字段、维等详细信息:

{

"tables": [{ //表列表

"name": "Customer", //表名

"type": "0", //表类型,实表、

"fields": [{ //字段列表

"name": "CUSTKEY", //字段名

"type": 1, //字段数据类型

"pk": 1, //是否为主键

"dim": "Customer", //维名

"destTable": "Customer" //目标维表

},

...

],

"fks": [{ //外键列表

"name": "fk1", //外键名称

"destTable": "Nation", //目标维表

"fields": ["NATIONKEY"] //外键字段,可多个

}],

"subTables": [{ //子表列表

"table":"Partsupp" //子表

}]

}],

"dims": [{ //维列表

"name": "Month", //维名称

"dt": "4", //时间维类型

"exp": "", //格式化表达式

"table": "Month", //维源表

"field": "Month", //维源字段

"destLevels": [{ //维层

"name": "Year", //层名称

"dest": "Year.Year", //目标维

"formula": "int(?/100)" //计算函数

}]

}],

"annexTables": [ //同维表

[{

"name": "Customer",

"pks": ["CUSTKEY"]

}, {

"name": "CustomerAdd",

"pks": ["CUSTKEY"]

}]

]

}

有了这些元数据信息,在WEB页面里就可以设计、实现易用的可视化查询操作了。

强调一下,这套操作方案只是按照通用功能简单设计,不一定直接适用于特定行业的信息化平台,但相信在了解了DQL模型的敏捷查询能力后,就容易基于它改造、或重新设计实现出自己的可视化数据平台。

2、查询界面概览

/raqsoft/dql/jsp/dqlQuery.jsp实现了WEB界面做可视化DQL查询,下面初步认识一下页面的基本布局,分为三部分:

上部是功能按钮,依次为执行撤销、重做、保存、打开,最右侧按钮是执行查询;

左侧是数据结构树,展示所有可选的表,字段,可以展开多层的外键关联树,点击表、字段后就选出到右侧主查询区了;

右侧主查询区显示选出的字段、设置查询条件;如果选出维字段和汇总字段,将会生成分组汇总DQL;如果涉及多个汇总表,按照相同维对齐,那页面会把每个汇总表,以及它们与维的对应关系都清晰的展现出来,最终生成多表关联DQL

32png

下面把DQL实践:元数据与语法中的几个DQL示例尝试用界面自动生成,详细地了解查询功能:

3、单表查询

1DQL示例2—广义字段

按照顺序从Orders表点击需要的字段:

331png

选出字段自动生成的别名不一定合适,可以点击修改:

332png

再点击执行查询,就弹出结果页面/raqsoft/dql/jsp/queryResult.jsp,能看到自动生成的DQL语句:

..

2DQL示例3—按维/维层分组汇总

直接选择字段会查询出字段原始值;鼠标指到某字段上时,还可以选求和、平均、计数、最大、最小等五种汇总方式,从而查询出该字段的汇总值:

333png

执行生成的DQL,查看结果:

..

3、主子表

子表汇总后的信息,可以认为是主表信息的扩展,看下面的Orders主表和Lineitem子表:

Orders.ORDERKEY

Orders.ORDERSTATUS

Orders@Lineitem.sum(QUANTITY)

Orders@Lineitem.min(DISCOUNT)

在界面中如下展现:

..

多表关联能力决定了查询的灵活度,DQL对表的关联关系做了更细致的分类,对不同关联类型做了针对性处理,最大化地实现自动化查询。无论在DQL语法中,还是可视化界面中,模型高度一致,非专业的普通用户理解起来没有思维障碍。

上面这三种DQL查询看上去是单表查询,实际上会自动关联涉及到的多个数据表。

4、对齐关联

除了上面的隐式自动关联,也有需要用户理解的关联类型。涉及从多个表汇总数据时,DQL先对各个表分别做分组汇总,再按照维度值对齐式地关联到一起。

1、DQL示例4—()表按同维对齐汇总

Supplier表和Customer表不直接相关联,但它们都可以按照国家统计供应商数、客户数:

341png

执行生成的DQL,查看结果:

..

2、单表和自己对齐关联

Lineitem表要按照年份统计总数量,最小折扣,但要求总数量按照SHIPDATE的年份、最小折扣按照RECEIPTDATE的年份统计。Lineitem表里有多个日期,先按照它们不同的年维汇总后,再对齐关联,也就是Lineitem和自己关联了。

先随便选出一个年维字段汇总:

342png

然后再把最小折扣拖到Table2上:

343png

这样就形成两组不同的汇总了,下拉Table2的年维字段列表,切换成RECEIPTDATE的年:

344png

观察生成的DQL,形成了两组汇总,并且是按照不同的年维汇总的:

..

5、明细和汇总值上的过滤条件

查询时经常要过滤明细数据,需要设置过滤条件;

如果做了分组汇总,可能会进一步还要对汇总值提过滤条件,筛选出想要的分组;

这两种过滤操作和SQL语法一致,分别为WHEREHAVING,界面上如下设置:

345png

执行生成的DQL,查看结果:

..

6、源代码

com.scudata.web.dql.esprocdql.DqlUtil.java封装了DQL JDBC查询,对查询结果进行初步整理;

/raqsoft/dql/jsp/dqlQuery.jsp,可视化查询的主界面;

/raqsoft/dql/jsp/queryResult.jsp,显示查询结果界面;

根据DQL元数据的JSON串生成元数据树,设置主查询区的操作都是用Javascript代码实现的,这些代码集中在/raqsoft/dql/js/query.js里;

/raqsoft/dql/img/下是一些依赖的图片,/raqsoft/dql/css/下是层叠样式表文件;

可以下载这些源代码自己尝试下。

四、后记

该文着重介绍了基于DQL能力,在WEB上如何实现灵活的可视化查询,读者要思考在自己的数据平台中如何利用这些DQL能力,思考清楚了,下一步用怎样的WEB技术实现,如何设计适用自己业务的界面,也就水到渠成了。