Spaces:
Sleeping
Sleeping
Add Browse data panel (table dropdown + row preview)
Browse files
app.py
CHANGED
|
@@ -223,6 +223,47 @@ def schema_map_html(uploaded_db: str | None) -> str:
|
|
| 223 |
return f"<p>Could not read database: {html.escape(str(exc))}</p>"
|
| 224 |
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
def prefetch_weights() -> None:
|
| 227 |
"""Download weights to disk at startup (CPU, no GPU timer).
|
| 228 |
|
|
@@ -303,6 +344,10 @@ with gr.Blocks(title="LocalSQL") as demo:
|
|
| 303 |
with gr.Accordion("What's in this database? (tables, columns, keys)", open=True):
|
| 304 |
schema_map = gr.HTML()
|
| 305 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
with gr.Row():
|
| 307 |
with gr.Column(scale=1):
|
| 308 |
uploaded_db = gr.File(
|
|
@@ -346,10 +391,15 @@ with gr.Blocks(title="LocalSQL") as demo:
|
|
| 346 |
inputs=[question, evidence, run_sql, uploaded_db],
|
| 347 |
outputs=[sql, rows, status, schema, reasoning],
|
| 348 |
)
|
| 349 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
for trigger in (uploaded_db.change, demo.load):
|
| 351 |
trigger(schema_map_html, inputs=[uploaded_db], outputs=[schema_map])
|
| 352 |
trigger(show_schema, inputs=[uploaded_db], outputs=[schema])
|
|
|
|
| 353 |
|
| 354 |
|
| 355 |
ensure_sample_db()
|
|
|
|
| 223 |
return f"<p>Could not read database: {html.escape(str(exc))}</p>"
|
| 224 |
|
| 225 |
|
| 226 |
+
def _list_tables(db_path: str) -> list[str]:
|
| 227 |
+
con = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
|
| 228 |
+
tables = [
|
| 229 |
+
r[0] for r in con.execute(
|
| 230 |
+
"SELECT name FROM sqlite_master WHERE type='table' "
|
| 231 |
+
"AND name NOT LIKE 'sqlite_%' ORDER BY name"
|
| 232 |
+
)
|
| 233 |
+
]
|
| 234 |
+
con.close()
|
| 235 |
+
return tables
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
def browse_table(uploaded_db: str | None, table_name: str | None) -> pd.DataFrame:
|
| 239 |
+
"""Return the first rows of the selected table (read-only preview)."""
|
| 240 |
+
if not table_name:
|
| 241 |
+
return pd.DataFrame()
|
| 242 |
+
db_path, err = resolve_db(uploaded_db)
|
| 243 |
+
if err:
|
| 244 |
+
return pd.DataFrame()
|
| 245 |
+
try:
|
| 246 |
+
con = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
|
| 247 |
+
# table_name comes from our own dropdown (populated from sqlite_master).
|
| 248 |
+
cur = con.execute(f'SELECT * FROM "{table_name}" LIMIT 10')
|
| 249 |
+
cols = [d[0] for d in cur.description]
|
| 250 |
+
data = cur.fetchall()
|
| 251 |
+
con.close()
|
| 252 |
+
return pd.DataFrame(data, columns=cols)
|
| 253 |
+
except Exception: # noqa: BLE001
|
| 254 |
+
return pd.DataFrame()
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def refresh_browser(uploaded_db: str | None):
|
| 258 |
+
"""Repopulate the table dropdown and preview the first table's rows."""
|
| 259 |
+
db_path, err = resolve_db(uploaded_db)
|
| 260 |
+
if err:
|
| 261 |
+
return gr.update(choices=[], value=None), pd.DataFrame()
|
| 262 |
+
tables = _list_tables(db_path)
|
| 263 |
+
first = tables[0] if tables else None
|
| 264 |
+
return gr.update(choices=tables, value=first), browse_table(uploaded_db, first)
|
| 265 |
+
|
| 266 |
+
|
| 267 |
def prefetch_weights() -> None:
|
| 268 |
"""Download weights to disk at startup (CPU, no GPU timer).
|
| 269 |
|
|
|
|
| 344 |
with gr.Accordion("What's in this database? (tables, columns, keys)", open=True):
|
| 345 |
schema_map = gr.HTML()
|
| 346 |
|
| 347 |
+
with gr.Accordion("Browse data (peek at rows)", open=False):
|
| 348 |
+
table_dropdown = gr.Dropdown(label="Table", choices=[], interactive=True)
|
| 349 |
+
browse_df = gr.Dataframe(label="First 10 rows", interactive=False)
|
| 350 |
+
|
| 351 |
with gr.Row():
|
| 352 |
with gr.Column(scale=1):
|
| 353 |
uploaded_db = gr.File(
|
|
|
|
| 391 |
inputs=[question, evidence, run_sql, uploaded_db],
|
| 392 |
outputs=[sql, rows, status, schema, reasoning],
|
| 393 |
)
|
| 394 |
+
# Preview rows when the user picks a table.
|
| 395 |
+
table_dropdown.change(
|
| 396 |
+
browse_table, inputs=[uploaded_db, table_dropdown], outputs=[browse_df]
|
| 397 |
+
)
|
| 398 |
+
# Refresh the schema map, raw DDL, and table browser for the selected database.
|
| 399 |
for trigger in (uploaded_db.change, demo.load):
|
| 400 |
trigger(schema_map_html, inputs=[uploaded_db], outputs=[schema_map])
|
| 401 |
trigger(show_schema, inputs=[uploaded_db], outputs=[schema])
|
| 402 |
+
trigger(refresh_browser, inputs=[uploaded_db], outputs=[table_dropdown, browse_df])
|
| 403 |
|
| 404 |
|
| 405 |
ensure_sample_db()
|