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()
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()
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}')```
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.
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"