<commit_before>module Veritas
  module SQL
    module Compiler
      class Generator

        # Generates an SQL statement for a binary relation
        class BinaryRelation < Generator
          extend Aliasable

          inheritable_alias(:visit_veritas_base_relation => :visit_veritas_relation_operation_unary)

          UNION     = 'UNION'.freeze
          INTERSECT = 'INTERSECT'.freeze
          EXCEPT    = 'EXCEPT'.freeze

          # Visit a Union
          #
          # @param [Algebra::Union] union
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_union(union)
            @left      = operand_dispatch(union.left)
            @right     = operand_dispatch(union.right)
            @operation = UNION
            @name      = [ @left.name, @right.name ].uniq.join('_')
            self
          end

          # Visit an Intersection
          #
          # @param [Algebra::Intersection] intersection
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_intersection(intersection)
            @left      = operand_dispatch(intersection.left)
            @right     = operand_dispatch(intersection.right)
            @operation = INTERSECT
            @name      = [ @left.name, @right.name ].uniq.join('_')
            self
          end

          # Visit an Difference
          #
          # @param [Algebra::Difference] difference
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_difference(difference)
            @left      = operand_dispatch(difference.left)
            @right     = operand_dispatch(difference.right)
            @operation = EXCEPT
            @name      = [ @left.name, @right.name ].uniq.join('_')
            self
          end

          # Visit a Unary Relation
          #
          # @param [Relation::Operation::Unary] unary
          #
          # @return [UnaryRelation]
          #
          # @api private
          def visit_veritas_relation_operation_unary(unary)
            UnaryRelation.new.visit(unary)
          end

          # Return the SQL for the visitable object
          #
          # @example
          #   sql = binary_relation.to_s
          #
          # @return [#to_s]
          #
          # @api public
          def to_s
            generate_sql(:to_s)
          end

          # Return the SQL suitable for an inner query
          #
          # @return [#to_s]
          #
          # @api private
          def to_inner
            generate_sql(:to_inner)
          end

        private

          # Generate the SQL using the supplied method
          #
          # @param [Symbol] method
          #
          # @return [#to_s]
          #
          # @api private
          def generate_sql(method)
            return EMPTY_STRING unless visited?
            "(#{@left.send(method)}) #{@operation} (#{@right.send(method)})"
          end

          # Dispatch the operand to the proper handler
          #
          # @param [Visitable] visitable
          #<commit_msg>Move common logic from set operations into private helper methods<commit_after>module Veritas
  module SQL
    module Compiler
      class Generator

        # Generates an SQL statement for a binary relation
        class BinaryRelation < Generator
          extend Aliasable

          inheritable_alias(:visit_veritas_base_relation => :visit_veritas_relation_operation_unary)

          UNION     = 'UNION'.freeze
          INTERSECT = 'INTERSECT'.freeze
          EXCEPT    = 'EXCEPT'.freeze

          # Visit a Union
          #
          # @param [Algebra::Union] union
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_union(union)
            set_operation(UNION)
            set_operands(union)
            set_name
            self
          end

          # Visit an Intersection
          #
          # @param [Algebra::Intersection] intersection
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_intersection(intersection)
            set_operation(INTERSECT)
            set_operands(intersection)
            set_name
            self
          end

          # Visit an Difference
          #
          # @param [Algebra::Difference] difference
          #
          # @return [self]
          #
          # @api private
          def visit_veritas_algebra_difference(difference)
            set_operation(EXCEPT)
            set_operands(difference)
            set_name
            self
          end

          # Visit a Unary Relation
          #
          # @param [Relation::Operation::Unary] unary
          #
          # @return [UnaryRelation]
          #
          # @api private
          def visit_veritas_relation_operation_unary(unary)
            UnaryRelation.new.visit(unary)
          end

          # Return the SQL for the visitable object
          #
          # @example
          #   sql = binary_relation.to_s
          #
          # @return [#to_s]
          #
          # @api public
          def to_s
            generate_sql(:to_s)
          end

          # Return the SQL suitable for an inner query
          #
          # @return [#to_s]
          #
          # @api private
          def to_inner
            generate_sql(:to_inner)
          end

        private

          # Generate the SQL using the supplied method
          #
          # @param [Symbol] method
          #
          # @return [#to_s]
          #
          # @api private
          def generate_sql(method)
            return EMPTY_STRING unless visited?
            "(#{@left.send(method)}) #{@operation} (#{@right.send(method)})"
          end

          # Set the operation
          #
          # @param [#to_s] operation
          #
          # @return [undefined]
          #
          # @api private
          def set_operation(operation)
            @operation = operation
          end

          # Set the operands from the relation
          #
          # @param [Relation::Operation::Set] relation
          #
          # @return [undefined]
          #
          # @api private
          def set_operands(relation)
            @left  = operand_dispatch(relation.left)
            @right = operand_dispatch(relation.right)
          end

          # Set the name using the operands' name
          #
          # @return [undefined]
          #
          # @api private
          def set_name
            @name = [ @left.name, @right.name ].uniq.join('_')
          end

          # Dispatch the operand to the proper handler
          #
          # @param [Visitable] visitable
          #
{'fraction_non_alphanumeric': 0.0782378075733019, 'fraction_numerical': 0.0, 'mean_word_length': 1.3175145100716967, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5446612', 'n_tokens_mistral': 1812, 'n_tokens_neox': 1762, 'n_words': 411}