@@ -241,11 +241,10 @@ def execute_sql(
241241 self , result_type = MULTI , chunked_fetch = False , chunk_size = GET_ITERATOR_CHUNK_SIZE
242242 ):
243243 self .pre_sql_setup ()
244- columns = self .get_columns ()
245244 try :
246245 query = self .build_query (
247246 # Avoid $project (columns=None) if unneeded.
248- columns
247+ self . columns
249248 if self .query .annotations or not self .query .default_cols or self .query .distinct
250249 else None
251250 )
@@ -259,10 +258,10 @@ def execute_sql(
259258 except StopIteration :
260259 return None # No result
261260 else :
262- return self ._make_result (obj , columns )
261+ return self ._make_result (obj , self . columns )
263262 # result_type is MULTI
264263 cursor .batch_size (chunk_size )
265- result = self .cursor_iter (cursor , chunk_size , columns )
264+ result = self .cursor_iter (cursor , chunk_size , self . columns )
266265 if not chunked_fetch :
267266 # If using non-chunked reads, read data into memory.
268267 return list (result )
@@ -394,7 +393,8 @@ def build_query(self, columns=None):
394393 query .subqueries = self .subqueries
395394 return query
396395
397- def get_columns (self ):
396+ @cached_property
397+ def columns (self ):
398398 """
399399 Return a tuple of (name, expression) with the columns and annotations
400400 which should be loaded by the query
@@ -485,8 +485,7 @@ def get_combinator_queries(self):
485485 query .get_compiler (self .using , self .connection , self .elide_empty )
486486 for query in self .query .combined_queries
487487 ]
488- main_query_columns = self .get_columns ()
489- main_query_fields , _ = zip (* main_query_columns , strict = True )
488+ main_query_fields , _ = zip (* self .columns , strict = True )
490489 for compiler_ in compilers :
491490 try :
492491 # If the columns list is limited, then all combined queries
@@ -507,7 +506,7 @@ def get_combinator_queries(self):
507506 )
508507 compiler_ .pre_sql_setup ()
509508 compiler_ .column_indices = self .column_indices
510- columns = compiler_ .get_columns ()
509+ columns = compiler_ .columns
511510 parts .append ((compiler_ .build_query (columns ), compiler_ , columns ))
512511 except EmptyResultSet :
513512 # Omit the empty queryset with UNION.
@@ -545,7 +544,7 @@ def get_combinator_queries(self):
545544 combinator_pipeline = inner_pipeline
546545 if not self .query .combinator_all :
547546 ids = defaultdict (dict )
548- for alias , expr in main_query_columns :
547+ for alias , expr in self . columns :
549548 # Unfold foreign fields.
550549 if isinstance (expr , Col ) and expr .alias != self .collection_name :
551550 ids [expr .alias ][expr .target .column ] = expr .as_mql (self , self .connection )
@@ -650,10 +649,9 @@ def explain_query(self):
650649 )
651650 # Build the query pipeline.
652651 self .pre_sql_setup ()
653- columns = self .get_columns ()
654652 query = self .build_query (
655653 # Avoid $project (columns=None) if unneeded.
656- columns if self .query .annotations or not self .query .default_cols else None
654+ self . columns if self .query .annotations or not self .query .default_cols else None
657655 )
658656 pipeline = query .get_pipeline ()
659657 # Explain the pipeline.
@@ -807,7 +805,7 @@ def build_query(self, columns=None):
807805 compiler .pre_sql_setup (with_col_aliases = False )
808806 # Avoid $project (columns=None) if unneeded.
809807 columns = (
810- compiler .get_columns ()
808+ compiler .columns
811809 if self .query .annotations or not self .query .default_cols or self .query .distinct
812810 else None
813811 )
0 commit comments