From 5b4e8e504ea072219c2d83697bd176172c06d498 Mon Sep 17 00:00:00 2001 From: singingbush Date: Mon, 30 Oct 2023 17:31:05 +0000 Subject: [PATCH] add Db2 to docker compose and update README --- README.md | 13 ++++++++++++- docker-compose.yml | 21 +++++++++++++++++++++ test/source/main.d | 36 +++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index eebecc1..b89085c 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,20 @@ There does seem to be some interest in updating the code in *etc.c.odbc* to supp If you plan to use odbc with the latest D compiler (2.106 and above) then *etc.c.odbc* may be the best choice for you. If your project needs to support multiple compiler releases and you don't want your builds to fail on compiler updates, consider using this package. +## Database support + +ODBC (Open Database Connectivity) is a widley supported standard that is used by all the major RDBMS vendors such as Microsoft SQL Server, IBM Db2. SAP ASE (previously Sybase), Oracle, PostgreSQL, MySQL (and MariaDB), and possibly more. That said, vendors have differing capabilities so potentially ODBC drivers may not implement all features. Some may even have non-standard features. Therefore efforts are made to test the code using different combinations of drivers and databases. As some providers are not as convenient for CI builds as others the level of testing may vary. + + - **Microsoft SQL Server** : Supported. Tests are run against SQL Server during CI + - **Oracle** : Limited Support. Some testing done locally using [Oracle's OCR database image](https://container-registry.oracle.com/ords/ocr/ba/database) (requires Oracle account) + - **IBM Db2** : Limited Support. Some testing done locally using `ibmcom/db2:latest` (the newer `icr.io/db2_community/db2` image from [IBM Cloud® Container Registry](https://cloud.ibm.com/registry/) requires IBM account) + - **Postgres** : Should work, not currently tested. + - **MySQL / MariaDB** : Should work, not currently tested. + - **SAP ASE (Adaptive Server Enterprise, formerly Sybase)** : Should work. Could do with testing using the [SAP ASE 90 day trial](https://www.sap.com/products/technology-platform/sybase-ase/trial.html) or their cloud offering. + ## Installing a driver -You'll need to have an ODBC driver installed. For example to use SQL Server you can use _msodbcsql17_, _msodbcsql18_ or _FreeTDS_. +You'll need to have an ODBC driver installed. For example to use SQL Server you can use _msodbcsql17_, _msodbcsql18_ or _FreeTDS_. For [IBM Db2](https://www.ibm.com/products/db2/database) (and possibly [SAP ASE](https://www.sap.com/uk/products/technology-platform/sybase-ase.html)) you'll likely need to download required libraries from the respective companies and install them manually. ### Windows diff --git a/docker-compose.yml b/docker-compose.yml index eeee2ef..4e93bd1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - MSSQL_PID=Developer - SA_PASSWORD=bbk4k77JKH88g54 - ACCEPT_EULA=Y + # You'll need to have a login for https://container-registry.oracle.com and have # accepted their terms & conditions. Then prior to running 'docker-compose up -d' you # will need to run 'docker login container-registry.oracle.com' to pull the Oracle Database image. @@ -25,3 +26,23 @@ services: # - DB_PASSWD=bbk4k77JKH88g54 # - USERNAME=travis # - PASSWORD=bbk4k77JKH88g54 + + ## IBM Db2 is currently on Docker Hub but moving to ICR + ## After container start please give a little time for the db to be ready for incoming connections + ## Note that in the connection string for Db2 you need to specify a value for Authentication, eg; 'Authentication=SERVER;' + db2: + image: ibmcom/db2:11.5.8.0 + ## Moving forward IBM will publish images to IBM Cloud Registry (which requires an IBM account) + ## image: icr.io/db2_community/db2 + privileged: true + restart: always + ports: ['50000:50000'] + environment: + - LICENSE=accept + - DB2INSTANCE=db2inst1 # (default: db2inst1) (this will be username) + - DB2INST1_PASSWORD=bbk4k77JKH88g54 + - DBNAME=odbc_tst # optional + # - ENABLE_ORACLE_COMPATIBILITY=true + - PERSISTENT_HOME=false + - ARCHIVE_LOGS=false # (default: true) disabling archive logs reduces start up time + - AUTOCONFIG=false # (default: true) disabling auto configuration on the instance and database reduces start up time diff --git a/test/source/main.d b/test/source/main.d index 78a23b8..49b4beb 100644 --- a/test/source/main.d +++ b/test/source/main.d @@ -110,7 +110,7 @@ int main(string[] argv) { writefln(" - DBMS Version:\t%s", fromStringz(cast(char*) dbms_ver)); SQLUSMALLINT max_concur_act; - SQLGetInfo(conn, SQL_MAX_CONCURRENT_ACTIVITIES, cast(SQLPOINTER)max_concur_act, max_concur_act.sizeof, null); + ret = SQLGetInfo(conn, SQL_MAX_CONCURRENT_ACTIVITIES, cast(SQLPOINTER)max_concur_act, max_concur_act.sizeof, null); if (max_concur_act == 0) { writeln("SQLGetData - SQL_MAX_CONCURRENT_ACTIVITIES = no limit or undefined"); @@ -118,20 +118,24 @@ int main(string[] argv) { writefln("SQLGetData - SQL_MAX_CONCURRENT_ACTIVITIES = %u", max_concur_act); } - SQLUINTEGER getdata_support; - SQLGetInfo(conn, SQL_GETDATA_EXTENSIONS, cast(SQLPOINTER)getdata_support, getdata_support.sizeof, null); - - if (getdata_support & SQL_GD_ANY_ORDER) { - writeln("SQLGetData - columns can be retrieved in any order"); - } else { - writeln("SQLGetData - columns must be retrieved in order"); - } + // todo: I've commented out this section for now as it causes a segmentation fault when using Db2. Needs further investigation and if possible a fix + // SQLUINTEGER getdata_support; + // if(SQL_SUCCEEDED(ret = SQLGetInfo(conn, SQL_GETDATA_EXTENSIONS, cast(SQLPOINTER)getdata_support, getdata_support.sizeof, null))) { + // if (getdata_support & SQL_GD_ANY_ORDER) { + // writeln("SQLGetData - columns can be retrieved in any order"); + // } else { + // writeln("SQLGetData - columns must be retrieved in order"); + // } - if (getdata_support & SQL_GD_ANY_COLUMN) { - writeln("SQLGetData - can retrieve columns before last bound one"); - } else { - writeln("SQLGetData - columns must be retrieved after last bound one"); - } + // if (getdata_support & SQL_GD_ANY_COLUMN) { + // writeln("SQLGetData - can retrieve columns before last bound one"); + // } else { + // writeln("SQLGetData - columns must be retrieved after last bound one"); + // } + // } else { + // errorCount++; + // stderr.writeln("SQLGetData - unable to use SQL_GETDATA_EXTENSIONS"); + // } @@ -176,6 +180,8 @@ int main(string[] argv) { SQLFreeHandle(SQL_HANDLE_ENV, env); } else { stderr.writefln("Failed to connect to database. SQL return code: %d", ret); + + writeErrorMessage(); return 1; } @@ -189,7 +195,7 @@ int main(string[] argv) { } // If a call to SQL reurns -1 (SQL_ERROR) then this function can be called to get the error message -void writeErrorMessage(SQLHSTMT stmt) { +void writeErrorMessage(SQLHSTMT stmt = null) { SQLCHAR[6] sqlstate; // A string of 5 characters terminated by a null character. The first 2 characters indicate error class; the next 3 indicate subclass. SQLINTEGER nativeError; SQLCHAR[SQL_MAX_MESSAGE_LENGTH] messageText;