首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >创建自定义ODBC驱动程序

在我目前的工作中,我们希望实现我们自己的odbc驱动程序,以允许许多不同的应用程序作为数据源连接到我们自己的应用程序。现在,我们正在考虑为实现规范开发自己的驱动程序的选择,或者使用SDK,允许程序员“填充”特定于数据的部分,并允许更高级别的抽象。

还有其他人实现了自定义odbc驱动程序吗?你遇到了什么陷阱?你认为自己做这件事有什么好处?你大概花了多少个小时?您使用过SDK吗?如果是的话,您从这种方法中看到了哪些好处/缺点?

如有任何意见和答复,将不胜感激。谢谢!

编辑:我们试图用我们的代码来维护可移植性,这是用C语言编写的。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-12-02 10:59:04

我没有,但我曾经在一家公司面试过,这家公司正是这样做的。他们制作了一个名为AMPS的4GL/DBMS产品,其架构与腮腺炎相同--这是一个具有集成4GL的层次数据库(1970年代出现了一种完整的此类系统类型)。他们有相当多的遗留代码库,并且客户希望使用MS连接到它。

采访我的首席开发人员分享了一些有关这方面的战争故事。显然,这样做非常痛苦,不应该掉以轻心。然而,他们确实成功地实现了这一目标。

这样做的一个替代方法是提供一个数据集市/BI产品(类似于SAP BW),该产品在外部数据库中显示应用程序数据,并将其转换成更友好的格式,如星型或雪花模式。

这将受到不支持实时访问的影响,但可能比ODBC驱动程序更容易实现(更重要的是维护)。如果您的实时访问需求是合理的预测和限制,您可能会公开一个web服务API来支持这些访问。

票数 9
EN

Stack Overflow用户

发布于 2012-12-03 06:32:28

另一种选择:不是创建ODBC驱动程序,而是实现一个后端,该后端讨论另一个数据库(例如Postgresql或MySQL )使用的有线协议。

然后,用户可以下载并使用Postgresql驱动程序。

确切地说,您选择要模拟的后端数据库很可能最依赖于电线协议格式的文档记录得有多好。

波斯特格斯MySQL都有很好的客户端服务器协议文档。

下面是一个简单的Python2.7服务器后端示例,它可以理解PostgreSQL导线协议的部分内容。示例脚本创建一个监听端口9876的服务器。我可以使用命令psql -h localhost -p 9876连接到服务器。执行的任何查询都将返回包含abc和def列以及两行的结果集,所有值均为NULL。

读取Postgresql文档并使用类似于wireshark的工具来检查真正的协议通信量将使实现与Postgresql兼容的后端变得非常简单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import SocketServer
import struct

def char_to_hex(char):
    retval = hex(ord(char))
    if len(retval) == 4:
        return retval[-2:]
    else:
        assert len(retval) == 3
        return "0" + retval[-1]

def str_to_hex(inputstr):
    return " ".join(char_to_hex(char) for char in inputstr)

class Handler(SocketServer.BaseRequestHandler):
    def handle(self):
        print "handle()"
        self.read_SSLRequest()
        self.send_to_socket("N")

        self.read_StartupMessage()
        self.send_AuthenticationClearText()
        self.read_PasswordMessage()
        self.send_AuthenticationOK()
        self.send_ReadyForQuery()
        self.read_Query()
        self.send_queryresult()

    def send_queryresult(self):
        fieldnames = ['abc', 'def']
        HEADERFORMAT = "!cih"
        fields = ''.join(self.fieldname_msg(name) for name in fieldnames)
        rdheader = struct.pack(HEADERFORMAT, 'T', struct.calcsize(HEADERFORMAT) - 1 + len(fields), len(fieldnames))
        self.send_to_socket(rdheader + fields)

        rows = [[1, 2], [3, 4]]
        DRHEADER = "!cih"
        for row in rows:
            dr_data = struct.pack("!ii", -1, -1)
            dr_header = struct.pack(DRHEADER, 'D', struct.calcsize(DRHEADER) - 1 + len(dr_data), 2)
            self.send_to_socket(dr_header + dr_data)

        self.send_CommandComplete()
        self.send_ReadyForQuery()

    def send_CommandComplete(self):
        HFMT = "!ci"
        msg = "SELECT 2\x00"
        self.send_to_socket(struct.pack(HFMT, "C", struct.calcsize(HFMT) - 1 + len(msg)) + msg)

    def fieldname_msg(self, name):
        tableid = 0
        columnid = 0
        datatypeid = 23
        datatypesize = 4
        typemodifier = -1
        format_code = 0 # 0=text 1=binary
        return name + "\x00" + struct.pack("!ihihih", tableid, columnid, datatypeid, datatypesize, typemodifier, format_code)

    def read_socket(self):
        print "Trying recv..."
        data = self.request.recv(1024)
        print "Received {} bytes: {}".format(len(data), repr(data))
        print "Hex: {}".format(str_to_hex(data))
        return data

    def send_to_socket(self, data):
        print "Sending {} bytes: {}".format(len(data), repr(data))
        print "Hex: {}".format(str_to_hex(data))
        return self.request.sendall(data)

    def read_Query(self):
        data = self.read_socket()
        msgident, msglen = struct.unpack("!ci", data[0:5])
        assert msgident == "Q"
        print data[5:]


    def send_ReadyForQuery(self):
        self.send_to_socket(struct.pack("!cic", 'Z', 5, 'I'))

    def read_PasswordMessage(self):
        data = self.read_socket()
        b, msglen = struct.unpack("!ci", data[0:5])
        assert b == "p"
        print "Password: {}".format(data[5:])


    def read_SSLRequest(self):
        data = self.read_socket()
        msglen, sslcode = struct.unpack("!ii", data)
        assert msglen == 8
        assert sslcode == 80877103

    def read_StartupMessage(self):
        data = self.read_socket()
        msglen, protoversion = struct.unpack("!ii", data[0:8])
        print "msglen: {}, protoversion: {}".format(msglen, protoversion)
        assert msglen == len(data)
        parameters_string = data[8:]
        print parameters_string.split('\x00')

    def send_AuthenticationOK(self):
        self.send_to_socket(struct.pack("!cii", 'R', 8, 0))

    def send_AuthenticationClearText(self):
        self.send_to_socket(struct.pack("!cii", 'R', 8, 3))

if __name__ == "__main__":
    server = SocketServer.TCPServer(("localhost", 9876), Handler)
    try:
        server.serve_forever()
    except:
        server.shutdown()

示例命令行psql会话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[~]
$ psql -h localhost -p 9876
Password:
psql (9.1.6, server 0.0.0)
WARNING: psql version 9.1, server version 0.0.
         Some psql features might not work.
Type "help" for help.

codeape=> Select;
 abc | def
-----+-----
     |
     |
(2 rows)

codeape=>

使用Postgresql协议的ODBC驱动程序也应该可以工作(但我还没有试过)。

票数 29
EN

Stack Overflow用户

发布于 2008-12-02 11:38:21

ODBC驱动程序非常复杂--编写一个驱动程序的决定不应掉以轻心。回顾现有的开源驱动程序是一个很好的方法,但是大多数都有您可能不想模仿的短消息:) API是相同的,而不管操作系统平台如何。FreeTDS for MSSQL/Sybase有我见过的更好的开源ODBC驱动程序实现之一。

如果您控制应用程序,您可以在合理的时间内实现可能只是规范的一个非常小的子集。在通用环境中使用可能需要付出更多的努力才能得到正确的结果。除了简单地实现几十个包装器调用之外,您还必须实现:

  • 元数据访问功能
  • ODBC特定查询语法解析
  • SQLSTATE错误消息映射
  • 多字节/字符集编组
  • ODBC版本2,3支持错误消息/函数映射
  • 游标
  • 用于管理数据源的DM配置UI
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/335008

复制
相关文章
进阶mapbox GL之paint和filter
通过前面的文章初识mapbox GL我们对mapbox GL有了一个相对比较全面的认识,本节结合一些示例,重点讲述一下mapbox GL里面的filter和paint的用法。
牛老师讲GIS
2020/03/31
8.5K1
进阶mapbox GL之paint和filter
JavaScript 使用 for 循环时出现的问题
有一些项目组在定位问题的时候发现,在使用 “for(x in array)” 这样的写法的时候,在 IE 浏览器下,x 出现了非预期的值。
四火
2022/07/15
4K0
JavaScript 使用 for 循环时出现的问题
初识mapbox GL
最近由于项目的需求,借此机会对mapbox GL做了一个系统的学习,同时也对整个学习过程做一个记录,一方面留作自用,另一方面也希望看到此文的人在学习mapbox GL的时候,能够有所启发、有所收获。
牛老师讲GIS
2020/03/25
2.4K0
JavaScript 同步和异步的执行机制问题
今天做项目的时候遇到了一个问题,当我在请求完后端数据的时候,想去立刻打印出请求出来的信息时,怎么打印都是空的,但是出来这个请求方法之后他又有数值了,于是我很纳闷,研究了1个小时找出了原因。
wsuo
2020/09/22
8350
mapbox GL台风路径的播放实现
前面的文章中写了基于openlayers4的台风路径播放,最近用到mapbox GL,也要实现相似的功能,网上找了好久都没有找到,于是就放弃了“拿来主义”的想法,只能自己动手了。经过一下午的努力,终于有了一个雏形,在此分享出来,希望对你有用!
牛老师讲GIS
2020/03/23
1.7K0
mapbox GL台风路径的播放实现
protobuf基于java和javascript的使用
ProtoBuf 是google团队开发的用于高效存储和读取结构化数据的工具,google出品,必属精品。 目前最新版本为3。文档地址:https://developers.google.com/protocol-buffers/docs/proto3 相比于xml,json,protobuf压缩率更高,传输高效,自然很节省流量。 protobuf支持跨语言,貌似前后端使用java和JavaScript的众多吧。
陈灬大灬海
2021/03/17
2.1K0
Javascript创建对象的学习和使用
1 <html> 2 <head> 3 <meta charset="utf-8"> 4 <title>javascript对象的学习</title> 5 </head>
别先生
2017/12/29
1.5K0
Javascript创建对象的学习和使用
JavaScript面试问题:事件委托和this
JavaScript不仅门槛低,而且是一门有趣、功能强大和非常重要的语言。各行各业的人发现自己最混乱的选择是JavaSscript编程语言。由于有着各种各样的背景,所以不是每个人都对JavaScript及其基本原理有广泛的认识。通常来书,除非你去参加工作面试才会去思考为什么或者怎么做,否则JavaScript只是你工作的内容。 这个系类的目标是深入探讨JavaScript的一些概念和理论。主题来自于 Darcy Clarke的JavaScript典型面试问题列表。希望你不仅仅是为了答案而阅读完这篇文章,每一
前朝楚水
2018/04/02
1.3K0
javascript 变量、作用域和内存问题
一、基本类型和引用类型的值   1.基本类型和引用类型的值  基本类型值:指那些保存在栈内存中的简单数据,即这种值完全保存在内存中的一个位置,他们所占据的空间大小是固定的。 引用类型值:指那些保存在堆内存中的对象,这些类型的真正数据是保存在堆内存中的,而同时在栈内存中保存的只是一个指针,这个指针指向的是这个对象在堆内存中的一块地址。 基本类型的复制:基本类型在内存中占有的空间大小是固定的,复制的时候会重新在栈内存中开辟一块空间,是按值来访问的。 引用类型的复制:由于这种对象所占的大小是不固定的,是放在堆内
柴小智
2018/04/10
1K0
JavaScript——JavaScript的使用方式
1. 行内式(主要用于事件) <input type="button" name="" onclick="alert('ok!');"> 2. 内嵌式 <script type="text/javascript"> alert('ok!'); </script> 3. 外链式 <script type="text/javascript" src="js/index.js"></script> 4. 小结 JavaScript的使用方式有三种,分别是: 行内式 内嵌式 外链式
落雨
2022/03/31
29.8K0
【说站】javascript max和min的使用
以上就是javascript max和min的使用,希望对大家有所帮助。更多Javascript学习指路:Javascript
很酷的站长
2022/11/24
6310
【说站】javascript max和min的使用
make和new的使用问题
//两者都是在堆上分配内存,new执行之后返回的是指针类型的指针,创建之后把变量置为0值,make是用于引用类型(map,chan,slice)的创建,返回是引用类型的本身。
公众号-利志分享
2022/04/25
5960
JavaScript中的this指向问题
在JavaScript中,关键字 this 是一个特殊的对象,它在函数被调用时自动创建。通常用来指向当前执行的函数所属的对象。this 的值在函数的每次调用时可能会发生变化,具体取决于函数是如何被调用的。
九仞山
2023/10/14
2650
JavaScript !!的使用
第二、三种写法明显优于第一种,第二种写法相较第三种写法可以直接获取str是否为有效值的布尔值,有这种需求的用第二种更佳
听着music睡
2021/11/03
5470
前端-JavaScript的内存问题
一直以来,对于Js的内存空间这部分的知识概念有些模糊,最近在回顾一些知识点的时候,特地的对js的内存这部分知识加深了一下理解,比如基本类型数据和引用类型数据在js内存中是怎么回事?什么是按值传递和按引用传递?以及对作用域和闭包的理解等等。
grain先森
2019/03/29
1.1K0
前端-JavaScript的内存问题
JavaScript中的this指向问题
this一般指向的是调用它的对象,比如调用它的上下文是window对象,那就是指向window对象,如果调用它的上下文是某对象就是指向某对象……
全栈开发Dream
2021/05/12
1.1K0
JavaScript中的this指向问题
盘点JavaScript中getter()和setter()函数的使用
第一种是 数据属性。已经知道如何使用它们了。到目前为止,使用过的所有属性都是数据属性。
前端进阶者
2021/09/10
1.7K0
盘点JavaScript中getter()和setter()函数的使用
JavaScript 学习-47.export 和 import 的使用
前言 JavaScript 的每个.js文件都是独立的,在开发一个项目会有很多的.js文件,有些是公共的方法,可以单独放到一个.js文件中,其它的文件去调用公共方法。 但是,Javascript不是一种模块化编程语言,在es6以前,它是不支持类(class),所以也就没有”模块”(module)了。 export导出模块 在es6以前,还没有提出一套官方的规范,从社区和框架推广程度而言,目前通行的javascript模块规范有两种:CommonJS 和 AMD ES6标准发布后,module成为标准,标准使
上海-悠悠
2022/09/28
7520
JavaScript 学习-47.export 和 import 的使用
mapbox尝鲜值之云图动画
昨天收到了mapbox中国的推送,看到了mapboxgl的更新,此次更新版本加入了globa,终于有个球了,于是就迫不及待的今天想尝个鲜。
牛老师讲GIS
2022/09/01
1.5K0
mapbox尝鲜值之云图动画
javascript-this的指向的问题
javasript函数中this的指向一直都是许多编程入门新手的一个问题,老师把这个this的指向弄错误。下面我们可以来看看关于this指向的几种情况。
踏浪
2019/07/31
6320

相似问题

如何在Mapbox GL map.setFilter中使用`in`表达式

1330

mapbox gl setFilter by feature属性是一个数组

144

HBase addColumn和setFilter

13

Php,使用或在setFilter()

10

关于QSqlTableModel::setFilter

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文