@@ -224,6 +224,7 @@ def _render_results_table_incremental(
224224 escape : bool ,
225225 row_limit : int ,
226226 render_token : int ,
227+ table_info : dict [str , Any ] | None = None ,
227228 ) -> None :
228229 initial_count = min (RESULTS_RENDER_INITIAL_ROWS , row_limit )
229230 initial_rows = rows [:initial_count ] if initial_count > 0 else []
@@ -269,9 +270,16 @@ def _render_results_table_incremental(
269270 pass
270271 if render_token == getattr (self , "_results_render_token" , 0 ):
271272 self ._replace_results_table_with_data (columns , rows , escape = escape )
273+ if table_info is not None :
274+ try :
275+ self .results_table .result_table_info = table_info
276+ except Exception :
277+ pass
272278 return
273279 if render_token != getattr (self , "_results_render_token" , 0 ):
274280 return
281+ if table_info is not None :
282+ table .result_table_info = table_info
275283 self ._replace_results_table_with_table (table )
276284 self ._schedule_results_render (
277285 table ,
@@ -291,6 +299,7 @@ async def _display_query_results(
291299 self ._last_result_columns = columns
292300 self ._last_result_rows = rows
293301 self ._last_result_row_count = row_count
302+ table_info = getattr (self , "_pending_result_table_info" , None )
294303
295304 # Switch to single result mode (in case we were showing stacked results)
296305 self ._show_single_result_mode ()
@@ -304,12 +313,15 @@ async def _display_query_results(
304313 escape = True ,
305314 row_limit = row_limit ,
306315 render_token = render_token ,
316+ table_info = table_info ,
307317 )
308318 else :
309319 render_rows = rows [:row_limit ] if row_limit else []
310320 table = self ._build_results_table (columns , render_rows , escape = True )
311321 if render_token != getattr (self , "_results_render_token" , 0 ):
312322 return
323+ if table_info is not None :
324+ table .result_table_info = table_info
313325 self ._replace_results_table_with_table (table )
314326
315327 time_str = format_duration_ms (elapsed_ms )
@@ -320,9 +332,15 @@ async def _display_query_results(
320332 )
321333 else :
322334 self .notify (f"Query returned { row_count } rows in { time_str } " )
335+ if table_info is not None :
336+ prime = getattr (self , "_prime_result_table_columns" , None )
337+ if callable (prime ):
338+ prime (table_info )
339+ self ._pending_result_table_info = None
323340
324341 def _display_non_query_result (self : QueryMixinHost , affected : int , elapsed_ms : float ) -> None :
325342 """Display non-query result (called on main thread)."""
343+ self ._pending_result_table_info = None
326344 self ._last_result_columns = ["Result" ]
327345 self ._last_result_rows = [(f"{ affected } row(s) affected" ,)]
328346 self ._last_result_row_count = 1
@@ -337,6 +355,7 @@ def _display_non_query_result(self: QueryMixinHost, affected: int, elapsed_ms: f
337355 def _display_query_error (self : QueryMixinHost , error_message : str ) -> None :
338356 """Display query error (called on main thread)."""
339357 self ._cancel_results_render ()
358+ self ._pending_result_table_info = None
340359 # notify(severity="error") handles displaying the error in results via _show_error_in_results
341360 self .notify (f"Query error: { error_message } " , severity = "error" )
342361
@@ -360,7 +379,17 @@ def _display_multi_statement_results(
360379
361380 # Add each result section
362381 for i , stmt_result in enumerate (multi_result .results ):
363- container .add_result_section (stmt_result , i , auto_collapse = auto_collapse )
382+ table_info = self ._infer_result_table_info (stmt_result .statement )
383+ if table_info is not None :
384+ prime = getattr (self , "_prime_result_table_columns" , None )
385+ if callable (prime ):
386+ prime (table_info )
387+ container .add_result_section (
388+ stmt_result ,
389+ i ,
390+ auto_collapse = auto_collapse ,
391+ table_info = table_info ,
392+ )
364393
365394 # Show the stacked results container, hide single result table
366395 self ._show_stacked_results_mode ()
@@ -378,6 +407,7 @@ def _display_multi_statement_results(
378407 )
379408 else :
380409 self .notify (f"Executed { total } statements in { time_str } " )
410+ self ._pending_result_table_info = None
381411
382412 def _get_stacked_results_container (self : QueryMixinHost ) -> Any :
383413 """Get the stacked results container."""
@@ -410,3 +440,30 @@ def _show_single_result_mode(self: QueryMixinHost) -> None:
410440 stacked .remove_class ("active" )
411441 except Exception :
412442 pass
443+
444+ def _infer_result_table_info (self : QueryMixinHost , sql : str ) -> dict [str , Any ] | None :
445+ """Best-effort inference of a single source table for query results."""
446+ from sqlit .domains .query .completion import extract_table_refs
447+
448+ refs = extract_table_refs (sql )
449+ if len (refs ) != 1 :
450+ return None
451+ ref = refs [0 ]
452+ schema = ref .schema
453+ name = ref .name
454+ database = None
455+ table_metadata = getattr (self , "_table_metadata" , {}) or {}
456+ key_candidates = [name .lower ()]
457+ if schema :
458+ key_candidates .insert (0 , f"{ schema } .{ name } " .lower ())
459+ for key in key_candidates :
460+ metadata = table_metadata .get (key )
461+ if metadata :
462+ schema , name , database = metadata
463+ break
464+ return {
465+ "database" : database ,
466+ "schema" : schema ,
467+ "name" : name ,
468+ "columns" : [],
469+ }
0 commit comments