class_docstr: Generates an SQL query plan from a node in the a metric dataflow plan.
class_docstr_tok: ["Generates","an","SQL","query","plan","from","a","node","in","the","a","metric","dataflow","plan","."]
docstr: Convert ConstrainTimeRangeNode to a SqlDataSet by building the time constraint comparison.
  
  Use the smallest time granularity to build the comparison since that's what was used in the semantic model
  definition and it wouldn't have a DATE_TRUNC() in the expression. We want to build this:
  
      ds >= '2020-01-01' AND ds <= '2020-02-01'
  
  instead of this: DATE_TRUNC('month', ds) >= '2020-01-01' AND DATE_TRUNC('month', ds <= '2020-02-01')
docstr_tok: ["Convert","ConstrainTimeRangeNode","to","a","SqlDataSet","by","building","the","time","constraint","comparison",".","Use","the","smallest","time","granularity","to","build","the","comparison","since","that","'s","what","was","used","in","the","semantic","model","definition","and","it","would","n't","have","a","DATE_TRUNC","(",")","in","the","expression",".","We","want","to","build","this",":","ds",">","=","'2020-01-01","'","AND","ds","<","=","'2020-02-01'","instead","of","this",":","DATE_TRUNC","(","'month","'",",","ds",")",">","=","'2020-01-01","'","AND","DATE_TRUNC","(","'month","'",",","ds","<","=","'2020-02-01","'",")"]
code: def visit_constrain_time_range_node(
      self, node: ConstrainTimeRangeNode
  ) -> SqlDataSet:
      """Convert ConstrainTimeRangeNode to a SqlDataSet by building the time constraint comparison.
  
      Use the smallest time granularity to build the comparison since that's what was used in the semantic model
      definition and it wouldn't have a DATE_TRUNC() in the expression. We want to build this:
  
          ds >= '2020-01-01' AND ds <= '2020-02-01'
  
      instead of this: DATE_TRUNC('month', ds) >= '2020-01-01' AND DATE_TRUNC('month', ds <= '2020-02-01')
      """
      from_data_set: SqlDataSet = node.parent_node.accept(self)
      from_data_set_alias = self._next_unique_table_alias()
  
      time_dimension_instances_for_metric_time = sorted(
          from_data_set.metric_time_dimension_instances,
          key=lambda x: x.spec.time_granularity.to_int(),
      )
  
      assert (
          len(time_dimension_instances_for_metric_time) > 0
      ), "No metric time dimensions found in the input data set for this node"
  
      time_dimension_instance_for_metric_time = (
          time_dimension_instances_for_metric_time[0]
      )
  
      # Build an expression like "ds >= CAST('2020-01-01' AS TIMESTAMP) AND ds <= CAST('2020-01-02' AS TIMESTAMP)"
      constrain_metric_time_column_condition = _make_time_range_comparison_expr(
          table_alias=from_data_set_alias,
          column_alias=time_dimension_instance_for_metric_time.associated_column.column_name,
          time_range_constraint=node.time_range_constraint,
      )
  
      output_instance_set = from_data_set.instance_set
      # Output columns should always follow the resolver format.
      output_instance_set = output_instance_set.transform(
          ChangeAssociatedColumns(self._column_association_resolver)
      )
  
      return SqlDataSet(
          instance_set=output_instance_set,
          sql_select_node=SqlSelectStatementNode(
              description=node.description,
              # This creates select expressions for all columns referenced in the instance set.
              select_columns=output_instance_set.transform(
                  CreateSelectColumnsForInstances(
                      from_data_set_alias,
                      self._column_association_resolver,
                  )
              ).as_tuple(),
              from_source=from_data_set.sql_select_node,
              from_source_alias=from_data_set_alias,
              joins_descs=(),
              group_bys=(),
              where=constrain_metric_time_column_condition,
              order_bys=(),
          ),
      )
  
imports: from __future__ import annotations
  import logging
  from collections import OrderedDict
  from typing import List, Optional, Sequence, Tuple, Union
  from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
  from dbt_semantic_interfaces.protocols.metric import MetricInputMeasure, MetricType
  from dbt_semantic_interfaces.references import MetricModelReference
  from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType
  from dbt_semantic_interfaces.type_enums.conversion_calculation_type import ConversionCalculationType
  from dbt_semantic_interfaces.validations.unique_valid_name import MetricFlowReservedKeywords
  from metricflow.aggregation_properties import AggregationState
  from metricflow.dag.id_generation import IdGeneratorRegistry
  from metricflow.dataflow.dataflow_plan import AddGeneratedUuidColumnNode, AggregateMeasuresNode, BaseOutput, CombineAggregatedOutputsNode, ComputedMetricsOutput, ComputeMetricsNode, ConstrainTimeRangeNode, DataflowPlanNodeVisitor, FilterElementsNode, JoinConversionEventsNode, JoinOverTimeRangeNode, JoinToBaseOutputNode, JoinToTimeSpineNode, MetricTimeDimensionTransformNode, MinMaxNode, OrderByLimitNode, ReadSqlSourceNode, SemiAdditiveJoinNode, WhereConstraintNode, WriteToResultDataframeNode, WriteToResultTableNode
  from metricflow.dataset.dataset import DataSet
  from metricflow.dataset.sql_dataset import SqlDataSet
  from metricflow.filters.time_constraint import TimeRangeConstraint
  from metricflow.instances import InstanceSet, MetadataInstance, MetricInstance, TimeDimensionInstance
  from metricflow.model.semantic_manifest_lookup import SemanticManifestLookup
  from metricflow.plan_conversion.instance_converters import AddLinkToLinkableElements, AddMetadata, AddMetrics, AliasAggregatedMeasures, ChangeAssociatedColumns, ChangeMeasureAggregationState, ConvertToMetadata, CreateSelectColumnForCombineOutputNode, CreateSelectColumnsForInstances, CreateSelectColumnsWithMeasuresAggregated, CreateSqlColumnReferencesForInstances, FilterElements, FilterLinkableInstancesWithLeadingLink, RemoveMeasures, RemoveMetrics, UpdateMeasureFillNullsWith, create_select_columns_for_instance_sets
  from metricflow.plan_conversion.select_column_gen import SelectColumnSet
  from metricflow.plan_conversion.spec_transforms import CreateColumnAssociations, CreateSelectCoalescedColumnsForLinkableSpecs, SelectOnlyLinkableSpecs
  from metricflow.plan_conversion.sql_join_builder import AnnotatedSqlDataSet, ColumnEqualityDescription, SqlQueryPlanJoinBuilder
  from metricflow.plan_conversion.time_spine import TimeSpineSource
  from metricflow.protocols.sql_client import SqlEngine
  from metricflow.specs.column_assoc import ColumnAssociation, ColumnAssociationResolver, SingleColumnCorrelationKey
  from metricflow.specs.specs import InstanceSpecSet, MeasureSpec, MetadataSpec, MetricSpec, TimeDimensionSpec
  from metricflow.sql.optimizer.optimization_levels import SqlQueryOptimizationLevel, SqlQueryOptimizerConfiguration
  from metricflow.sql.sql_exprs import SqlAggregateFunctionExpression, SqlBetweenExpression, SqlColumnReference, SqlColumnReferenceExpression, SqlComparison, SqlComparisonExpression, SqlDateTruncExpression, SqlExpressionNode, SqlExtractExpression, SqlFunction, SqlFunctionExpression, SqlGenerateUuidExpression, SqlLogicalExpression, SqlLogicalOperator, SqlRatioComputationExpression, SqlStringExpression, SqlStringLiteralExpression, SqlWindowFunction, SqlWindowFunctionExpression, SqlWindowOrderByArgument
  from metricflow.sql.sql_plan import SqlJoinDescription, SqlJoinType, SqlOrderByDescription, SqlQueryPlan, SqlQueryPlanNode, SqlSelectColumn, SqlSelectStatementNode, SqlTableFromClauseNode
  from metricflow.time.time_constants import ISO8601_PYTHON_FORMAT
label_desc: Use image node_id 17 for calling the DataflowToSqlQueryPlanConverter obj's underlying member method code with example usage: obj.visit_constrain_time_range_node(node) and returns: SqlDataSet