pg_search 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ ### 0.3.2
2
+
3
+ * Fix :prefix search in PostgreSQL 8.x
4
+
5
+ * Disable {:ignoring => :accents} in PostgreSQL 8.x
6
+
1
7
  ### 0.3.1
2
8
 
3
9
  * Fix syntax error in generated dmetaphone migration. (Max De Marzi)
data/README.rdoc CHANGED
@@ -105,7 +105,7 @@ To remove all of the documents for a given class, you can simply delete all of t
105
105
 
106
106
  Run this Rake task to regenerate all of the documents for a given class.
107
107
 
108
- $ rake pg_search:multisearch:rebuild CLASS=BlogPost
108
+ $ rake pg_search:multisearch:rebuild MODEL=BlogPost
109
109
 
110
110
  Currently this is only supported for :against methods that directly map to Active Record attributes. Until that is fixed, you could also manually rebuild all of the documents.
111
111
 
@@ -414,7 +414,7 @@ Trigram support is currently available as part of the {pg_trgm contrib package}[
414
414
 
415
415
  Website.kinda_spelled_like("Yahoo!") # => [yahooo, yohoo]
416
416
 
417
- === Ignoring accent marks
417
+ === Ignoring accent marks (PostgreSQL 9.0 and above only)
418
418
 
419
419
  Most of the time you will want to ignore accent marks when searching. This makes it possible to find words like "piñata" when searching with the query "pinata". If you set a pg_search_scope to ignore accents, it will ignore accents in both the searchable text and the query terms.
420
420
 
data/lib/pg_search.rb CHANGED
@@ -41,6 +41,8 @@ module PgSearch
41
41
  Thread.current.key?("PgSearch.enable_multisearch") ? Thread.current["PgSearch.enable_multisearch"] : true
42
42
  end
43
43
  end
44
+
45
+ class NotSupportedForPostgresqlVersion < StandardError; end
44
46
  end
45
47
 
46
48
  require "pg_search/configuration"
@@ -61,6 +61,14 @@ module PgSearch
61
61
  @options[:order_within_rank]
62
62
  end
63
63
 
64
+ def postgresql_version
65
+ @model.connection.send(:postgresql_version)
66
+ end
67
+
68
+ def logger
69
+ @model.logger
70
+ end
71
+
64
72
  private
65
73
 
66
74
  def default_options
@@ -19,7 +19,12 @@ module PgSearch
19
19
 
20
20
  def join(primary_key)
21
21
  selects = columns.map do |column|
22
- "string_agg(#{column.full_name}, ' ') AS #{column.alias}"
22
+ case @model.connection.send(:postgresql_version)
23
+ when 0..90000
24
+ "array_to_string(array_agg(#{column.full_name}), ' ') AS #{column.alias}"
25
+ else
26
+ "string_agg(#{column.full_name}, ' ') AS #{column.alias}"
27
+ end
23
28
  end.join(", ")
24
29
  relation = @model.joins(@name).select("#{primary_key} AS id, #{selects}").group(primary_key)
25
30
  "LEFT OUTER JOIN (#{relation.to_sql}) #{subselect_alias} ON #{subselect_alias}.id = #{primary_key}"
@@ -31,22 +31,28 @@ module PgSearch
31
31
  @columns.map { |column| column.to_sql }.join(" || ' ' || ")
32
32
  end
33
33
 
34
- def tsquery
35
- return "''" if @query.blank?
34
+ DISALLOWED_TSQUERY_CHARACTERS = /['?\-\\:]/
36
35
 
37
- @query.split(" ").compact.map do |term|
38
- sanitized_term = term.gsub(/['?\-\\:]/, " ")
36
+ def tsquery_for_term(term)
37
+ sanitized_term = term.gsub(DISALLOWED_TSQUERY_CHARACTERS, " ")
39
38
 
40
- term_sql = @normalizer.add_normalization(connection.quote(sanitized_term))
39
+ term_sql = @normalizer.add_normalization(connection.quote(sanitized_term))
41
40
 
42
- # After this, the SQL expression evaluates to a string containing the term surrounded by single-quotes.
43
- tsquery_sql = "#{connection.quote("' ")} || #{term_sql} || #{connection.quote(" '")}"
41
+ # After this, the SQL expression evaluates to a string containing the term surrounded by single-quotes.
42
+ # If :prefix is true, then the term will also have :* appended to the end.
43
+ tsquery_sql = [
44
+ connection.quote("' "),
45
+ term_sql,
46
+ connection.quote(" '"),
47
+ (connection.quote(':*') if @options[:prefix])
48
+ ].compact.join(" || ")
44
49
 
45
- # Add tsearch prefix operator if we're using a prefix search.
46
- tsquery_sql = "#{tsquery_sql} || #{connection.quote(':*')}" if @options[:prefix]
50
+ "to_tsquery(:dictionary, #{tsquery_sql})"
51
+ end
47
52
 
48
- "to_tsquery(:dictionary, #{tsquery_sql})"
49
- end.join(@options[:any_word] ? ' || ' : ' && ')
53
+ def tsquery
54
+ return "''" if @query.blank?
55
+ @query.split(" ").compact.map { |term| tsquery_for_term(term) }.join(@options[:any_word] ? ' || ' : ' && ')
50
56
  end
51
57
 
52
58
  def tsdocument
@@ -55,7 +61,7 @@ module PgSearch
55
61
  search_column.weight.nil? ? tsvector : "setweight(#{tsvector}, #{connection.quote(search_column.weight)})"
56
62
  end.join(" || ")
57
63
  end
58
-
64
+
59
65
  # From http://www.postgresql.org/docs/8.3/static/textsearch-controls.html
60
66
  # 0 (the default) ignores the document length
61
67
  # 1 divides the rank by 1 + the logarithm of the document length
@@ -6,7 +6,16 @@ module PgSearch
6
6
 
7
7
  def add_normalization(original_sql)
8
8
  normalized_sql = original_sql
9
- normalized_sql = "unaccent(#{normalized_sql})" if @config.ignore.include?(:accents)
9
+ if @config.ignore.include?(:accents)
10
+ if @config.postgresql_version < 90000
11
+ raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE)
12
+ Sorry, {:ignoring => :accents} only works in PostgreSQL 9.0 and above.
13
+ #{@config.inspect}
14
+ MESSAGE
15
+ else
16
+ normalized_sql = "unaccent(#{normalized_sql})"
17
+ end
18
+ end
10
19
  normalized_sql
11
20
  end
12
21
  end
@@ -1,3 +1,3 @@
1
1
  module PgSearch
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -369,14 +369,14 @@ describe "an ActiveRecord model which includes PgSearch" do
369
369
  results.should =~ included
370
370
  end
371
371
  end
372
-
372
+
373
373
  describe "ranking" do
374
374
  before do
375
375
  ["Strip Down", "Down", "Down and Out", "Won't Let You Down"].each do |name|
376
376
  ModelWithPgSearch.create! :content => name
377
377
  end
378
378
  end
379
-
379
+
380
380
  context "with a normalization specified" do
381
381
  before do
382
382
  ModelWithPgSearch.class_eval do
@@ -389,12 +389,12 @@ describe "an ActiveRecord model which includes PgSearch" do
389
389
  end
390
390
  it "ranks the results for documents with less text higher" do
391
391
  results = ModelWithPgSearch.search_content_with_normalization("down")
392
-
392
+
393
393
  results.map(&:content).should == ["Down", "Strip Down", "Down and Out", "Won't Let You Down"]
394
394
  results.first.rank.should be > results.last.rank
395
395
  end
396
396
  end
397
-
397
+
398
398
  context "with no normalization" do
399
399
  before do
400
400
  ModelWithPgSearch.class_eval do
@@ -405,7 +405,7 @@ describe "an ActiveRecord model which includes PgSearch" do
405
405
  end
406
406
  it "ranks the results equally" do
407
407
  results = ModelWithPgSearch.search_content_without_normalization("down")
408
-
408
+
409
409
  results.map(&:content).should == ["Strip Down", "Down", "Down and Out", "Won't Let You Down"]
410
410
  results.first.rank.should == results.last.rank
411
411
  end
@@ -599,14 +599,22 @@ describe "an ActiveRecord model which includes PgSearch" do
599
599
  end
600
600
  end
601
601
 
602
- it "returns rows that match the query but not its accents" do
603
- # \303\241 is a with acute accent
604
- # \303\251 is e with acute accent
602
+ if ActiveRecord::Base.connection.send(:postgresql_version) < 90000
603
+ it "is unsupported in PostgreSQL 8.x" do
604
+ lambda do
605
+ ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
606
+ end.should raise_exception(PgSearch::NotSupportedForPostgresqlVersion)
607
+ end
608
+ else
609
+ it "returns rows that match the query but not its accents" do
610
+ # \303\241 is a with acute accent
611
+ # \303\251 is e with acute accent
605
612
 
606
- included = ModelWithPgSearch.create!(:title => "\303\241bcdef")
613
+ included = ModelWithPgSearch.create!(:title => "\303\241bcdef")
607
614
 
608
- results = ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
609
- results.should == [included]
615
+ results = ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
616
+ results.should == [included]
617
+ end
610
618
  end
611
619
  end
612
620
 
data/spec/spec_helper.rb CHANGED
@@ -35,7 +35,9 @@ rescue => e
35
35
  end
36
36
 
37
37
  install_contrib_module_if_missing("pg_trgm", "SELECT 'abcdef' % 'cdef'", "t")
38
- install_contrib_module_if_missing("unaccent", "SELECT unaccent('foo')", "foo")
38
+ unless connection.send(:postgresql_version) < 90000
39
+ install_contrib_module_if_missing("unaccent", "SELECT unaccent('foo')", "foo")
40
+ end
39
41
  install_contrib_module_if_missing("fuzzystrmatch", "SELECT dmetaphone('foo')", "f")
40
42
 
41
43
  ActiveRecord::Base.connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'dmetaphone.sql')))
metadata CHANGED
@@ -1,46 +1,60 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: pg_search
3
- version: !ruby/object:Gem::Version
4
- version: 0.3.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 2
10
+ version: 0.3.2
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Case Commons, LLC
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-09-08 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2011-10-18 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: activerecord
16
- requirement: &2164362320 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '3'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 5
29
+ segments:
30
+ - 3
31
+ version: "3"
22
32
  type: :runtime
23
- prerelease: false
24
- version_requirements: *2164362320
25
- - !ruby/object:Gem::Dependency
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
26
35
  name: activesupport
27
- requirement: &2164361700 !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
28
38
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '3'
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 5
43
+ segments:
44
+ - 3
45
+ version: "3"
33
46
  type: :runtime
34
- prerelease: false
35
- version_requirements: *2164361700
36
- description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
37
- full text search
38
- email:
47
+ version_requirements: *id002
48
+ description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
49
+ email:
39
50
  - casecommons-dev@googlegroups.com
40
51
  executables: []
52
+
41
53
  extensions: []
54
+
42
55
  extra_rdoc_files: []
43
- files:
56
+
57
+ files:
44
58
  - .autotest
45
59
  - .gitignore
46
60
  - .rspec
@@ -80,30 +94,38 @@ files:
80
94
  - sql/uninstall_dmetaphone.sql
81
95
  homepage: https://github.com/Casecommons/pg_search
82
96
  licenses: []
97
+
83
98
  post_install_message:
84
99
  rdoc_options: []
85
- require_paths:
100
+
101
+ require_paths:
86
102
  - lib
87
- required_ruby_version: !ruby/object:Gem::Requirement
103
+ required_ruby_version: !ruby/object:Gem::Requirement
88
104
  none: false
89
- requirements:
90
- - - ! '>='
91
- - !ruby/object:Gem::Version
92
- version: '0'
93
- required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
113
  none: false
95
- requirements:
96
- - - ! '>='
97
- - !ruby/object:Gem::Version
98
- version: '0'
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
99
121
  requirements: []
122
+
100
123
  rubyforge_project:
101
- rubygems_version: 1.8.10
124
+ rubygems_version: 1.8.4
102
125
  signing_key:
103
126
  specification_version: 3
104
- summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
105
- full text search
106
- test_files:
127
+ summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
128
+ test_files:
107
129
  - spec/associations_spec.rb
108
130
  - spec/pg_search/document_spec.rb
109
131
  - spec/pg_search/multisearch_spec.rb