class_docstr: Helper class for constructing various join components in a SqlQueryPlan.
docstr: Helper to generate a renderable SqlExpression for expressing a time range window join condition.
  
  The output will render the following expression:
  
      a.ds <= b.ds AND a.ds > b.ds - <window>
      If no window is present we join across all time -> "a.ds <= b.ds"
docstr_tok: ["Helper","to","generate","a","renderable","SqlExpression","for","expressing","a","time","range","window","join","condition",".","The","output","will","render","the","following","expression",":","a.ds","<","=","b.ds","AND","a.ds",">","b.ds","-","<","window",">","If","no","window","is","present","we","join","across","all","time","-",">","``","a.ds","<","=","b.ds","''"]
code: def _make_time_range_window_join_condition(
      base_data_set: AnnotatedSqlDataSet,
      time_comparison_dataset: AnnotatedSqlDataSet,
      window: Optional[MetricTimeWindow] = None,
      grain_to_date: Optional[TimeGranularity] = None,
  ) -> SqlLogicalExpression:
      """Helper to generate a renderable SqlExpression for expressing a time range window join condition.
  
      The output will render the following expression:
  
          a.ds <= b.ds AND a.ds > b.ds - <window>
          If no window is present we join across all time -> "a.ds <= b.ds"
      """
      if window or grain_to_date:
          assert_exactly_one_arg_set(
              window=window, grain_to_date=grain_to_date
          )
      base_column_expr = SqlColumnReferenceExpression(
          SqlColumnReference(
              table_alias=base_data_set.alias,
              column_name=base_data_set.metric_time_column_name,
          )
      )
      time_comparison_column_expr = SqlColumnReferenceExpression(
          SqlColumnReference(
              table_alias=time_comparison_dataset.alias,
              column_name=time_comparison_dataset.metric_time_column_name,
          )
      )
  
      # Comparison expression against the endpoint of the cumulative time range,
      # meaning the base metrc time must always be BEFORE the comparison metric time
      end_of_range_comparison_expression = SqlComparisonExpression(
          left_expr=base_column_expr,
          comparison=SqlComparison.LESS_THAN_OR_EQUALS,
          right_expr=time_comparison_column_expr,
      )
  
      comparison_expressions: List[SqlComparisonExpression] = [
          end_of_range_comparison_expression
      ]
      if window:
          start_of_range_comparison_expr = SqlComparisonExpression(
              left_expr=base_column_expr,
              comparison=SqlComparison.GREATER_THAN,
              right_expr=SqlSubtractTimeIntervalExpression(
                  arg=time_comparison_column_expr,
                  count=window.count,
                  granularity=window.granularity,
              ),
          )
          comparison_expressions.append(start_of_range_comparison_expr)
      elif grain_to_date:
          start_of_range_comparison_expr = SqlComparisonExpression(
              left_expr=base_column_expr,
              comparison=SqlComparison.GREATER_THAN_OR_EQUALS,
              right_expr=SqlDateTruncExpression(
                  arg=time_comparison_column_expr,
                  time_granularity=grain_to_date,
              ),
          )
          comparison_expressions.append(start_of_range_comparison_expr)
  
      return SqlLogicalExpression(
          operator=SqlLogicalOperator.AND,
          args=tuple(comparison_expressions),
      )
  
imports: from __future__ import annotations
  from dataclasses import dataclass
  from typing import List, Optional, Sequence, Tuple
  from dbt_semantic_interfaces.protocols.metric import MetricTimeWindow
  from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
  from metricflow.assert_one_arg import assert_exactly_one_arg_set
  from metricflow.dataflow.dataflow_plan import JoinConversionEventsNode, JoinDescription, JoinOverTimeRangeNode, JoinToTimeSpineNode
  from metricflow.dataset.sql_dataset import SqlDataSet
  from metricflow.plan_conversion.sql_expression_builders import make_coalesced_expr
  from metricflow.sql.sql_exprs import SqlColumnReference, SqlColumnReferenceExpression, SqlComparison, SqlComparisonExpression, SqlDateTruncExpression, SqlIsNullExpression, SqlLogicalExpression, SqlLogicalOperator, SqlSubtractTimeIntervalExpression
  from metricflow.sql.sql_plan import SqlExpressionNode, SqlJoinDescription, SqlJoinType, SqlSelectStatementNode
label_desc: Use image node_id 7 for calling the SqlQueryPlanJoinBuilder obj's underlying member method code with example usage: obj._make_time_range_window_join_condition(base_data_set, time_comparison_dataset, window, grain_to_date) and returns: SqlLogicalExpression