Class: DbMemoize::Value

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
lib/db_memoize/value.rb

Constant Summary collapse

SQL =
::Simple::SQL
ALL_COLUMNS =
[
  :val_string,
  :val_integer,
  :val_float,
  :val_time,
  :val_object,
  :val_boolean,
  :val_nil
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._reformat_object(value) ⇒ Object



105
106
107
# File 'lib/db_memoize/value.rb', line 105

def self._reformat_object(value)
  JSON.generate(value)
end

._reformat_time(t) ⇒ Object

Apparently the pg, and for that matter also simple-sql, drops subsecond resolution when passing in time objects. (Note that this seems not always to be the case, it probably depends on some encoder configuration within pg - which simple-sql is not touching, since this is a setting on a connection which might not be exclusive to simple-sql.)

Instead we’ll just pass along a string, postgresql will then convert it into a proper timestamp.



101
102
103
# File 'lib/db_memoize/value.rb', line 101

def self._reformat_time(t) # rubocop:disable Naming/UncommunicativeMethodParamName
  format('%04d-%02d-%02d %02d:%02d:%02d.%06d', t.year, t.mon, t.day, t.hour, t.min, t.sec, t.usec)
end

.delete_all_orderedObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/db_memoize/value.rb', line 32

def self.delete_all_ordered
  relation = self
  relation = all unless is_a?(ActiveRecord::Relation)

  sql = relation.select(:ctid).to_sql
  SQL.ask <<-SQL
    DO $$DECLARE c record;
    BEGIN
      FOR c IN SELECT * FROM (#{sql}) sq ORDER BY ctid LOOP
        DELETE FROM #{DbMemoize::Value.table_name} WHERE ctid = c.ctid;
      END LOOP;
    END$$;
  SQL
end

.fast_create(entity_table_name, entity_id, method_name, value) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/db_memoize/value.rb', line 57

def self.fast_create(entity_table_name, entity_id, method_name, value)
  method_name = method_name.to_s

  column = case value
           when String   then :val_string
           when Integer  then :val_integer
           when Float    then :val_float
           when Time     then :val_time
           when false    then :val_boolean
           when true     then :val_boolean
           when nil      then :val_nil
           when Hash     then :val_object
           when Array    then :val_object
           else
             raise "Unsupported value of type #{value.class.name}: #{value.inspect}"
           end

  # some types need special encoding
  case column
  when :val_object  then value = _reformat_object(value)
  when :val_time    then value = _reformat_time(value)
  end

  # We initialize created_at with +statement_timestamp()+ since this
  # reflects the current time when running the insert, resulting in
  # increasing timestamps even within the same transaction.
  #
  # (This is only relevant for tests, though.)
  sql = <<~SQL.freeze
    INSERT INTO #{table_name}(entity_table_name, entity_id, method_name, #{column}, created_at)
      VALUES($1,$2,$3,$4,statement_timestamp())
  SQL

  SQL.ask sql, entity_table_name, entity_id, method_name, value
end

Instance Method Details

#valueObject



27
28
29
30
# File 'lib/db_memoize/value.rb', line 27

def value
  # Note: val_boolean should come last.
  val_string || val_integer || val_float || val_time || val_object || val_boolean
end

#value=(value) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/db_memoize/value.rb', line 12

def value=(value)
  self.val_integer = self.val_float = self.val_string = self.val_boolean = self.val_time = nil

  case value
  when String   then self.val_string = value
  when Integer  then self.val_integer = value
  when Float    then self.val_float = value
  when Time     then self.val_time = value
  when false    then self.val_boolean = value
  when true     then self.val_boolean = value
  when nil      then :nop
  else raise "Unsupported type #{value.class.name.inspect}, for DbMemoize"
  end
end