fix(datasources): MySQL browser race + slow row counts
When switching source engine, the sample effect fired with the previous engine selected object (e.g. public.sales_orders against MySQL), surfacing "Table hr.sales_orders doesn't exist". Track which engine the selected object belongs to and only sample when it matches the active engine, plus guard against stale responses overwriting newer ones. Row-count for the browser used an exact count(*) which full-scanned huge tables (~30s on 24M rows). Use planner/statistics estimates and only run a time-bounded exact count for small (<=50k) tables.
This commit is contained in:
+30
-4
@@ -693,8 +693,20 @@ def _table_row_count(engine: str, object_name: str) -> int | None:
|
||||
)
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(f'SELECT count(*) FROM "{schema}"."{table}"')
|
||||
return int(cur.fetchone()[0])
|
||||
# Planner estimate first; only do a (bounded) exact count for small
|
||||
# tables so huge tables don't trigger a slow full scan.
|
||||
cur.execute("SELECT reltuples::bigint FROM pg_class WHERE oid = %s::regclass", (f'"{schema}"."{table}"',))
|
||||
row = cur.fetchone()
|
||||
est = int(row[0]) if row and row[0] is not None and row[0] >= 0 else 0
|
||||
if est <= 50000:
|
||||
try:
|
||||
cur.execute("SET LOCAL statement_timeout = 4000")
|
||||
cur.execute(f'SELECT count(*) FROM "{schema}"."{table}"')
|
||||
return int(cur.fetchone()[0])
|
||||
except Exception:
|
||||
conn.rollback()
|
||||
return est
|
||||
return est
|
||||
finally:
|
||||
conn.close()
|
||||
if engine == "mysql":
|
||||
@@ -705,8 +717,22 @@ def _table_row_count(engine: str, object_name: str) -> int | None:
|
||||
)
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(f"SELECT count(*) FROM `{table}`")
|
||||
return int(cur.fetchone()[0])
|
||||
# Fast estimate from statistics; only do a (bounded) exact count for
|
||||
# small tables to avoid full scans on huge ones (e.g. 24M rows).
|
||||
cur.execute(
|
||||
"SELECT table_rows FROM information_schema.tables WHERE table_schema=%s AND table_name=%s",
|
||||
(schema, table),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
est = int(row[0]) if row and row[0] is not None else 0
|
||||
if est <= 50000:
|
||||
try:
|
||||
cur.execute("SET SESSION MAX_EXECUTION_TIME=4000")
|
||||
cur.execute(f"SELECT count(*) FROM `{table}`")
|
||||
return int(cur.fetchone()[0])
|
||||
except Exception:
|
||||
return est
|
||||
return est
|
||||
finally:
|
||||
conn.close()
|
||||
if engine == "mongodb":
|
||||
|
||||
Reference in New Issue
Block a user