-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #153 from octoenergy/add_databricks_db_client
Add databricks db client
- Loading branch information
Showing
8 changed files
with
131 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
"""Databricks query client.""" | ||
from typing import Dict | ||
import urllib | ||
|
||
from sqlalchemy.engine import Connection, create_engine | ||
|
||
from . import sqla_client | ||
|
||
|
||
class DatabricksClient(sqla_client.SQLAlchemyClient): | ||
"""Databricks client, backed by a pyodbc + SQLAlchemy connection.""" | ||
|
||
def _connect(self) -> Connection: | ||
odbc_connection_map = self._build_odbc_connection_dict() | ||
connection_url = build_odbc_connection_string(**odbc_connection_map) | ||
|
||
if self.engine is None: | ||
self.engine = create_engine( | ||
f"mssql+pyodbc:///?odbc_connect={connection_url}" | ||
) | ||
return self.engine.connect() | ||
|
||
def _build_odbc_connection_dict(self) -> Dict: | ||
odbc_connection_string_map = { | ||
"UID": "token", | ||
"PWD": self.username, | ||
"HOST": self.host, | ||
"PORT": self.port, | ||
"Schema": self.database, | ||
} | ||
if self.url.query: | ||
odbc_connection_string_map.update(self.url.query) | ||
return odbc_connection_string_map | ||
|
||
|
||
def build_odbc_connection_string(**kwargs) -> str: | ||
"""Build a url formatted odbc connection string from kwargs.""" | ||
connection_url = ";".join([f"{k}={v}" for k, v in kwargs.items()]) | ||
return urllib.parse.quote(connection_url) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import pytest | ||
from tentaclio.clients.databricks_client import ( | ||
build_odbc_connection_string, | ||
DatabricksClient, | ||
) | ||
from typing import Dict | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"url, expected", | ||
[ | ||
( | ||
"databricks+pyodbc://my_t0k3n@db_host:443/database", | ||
{ | ||
"UID": "token", | ||
"PWD": "my_t0k3n", | ||
"HOST": "db_host", | ||
"PORT": 443, | ||
"Schema": "database", | ||
} | ||
), | ||
( | ||
"databricks+pyodbc://my_t0k3n@db_host:443/", | ||
{ | ||
"UID": "token", | ||
"PWD": "my_t0k3n", | ||
"HOST": "db_host", | ||
"PORT": 443, | ||
"Schema": "", | ||
} | ||
), | ||
( | ||
"databricks+pyodbc://my_t0k3n@db_host:443/database" | ||
"?HTTPPath=sql/protocolv1/&AuthMech=3&SparkServerType=3" | ||
"&ThriftTransport=2&SSL=1&IgnoreTransactions=1&DRIVER=/path/to/driver", | ||
{ | ||
"UID": "token", | ||
"PWD": "my_t0k3n", | ||
"HOST": "db_host", | ||
"PORT": 443, | ||
"Schema": "database", | ||
"AuthMech": '3', | ||
"HTTPPath": "sql/protocolv1/", | ||
"IgnoreTransactions": "1", | ||
"SSL": "1", | ||
"ThriftTransport": "2", | ||
"SparkServerType": "3", | ||
"DRIVER": "/path/to/driver" | ||
} | ||
) | ||
], | ||
) | ||
def test_build_odbc_connection_dict(url: str, expected: Dict): | ||
output = DatabricksClient(url)._build_odbc_connection_dict() | ||
assert output == expected | ||
|
||
|
||
def test_build_odbc_connection_string(): | ||
conn_dict = {"UID": "user", "PWD": "p@ssw0rd", "HOST": "db_host", "PORT": 443} | ||
output = build_odbc_connection_string(**conn_dict) | ||
assert output == "UID%3Duser%3BPWD%3Dp%40ssw0rd%3BHOST%3Ddb_host%3BPORT%3D443" |