Skip to content

Commit 83be1c9

Browse files
authored
Merge pull request #11 from scottDBX1886/main
Modification to Table Read and Edit
2 parents 13e4aac + c4c1ac8 commit 83be1c9

File tree

4 files changed

+142
-33
lines changed

4 files changed

+142
-33
lines changed

streamlit/view_groups.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,16 @@
133133
},
134134
],
135135
},
136+
137+
{
138+
"title": "Unity Catalog",
139+
"views": [
140+
{
141+
"label": "Get Catalogs",
142+
"help": "Get meta data.",
143+
"page": "views/unity_catalog_get.py",
144+
"icon": ":material/lan:",
145+
},
146+
],
147+
}
136148
]

streamlit/views/embed_dashboard.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import streamlit as st
22
import streamlit.components.v1 as components
3+
import requests
4+
from databricks.sdk.core import Config
35

46
st.header("Data Visualization", divider=True)
57
st.subheader("AI/BI Dashboard")
@@ -12,13 +14,46 @@
1214

1315

1416
with tab_a:
15-
iframe_source = st.text_input(
16-
"Embed the dashboard:",
17-
placeholder="https://dbc-f0e9b24f-3d49.cloud.databricks.com/embed/dashboardsv3/01eff8112e9411cd930f0ae0d2c6b63d?o=37581543725667790",
18-
help="Copy and paste the URL from the dashboard UI Share -> Embed iframe.",
17+
18+
19+
cfg = Config()
20+
21+
host = cfg.host
22+
23+
token = list(cfg.authenticate().values())[0].split(" ")[1]
24+
url = f"{host}/api/2.0/lakeview/dashboards"
25+
headers = {
26+
"Authorization": f"Bearer {token}"
27+
}
28+
29+
response = requests.get(url, headers=headers)
30+
dashboards = response.json()
31+
dashboard_paths = {dashboard['display_name']: dashboard['dashboard_id'] for dashboard in dashboards['dashboards']}
32+
33+
published_dashboards = []
34+
35+
for dashboard in dashboards['dashboards']:
36+
dashboard_id = dashboard['dashboard_id']
37+
38+
published_url = f"{host}/api/2.0/lakeview/dashboards/{dashboard_id}/published"
39+
response = requests.get(published_url, headers=headers)
40+
41+
if response.status_code == 200:
42+
published_dashboards.append((dashboard['display_name'], dashboard['dashboard_id']))
43+
print( dashboard['display_name'] + ' ' + dashboard['dashboard_id'])
44+
final_published_dashboards = {k: v for k, v in published_dashboards }
45+
46+
#st.info(final_published_dashboards)
47+
iframe_source_temp = st.selectbox(
48+
"Select your AI/BI Dashboard:", [""] + list(final_published_dashboards.keys()),
49+
help="Dashboard list populated from your workspace using app service principal.",
1950
)
51+
52+
dashboard_id = final_published_dashboards.get(iframe_source_temp)
2053

21-
if iframe_source:
54+
if iframe_source_temp and iframe_source_temp != "":
55+
iframe_source = f"{host}/embed/dashboardsv3/{dashboard_id}"
56+
#st.info(iframe_source)
2257
components.iframe(src=iframe_source, width=700, height=600, scrolling=True)
2358

2459
with tab_b:

streamlit/views/tables_edit.py

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import streamlit as st
33
from databricks import sql
44
from databricks.sdk.core import Config
5+
from databricks.sdk import WorkspaceClient
56

67

78
st.header(body="Tables", divider=True)
@@ -14,6 +15,14 @@
1415

1516
cfg = Config()
1617

18+
w = WorkspaceClient()
19+
20+
warehouses = w.warehouses.list()
21+
22+
warehouse_paths = {wh.name: wh.odbc_params.path for wh in warehouses}
23+
24+
catalogs = w.catalogs.list()
25+
1726

1827
@st.cache_resource
1928
def get_connection(http_path):
@@ -24,12 +33,23 @@ def get_connection(http_path):
2433
)
2534

2635

27-
def read_table(table_name: str, conn) -> pd.DataFrame:
36+
def read_table(table_name, conn):
2837
with conn.cursor() as cursor:
29-
cursor.execute(f"SELECT * FROM {table_name}")
38+
query = f"SELECT * FROM {table_name}"
39+
cursor.execute(query)
3040
return cursor.fetchall_arrow().to_pandas()
3141

3242

43+
def get_schema_names(catalog_name):
44+
schemas = w.schemas.list(catalog_name=catalog_name)
45+
return [schema.name for schema in schemas]
46+
47+
48+
def get_table_names(catalog_name, schema_name):
49+
tables = w.tables.list(catalog_name=catalog_name, schema_name=schema_name)
50+
return [table.name for table in tables]
51+
52+
3353
def insert_overwrite_table(table_name: str, df: pd.DataFrame, conn):
3454
progress = st.empty()
3555
with conn.cursor() as cursor:
@@ -45,26 +65,40 @@ def insert_overwrite_table(table_name: str, df: pd.DataFrame, conn):
4565
tab_a, tab_b, tab_c = st.tabs(["**Try it**", "**Code snippet**", "**Requirements**"])
4666

4767
with tab_a:
48-
http_path_input = st.text_input(
49-
"Specify the HTTP Path to your Databricks SQL Warehouse:",
50-
placeholder="/sql/1.0/warehouses/xxxxxx",
68+
http_path_input = st.selectbox(
69+
"Select a SQL warehouse:", [""] + list(warehouse_paths.keys())
5170
)
5271

53-
table_name = st.text_input(
54-
"Specify a Catalog table name:", placeholder="catalog.schema.table"
72+
catalog_name = st.selectbox(
73+
"Select a catalog:", [""] + [catalog.name for catalog in catalogs]
5574
)
5675

57-
if http_path_input and table_name:
58-
conn = get_connection(http_path_input)
59-
original_df = read_table(table_name, conn)
60-
edited_df = st.data_editor(original_df, num_rows="dynamic", hide_index=True)
76+
if catalog_name and catalog_name != "":
77+
schema_names = get_schema_names(catalog_name)
78+
schema_name = st.selectbox("Select a schema:", [""] + schema_names)
79+
80+
if catalog_name and catalog_name != "" and schema_name and schema_name != "":
81+
table_names = get_table_names(catalog_name, schema_name)
82+
table_name = st.selectbox("Select a table:", [""] + table_names)
83+
84+
in_table_name = f"{catalog_name}.{schema_name}.{table_name}"
85+
86+
if (
87+
http_path_input
88+
and table_name
89+
and catalog_name
90+
and schema_name
91+
and table_name != ""
92+
):
93+
http_path = warehouse_paths[http_path_input]
94+
conn = get_connection(http_path)
95+
original_df = read_table(in_table_name, conn)
96+
edited_df = st.data_editor(original_df, num_rows="dynamic", hide_index=True)
6197

62-
df_diff = pd.concat([original_df, edited_df]).drop_duplicates(keep=False)
63-
if not df_diff.empty:
64-
if st.button("Save changes"):
65-
insert_overwrite_table(table_name, edited_df, conn)
66-
else:
67-
st.warning("Provide both the warehouse path and a table name to load data.")
98+
df_diff = pd.concat([original_df, edited_df]).drop_duplicates(keep=False)
99+
if not df_diff.empty:
100+
if st.button("Save changes"):
101+
insert_overwrite_table(in_table_name, edited_df, conn)
68102

69103

70104
with tab_b:
@@ -75,6 +109,7 @@ def insert_overwrite_table(table_name: str, df: pd.DataFrame, conn):
75109
from databricks import sql
76110
from databricks.sdk.core import Config
77111
112+
78113
cfg = Config() # Set the DATABRICKS_HOST environment variable when running locally
79114
80115

streamlit/views/tables_read.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import streamlit as st
22
from databricks import sql
33
from databricks.sdk.core import Config
4+
from databricks.sdk import WorkspaceClient
45

56
st.header(body="Tables", divider=True)
67
st.subheader("Read a table")
@@ -10,6 +11,14 @@
1011

1112
cfg = Config()
1213

14+
w = WorkspaceClient()
15+
16+
warehouses = w.warehouses.list()
17+
18+
warehouse_paths = {wh.name: wh.odbc_params.path for wh in warehouses}
19+
20+
catalogs = w.catalogs.list()
21+
1322

1423
@st.cache_resource
1524
def get_connection(http_path):
@@ -27,21 +36,41 @@ def read_table(table_name, conn):
2736
return cursor.fetchall_arrow().to_pandas()
2837

2938

39+
def get_schema_names(catalog_name):
40+
schemas = w.schemas.list(catalog_name=catalog_name)
41+
return [schema.name for schema in schemas]
42+
43+
44+
def get_table_names(catalog_name, schema_name):
45+
tables = w.tables.list(catalog_name=catalog_name, schema_name=schema_name)
46+
return [table.name for table in tables]
47+
48+
3049
tab_a, tab_b, tab_c = st.tabs(["**Try it**", "**Code snippet**", "**Requirements**"])
3150

3251
with tab_a:
33-
http_path_input = st.text_input(
34-
"Enter your Databricks HTTP Path:", placeholder="/sql/1.0/warehouses/xxxxxx"
52+
http_path_input = st.selectbox(
53+
"Select a SQL warehouse:", [""] + list(warehouse_paths.keys())
3554
)
3655

37-
table_name = st.text_input(
38-
"Specify a Unity Catalog table name:", placeholder="catalog.schema.table"
56+
catalog_name = st.selectbox(
57+
"Select a catalog:", [""] + [catalog.name for catalog in catalogs]
3958
)
4059

41-
if http_path_input and table_name:
42-
conn = get_connection(http_path_input)
43-
df = read_table(table_name, conn)
44-
st.dataframe(df)
60+
if catalog_name and catalog_name != "":
61+
schema_names = get_schema_names(catalog_name)
62+
schema_name = st.selectbox("Select a schema:", [""] + schema_names)
63+
64+
if catalog_name and catalog_name != "" and schema_name and schema_name != "":
65+
table_names = get_table_names(catalog_name, schema_name)
66+
table_name = st.selectbox("Select a table:", [""] + table_names)
67+
68+
if http_path_input and table_name and table_name != "":
69+
http_path = warehouse_paths[http_path_input]
70+
conn = get_connection(http_path)
71+
df = read_table(f"{catalog_name}.{schema_name}.{table_name}", conn)
72+
st.dataframe(df)
73+
4574

4675
with tab_b:
4776
st.code(
@@ -54,22 +83,20 @@ def read_table(table_name, conn):
5483
cfg = Config() # Set the DATABRICKS_HOST environment variable when running locally
5584
5685
57-
@st.cache_resource
86+
@st.cache_resource # connection is cached
5887
def get_connection(http_path):
5988
return sql.connect(
6089
server_hostname=cfg.host,
6190
http_path=http_path,
6291
credentials_provider=lambda: cfg.authenticate,
6392
)
6493
65-
6694
def read_table(table_name, conn):
6795
with conn.cursor() as cursor:
6896
query = f"SELECT * FROM {table_name}"
6997
cursor.execute(query)
7098
return cursor.fetchall_arrow().to_pandas()
7199
72-
73100
http_path_input = st.text_input(
74101
"Enter your Databricks HTTP Path:", placeholder="/sql/1.0/warehouses/xxxxxx"
75102
)

0 commit comments

Comments
 (0)