class_docstr: Helper class for constructing various join components in a SqlQueryPlan.
docstr: Build a time window join condition if the join description includes a validity window description.
  
  When the validity window is set, it means we are dealing with a dataset representing an SCD Type II
  style semantic model, with a start and end boundary on the window. A base output join against such data
  sources requires a metric_time dimension to process the join.
  
  By convention, the join description ties the validity window to the "right" side semantic model, and so
  we extract the metric time instance from the left data set.
  
  We use the instance with the smallest granularity and shortest entity link path, since it will be
  used in the ON statement for the join against the validity window.
docstr_tok: ["Build","a","time","window","join","condition","if","the","join","description","includes","a","validity","window","description",".","When","the","validity","window","is","set",",","it","means","we","are","dealing","with","a","dataset","representing","an","SCD","Type","II","style","semantic","model",",","with","a","start","and","end","boundary","on","the","window",".","A","base","output","join","against","such","data","sources","requires","a","metric_time","dimension","to","process","the","join",".","By","convention",",","the","join","description","ties","the","validity","window","to","the","``","right","''","side","semantic","model",",","and","so","we","extract","the","metric","time","instance","from","the","left","data","set",".","We","use","the","instance","with","the","smallest","granularity","and","shortest","entity","link","path",",","since","it","will","be","used","in","the","ON","statement","for","the","join","against","the","validity","window","."]
code: def _make_validity_window_on_conditions(
      left_data_set: AnnotatedSqlDataSet,
      right_data_set: AnnotatedSqlDataSet,
      join_description: JoinDescription,
  ) -> Tuple[SqlExpressionNode, ...]:
      """Build a time window join condition if the join description includes a validity window description.
  
      When the validity window is set, it means we are dealing with a dataset representing an SCD Type II
      style semantic model, with a start and end boundary on the window. A base output join against such data
      sources requires a metric_time dimension to process the join.
  
      By convention, the join description ties the validity window to the "right" side semantic model, and so
      we extract the metric time instance from the left data set.
  
      We use the instance with the smallest granularity and shortest entity link path, since it will be
      used in the ON statement for the join against the validity window.
      """
      if join_description.validity_window is None:
          return tuple()
  
      left_data_set_metric_time_dimension_instances = sorted(
          left_data_set.data_set.metric_time_dimension_instances,
          key=lambda x: (
              x.spec.time_granularity.to_int(),
              len(x.spec.entity_links),
          ),
      )
      assert left_data_set_metric_time_dimension_instances, (
          f"Cannot process join to data set with alias {right_data_set.alias} because it has a validity "
          f"window set: {join_description.validity_window}, but source data set with alias "
          f"{left_data_set.alias} does not have a metric time dimension we can use for the window join!"
      )
      left_data_set_time_dimension_name = (
          left_data_set.data_set.column_association_for_time_dimension(
              left_data_set_metric_time_dimension_instances[0].spec,
          ).column_name
      )
      window_start_dimension_name = (
          right_data_set.data_set.column_association_for_time_dimension(
              join_description.validity_window.window_start_dimension
          ).column_name
      )
      window_end_dimension_name = (
          right_data_set.data_set.column_association_for_time_dimension(
              join_description.validity_window.window_end_dimension
          ).column_name
      )
      window_join_condition = SqlQueryPlanJoinBuilder._make_time_window_join_condition(
          left_source_alias=left_data_set.alias,
          left_source_time_dimension_name=left_data_set_time_dimension_name,
          right_source_alias=right_data_set.alias,
          window_start_dimension_name=window_start_dimension_name,
          window_end_dimension_name=window_end_dimension_name,
      )
  
      return (window_join_condition,)
  
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 3 for calling the SqlQueryPlanJoinBuilder obj's underlying member method code with example usage: obj._make_validity_window_on_conditions(left_data_set, right_data_set, join_description) and returns: window_join_condition, tuple