<commit_before>module RecordCache
  module Strategy
    class UniqueIndexCache < Base
      
      # All attributes with a unique index for the given model
      def self.attributes(base)
        (@attributes ||= {})[base.name] ||= []
      end

      # parse the options and return (an array of) instances of this strategy
      def self.parse(base, record_store, options)
        attributes = [options[:unique_index]].flatten.compact
        # add unique index for :id by default
        attributes << :id if base.columns_hash['id'] unless base.record_cache[:id] 
        return nil if attributes.empty?
        attributes.map do |attribute|
          type = base.columns_hash[attribute.to_s].try(:type)
          raise "No column found for unique index '#{index}' on #{base.name}." unless type
          raise "Incorrect type (expected string or integer, found #{type}) for unique index '#{attribute}' on #{base.name}." unless type == :string || type == :integer
          UniqueIndexCache.new(base, attribute, record_store, options, type)
        end
      end

      def initialize(base, attribute, record_store, options, type)
        super(base, attribute, record_store, options)
        # remember the attributes with a unique index
        UniqueIndexCache.attributes(base) << attribute
        # for unique indexes that are not on the :id column, use key: rc/<key or model name>/<attribute>:
        @cache_key_prefix << "#{attribute}:" unless attribute == :id
        @type = type
      end

      # Can the cache retrieve the records based on this query?
      def cacheable?(query)
        values = query.where_values(@attribute, @type)
        values && (query.limit.nil? || (query.limit == 1 && values.size == 1))
      end

      # Update the version store and the record store
      def record_change(record, action)
        key = cache_key(record.send(@attribute))
        #if action == :destroy
        version_store.delete(key)
        #else
        #  # update the version store and add the record to the cache
        #  new_version = version_store.increment(key)
        #  record_store.write(versioned_key(key, new_version), Util.serialize(record))
        #end
      end

      # Handle invalidation call
      def invalidate(id)
        version_store.delete(cache_key(@type == :integer ? id.to_i : id.to_s))
      end
  
      protected
  
      # retrieve the record(s) with the given id(s) as an array
      def fetch_records(query)
        ids = query.where_values(@attribute, @type)
        query.wheres.delete(@attribute) # make sure CacheCase.filter! does not see this where anymore
        id_to_key_map = ids.inject({}){|h,id| h[id] = cache_key(id); h }<commit_msg>Fixed unique index<commit_after>module RecordCache
  module Strategy
    class UniqueIndexCache < Base
      
      # All attributes with a unique index for the given model
      def self.attributes(base)
        (@attributes ||= {})[base.name] ||= []
      end

      # parse the options and return (an array of) instances of this strategy
      def self.parse(base, record_store, options)
        attributes = [options[:unique_index]].flatten.compact
        # add unique index for :id by default
        attributes << :id if base.columns_hash['id'] unless base.record_cache[:id] 
        return nil if attributes.empty?
        attributes.map do |attribute|
          type = base.columns_hash[attribute.to_s].try(:type)
          raise "No column found for unique index '#{index}' on #{base.name}." unless type
          raise "Incorrect type (expected string or integer, found #{type}) for unique index '#{attribute}' on #{base.name}." unless type == :string || type == :integer
          UniqueIndexCache.new(base, attribute, record_store, options, type)
        end
      end

      def initialize(base, attribute, record_store, options, type)
        super(base, attribute, record_store, options)
        # remember the attributes with a unique index
        UniqueIndexCache.attributes(base) << attribute
        # for unique indexes that are not on the :id column, use key: rc/<key or model name>/<attribute>:
        @cache_key_prefix << "#{attribute}:" unless attribute == :id
        @type = type
      end

      # Can the cache retrieve the records based on this query?
      def cacheable?(query)
        values = query.where_values(@attribute, @type)
        values && (query.limit.nil? || (query.limit == 1 && values.size == 1))
      end

      # Update the version store and the record store
      def record_change(record, action)
        key = cache_key(record.send(@attribute))
        if action == :destroy
          version_store.delete(key)
        else
          # update the version store and add the record to the cache
          new_version = version_store.increment(key)
          record_store.write(versioned_key(key, new_version), Util.serialize(record))
        end
      end

      # Handle invalidation call
      def invalidate(id)
        version_store.delete(cache_key(@type == :integer ? id.to_i : id.to_s))
      end
  
      protected
  
      # retrieve the record(s) with the given id(s) as an array
      def fetch_records(query)
        ids = query.where_values(@attribute, @type)
        query.wheres.delete(@attribute) # make sure CacheCase.filter! does not see this where anymore
        id_to_key_map = ids.inject({}){|h,id| h[id] = cache_key(id); h }
{'fraction_non_alphanumeric': 0.10224115576958696, 'fraction_numerical': 0.0007408779403593258, 'mean_word_length': 2.696098562628337, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 7, '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': '1452742', 'n_tokens_mistral': 1488, 'n_tokens_neox': 1461, 'n_words': 488}