2008-12-02 37 views
32

Hiện tại, chúng tôi đang tìm cách triển khai trình điều khiển odbc của riêng mình để cho phép nhiều ứng dụng khác nhau có thể kết nối với ứng dụng của chúng tôi dưới dạng nguồn dữ liệu. Ngay bây giờ, chúng tôi đang cố gắng cân nhắc các tùy chọn phát triển trình điều khiển của riêng mình thành thông số triển khai, lớn, hoặc bằng SDK cho phép các lập trình viên 'điền vào' các phần dữ liệu cụ thể và cho phép mức trừu tượng cao hơn.Tạo trình điều khiển ODBC tùy chỉnh

Có ai khác đã triển khai trình điều khiển odbc tùy chỉnh không? Bạn đã gặp phải những cạm bẫy nào? Bạn thấy lợi ích gì khi tự mình làm? Làm thế nào nhiều manhours bạn sẽ gần đúng nó đã? Bạn đã sử dụng SDK chưa, và nếu có, bạn thấy lợi ích/nhược điểm nào từ phương pháp đó?

Mọi nhận xét và câu trả lời sẽ được đánh giá cao. Cảm ơn!

EDIT: Chúng tôi đang cố gắng để duy trì tính di động với mã của chúng tôi, được viết bằng C.

+2

Tôi có thể hỏi - Tại sao bạn chọn xây dựng trình điều khiển odbc tùy chỉnh, (công nghệ 15 tuổi) thay vì trình điều khiển oleDb (công nghệ 10 tuổi) hoặc quản lý mã ADO, nhà cung cấp dữ liệu Net (8 tuổi và hiện tại) ?? –

+0

Mã của chúng tôi được viết bằng C và chúng tôi muốn nó duy trì tính di động. –

+0

Ngoài ra, khá một vài hệ thống (MSQuery và Access đến tâm trí) đã được thiết kế thực sự với ODBC trong tâm trí và làm việc tốt nhất với điều này. – ConcernedOfTunbridgeWells

Trả lời

7

Tôi chưa, nhưng tôi đã từng phỏng vấn tại một công ty đã thực hiện chính xác điều này. Họ đã thực hiện một sản phẩm 4GL/DBMS được gọi là AMPS của cùng một loại kiến ​​trúc như MUMPS - một cơ sở dữ liệu phân cấp với 4GL tích hợp (toàn bộ thể loại của các hệ thống này xuất hiện trong thập niên 1970). Họ có khá nhiều cơ sở mã di sản đáng kể và khách hàng có nhu cầu kết nối với nó bằng cách sử dụng MS Access.

Nhà phát triển chính đã phỏng vấn tôi đã chia sẻ một số câu chuyện về chiến tranh về điều này. Rõ ràng nó là cực kỳ đau đớn để làm và không nên được đưa nhẹ. Tuy nhiên, họ đã thực sự thành công trong việc thực hiện nó. Một thay thế để thực hiện điều này là cung cấp sản phẩm dữ liệu mart/BI (dọc theo dòng SAP BW) trình bày dữ liệu ứng dụng của bạn trong cơ sở dữ liệu bên ngoài và đưa nó vào một định dạng thân thiện hơn như sao hoặc bông tuyết lược đồ.

Điều này sẽ không hỗ trợ truy cập thời gian thực, nhưng có thể dễ dàng thực hiện hơn (và quan trọng hơn là duy trì) so với trình điều khiển ODBC. Nếu các yêu cầu truy cập thời gian thực của bạn là có thể dự đoán hợp lý và có giới hạn, bạn có thể có thể đưa ra một API dịch vụ web để hỗ trợ các yêu cầu này.

5

Tôi đã không được thực hiện một trình điều khiển ODBC, nhưng chỉ muốn đưa ra một gợi ý mà bạn có thể bắt đầu với một mở thực hiện nguồn và thêm các tùy chỉnh của riêng bạn. Điều này có thể giúp bạn bắt đầu nhanh hơn rất nhiều.

Có ít nhất hai lựa chọn:

  • unixODBC được cấp phép theo LGPL, có nghĩa là nếu bạn sửa đổi mã bạn cần phải thực hiện những thay đổi của bạn mã nguồn mở.

  • iODBC được cấp phép theo LGPL hoặc New BSD, theo lựa chọn của bạn. BSD mới cho phép bạn thực hiện sửa đổi mà không cần thực hiện sửa đổi nguồn mở của bạn.

Tuy nhiên, không rõ nếu các gói này chạy trên Windows, trái với chạy trên UNIX/Linux với API ứng dụng khách phù hợp với ODBC chuẩn. Bạn không nói bạn đang sử dụng nền tảng nào, vì vậy tôi không biết điều này có liên quan đến bạn hay không.

9

Trình điều khiển ODBC rất phức tạp - quyết định viết một tài khoản không nên được xem nhẹ.Xem xét các trình điều khiển nguồn mở hiện có là một cách tiếp cận tốt cho các ví dụ nhưng hầu hết đều có những thiếu sót mà bạn có thể không muốn mô phỏng :) Các API giống nhau bất kể nền tảng hệ điều hành. FreeTDS cho MSSQL/Sybase có một trong những triển khai trình điều khiển ODBC nguồn mở tốt hơn mà tôi đã nhìn thấy.

Nếu bạn kiểm soát các ứng dụng bạn có thể lấy đi với việc thực hiện những gì có thể chỉ là một tập hợp con rất nhỏ của spec trong một khoảng thời gian hợp lý. Để sử dụng trong một môi trường mục đích chung có thể yêu cầu nỗ lực nhiều hơn một chút để có được quyền. Off đỉnh đầu của tôi ngoài việc chỉ đơn giản là thực hiện hàng chục bao bọc các cuộc gọi bạn cũng sẽ phải thực hiện:

  • chức năng truy cập Metadata
  • ODBC cú pháp truy vấn cụ thể phân tích cú pháp
  • SQLSTATE Lỗi ánh xạ thông điệp
  • nhiều byte/Character set marshalling
  • Hỗ trợ phiên bản ODBC 2,3 - thông báo lỗi/ánh xạ chức năng
  • Cursors
  • Giao diện người dùng cấu hình DM để quản lý nguồn dữ liệu
+2

Làm thế nào về trình điều khiển ODBC MySQL, hoặc trình điều khiển ODBC Postgresql? Có ai có ý kiến ​​về chất lượng mã của các trình điều khiển này không? – codeape

15

Một tùy chọn khác: Thay vì tạo trình điều khiển ODBC, hãy thực hiện kết thúc giao tiếp với giao thức dây mà cơ sở dữ liệu khác (Postgresql hoặc MySQL sử dụng).

Người dùng của bạn sau đó có thể tải xuống và sử dụng trình điều khiển ODBC Postgresql.

Cơ sở dữ liệu back-end chính xác mà bạn chọn để mô phỏng có lẽ phụ thuộc nhiều nhất vào định dạng giao thức dây được ghi nhận như thế nào.

Cả hai PostgresMySQL có tài liệu phong nha cho các giao thức máy khách-máy chủ của họ.

Ví dụ đơn giản Python 2.7 của phần cuối máy chủ hiểu các phần của giao thức dây Postgresql ở dưới. Kịch bản ví dụ tạo ra một máy chủ lắng nghe cổng 9876. Tôi có thể sử dụng lệnh psql -h localhost -p 9876 để kết nối với máy chủ. Bất kỳ truy vấn nào được thực hiện sẽ trả về một tập kết quả với các cột abc và def và hai hàng, tất cả các giá trị NULL.

Đọc tài liệu Postgresql và sử dụng một cái gì đó như wireshark để kiểm tra lưu lượng giao thức thực sẽ làm cho việc triển khai kết thúc trở lại tương thích với Postgresql khá đơn giản.

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() 

Ví dụ phiên dòng lệnh psql:

[~] 
$ 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=> 

tài xế Một ODBC mà nói giao thức PostgreSQL nên làm việc cũng như (nhưng tôi đã không thử nó chưa).

+1

Hiện đang cố gắng để làm cho nó hoạt động với một trình điều khiển ODBC và có vẻ đầy hứa hẹn. Tôi chỉ cần phải loại bỏ phần SSLRequest lúc bắt đầu và trả lại kết quả tương ứng với những gì trình điều khiển ODBC yêu cầu, tôi có thể xem tất cả các yêu cầu đến bằng :) – Gregory

+1

Câu trả lời hay! Đây là những gì cơ sở dữ liệu h2 làm: http://www.h2database.com/html/advanced.html#odbc_driver –

0

Bài đăng này hiện đã cũ, nhưng đáng nói rằng nếu bạn cần có trình điều khiển ODBC, bạn có thể sử dụng SDK như sau: http://www.simba.com/drivers/simba-engine-sdk/ Nó sẽ chăm sóc hầu hết các điểm được nêu trong các câu trả lời khác và cung cấp cho bạn một giao diện được đơn giản hóa nhiều để thực hiện.

Tôi tình cờ làm việc cho Simba, vì vậy tôi hơi thiên vị, nhưng việc sử dụng SDK sẽ giúp bạn dễ dàng tạo trình điều khiển ODBC cho bất kỳ điều gì bạn đang cố gắng làm. Bạn có thể nhận được một cái gì đó đi trong 5 ngày nếu bạn hơi thành thạo trong mã hóa.

Một trong các bài đăng khác đề xuất unixODBC hoặc iODBC làm điểm xuất phát, tuy nhiên điều này sẽ không hoạt động. Điều quan trọng là phải nhận ra sự khác biệt giữa một người quản lý lái xe (unixODBC, iODBC, vv) và một người lái xe. Trình quản lý trình điều khiển đóng vai trò là người trung gian giữa ứng dụng và trình điều khiển, loại bỏ nhu cầu liên kết trực tiếp với người lái xe.

Bạn có thể bắt đầu với trình điều khiển Postgres hoặc MySQL làm điểm bắt đầu và chia nhỏ chúng để sử dụng cơ sở dữ liệu của riêng bạn, tuy nhiên đây không phải là một nhiệm vụ tầm thường. Việc tạo ra một trình điều khiển từ đầu thậm chí còn khó khăn hơn và có thể sẽ có chi phí bảo trì liên tục (và cao hơn dự kiến). Miễn là bạn nhận thức được chi phí của phương pháp này, nó cũng có thể tồn tại.

1

Nhập bổ sung về điều này: Xin lưu ý rằng không còn phức tạp nữa khi sử dụng SDK. Như kyle đã đề xuất ở trên, việc xây dựng một trình điều khiển odbc tùy chỉnh không còn phức tạp nữa. Với một giải pháp như OpenAccess 99% mã đã được cung cấp và bạn chỉ thực hiện 12 chức năng. Bạn có thể chọn bất kỳ ngôn ngữ nào sau đây để viết mã bằng: C/C++, Java, .NET, C#, ABL hoặc 4GL. Để biết thêm thông tin về cách bắt đầu, hãy đọc blog này: https://www.progress.com/blogs/quick-guide-build-custom-odbc-driver-in-java-or-c

+0

Điều này trông giống như một giải pháp thương mại (đúng với tôi nếu tôi sai). Có phiên bản "cộng đồng" có sẵn không? Bạn có thể đề xuất giải pháp nguồn mở không? –

+0

Bạn có thể giúp tôi hiểu trường hợp sử dụng mà bạn đang cố gắng giải quyết không? – user6641561

+0

Đây là một lợi ích của người có sở thích hơn là trường hợp sử dụng cụ thể tại thời điểm này. Tôi bị bối rối bởi việc thiếu các công cụ nguồn mở trong miền này và đây là trường hợp bất khả tri. Có một số dịch vụ đắt tiền ra có âm thanh như họ thực sự làm công việc mã nguồn mở nhưng khi bạn cố gắng để bắt đầu, bạn thấy rằng có một thẻ giá khổng lồ trên đó. –

Các vấn đề liên quan