4141import bigframes .session .metrics
4242import bigframes .session .planner
4343import bigframes .session .temporary_storage
44+ from bigframes ._config import ComputeOptions
4445from bigframes .core import bq_data , compile , guid , identifiers , local_data , rewrite
4546from bigframes .core .compile .sqlglot import sql as sg_sql
4647from bigframes .core .compile .sqlglot import sqlglot_ir
@@ -183,6 +184,8 @@ def execute(
183184 array_value : bigframes .core .ArrayValue ,
184185 execution_spec : ex_spec .ExecutionSpec ,
185186 ) -> executor .ExecuteResult :
187+ # Need to grab thread local before starting async execution.
188+ execution_spec = execution_spec .with_compute_options (bigframes .options .compute )
186189 return _run_sync (
187190 self ._execute_async (
188191 array_value ,
@@ -319,7 +322,9 @@ async def _execute_gbq_query_only(
319322 array_value : bigframes .core .ArrayValue ,
320323 execution_spec : ex_spec .ExecutionSpec ,
321324 ) -> executor .ExecuteResult :
322- gbq_plan = await self ._prepare_plan_bq_execution (array_value .node )
325+ gbq_plan = await self ._prepare_plan_bq_execution (
326+ array_value .node , execution_spec .bigquery_config
327+ )
323328 result = await self ._gbq_executor .execute (gbq_plan , execution_spec )
324329 if result is None :
325330 raise ValueError (
@@ -395,10 +400,13 @@ def dry_run(
395400 def cached (
396401 self , array_value : bigframes .core .ArrayValue , * , config : executor .CacheConfig
397402 ) -> None :
403+ # Get compute options before passing to async method, can be thread-local
404+ bq_compute_options = ex_spec .BqComputeOptions .from_compute_options (
405+ bigframes .options .compute
406+ )
398407 return _run_sync (
399408 self ._cached_async (
400- array_value ,
401- config = config ,
409+ array_value , config = config , compute_options = bq_compute_options
402410 )
403411 )
404412
@@ -407,6 +415,7 @@ async def _cached_async(
407415 array_value : bigframes .core .ArrayValue ,
408416 * ,
409417 config : executor .CacheConfig ,
418+ compute_options : ex_spec .BqComputeOptions ,
410419 ) -> None :
411420 """Write the block to a session table."""
412421 # First, see if we can reuse the existing cache
@@ -429,25 +438,23 @@ async def _cached_async(
429438
430439 if config .optimize_for == "auto" :
431440 await self ._cache_with_session_awareness (
432- array_value , enable_multi_query_execution = enable_multi_query_execution
441+ array_value , compute_options = compute_options
433442 )
434443 elif config .optimize_for == "head" :
435- await self ._cache_with_offsets (
436- array_value , enable_multi_query_execution = enable_multi_query_execution
437- )
444+ await self ._cache_with_offsets (array_value , compute_options = compute_options )
438445 else :
439446 assert isinstance (config .optimize_for , executor .HierarchicalKey )
440447 await self ._cache_with_cluster_cols (
441448 array_value ,
442449 cluster_cols = config .optimize_for .columns ,
443- enable_multi_query_execution = enable_multi_query_execution ,
450+ compute_options = compute_options ,
444451 )
445452
446453 async def _execute_to_cached_table (
447454 self ,
448455 plan : nodes .BigFrameNode ,
449456 cache_spec : ex_spec .CacheSpec ,
450- enable_multi_query_execution : bool ,
457+ compute_options : ex_spec . BqComputeOptions ,
451458 ) -> executor .ExecuteResult :
452459 # "ephemeral" temp tables created in the course of exeuction, don't need to be allocated
453460 # materialized ordering only really makes sense for internal temp tables used by caching
@@ -474,7 +481,7 @@ async def _execute_to_cached_table(
474481 cluster_cols = cluster_cols ,
475482 if_exists = "replace" ,
476483 ),
477- enable_multi_query_execution = enable_multi_query_execution ,
484+ bigquery_config = compute_options ,
478485 )
479486 # We don't use _execute_gbq_table_export, as this result is internal, not exported.
480487 result = await self ._execute_gbq_query_only (
@@ -506,13 +513,13 @@ def _prepare_plan_simplify(self, plan: nodes.BigFrameNode) -> nodes.BigFrameNode
506513 return plan
507514
508515 async def _prepare_plan_bq_execution (
509- self , plan : nodes .BigFrameNode , enable_multi_query_execution : bool
516+ self ,
517+ plan : nodes .BigFrameNode ,
518+ compute_options : ex_spec .BqComputeOptions ,
510519 ) -> nodes .BigFrameNode :
511520 """Prepare the plan for BigQuery execution by caching subtrees and uploading large local sources."""
512- if enable_multi_query_execution :
513- await self ._simplify_with_caching (
514- plan , enable_multi_query_execution = enable_multi_query_execution
515- )
521+ if compute_options .enable_multi_query_execution :
522+ await self ._simplify_with_caching (plan , compute_options = compute_options )
516523 plan = self ._prepare_plan_simplify (plan )
517524 plan = await self ._substitute_large_local_sources (plan )
518525 return plan
@@ -521,7 +528,7 @@ async def _cache_with_cluster_cols(
521528 self ,
522529 array_value : bigframes .core .ArrayValue ,
523530 cluster_cols : Sequence [str ],
524- enable_multi_query_execution : bool ,
531+ compute_options : ex_spec . BqComputeOptions ,
525532 ):
526533 """Executes the query and uses the resulting table to rewrite future executions."""
527534 cluster_cols = [
@@ -533,7 +540,7 @@ async def _cache_with_cluster_cols(
533540 result = await self ._execute_to_cached_table (
534541 array_value .node ,
535542 ex_spec .CacheSpec (cluster_cols = tuple (cluster_cols ), ordering = "order_key" ),
536- enable_multi_query_execution = enable_multi_query_execution ,
543+ compute_options = compute_options ,
537544 )
538545 assert isinstance (result , executor .BQTableExecuteResult )
539546 assert result ._data .ordering is not None
@@ -542,13 +549,13 @@ async def _cache_with_cluster_cols(
542549 async def _cache_with_offsets (
543550 self ,
544551 array_value : bigframes .core .ArrayValue ,
545- enable_multi_query_execution : bool ,
552+ compute_options : ex_spec . BqComputeOptions ,
546553 ):
547554 """Executes the query and uses the resulting table to rewrite future executions."""
548555 result = await self ._execute_to_cached_table (
549556 array_value .node ,
550557 ex_spec .CacheSpec (ordering = "offsets_col" ),
551- enable_multi_query_execution = enable_multi_query_execution ,
558+ compute_options = compute_options ,
552559 )
553560 assert isinstance (result , executor .BQTableExecuteResult )
554561 assert result ._data .ordering is not None
@@ -557,7 +564,7 @@ async def _cache_with_offsets(
557564 async def _cache_with_session_awareness (
558565 self ,
559566 array_value : bigframes .core .ArrayValue ,
560- enable_multi_query_execution : bool ,
567+ compute_options : ex_spec . BqComputeOptions ,
561568 ) -> None :
562569 session_forest = [obj ._block ._expr .node for obj in array_value .session .objects ]
563570 # These node types are cheap to re-compute
@@ -569,22 +576,22 @@ async def _cache_with_session_awareness(
569576 await self ._cache_with_cluster_cols (
570577 bigframes .core .ArrayValue (target ),
571578 cluster_cols_sql_names ,
572- enable_multi_query_execution = enable_multi_query_execution ,
579+ compute_options = compute_options ,
573580 )
574581 elif not target .order_ambiguous :
575582 await self ._cache_with_offsets (
576583 bigframes .core .ArrayValue (target ),
577- enable_multi_query_execution = enable_multi_query_execution ,
584+ compute_options = compute_options ,
578585 )
579586 else :
580587 await self ._cache_with_cluster_cols (
581588 bigframes .core .ArrayValue (target ),
582589 [],
583- enable_multi_query_execution = enable_multi_query_execution ,
590+ compute_options = compute_options ,
584591 )
585592
586593 async def _simplify_with_caching (
587- self , plan : nodes .BigFrameNode , enable_multi_query_execution : bool
594+ self , plan : nodes .BigFrameNode , compute_options : ex_spec . BqComputeOptions
588595 ):
589596 """Attempts to handle the complexity by caching duplicated subtrees and breaking the query into pieces."""
590597 # Apply existing caching first
@@ -596,13 +603,13 @@ async def _simplify_with_caching(
596603 return
597604
598605 did_cache = await self ._cache_most_complex_subtree (
599- plan , enable_multi_query_execution = enable_multi_query_execution
606+ plan , compute_options = compute_options
600607 )
601608 if not did_cache :
602609 return
603610
604611 async def _cache_most_complex_subtree (
605- self , node : nodes .BigFrameNode , enable_multi_query_execution : bool
612+ self , node : nodes .BigFrameNode , compute_options : ex_spec . BqComputeOptions
606613 ) -> bool :
607614 # TODO: If query fails, retry with lower complexity limit
608615 selection = tree_properties .select_cache_target (
@@ -622,7 +629,7 @@ async def _cache_most_complex_subtree(
622629 await self ._cache_with_cluster_cols (
623630 bigframes .core .ArrayValue (selection ),
624631 [],
625- enable_multi_query_execution = enable_multi_query_execution ,
632+ compute_options = compute_options ,
626633 )
627634 return True
628635
0 commit comments