kasket 4.9.1 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75e9005963ca629245005b0c9a2a9d94cb9023fac9cc12327045e25eaca547e0
4
- data.tar.gz: e7aec95609b6918646f3b2b420d5af038ef171888ac98cdea4c0fb16cf6ce086
3
+ metadata.gz: 5b7ff0fe3b5afa5c01eb36fc7f89bfe94669b98340bb1537546fe6019b0d61db
4
+ data.tar.gz: d69c8e0d2f9303456f5f647867a67496b49d95e8af114f51ec54acf95947d257
5
5
  SHA512:
6
- metadata.gz: f19bd6ca3a60073c738907e20052d461cdcc0139a1c300765ed3b029022107d7c477b6a5e6437bb34d73de5d8e2c6050eac3e6834ec6c7f27c3e7e1e5a0fa200
7
- data.tar.gz: effe82d0f1620cc7742407a46054b558675ac061050af22313daccdc52dc30204c5ae02c67f91aeea64ce07f4c687d2a6eb699c132a0914284d2554cec0d014b
6
+ metadata.gz: 610b4879bebfdd27f4796ce840aac305d30502702befab16623f8c1e7bd316dd7529ab5af4513d05e565b25cb716089e7b71ed34aad8c75099bf5493137c3e31
7
+ data.tar.gz: b6710e8aa232d3105822aec11431a8d3c76618c7d124e3e1773528c3decc3de57617ffa17f6a60425729e694a4cde8e281d74ed0bd7e88fcd3b34e371cae245b
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Kasket [![Build status](https://circleci.com/gh/zendesk/kasket.svg?style=svg)](https://circleci.com/gh/zendesk/kasket)
1
+ # Kasket
2
2
 
3
3
  ### Puts a cap on your queries
4
4
  A caching layer for ActiveRecord (3.x and 4.x)
@@ -12,26 +12,43 @@ module Kasket
12
12
  def initialize(model_class)
13
13
  @model_class = model_class
14
14
 
15
- @supported_query_pattern = /^select\s+((?:`|")#{@model_class.table_name}(?:`|")\.)?\* from (?:`|")#{@model_class.table_name}(?:`|") where (.*?)(|\s+limit 1)\s*$/i
15
+ @supported_query_pattern = /^select\s+(.+?)\s+from (?:`|")#{@model_class.table_name}(?:`|") where (.*?)(|\s+limit 1)\s*$/i
16
16
 
17
+ @star_pattern = /^((`|")#{@model_class.table_name}\2\.)?\*$/
17
18
  # Matches: `users`.id, `users`.`id`, users.id, id
18
19
  @table_and_column_pattern = /(?:(?:`|")?#{@model_class.table_name}(?:`|")?\.)?(?:`|")?([a-zA-Z]\w*)(?:`|")?/
19
20
  # Matches: KEY = VALUE, (KEY = VALUE), ()(KEY = VALUE))
20
21
  @key_eq_value_pattern = /^[\(\s]*#{@table_and_column_pattern}\s+(=|IN)\s+#{VALUE}[\)\s]*$/
21
22
  end
22
23
 
24
+ ##
25
+ # Parses a SQL query to produce a kasket query
26
+ #
27
+ # @param sql [String] the sql query to parse
28
+ # @return [Hash|nil] the kasket query, or nil if the sql query is not supported
23
29
  def parse(sql)
24
30
  if match = @supported_query_pattern.match(sql)
31
+ select = match[1]
32
+ unless @star_pattern.match? select
33
+ # If we're not selecting all columns using star, then ensure all columns are selected explicitly
34
+ select_columns = select.split(/\s*,\s*/).map do |s|
35
+ break unless column_match = @table_and_column_pattern.match(s)
36
+
37
+ column_match[1]
38
+ end.uniq
39
+ columns = @model_class.column_names
40
+ return unless columns.size == select_columns.size && (columns - select_columns).empty?
41
+ end
25
42
  where = match[2]
26
43
  limit = match[3]
27
44
 
28
45
  query = {}
29
46
  query[:attributes] = sorted_attribute_value_pairs(where)
30
- return nil if query[:attributes].nil?
47
+ return if query[:attributes].nil?
31
48
 
32
- if query[:attributes].size > 1 && query[:attributes].map(&:last).any? {|a| a.is_a?(Array)}
49
+ if query[:attributes].size > 1 && query[:attributes].map(&:last).any?(Array)
33
50
  # this is a query with IN conditions AND other conditions
34
- return nil
51
+ return
35
52
  end
36
53
 
37
54
  query[:index] = query[:attributes].map(&:first)
@@ -64,23 +64,11 @@ module Kasket
64
64
  end
65
65
 
66
66
  def find_by_sql_with_kasket_on_id_array(keys)
67
- begin
68
- key_attributes_map = Kasket.cache.read_multi(*keys)
69
- rescue RuntimeError => e
70
- # Elasticache Memcached has a bug where it returns a 0x00 binary protocol response with no data
71
- # during a reboot, causing the Dalli memcached client to throw a RuntimeError during a multi get
72
- # (https://github.com/petergoldstein/dalli/blob/v2.7.7/lib/dalli/server.rb#L148).
73
- # Fall back to the database when this happens.
74
- if e.message == "multi_response has completed"
75
- key_attributes_map = missing_records_from_db(keys)
76
- else
77
- raise
78
- end
79
- else
80
- found_keys, missing_keys = keys.partition {|k| key_attributes_map[k] }
81
- found_keys.each {|k| key_attributes_map[k] = instantiate(key_attributes_map[k].dup) }
82
- key_attributes_map.merge!(missing_records_from_db(missing_keys))
83
- end
67
+ key_attributes_map = Kasket.cache.read_multi(*keys)
68
+
69
+ found_keys, missing_keys = keys.partition {|k| key_attributes_map[k] }
70
+ found_keys.each {|k| key_attributes_map[k] = instantiate(key_attributes_map[k].dup) }
71
+ key_attributes_map.merge!(missing_records_from_db(missing_keys))
84
72
 
85
73
  key_attributes_map.values.compact
86
74
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Kasket
3
- VERSION = '4.9.1'
3
+ VERSION = '4.10.0'
4
4
  class Version
5
5
  MAJOR = Kasket::VERSION.split('.')[0]
6
6
  MINOR = Kasket::VERSION.split('.')[1]
@@ -52,11 +52,18 @@ module Kasket
52
52
  return :unsupported if ActiveRecord::VERSION::MAJOR < 5 ? node.having : node.havings.present?
53
53
  return :unsupported if node.set_quantifier
54
54
  return :unsupported if !node.source || node.source.empty?
55
- return :unsupported if node.projections.size != 1
55
+ return :unsupported if node.projections.empty?
56
56
 
57
57
  select = node.projections[0]
58
58
  select = select.name if select.respond_to?(:name)
59
- return :unsupported if select != '*'
59
+ if select != '*'
60
+ # If we're not selecting all columns using star, then ensure all columns are selected explicitly
61
+ column_names = @model_class.column_names
62
+ return :unsupported unless node.projections.size == column_names.size
63
+
64
+ projection_names = node.projections.map { |p| p.name if p.respond_to?(:name) }.compact
65
+ return unless (column_names - projection_names).empty?
66
+ end
60
67
 
61
68
  parts = [visit(node.source)]
62
69
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kasket
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.9.1
4
+ version: 4.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mick Staugaard
8
8
  - Eric Chapweske
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-08-27 00:00:00.000000000 Z
12
+ date: 2022-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -31,118 +31,6 @@ dependencies:
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '6.1'
34
- - !ruby/object:Gem::Dependency
35
- name: bump
36
- requirement: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- type: :development
42
- prerelease: false
43
- version_requirements: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- - !ruby/object:Gem::Dependency
49
- name: bundler
50
- requirement: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- type: :development
56
- prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: minitest
64
- requirement: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- type: :development
70
- prerelease: false
71
- version_requirements: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- - !ruby/object:Gem::Dependency
77
- name: minitest-rg
78
- requirement: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- type: :development
84
- prerelease: false
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- - !ruby/object:Gem::Dependency
91
- name: mocha
92
- requirement: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- type: :development
98
- prerelease: false
99
- version_requirements: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- - !ruby/object:Gem::Dependency
105
- name: rake
106
- requirement: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- type: :development
112
- prerelease: false
113
- version_requirements: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- - !ruby/object:Gem::Dependency
119
- name: timecop
120
- requirement: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- type: :development
126
- prerelease: false
127
- version_requirements: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- - !ruby/object:Gem::Dependency
133
- name: wwtd
134
- requirement: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- type: :development
140
- prerelease: false
141
- version_requirements: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
34
  description: puts a cap on your queries
147
35
  email:
148
36
  - mick@zendesk.com
@@ -165,7 +53,7 @@ homepage: http://github.com/zendesk/kasket
165
53
  licenses:
166
54
  - Apache License Version 2.0
167
55
  metadata: {}
168
- post_install_message:
56
+ post_install_message:
169
57
  rdoc_options: []
170
58
  require_paths:
171
59
  - lib
@@ -180,8 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
68
  - !ruby/object:Gem::Version
181
69
  version: '0'
182
70
  requirements: []
183
- rubygems_version: 3.1.6
184
- signing_key:
71
+ rubygems_version: 3.0.3.1
72
+ signing_key:
185
73
  specification_version: 4
186
74
  summary: A write back caching layer on active record
187
75
  test_files: []