forest_liana 9.20.8 → 9.20.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfcdfafce741a2f8305f64a7241219a6f9b54227dd310dd7269ff83043f0f35d
4
- data.tar.gz: c3ce3c647b53d3cc7bd8c5d45ed98c887588112c6e5e7fc558ca6ca5ddf385f2
3
+ metadata.gz: 8081936e6d6a125213c778a94576d1eaaf5560eb838a89563a6e113ab79a2e46
4
+ data.tar.gz: b5cb7df552d00872c40981ee37009b534bb5a254ee637d7dd39dd71b840f6124
5
5
  SHA512:
6
- metadata.gz: debd8bdb65d707795b7e895769c3ec1bd1fc0796bc971edfad2d0446a6b19e1b2b78bdd1c64cd77b2dc615eecc5384b868d1e8ab01810646aa287fd8c7c1a1f1
7
- data.tar.gz: 9534d5fd16d409d282dd806955386e730a428c3c8405b0beb0284bd317f6825a8f5cdf616ca662e4148a8df9703b23e0370772edd9a35d9c6dbca9e5fe72ff76
6
+ metadata.gz: a1e231f576b02caed5a80f12fff4d6baabd4355ef9f5aae79afb3f4a6663e29cda2cdd078088e4949d42435c1bcf8f28b82bc7c90c619f971e17da7fa81bd45a
7
+ data.tar.gz: 0a93106150c9ead61198c464baaab09c0eb0974abc5c78570e980baa48bd3a05bdb4677720fa8b35704375665c06b297cad763325249601d08962222a9c444d4
@@ -85,7 +85,7 @@ module ForestLiana
85
85
  !@resource.defined_enums[column.name][@search.downcase].nil?
86
86
  conditions << "#{column_name} =
87
87
  #{@resource.defined_enums[column.name][@search.downcase]}"
88
- elsif !(column.respond_to?(:array) && column.array) && text_type?(column.type)
88
+ elsif !(column.respond_to?(:array) && column.array) && text_type?(column.type) && !malformed_uuid_search?
89
89
  conditions << "LOWER(#{column_name}) LIKE :search_value_for_string"
90
90
  end
91
91
  end
@@ -114,7 +114,7 @@ module ForestLiana
114
114
  resource = @resource.reflect_on_association(association.to_sym)
115
115
  unless (SchemaUtils.polymorphic?(resource))
116
116
  resource.klass.columns.each do |column|
117
- if !(column.respond_to?(:array) && column.array) && text_type?(column.type)
117
+ if !(column.respond_to?(:array) && column.array) && text_type?(column.type) && !malformed_uuid_search?
118
118
  if @collection.search_fields.nil? || (association_search &&
119
119
  association_search.include?(column.name))
120
120
  conditions << association_search_condition(resource.table_name,
@@ -138,7 +138,7 @@ module ForestLiana
138
138
  unless association_search.empty?
139
139
  resource = @resource.reflect_on_association(association.to_sym)
140
140
  resource.klass.columns.each do |column|
141
- if !(column.respond_to?(:array) && column.array) && text_type?(column.type)
141
+ if !(column.respond_to?(:array) && column.array) && text_type?(column.type) && !malformed_uuid_search?
142
142
  if association_search.include?(column.name)
143
143
  conditions << association_search_condition(resource.table_name,
144
144
  column.name)
@@ -150,11 +150,18 @@ module ForestLiana
150
150
  end
151
151
  end
152
152
 
153
- @records = @resource.where(
154
- conditions.join(' OR '),
155
- search_value_for_string: "%#{@search.downcase}%",
156
- search_value_for_uuid: @search.to_s
157
- ) unless conditions.empty?
153
+ if conditions.empty?
154
+ # NOTICE: a malformed-UUID search suppresses the only conditions it could
155
+ # have produced (text LIKE scans); match nothing rather than fall
156
+ # through to an unfiltered query that returns the whole table.
157
+ @records = @resource.none if malformed_uuid_search?
158
+ else
159
+ @records = @resource.where(
160
+ conditions.join(' OR '),
161
+ search_value_for_string: "%#{@search.downcase}%",
162
+ search_value_for_uuid: @search.to_s
163
+ )
164
+ end
158
165
  end
159
166
 
160
167
  @records
@@ -223,5 +230,17 @@ module ForestLiana
223
230
  def text_type?(type_sym)
224
231
  [:string, :text, :citext].include? type_sym
225
232
  end
233
+
234
+ # NOTICE: A search that is UUID-shaped but fails the strict REGEX_UUID (a
235
+ # truncated or mistyped UUID) can never match a real UUID column and,
236
+ # on text columns, only triggers `LOWER(col) LIKE '%…%'` sequential
237
+ # scans that can hit the statement timeout. Valid UUIDs are excluded
238
+ # so they keep matching UUIDs stored in varchar/text columns.
239
+ def malformed_uuid_search?
240
+ return false unless @search.is_a?(String)
241
+
242
+ @search.match?(/\A[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+\z/i) &&
243
+ !REGEX_UUID.match?(@search)
244
+ end
226
245
  end
227
246
  end
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "9.20.8"
2
+ VERSION = "9.20.9"
3
3
  end
@@ -16,6 +16,50 @@ module ForestLiana
16
16
  end
17
17
 
18
18
  describe '#perform' do
19
+ context 'when the search is a malformed UUID' do
20
+ # UUID-shaped but fails the strict REGEX_UUID (mistyped/truncated group).
21
+ # Starts with a letter so #to_i is 0 and adds no integer-`id` condition,
22
+ # leaving the text LIKE scans as the only possible matches.
23
+ let(:params) { { search: 'abcdef12-3456-4ae-ad4f-5662757713a2', searchExtended: '0' } }
24
+
25
+ before do
26
+ Tree.create!(name: 'Oak')
27
+ Tree.create!(name: 'Elm')
28
+ end
29
+
30
+ after { Tree.destroy_all }
31
+
32
+ it 'matches nothing instead of returning the unfiltered table' do
33
+ expect(builder.perform(Tree.all).count).to eq(0)
34
+ end
35
+ end
36
+
37
+ context 'when searchExtended is on and the search is a malformed UUID' do
38
+ # HashWithIndifferentAccess: the code reads @params['searchExtended'] (string).
39
+ let(:params) do
40
+ ActiveSupport::HashWithIndifferentAccess.new(
41
+ search: 'abcdef12-3456-4ae-ad4f-5662757713a2', searchExtended: '1'
42
+ )
43
+ end
44
+ let(:builder) { described_class.new(params, [:owner], collection, user) }
45
+
46
+ before { Tree.create!(name: 'Oak') }
47
+
48
+ after { Tree.destroy_all }
49
+
50
+ it 'does not build LIKE scans on associated text columns either' do
51
+ expect(builder.perform(Tree.all).to_sql).not_to match(/LIKE/i)
52
+ end
53
+ end
54
+
55
+ context 'when the search is a valid UUID' do
56
+ let(:params) { { search: '75fbcb43-f6f8-4cd1-861f-09a61fd1ddad', searchExtended: '0' } }
57
+
58
+ it 'still builds a LIKE scan on text columns (UUIDs stored as text)' do
59
+ expect(builder.perform(Tree.all).to_sql).to match(/LIKE/i)
60
+ end
61
+ end
62
+
19
63
  context 'when a column is an array uuid type' do
20
64
  let(:array_uuid_column) do
21
65
  double('Column', name: 'attachment_ids', type: :uuid, array: true).tap do |col|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.20.8
4
+ version: 9.20.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda