master
go 113 lines 2.92 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build !windows && cgo
4
5 package dbdriver
6
7 import (
8 "fmt"
9 "strings"
10
11 _ "github.com/alexbrainman/odbc"
12 )
13
14 func init() {
15 // Try to register ODBC driver with panic recovery
16 defer func() {
17 if r := recover(); r != nil {
18 // ODBC libraries not found or incompatible
19 Register("odbc", &Driver{
20 Name: "odbc",
21 Description: "ODBC driver (unixODBC libraries not found or incompatible)",
22 Available: false,
23 RequiresCGO: true,
24 RequiresLibs: []string{"unixODBC", "IBM i Access ODBC Driver"},
25 DSNFormat: "Driver={IBM i Access ODBC Driver};System=host;Uid=user;Pwd=pass",
26 })
27 return
28 }
29 }()
30
31 // Test if ODBC driver is actually available by trying to use it
32 available := testODBCAvailability()
33
34 Register("odbc", &Driver{
35 Name: "odbc",
36 Description: "ODBC driver (requires unixODBC and database-specific ODBC driver)",
37 Available: available,
38 RequiresCGO: true,
39 RequiresLibs: []string{"unixODBC", "IBM i Access ODBC Driver"},
40 DSNFormat: "Driver={IBM i Access ODBC Driver};System=host;Uid=user;Pwd=pass",
41 })
42 }
43
44 // testODBCAvailability tests if ODBC is actually available
45 func testODBCAvailability() bool {
46 defer func() {
47 if recover() != nil {
48 // ODBC not available
49 }
50 }()
51
52 // ODBC availability is tested at runtime during connection attempts
53 // The alexbrainman/odbc driver will handle library availability automatically
54 return true
55 }
56
57 // BuildODBCDSN creates an ODBC connection string
58 func BuildODBCDSN(config *ConnectionConfig) string {
59 // Determine the ODBC driver name
60 driverName := config.ODBCDriver
61 if driverName == "" {
62 if config.SystemType == "AS400" {
63 // Common AS/400 ODBC driver names
64 driverName = "IBM i Access ODBC Driver"
65 } else {
66 // Common DB2 ODBC driver names
67 driverName = "IBM DB2 ODBC DRIVER"
68 }
69 }
70
71 // Handle AS/400 specific format
72 if config.SystemType == "AS400" ||
73 strings.Contains(driverName, "AS400") ||
74 strings.Contains(driverName, "IBM i") {
75 // AS/400 style ODBC connection
76 dsn := fmt.Sprintf("Driver={%s};System=%s;Uid=%s;Pwd=%s;",
77 driverName, config.Hostname, config.Username, config.Password)
78
79 // AS/400 specific options
80 if config.Database != "" && config.Database != "*SYSBAS" {
81 dsn += fmt.Sprintf("DefaultLibraries=%s;", config.Database)
82 }
83
84 if config.Port != 0 && config.Port != 8471 {
85 dsn += fmt.Sprintf("Port=%d;", config.Port)
86 }
87
88 if config.UseSSL {
89 dsn += "SSL=1;"
90 }
91
92 return dsn
93 }
94
95 // Standard DB2 ODBC format
96 dsn := fmt.Sprintf("Driver={%s};", driverName)
97
98 if config.Database != "" {
99 dsn += fmt.Sprintf("Database=%s;", config.Database)
100 }
101
102 dsn += fmt.Sprintf("Hostname=%s;Port=%d;Protocol=TCPIP;Uid=%s;Pwd=%s;",
103 config.Hostname, config.Port, config.Username, config.Password)
104
105 if config.UseSSL {
106 dsn += "Security=SSL;"
107 if config.SSLServerCertPath != "" {
108 dsn += fmt.Sprintf("SSLServerCertificate=%s;", config.SSLServerCertPath)
109 }
110 }
111
112 return dsn
113 }