identity_cache 0.4.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/.github/probots.yml +2 -0
  3. data/.github/workflows/ci.yml +92 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +5 -0
  6. data/CAVEATS.md +25 -0
  7. data/CHANGELOG.md +73 -19
  8. data/Gemfile +5 -1
  9. data/LICENSE +1 -1
  10. data/README.md +49 -27
  11. data/Rakefile +14 -5
  12. data/dev.yml +12 -16
  13. data/gemfiles/Gemfile.latest-release +8 -0
  14. data/gemfiles/Gemfile.min-supported +7 -0
  15. data/gemfiles/Gemfile.rails-edge +7 -0
  16. data/identity_cache.gemspec +29 -10
  17. data/lib/identity_cache.rb +78 -51
  18. data/lib/identity_cache/belongs_to_caching.rb +12 -40
  19. data/lib/identity_cache/cache_fetcher.rb +6 -5
  20. data/lib/identity_cache/cache_hash.rb +2 -2
  21. data/lib/identity_cache/cache_invalidation.rb +4 -11
  22. data/lib/identity_cache/cache_key_generation.rb +17 -65
  23. data/lib/identity_cache/cache_key_loader.rb +128 -0
  24. data/lib/identity_cache/cached.rb +7 -0
  25. data/lib/identity_cache/cached/association.rb +87 -0
  26. data/lib/identity_cache/cached/attribute.rb +123 -0
  27. data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
  28. data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
  29. data/lib/identity_cache/cached/belongs_to.rb +100 -0
  30. data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
  31. data/lib/identity_cache/cached/prefetcher.rb +61 -0
  32. data/lib/identity_cache/cached/primary_index.rb +96 -0
  33. data/lib/identity_cache/cached/recursive/association.rb +109 -0
  34. data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
  35. data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
  36. data/lib/identity_cache/cached/reference/association.rb +16 -0
  37. data/lib/identity_cache/cached/reference/has_many.rb +105 -0
  38. data/lib/identity_cache/cached/reference/has_one.rb +100 -0
  39. data/lib/identity_cache/configuration_dsl.rb +53 -215
  40. data/lib/identity_cache/encoder.rb +95 -0
  41. data/lib/identity_cache/expiry_hook.rb +36 -0
  42. data/lib/identity_cache/fallback_fetcher.rb +2 -1
  43. data/lib/identity_cache/load_strategy/eager.rb +28 -0
  44. data/lib/identity_cache/load_strategy/lazy.rb +71 -0
  45. data/lib/identity_cache/load_strategy/load_request.rb +20 -0
  46. data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
  47. data/lib/identity_cache/mem_cache_store_cas.rb +53 -0
  48. data/lib/identity_cache/memoized_cache_proxy.rb +137 -58
  49. data/lib/identity_cache/parent_model_expiration.rb +46 -11
  50. data/lib/identity_cache/query_api.rb +102 -408
  51. data/lib/identity_cache/railtie.rb +8 -0
  52. data/lib/identity_cache/record_not_found.rb +6 -0
  53. data/lib/identity_cache/should_use_cache.rb +1 -0
  54. data/lib/identity_cache/version.rb +3 -2
  55. data/lib/identity_cache/with_primary_index.rb +136 -0
  56. data/lib/identity_cache/without_primary_index.rb +24 -3
  57. data/performance/cache_runner.rb +25 -73
  58. data/performance/cpu.rb +4 -3
  59. data/performance/externals.rb +4 -3
  60. data/performance/profile.rb +6 -5
  61. data/railgun.yml +16 -0
  62. metadata +60 -73
  63. data/.travis.yml +0 -30
  64. data/Gemfile.rails42 +0 -6
  65. data/Gemfile.rails50 +0 -6
  66. data/test/attribute_cache_test.rb +0 -110
  67. data/test/cache_fetch_includes_test.rb +0 -46
  68. data/test/cache_hash_test.rb +0 -14
  69. data/test/cache_invalidation_test.rb +0 -139
  70. data/test/deeply_nested_associated_record_test.rb +0 -19
  71. data/test/denormalized_has_many_test.rb +0 -211
  72. data/test/denormalized_has_one_test.rb +0 -160
  73. data/test/fetch_multi_test.rb +0 -308
  74. data/test/fetch_test.rb +0 -258
  75. data/test/fixtures/serialized_record.mysql2 +0 -0
  76. data/test/fixtures/serialized_record.postgresql +0 -0
  77. data/test/helpers/active_record_objects.rb +0 -106
  78. data/test/helpers/database_connection.rb +0 -72
  79. data/test/helpers/serialization_format.rb +0 -42
  80. data/test/helpers/update_serialization_format.rb +0 -24
  81. data/test/identity_cache_test.rb +0 -29
  82. data/test/index_cache_test.rb +0 -161
  83. data/test/memoized_attributes_test.rb +0 -49
  84. data/test/memoized_cache_proxy_test.rb +0 -107
  85. data/test/normalized_belongs_to_test.rb +0 -107
  86. data/test/normalized_has_many_test.rb +0 -231
  87. data/test/normalized_has_one_test.rb +0 -9
  88. data/test/prefetch_associations_test.rb +0 -364
  89. data/test/readonly_test.rb +0 -109
  90. data/test/recursive_denormalized_has_many_test.rb +0 -131
  91. data/test/save_test.rb +0 -82
  92. data/test/schema_change_test.rb +0 -112
  93. data/test/serialization_format_change_test.rb +0 -16
  94. data/test/test_helper.rb +0 -140
@@ -1,131 +0,0 @@
1
- require "test_helper"
2
-
3
- class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
4
- def setup
5
- super
6
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
7
- Item.cache_has_many :associated_records, :embed => true
8
- Item.cache_has_one :associated
9
-
10
- @record = Item.new(:title => 'foo')
11
-
12
- @associated_record = AssociatedRecord.new(:name => 'bar')
13
- @record.associated_records << AssociatedRecord.new(:name => 'baz')
14
- @record.associated_records << @associated_record
15
-
16
- @deeply_associated_record = DeeplyAssociatedRecord.new(:name => "corge")
17
- @associated_record.deeply_associated_records << @deeply_associated_record
18
- @associated_record.deeply_associated_records << DeeplyAssociatedRecord.new(:name => "qux")
19
-
20
- @record.save
21
- @record.reload
22
- @associated_record.reload
23
- end
24
-
25
- def test_cache_fetch_includes
26
- assert_equal [{:associated_records => [:deeply_associated_records]}, :associated => [:deeply_associated_records]], Item.send(:cache_fetch_includes)
27
- end
28
-
29
- def test_uncached_record_from_the_db_will_use_normal_association_for_deeply_associated_records
30
- expected = @associated_record.deeply_associated_records
31
- record_from_db = Item.find(@record.id)
32
- assert_equal expected, record_from_db.fetch_associated_records[0].fetch_deeply_associated_records
33
- end
34
-
35
- def test_on_cache_miss_record_should_embed_associated_objects_and_return
36
- record_from_cache_miss = Item.fetch(@record.id)
37
- expected = @associated_record.deeply_associated_records
38
-
39
- child_record_from_cache_miss = record_from_cache_miss.fetch_associated_records[0]
40
- assert_equal @associated_record, child_record_from_cache_miss
41
- assert_equal expected, child_record_from_cache_miss.fetch_deeply_associated_records
42
- end
43
-
44
- def test_on_cache_hit_record_should_return_embed_associated_objects
45
- Item.fetch(@record.id) # warm cache
46
- expected = @associated_record.deeply_associated_records
47
-
48
- Item.any_instance.expects(:associated_records).never
49
- AssociatedRecord.any_instance.expects(:deeply_associated_records).never
50
-
51
- record_from_cache_hit = Item.fetch(@record.id)
52
- child_record_from_cache_hit = record_from_cache_hit.fetch_associated_records[0]
53
- assert_equal @associated_record, child_record_from_cache_hit
54
- assert_equal expected, child_record_from_cache_hit.fetch_deeply_associated_records
55
- end
56
-
57
- def test_on_cache_miss_child_record_fetch_should_include_nested_associations_to_avoid_n_plus_ones
58
- assert_queries(5) do
59
- # one for the top level record
60
- # one for the mid level has_many association
61
- # one for the mid level has_one association
62
- # one for the deep level level has_many on the mid level has_many association
63
- # one for the deep level level has_many on the mid level has_one association
64
- Item.fetch(@record.id)
65
- end
66
- end
67
-
68
- def test_saving_child_record_should_expire_parent_record
69
- IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key)
70
- if AssociatedRecord.primary_cache_index_enabled
71
- IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key)
72
- else
73
- IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key).never
74
- end
75
- @associated_record.name = 'different'
76
- @associated_record.save!
77
- end
78
-
79
- def test_saving_grand_child_record_should_expire_parent_record
80
- IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key)
81
- if AssociatedRecord.primary_cache_index_enabled
82
- IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key)
83
- else
84
- IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key).never
85
- end
86
- IdentityCache.cache.expects(:delete).with(@deeply_associated_record.primary_cache_index_key)
87
- @deeply_associated_record.name = 'different'
88
- @deeply_associated_record.save!
89
- end
90
-
91
- def test_set_inverse_associations
92
- DeeplyAssociatedRecord.cache_belongs_to :associated_record
93
- AssociatedRecord.cache_belongs_to :item
94
- Item.fetch(@record.id) # warm cache
95
-
96
- item = Item.fetch(@record.id)
97
-
98
- assert_queries(0) do
99
- assert_memcache_operations(0) do
100
- associated_record = item.fetch_associated_records.to_a.first
101
- deeply_associated_record = associated_record.fetch_deeply_associated_records.first
102
- assert_equal item.id, deeply_associated_record.fetch_associated_record.fetch_item.id
103
- end
104
- end
105
- end
106
-
107
- end
108
-
109
- class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
110
- def setup
111
- super
112
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
113
- Item.cache_has_many :associated_records, :embed => :ids
114
-
115
- @record = Item.new(:title => 'foo')
116
- @record.save
117
- @record.reload
118
- end
119
-
120
- def test_cache_repopulation_should_not_fetch_non_embedded_associations
121
- Item.any_instance.expects(:fetch_associated_records).never
122
- Item.fetch(@record.id) # cache miss
123
- end
124
- end
125
-
126
- class DisabledPrimaryIndexTest < RecursiveDenormalizedHasManyTest
127
- def setup
128
- super
129
- AssociatedRecord.disable_primary_cache_index
130
- end
131
- end
@@ -1,82 +0,0 @@
1
- require "test_helper"
2
-
3
- class SaveTest < IdentityCache::TestCase
4
- NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
5
-
6
- def setup
7
- super
8
- Item.cache_index :title, :unique => true
9
- Item.cache_index :id, :title, :unique => true
10
-
11
- @record = Item.create(:title => 'bob')
12
- @blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:1"
13
- end
14
-
15
- def test_create
16
- @record = Item.new
17
- @record.title = 'bob'
18
-
19
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('2/bob')}")
20
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
21
- expect_cache_delete("#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:2").once
22
- @record.save
23
- end
24
-
25
- def test_update
26
- # Regular flow, write index id, write index id/tile, delete data blob since Record has changed
27
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/fred')}")
28
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('fred')}")
29
- expect_cache_delete(@blob_key)
30
-
31
- # Delete index id, delete index id/title
32
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
33
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
34
-
35
- @record.title = 'fred'
36
- @record.save
37
- end
38
-
39
- def test_destroy
40
- # Regular flow: delete data blob, delete index id, delete index id/tile
41
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
42
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
43
- expect_cache_delete(@blob_key)
44
-
45
- @record.destroy
46
- end
47
-
48
- def test_destroy_with_changed_attributes
49
- # Make sure to delete the old cache index key, since the new title never ended up in an index
50
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
51
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
52
- expect_cache_delete(@blob_key)
53
-
54
- @record.title = 'fred'
55
- @record.destroy
56
- end
57
-
58
- def test_touch_will_expire_the_caches
59
- # Regular flow: delete data blob, delete index id, delete index id/tile
60
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
61
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
62
- expect_cache_delete(@blob_key)
63
-
64
- @record.touch
65
- end
66
-
67
- def test_expire_cache_works_in_a_transaction
68
- expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
69
- expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
70
- expect_cache_delete(@blob_key)
71
-
72
- ActiveRecord::Base.transaction do
73
- @record.send(:expire_cache)
74
- end
75
- end
76
-
77
- private
78
-
79
- def expect_cache_delete(key)
80
- @backend.expects(:write).with(key, IdentityCache::DELETED, anything)
81
- end
82
- end
@@ -1,112 +0,0 @@
1
- require "test_helper"
2
-
3
- class SchemaChangeTest < IdentityCache::TestCase
4
- class AddColumnToChild < ActiveRecord::Migration
5
- def up
6
- add_column :associated_records, :shiny, :string
7
- end
8
- end
9
-
10
- class AddColumnToDeepChild < ActiveRecord::Migration
11
- def up
12
- add_column :deeply_associated_records, :new_column, :string
13
- end
14
- end
15
-
16
- def setup
17
- super
18
- ActiveRecord::Migration.verbose = false
19
-
20
- read_new_schema
21
- Item.cache_has_one :associated, :embed => true
22
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
23
-
24
- @associated_record = AssociatedRecord.new(:name => 'bar')
25
- @deeply_associated_record = DeeplyAssociatedRecord.new(:name => "corge")
26
- @associated_record.deeply_associated_records << @deeply_associated_record
27
- @associated_record.deeply_associated_records << DeeplyAssociatedRecord.new(:name => "qux")
28
- @record = Item.new(:title => 'foo')
29
- @record.associated = @associated_record
30
-
31
- @associated_record.save!
32
- @record.save!
33
-
34
- @record.reload
35
- end
36
-
37
- def teardown
38
- active_records = [AssociatedRecord, DeeplyAssociatedRecord]
39
- super
40
- active_records.each {|ar| ar.reset_column_information }
41
- end
42
-
43
- # This helper simulates the models being reloaded
44
- def read_new_schema
45
- AssociatedRecord.reset_column_information
46
- DeeplyAssociatedRecord.reset_column_information
47
-
48
- AssociatedRecord.send(:instance_variable_set, :@rails_cache_key_prefix, nil)
49
- Item.send(:instance_variable_set, :@rails_cache_key_prefix, nil)
50
- end
51
-
52
- def test_schema_changes_on_embedded_association_should_cause_cache_miss_for_old_cached_objects
53
- record = Item.fetch(@record.id)
54
- record.fetch_associated
55
-
56
- AddColumnToChild.new.up
57
- read_new_schema
58
-
59
- Item.expects(:resolve_cache_miss).returns(@record)
60
- record = Item.fetch(@record.id)
61
- end
62
-
63
- def test_schema_changes_on_deeply_embedded_association_should_cause_cache_miss_for_old_cached_objects
64
- record = Item.fetch(@record.id)
65
- associated_record_from_cache = record.fetch_associated
66
- associated_record_from_cache.fetch_deeply_associated_records
67
-
68
- AddColumnToDeepChild.new.up
69
- read_new_schema
70
-
71
- Item.expects(:resolve_cache_miss).returns(@record)
72
- record = Item.fetch(@record.id)
73
- end
74
-
75
- def test_schema_changes_on_new_cached_child_association
76
- record = Item.fetch(@record.id)
77
-
78
- PolymorphicRecord.include(IdentityCache::WithoutPrimaryIndex)
79
- Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => true
80
- read_new_schema
81
-
82
- Item.expects(:resolve_cache_miss).returns(@record)
83
- record = Item.fetch(@record.id)
84
- end
85
-
86
- def test_embed_existing_cache_has_many
87
- PolymorphicRecord.include(IdentityCache)
88
- Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
89
- read_new_schema
90
-
91
- record = Item.fetch(@record.id)
92
-
93
- teardown_models
94
- setup_models
95
-
96
- PolymorphicRecord.include(IdentityCache::WithoutPrimaryIndex)
97
- Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => true
98
- read_new_schema
99
-
100
- record = Item.fetch(@record.id)
101
- end
102
-
103
- def test_add_non_embedded_cache_has_many
104
- PolymorphicRecord.include(IdentityCache)
105
- record = Item.fetch(@record.id)
106
-
107
- Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
108
- read_new_schema
109
-
110
- record = Item.fetch(@record.id)
111
- end
112
- end
@@ -1,16 +0,0 @@
1
- require "test_helper"
2
- require "helpers/serialization_format"
3
-
4
- class SerializationFormatChangeTest < IdentityCache::TestCase
5
- include SerializationFormat
6
-
7
- MESSAGE = "serialization format changed => increment IdentityCache.CACHE_VERSION and run rake update_serialization_format"
8
-
9
- def test_serialization_format_has_not_changed
10
- serialization = Marshal.load(serialize(serialized_record))
11
- preserialization = Marshal.load(File.binread(serialized_record_file))
12
- assert_equal(preserialization, serialization, MESSAGE)
13
- rescue SystemCallError
14
- assert(false, MESSAGE)
15
- end
16
- end
@@ -1,140 +0,0 @@
1
- require 'logger'
2
- require 'minitest/autorun'
3
- require 'mocha/setup'
4
- require 'active_record'
5
- require 'helpers/database_connection'
6
- require 'helpers/active_record_objects'
7
- require 'spy/integration'
8
- require 'memcached_store'
9
- require 'active_support/cache/memcached_store'
10
-
11
- require File.dirname(__FILE__) + '/../lib/identity_cache'
12
-
13
- DatabaseConnection.setup
14
- ActiveSupport::Cache::Store.instrument = true if ActiveSupport.version < Gem::Version.new("4.2.0")
15
-
16
- # This patches AR::MemcacheStore to notify AS::Notifications upon read_multis like the rest of rails does
17
- module MemcachedStoreInstrumentation
18
- def read_multi(*args, &block)
19
- instrument('read_multi', 'MULTI', keys: args) do
20
- super(*args, &block)
21
- end
22
- end
23
- end
24
- ActiveSupport::Cache::MemcachedStore.prepend(MemcachedStoreInstrumentation)
25
-
26
-
27
- MiniTest::Test = MiniTest::Unit::TestCase unless defined?(MiniTest::Test)
28
- class IdentityCache::TestCase < Minitest::Test
29
- include ActiveRecordObjects
30
- attr_reader :backend
31
-
32
- def setup
33
- if ActiveRecord.gem_version < Gem::Version.new('5') && ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks=)
34
- ActiveRecord::Base.raise_in_transactional_callbacks = true
35
- end
36
-
37
- DatabaseConnection.drop_tables
38
- DatabaseConnection.create_tables
39
-
40
- IdentityCache.logger = Logger.new(nil)
41
-
42
- memcached_host = ENV['MEMCACHED_HOST'] || "127.0.0.1"
43
- IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemcachedStore.new("#{memcached_host}:11211", :support_cas => true)
44
-
45
- setup_models
46
- end
47
-
48
- def teardown
49
- IdentityCache.cache.clear
50
- teardown_models
51
- end
52
-
53
- private
54
-
55
- def fetcher
56
- IdentityCache.cache.cache_fetcher
57
- end
58
-
59
- def assert_nothing_raised
60
- yield
61
- end
62
-
63
- def assert_not_nil(*args)
64
- assert(*args)
65
- end
66
-
67
- def assert_queries(num = 1)
68
- counter = SQLCounter.new
69
- subscriber = ActiveSupport::Notifications.subscribe('sql.active_record', counter)
70
- exception = false
71
- yield
72
- rescue
73
- exception = true
74
- raise
75
- ensure
76
- ActiveSupport::Notifications.unsubscribe(subscriber)
77
- assert_equal num, counter.log.size, "#{counter.log.size} instead of #{num} queries were executed.#{counter.log.size == 0 ? '' : "\nQueries:\n#{counter.log.join("\n")}"}" unless exception
78
- end
79
-
80
- def assert_memcache_operations(num)
81
- counter = CacheCounter.new
82
- subscriber = ActiveSupport::Notifications.subscribe(/cache_.*\.active_support/, counter)
83
- exception = false
84
- yield
85
- rescue
86
- exception = true
87
- raise
88
- ensure
89
- ActiveSupport::Notifications.unsubscribe(subscriber)
90
- assert_equal num, counter.log.size, "#{counter.log.size} instead of #{num} memcache operations were executed. #{counter.log.size == 0 ? '' : "\nOperations:\n#{counter.log.join("\n")}"}" unless exception
91
- end
92
-
93
- def assert_no_queries
94
- assert_queries(0) do
95
- yield
96
- end
97
- end
98
-
99
- def cache_hash(key)
100
- IdentityCache.memcache_hash(key)
101
- end
102
- end
103
-
104
- class SQLCounter
105
- cattr_accessor :ignored_sql
106
- self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/, /^SHOW /]
107
-
108
- # FIXME: this needs to be refactored so specific database can add their own
109
- # ignored SQL. This ignored SQL is for Oracle.
110
- ignored_sql.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im]
111
-
112
- attr_reader :ignore
113
- attr_accessor :log
114
-
115
- def initialize(ignore = self.class.ignored_sql)
116
- @ignore = ignore
117
- @log = []
118
- end
119
-
120
- def call(name, start, finish, message_id, values)
121
- sql = values[:sql]
122
-
123
- # FIXME: this seems bad. we should probably have a better way to indicate
124
- # the query was cached
125
- return if 'CACHE' == values[:name] || ignore.any? { |x| x =~ sql }
126
- self.log << sql
127
- end
128
- end
129
-
130
- class CacheCounter
131
- attr_accessor :log
132
-
133
- def initialize()
134
- @log = []
135
- end
136
-
137
- def call(name, start, finish, message_id, values)
138
- self.log << "#{name} #{(values[:keys].try(:join, ', ') || values[:key])}"
139
- end
140
- end