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;
连接URL是jdbc: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 </span><input name="dataSource" value="<%=dataSource%>" type="text">
<br>
<span>DQL </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:
下面把《DQL实践:元数据与语法》中的几个DQL示例尝试用界面自动生成,详细地了解查询功能:
3、单表查询
1、DQL示例2—广义字段
按照顺序从Orders表点击需要的字段:
选出字段自动生成的别名不一定合适,可以点击修改:
再点击执行查询,就弹出结果页面/raqsoft/dql/jsp/queryResult.jsp,能看到自动生成的DQL语句:
2、DQL示例3—按维/维层分组汇总
直接选择字段会查询出字段原始值;鼠标指到某字段上时,还可以选求和、平均、计数、最大、最小等五种汇总方式,从而查询出该字段的汇总值:
执行生成的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表不直接相关联,但它们都可以按照国家统计供应商数、客户数:
执行生成的DQL,查看结果:
2、单表和自己对齐关联
Lineitem表要按照年份统计总数量,最小折扣,但要求总数量按照SHIPDATE的年份、最小折扣按照RECEIPTDATE的年份统计。Lineitem表里有多个日期,先按照它们不同的年维汇总后,再对齐关联,也就是Lineitem和自己关联了。
先随便选出一个年维字段汇总:
然后再把最小折扣拖到Table2上:
这样就形成两组不同的汇总了,下拉Table2的年维字段列表,切换成RECEIPTDATE的年:
观察生成的DQL,形成了两组汇总,并且是按照不同的年维汇总的:
5、明细和汇总值上的过滤条件
查询时经常要过滤明细数据,需要设置过滤条件;
如果做了分组汇总,可能会进一步还要对汇总值提过滤条件,筛选出想要的分组;
这两种过滤操作和SQL语法一致,分别为WHERE、HAVING,界面上如下设置:
执行生成的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技术实现,如何设计适用自己业务的界面,也就水到渠成了。
英文版