如何定制一个基于REST Service的ODBC驱动程序

本文介绍了如何基于REST Service定制一个ODBC驱动程序,以满足数据分析工具如Tableau、Excel对ODBC数据源的需求。文章详细讲解了ODBC驱动的实现原理,包括ODBC架构、API实现、驱动安装与注册、Descriptors和REST API的数据交互。通过实例代码展示了ODBC客户端行为,指导开发者如何从零开始构建ODBC Driver,提供了一种将REST Server与ODBC Driver结合的方法,以处理客户端与自定义SQL引擎的数据交互。
摘要由CSDN通过智能技术生成

Author:  Ma, Hongbin

概要

REST Service能够帮助开发者以简单统一的接口向终端用户提供服务。然而数据分析的应用场景中,一些成熟的数据分析工具(例如Tableau, Excel等)要求用户提供ODBC数据源,在这种情况下,REST Service并不能满足用户所有对数据的使用需求。本文从实现的角度详细介绍了如何在现有REST Service的基础上,完成一个定制ODBC驱动程序的开发。文章侧重介绍了ODBC驱动程序的实现原理,结合代码详细说明了ODBC与REST Service之间的数据交互,并在文章末尾介绍了ODBC客户端程序调用ODBC API的原理,以及实际开发中调试环境的搭建。

可能受益的读者

目前主流的数据分析工具,例如Tableau,Microstrategy,excel都只能够ODBC Driver,来访问底层的数据源。也就是说,在开发数据库或者数据仓库的过程中,即使我们已经实现了符合SQL规范的数据访问接口,哪怕提供了自己的JDBC驱动程序,仍然无法保证数据用户能够有效地使用我们的数据。为此,我们需要额外地为数据源定制一个ODBC Driver。

如果你的数据源恰好是类似MongoDB,Hbase这样的常见数据库产品,你或许可以考虑直接从购买一些商业产品,例如Simba ODBC Driver来一劳永逸地解决你的需求,但是将意味着不小的开支。更难办的情况是你的数据源并不是那么主流,还没有任何可以直接购买的驱动程序可以适用于它,那么定制一个自己的ODBC Driver可能是你最好的选择。即使你是一个对ODBC Driver一无所知的开发者,本文也将给你带来或多或少的帮助。

我们的处境

简单地说,我们团队用java开发了一个特别的SQL引擎。在项目初期我们只有JDBC驱动程序,还有一个用于服务于网页客户端的REST Server,但是我们没有ODBC 驱动,因此大多数的客户并不能真正地使用我们的产品完成他们地工作。

为了解决这个问题,我们设计了如下图的解决方案:我们使用REST Server统一地接受来自所有客户端的请求,包括网页客户端和使用ODBC Driver的客户端。REST Server中使用JDBC驱动来访问我们的数据库。当然如果你的客户端就是一个java程序,你完全可以直接通过JDBC来访问我们的数据库,从而节省这些步骤带来的开销。这张图片中并未展示这种情况。

在客户端,我们深度定制了一个专有的ODBC Driver,它向上层的应用程序提供了标准的ODBC API,封装所有实现的逻辑。在底层实现上,它调用C++的REST库,将应用程序发送过来的SQL查询请求封装成REST请求,发送给我们的REST Server,并在得到结果后,再以符合ODBC规范的方式,返回给上层的应用程序。

从Hello World开始

对于从来没有接触过ODBC的开发者来说,了解一个ODBC客户端的行为有助于理解定制一个ODBC驱动需要实现哪些具体的API。下图中展示了一个简单的ODBC客户端程序的实现,每一行代码都配有详细的注释解释它的行为,通读代码,不难拥有一个直观的理解。为了简化代码,我们省略了所有错误检查的代码。所有的SQLXXX格式的函数,都是ODBC定义的标准API。

我们将这段程序分成了五块区域,分别标记为A~E。A区域和B区域依次初始化了三个与ODBC相关的句柄,分别是:

Environment handle (hEnv): 包含一个或者多个Connection handle。同时,一些全局的信息也包含在内,例如客户端所需要的ODBC版本,以及环境级别的诊断信息。

Connection handle (hConn):代表了一个对DBMS/数据源的连接,包含了连接级别的信息,例如连接的超时时间,隔离级别,以及连接级别的诊断信息。

Statement handle (hStmt):可以将它看做是某个具体的查询请求,例如 SELECT * FROM employee。

值得一提的是ODBC规范只定义了数据源以何种方式暴露数据访问的接口,但是并没有规定如何实现,这也包括三类句柄的具体实现。事实上,在代码中这三类句柄都通过SQLHANDLE类型来传递,而SQLHANDLE本质上是一个void *类型,指向我们自定义的相应的结构体。

ODBC为应用程序提供了一系列的C语言风格的API来支持访问查询。不同于面向对象语言的驱动程序,使用ODBC驱动程序的应用程序需要为将要返回的数据提前准备好内存区域,从这个角度说,ODBC的任务是正确地将用户需要的数据,搬运到用户指定的内存区域之中(可能带有一些数据转化,例如如果应用程序需要支持Unicode,那么ODBC Driver可能需要将char类型的源数据转化为wchar类型)。下图的A区域中初始化了一系列的句柄和变量,其中第305~307行就在程序的栈上开辟了这样一些用作缓存的内存区域。事实上,在E区域,我们传入了变量x和i的引用,因此我们可以把第308~309行的两个数值变量也看作是这样存储返回结果的内存区域。

在区域C中,我们调用SQLDriverConnect函数,同时传入hConn句柄和连接数据源所需要的用户名,密码,驱动名称等信息。我们在ODBC Driver的实现中,完成对hConn的一系列赋值操作(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值