|
| 1 | +--- |
| 2 | +sidebar_position: 1 |
| 3 | +--- |
| 4 | + |
| 5 | +# Connect an OLTP database |
| 6 | + |
| 7 | +This app connects to a [Databricks Lakebase](https://docs.databricks.com/aws/en/oltp/) OLTP database instance. Provide the instance name, database, schema, and table. |
| 8 | + |
| 9 | +## Code snippet |
| 10 | + |
| 11 | +```python title="app.py" |
| 12 | +import uuid |
| 13 | +import streamlit as st |
| 14 | +import pandas as pd |
| 15 | + |
| 16 | +from databricks.sdk import WorkspaceClient |
| 17 | + |
| 18 | +import psycopg |
| 19 | +from psycopg_pool import ConnectionPool |
| 20 | + |
| 21 | + |
| 22 | +w = WorkspaceClient() |
| 23 | + |
| 24 | + |
| 25 | +def _generate_token(instance_name: str) -> str: |
| 26 | + cred = w.database.generate_database_credential( |
| 27 | + request_id=str(uuid.uuid4()), instance_names=[instance_name] |
| 28 | + ) |
| 29 | + return cred.token |
| 30 | + |
| 31 | + |
| 32 | +class RotatingTokenConnection(psycopg.Connection): |
| 33 | + @classmethod |
| 34 | + def connect(cls, conninfo: str = "", **kwargs): |
| 35 | + instance_name = kwargs.pop("_instance_name") |
| 36 | + kwargs["password"] = _generate_token(instance_name) |
| 37 | + kwargs.setdefault("sslmode", "require") |
| 38 | + return super().connect(conninfo, **kwargs) |
| 39 | + |
| 40 | + |
| 41 | +@st.cache_resource |
| 42 | +def build_pool(instance_name: str, host: str, user: str, database: str) -> ConnectionPool: |
| 43 | + return ConnectionPool( |
| 44 | + conninfo=f"host={host} dbname={database} user={user}", |
| 45 | + connection_class=RotatingTokenConnection, |
| 46 | + kwargs={"_instance_name": instance_name}, |
| 47 | + min_size=1, |
| 48 | + max_size=10, |
| 49 | + open=True, |
| 50 | + ) |
| 51 | + |
| 52 | + |
| 53 | +def query_df(pool: ConnectionPool, sql: str) -> pd.DataFrame: |
| 54 | + with pool.connection() as conn: |
| 55 | + with conn.cursor() as cur: |
| 56 | + cur.execute(sql) |
| 57 | + cols = [d.name for d in cur.description] |
| 58 | + rows = cur.fetchall() |
| 59 | + |
| 60 | + return pd.DataFrame(rows, columns=cols) |
| 61 | + |
| 62 | + |
| 63 | +instance_name = "dbase_instance" |
| 64 | +database = "customer_database" |
| 65 | +table = "customer_core.customers_oltp" |
| 66 | +user = w.current_user.me().user_name |
| 67 | +host = w.database.get_database_instance(name=instance_name).read_write_dns |
| 68 | + |
| 69 | +pool = build_pool(instance_name, host, user, database) |
| 70 | +df = query_df(pool, f'SELECT * FROM {table} LIMIT 100') |
| 71 | +st.dataframe(df) |
| 72 | +``` |
| 73 | + |
| 74 | +:::info |
| 75 | + |
| 76 | +This sample uses Streamlit's [st.cache_resource](https://docs.streamlit.io/develop/concepts/architecture/caching#stcache_resource) to cache the database connection across users, sessions, and reruns. Use Streamlit's caching decorators to implement a caching strategy that works for your use case. |
| 77 | + |
| 78 | +::: |
| 79 | + |
| 80 | +## Resources |
| 81 | + |
| 82 | +- [Lakebase](https://docs.databricks.com/aws/en/oltp/) database instance (PostgreSQL). |
| 83 | +- Target PostgreSQL database/schema/table. |
| 84 | + |
| 85 | +## Permissions |
| 86 | + |
| 87 | +First, the database instance should be specified in your [**App resources**](https://docs.databricks.com/aws/en/dev-tools/databricks-apps/resources). |
| 88 | + |
| 89 | +Then, your [app service principal](https://docs.databricks.com/aws/en/dev-tools/databricks-apps/#how-does-databricks-apps-manage-authorization) needs the following permissions: |
| 90 | + |
| 91 | +GRANT CONNECT ON DATABASE databricks_postgres TO "099f0306-9e29-4a87-84c0-3046e4bcea02"; |
| 92 | +GRANT USAGE ON SCHEMA public TO "099f0306-9e29-4a87-84c0-3046e4bcea02"; |
| 93 | +GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE quotes_history TO "099f0306-9e29-4a87-84c0-3046e4bcea02"; |
| 94 | + |
| 95 | +See [this guide](https://docs.databricks.com/aws/en/oltp/pg-roles?language=PostgreSQL#create-postgres-roles-and-grant-privileges-for-databricks-identities) for more information. |
| 96 | + |
| 97 | +[This guide](https://learn.microsoft.com/en-us/azure/databricks/oltp/query/sql-editor#create-a-new-query) shows you how to query your Lakebase. |
| 98 | + |
| 99 | +## Dependencies |
| 100 | + |
| 101 | +- [Databricks SDK](https://pypi.org/project/databricks-sdk/) - `databricks-sdk` |
| 102 | +- [`psycopg[binary]`](https://pypi.org/project/psycopg/), [`psycopg-pool`](https://pypi.org/project/psycopg-pool/) |
| 103 | +- [Pandas](https://pypi.org/project/pandas/) - `pandas` |
| 104 | +- [Streamlit](https://pypi.org/project/streamlit/) - `streamlit` |
| 105 | + |
| 106 | +```python title="requirements.txt" |
| 107 | +databricks-sdk |
| 108 | +databricks-sql-connector |
| 109 | +pandas |
| 110 | +streamlit |
| 111 | +psycopg[binary] |
| 112 | +psycopg-pool |
| 113 | +``` |
0 commit comments