Retrieving data from IBM DB2 using pyodbc and the related error - python-3.x

I confirm that I have gone through multiple posts in StackOverflow with respect to similar problem, still stuck with the below problem, hence posting to seek guidance/pointers.
Following is the code
import pypyodbc as pyodbc
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
conn_str = 'DRIVER={' + config['db2']['driver'] + '};' \
+ 'SERVER=' + config['db2']['server'] + ';' \
+ 'DATABASE=' + config['db2']['database'] + ';' \
+ 'UID=' + config['db2']['uid'] + ';' \
+ 'PWD=' + config['db2']['password']
print(conn_str)
connection = pyodbc.connect(
conn_str
)
cur = connection.cursor()
cur.execute('SELECT col_1, col_2 FROM schema.table_name LIMIT 2')
for row in cur:
print (row)
Output from code execution
[connect string output]
DRIVER={'IBM i Access ODBC Driver 64-bit'};SERVER='hostname';DATABASE='database';UID='userid';PWD='password'
[error from executing the code]
raise Error(state,err_text)
pypyodbc.Error: ('IM002', '[IM002] [unixODBC][Driver Manager]Data source name not found, and no default driver specified')
Configuration file
$ cat config.ini
[db2]
driver = 'IBM i Access ODBC Driver 64-bit'
server = 'hostname'
database = 'database'
uid = 'userid'
password = 'password'
Output of ODBC installer and uninstaller command
odbcinst -j
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/useradmin/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
cat /etc/odbcinst.ini
[PostgreSQL]
Description=ODBC for PostgreSQL
Driver=/usr/lib/psqlodbcw.so
Setup=/usr/lib/libodbcpsqlS.so
Driver64=/usr/lib64/psqlodbcw.so
Setup64=/usr/lib64/libodbcpsqlS.so
FileUsage=1
[MySQL]
Description=ODBC for MySQL
Driver=/usr/lib/libmyodbc5.so
Setup=/usr/lib/libodbcmyS.so
Driver64=/usr/lib64/libmyodbc5.so
Setup64=/usr/lib64/libodbcmyS.so
FileUsage=1
[IBM i Access ODBC Driver]
Description=IBM i Access for Linux ODBC Driver
Driver=/opt/ibm/iaccess/lib/libcwbodbc.so
Setup=/opt/ibm/iaccess/lib/libcwbodbcs.so
Driver64=/opt/ibm/iaccess/lib64/libcwbodbc.so
Setup64=/opt/ibm/iaccess/lib64/libcwbodbcs.so
Threading=0
DontDLClose=1
UsageCount=1
[IBM i Access ODBC Driver 64-bit]
Description=IBM i Access for Linux 64-bit ODBC Driver
Driver=/opt/ibm/iaccess/lib64/libcwbodbc.so
Setup=/opt/ibm/iaccess/lib64/libcwbodbcs.so
Threading=0
DontDLClose=1
UsageCount=1
$ cat ~/.odbc.ini
[db2]
Driver = IBM i Access ODBC Driver 64-bit
DATABASE = 'database'
SYSTEM = hostname
HOSTNAME = hostname
PORT = 446
PROTOCOL = TCPIP
$ isql db2 $username $password -v
[08001][unixODBC][IBM][System i Access ODBC Driver]The specified database can not be accessed at this time.
[ISQL]ERROR: Could not SQLConnect
I have double checked and confirm that there is no typo with driver name "IBM i Access ODBC Driver 64-bit"
OS information
x86_64 GNU/Linux
Any pointers/guidance on how to debug the issue, please?

I think you are confusing the schema name with the database name.
Odds are you can omit the database name completely (or leave it empty string and let it default to *SYSBAS). Instead, you can specify the DefaultLibraries argument.
See the IBM doc here for info on the valid connection string (and odbc.ini) keywords.
Similarly, you can omit the PORT, PROTOCOL, and HOSTNAME keywords, as they're not supported by this driver.
That will leave you with an odbc.ini that looks as simple as this:
[db2]
Driver = IBM i Access ODBC Driver 64-bit
DefaultLibraries = 'database'
SYSTEM = hostname

Related

Receiving `Login timeout expired` when connecting to a serverless Azure Synapse SQL pool using `ActiveDirectoryPassword` authentication and pyodbc

I'm trying to run Azure Synapse SQL queries on a serverless SQL pool from Python using pyodbc. I'm trying to authenticate with an Azure Active Directory user. Here is my code:
import pyodbc
driver = '{ODBC Driver 18 for SQL Server}'
server = '<server>'
db = '<db>'
username = '<user>#<domain>#<synapse-workspace>'
password = '<password>'
with pyodbc.connect(
f'Driver={driver};Server=tcp:{server},1433;Database={db};Uid={username};Pwd={password};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;Authentication=ActiveDirectoryPassword;') as conn:
cursor = conn.cursor()
cursor.execute('SELECT TOP 100 * from foo')
row = cursor.fetchone()
while row:
print(row)
row = cursor.fetchone()
I get the following error:
pyodbc.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 18 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')
I'm pretty stumped because I'm able to sign in with the same username and password to both the Synapse Workspace and Azure Data Studio.
Any ideas what's wrong? Or any ideas for how to get a more helpful error message?
UPDATE:
I increased the timeout and received a different error:
pyodbc.Error: ('FA004', '[FA004] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Failed to authenticate the user \'<user>#<domain>#<synapse-workspace>\' in Active Directory (Authentication option is \'ActiveDirectoryPassword\').\nError code 0xA190; state 41360\n{"ver":"1.0","account_type":"Unknown","cloud_instance_name":"microsoftonline.com","cloud_audience_urn":"urn:federation:MicrosoftOnline"}\nUnknown account type. (0) (SQLDriverConnect)')
The time out error is generally come because the server is not responding.
Two solutions you can try extending connection timeout period in connection string.
-- The default value is 30 seconds.
-- A value of 0 means to wait indefinitely and never time out.
Try by Downgrade the ODBC driver version to 17 or 13.
Or the work around is to use the ActiveDirectoryInteractive
import pyodbc
server = '<servername>'
database = '<database name>'
username = '<loginId>'
password = '<password>'
driver= '{ODBC Driver 18 for SQL Server}'
Authentication='ActiveDirectoryInteractive'
cnxn = pyodbc.connect(
'DRIVER='+driver+
';PORT=1433;SERVER='+server+
';PORT=1443;DATABASE='+database+
';UID='+username+
';Authentication='+Authentication)
cursor = cnxn.cursor()

pypyodbc "Login timeout expired" error on linux, same code working on windows machine

I have the below pypyodbc code running on my windows computer connecting to a windows server with a SQL database.
When I use the exact same code on a linux machine in the same network I receive a
pypyodbc.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired')
error. The suggestions in this Stackoverflow question or this question did not help. The query on the windows machine is successful, I can ping the windows server from both machines. Both machines run the pypyodbc version 1.3.5
import pypyodbc as pyodbc
server = "XXX.XXX.X.XX\INSTANCENAME"
port = "1433"
database = "DATABASENAME"
user = "sa"
PWD = "XXX"
tcon = "no"
driver = '{ODBC Driver 17 for SQL Server}'
con = pyodbc.connect(Trusted_Connection=tcon, driver = driver, server = server , database = database, UID=user, PWD=PWD)
crsr = con.cursor()
crsr.execute("SELECT * FROM dbo.DigiCenter where Number = '"+str(123456) +"'")
for row in crsr.fetchall():
print(row)
con.close()

schemacrawler oracle-plugin not returning SYNONYMS

I am using schema-crawler to crawl an oracle database (Retrieve Table/Synonym metadata including columns details and foreign keys)
INFO:
-- generated by: SchemaCrawler 16.15.1
-- database: Oracle Oracle Database 12c Standard Edition Release 12.1.0.2.0 - 64bit Production
-- driver: Oracle JDBC driver 19.3.0.0.0
-- JVM system: AdoptOpenJDK OpenJDK 64-Bit Server VM 1.8.0_292-b10
In my POM I have included the oracle plugin
<groupId>us.fatehi</groupId>
<artifactId>schemacrawler-oracle</artifactId>
<version>${schemacrawler.version}</version>
</dependency>
I have set the following in LimitOptionsBuilder & LoadOptions to crawl Schema:
limitOptionsBuilder.tableTypes("TABLE,VIEW,SYNONYM");
limitOptionsBuilder.includeAllSynonyms();
final SchemaCrawlerOptions options = SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
.withLimitOptions(limitOptionsBuilder.toOptions())
.withLoadOptions(loadOptionsBuilder.toOptions());
Catalog cat = SchemaCrawlerUtility.getCatalog(conn, options);
In the Catalog output, I don't see any SYNONYMS. I did some debugging and it seems that the the query that is sent to the database to get the tables is using DBA_TAB_COMMENTS, which unfortunately does not contain SYNONYM information. In oracle synonyms are stored in ALL_SYNONYMS
SELECT
NULL AS TABLE_CAT,
TABLES.OWNER AS TABLE_SCHEM,
TABLES.TABLE_NAME AS TABLE_NAME,
TABLES.TABLE_TYPE AS TABLE_TYPE,
TABLES.COMMENTS AS REMARKS
FROM
DBA_TAB_COMMENTS TABLES
WHERE
TABLES.OWNER NOT IN
('ANONYMOUS', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP',
'EXFSYS', 'FLOWS_30000', 'FLOWS_FILES', 'GSMADMIN_INTERNAL', 'IX', 'LBACSYS',
'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OE', 'OLAPSYS', 'ORACLE_OCM',
'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH',
'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR',
'SYS', 'SYSMAN', 'SYSTEM', 'TSMSYS', 'WKPROXY', 'WKSYS', 'WK_TEST',
'WMSYS', 'XDB', 'XS$NULL', 'RDSADMIN')
AND NOT REGEXP_LIKE(TABLES.OWNER, '^APEX_[0-9]{6}$')
AND NOT REGEXP_LIKE(TABLES.OWNER, '^FLOWS_[0-9]{5,6}$')
AND REGEXP_LIKE(TABLES.OWNER, '${schemas}')
AND TABLES.TABLE_NAME NOT LIKE 'BIN$%'
AND NOT REGEXP_LIKE(TABLES.TABLE_NAME, '^(SYS_IOT|MDOS|MDRS|MDRT|MDOT|MDXT)_.*$')
UNION ALL
SELECT
NULL AS TABLE_CAT,
MVIEWS.OWNER AS TABLE_SCHEM,
MVIEWS.MVIEW_NAME AS TABLE_NAME,
'MATERIALIZED VIEW' AS TABLE_TYPE,
MVIEWS.COMMENTS AS REMARKS
FROM
DBA_MVIEW_COMMENTS MVIEWS
WHERE
MVIEWS.OWNER NOT IN
('ANONYMOUS', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP',
'EXFSYS', 'FLOWS_30000', 'FLOWS_FILES', 'GSMADMIN_INTERNAL', 'IX', 'LBACSYS',
'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OE', 'OLAPSYS', 'ORACLE_OCM',
'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH',
'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR',
'SYS', 'SYSMAN', 'SYSTEM', 'TSMSYS', 'WKPROXY', 'WKSYS', 'WK_TEST',
'WMSYS', 'XDB', 'XS$NULL', 'RDSADMIN')
AND NOT REGEXP_LIKE(MVIEWS.OWNER, '^APEX_[0-9]{6}$')
AND NOT REGEXP_LIKE(MVIEWS.OWNER, '^FLOWS_[0-9]{5,6}$')
AND REGEXP_LIKE(MVIEWS.OWNER, '${schemas}')```

How to test jdbc connection in python?

I tried using the py4j referred Connecting and testing a JDBC driver from Python
from py4j.JavaGateway import java_gateway
# Open JVM interface with the JDBC Jar
jdbc_jar_path = 'C:\Program Files\CData\CData JDBC Driver for MongoDB 2019\lib\cdata.jdbc.mongodb.jar'
gateway = java_gateway(classpath=jdbc_jar_path)
# Load the JDBC Jar
jdbc_class = "cdata.jdbc.mongodb.MongoDBDriver"
gateway.jvm.class.forName(jdbc_class)
# Initiate connection
jdbc_uri = "jdbc:mongodb:Server=127.0.0.1;Port=27017;Database=EmployeeDB;"
con = gateway.jvm.DriverManager.getConnection(jdbc_uri)
# Run a query
sql = "select * from Employees"
stmt = con.createStatement(sql)
rs = stmt.executeQuery()
while rs.next():
rs.getInt(1)
rs.getFloat(2)
.
.
rs.close()
stmt.close()
Getting error as
File "assignment.py", line 9
gateway.jvm.class.forName(jdbc_class)
^
SyntaxError: invalid syntax
Try replacing
gateway.jvm.class.forName(jdbc_class)
with
gateway.jvm.Class.forName(jdbc_class)
(i.e. capitalise the c in class.)
Class.forName is the Java method you want to call here. (Note also how the D in DriverManager is capitalised in gateway.jvm.DriverManager.getConnection(...).) However, the syntax error is caused because class is a Python keyword. You can't have a local variable, or a function or method, named class.

how to connect to oracle db using OCCI on linux?

I am trying to connect to oracle database (PHK01200_SECCOMPAS_APPL.WORLD) from linux box (RHEL 6) using OCCI (Oracle instantclient version 12.1 (latest)). I am getting tns error while connection. tnsping works fine though. Could you please help in setting up correct configuration. What am I missing here?
Output
[m499757#hkl20030996 bin]$ ./sqlplus toolkit/******#PHK01200_SECCOMPAS_APPL.WORLD
SQL*Plus: Release 10.2.0.3.0 - Production on Thu May 22 12:32:56 2014
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
ERROR:
ORA-12505: TNS:listener does not currently know of SID given in connect
descriptor
Config details:
Tnsnames.ora
PHK01200_SECCOMPAS_APPL.WORLD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = PHKLOD2001-xxxx.xx.hedani.net)(PORT = 1522))
)
(CONNECT_DATA =
(SID = PHK01200_SECCOMPAS_APPL)
)
)
Odbc.ini
[PHK01200_SECCOMPAS_APPL]
Driver = OracleODBC-12g
DSN = OracleODBC-12g
ServerName = PHK01200_SECCOMPAS_APPL.WORLD
UserID = toolkit
Password = ******
Odbcinst.ini
[OracleODBC-12g]
Description = Oracle ODBC driver for Oracle 12g
Driver = /cs/gat/share/oracle/64/instantclient/libsqora.so.12.1
Driver64 = /cs/gat/share/oracle/64/instantclient/libsqora.so.12.1
FileUsage = 1
Driver Logging = 7
LDAP.ora
# LDAP.ORA Configuration
# Generated by Oracle configuration tools.
DEFAULT_ADMIN_CONTEXT = "dc=uk,dc=csfb,dc=com"
#DEFAULT_ADMIN_CONTEXT = "dc=corpny,dc=csfb,dc=com"
DIRECTORY_SERVERS= (oid_ldap_server_sg.sg.csfb.com:1522:1524,oid_ldap_server_ny.corpny.csfb.com:1522:1524,oid_l dap_server_ln.csfp.co.uk:1522:1524)
DIRECTORY_SERVER_TYPE = OID
sqlnet.ora
AUTOMATIC_IPC = OFF
TRACE_LEVEL_CLIENT = OFF
TCP.NODELAY = YES
NAMES.DIRECTORY_PATH= (TNSNAMES,LDAP,ONAMES,HOSTNAME)
names.default_domain = world
name.default_zone = world
Below wokred.
./sqlplus toolkit/******#PHK01200
And in my python script I used below connection string
"DRIVER={OracleODBC-12g}; Dbq=PHKLOD2001-scan.ap.hedani.net:1522/PHK01200_SECCOMPAS_APPL.WORLD"

Resources