Dynamoid/dynamoid

View on GitHub
lib/dynamoid/adapter_plugin/aws_sdk_v3/filter_expression_convertor.rb

Summary

Maintainability
A
2 hrs
Test Coverage
# frozen_string_literal: true

module Dynamoid
  # @private
  module AdapterPlugin
    class AwsSdkV3
      class FilterExpressionConvertor
        attr_reader :expression, :name_placeholders, :value_placeholders

        def initialize(conditions, name_placeholders, value_placeholders, name_placeholder_sequence, value_placeholder_sequence)
          @conditions = conditions
          @name_placeholders = name_placeholders.dup
          @value_placeholders = value_placeholders.dup
          @name_placeholder_sequence = name_placeholder_sequence
          @value_placeholder_sequence = value_placeholder_sequence

          build
        end

        private

        def build
          clauses = @conditions.map do |name, attribute_conditions|
            attribute_conditions.map do |operator, value|
              name_or_placeholder = name_or_placeholder_for(name)

              case operator
              when :eq
                "#{name_or_placeholder} = #{value_placeholder_for(value)}"
              when :ne
                "#{name_or_placeholder} <> #{value_placeholder_for(value)}"
              when :gt
                "#{name_or_placeholder} > #{value_placeholder_for(value)}"
              when :lt
                "#{name_or_placeholder} < #{value_placeholder_for(value)}"
              when :gte
                "#{name_or_placeholder} >= #{value_placeholder_for(value)}"
              when :lte
                "#{name_or_placeholder} <= #{value_placeholder_for(value)}"
              when :between
                "#{name_or_placeholder} BETWEEN #{value_placeholder_for(value[0])} AND #{value_placeholder_for(value[1])}"
              when :begins_with
                "begins_with (#{name_or_placeholder}, #{value_placeholder_for(value)})"
              when :in
                list = value.map(&method(:value_placeholder_for)).join(' , ')
                "#{name_or_placeholder} IN (#{list})"
              when :contains
                "contains (#{name_or_placeholder}, #{value_placeholder_for(value)})"
              when :not_contains
                "NOT contains (#{name_or_placeholder}, #{value_placeholder_for(value)})"
              when :null
                "attribute_not_exists (#{name_or_placeholder})"
              when :not_null
                "attribute_exists (#{name_or_placeholder})"
              end
            end
          end.flatten

          @expression = clauses.join(' AND ')
        end

        def name_or_placeholder_for(name)
          return name unless name.upcase.in?(Dynamoid::AdapterPlugin::AwsSdkV3::RESERVED_WORDS)

          placeholder = @name_placeholder_sequence.call
          @name_placeholders[placeholder] = name
          placeholder
        end

        def value_placeholder_for(value)
          placeholder = @value_placeholder_sequence.call
          @value_placeholders[placeholder] = value
          placeholder
        end
      end
    end
  end
end