tsearch 1.0.5
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.
- data/lib/texticle.rb +78 -0
- data/lib/texticle/full_text_index.rb +54 -0
- data/lib/texticle/nodes/and_term_node.rb +5 -0
- data/lib/texticle/nodes/boolean_term_node.rb +2 -0
- data/lib/texticle/nodes/expression_node.rb +17 -0
- data/lib/texticle/nodes/grouped_term_node.rb +15 -0
- data/lib/texticle/nodes/not_term_node.rb +5 -0
- data/lib/texticle/nodes/or_term_node.rb +5 -0
- data/lib/texticle/nodes/query_node.rb +8 -0
- data/lib/texticle/nodes/quoted_term_node.rb +5 -0
- data/lib/texticle/nodes/term_node.rb +23 -0
- data/lib/texticle/nodes/word_node.rb +9 -0
- data/lib/texticle/parser.rb +53 -0
- data/lib/texticle/tasks.rb +55 -0
- data/lib/texticle/tquery.rb +762 -0
- data/lib/texticle/tquery.treetop +66 -0
- data/rails/init.rb +3 -0
- data/test/helper.rb +43 -0
- data/test/test_full_text_index.rb +74 -0
- data/test/test_texticle.rb +60 -0
- metadata +81 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
grammar TQuery
|
2
|
+
rule query
|
3
|
+
space expression more_query? space <QueryNode>
|
4
|
+
end
|
5
|
+
|
6
|
+
rule more_query
|
7
|
+
space query space <QueryNode>
|
8
|
+
end
|
9
|
+
|
10
|
+
rule expression
|
11
|
+
term+ space more:more_expression? <ExpressionNode>
|
12
|
+
end
|
13
|
+
|
14
|
+
rule more_expression
|
15
|
+
space expression <ExpressionNode>
|
16
|
+
end
|
17
|
+
|
18
|
+
rule grouped_term
|
19
|
+
'(' term+ ')' <GroupedTermNode>
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO support single or double quotes
|
23
|
+
rule quoted_term
|
24
|
+
'"' quoted_stuff:[^\"]* '"' <QuotedTermNode>
|
25
|
+
end
|
26
|
+
|
27
|
+
rule term
|
28
|
+
space (boolean_term / quoted_term / word / grouped_term) space <TermNode>
|
29
|
+
end
|
30
|
+
|
31
|
+
rule word
|
32
|
+
word_char+ <WordNode>
|
33
|
+
end
|
34
|
+
|
35
|
+
rule word_char
|
36
|
+
letter / digit / '_' / '&' / '.' / '!'
|
37
|
+
end
|
38
|
+
|
39
|
+
rule letter
|
40
|
+
[A-Za-z]
|
41
|
+
end
|
42
|
+
|
43
|
+
rule digit
|
44
|
+
[0-9]
|
45
|
+
end
|
46
|
+
|
47
|
+
rule space
|
48
|
+
[\s]*
|
49
|
+
end
|
50
|
+
|
51
|
+
rule boolean_term
|
52
|
+
and_term / or_term
|
53
|
+
end
|
54
|
+
|
55
|
+
rule and_term
|
56
|
+
('and' / '&&') term <AndTermNode>
|
57
|
+
end
|
58
|
+
|
59
|
+
rule or_term
|
60
|
+
('or' / '||') term <OrTermNode>
|
61
|
+
end
|
62
|
+
|
63
|
+
#rule not_term
|
64
|
+
# '!' term <NotTermNode>
|
65
|
+
#end
|
66
|
+
end
|
data/rails/init.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "texticle"
|
3
|
+
|
4
|
+
class TexticleTestCase < Test::Unit::TestCase
|
5
|
+
unless RUBY_VERSION >= '1.9'
|
6
|
+
undef :default_test
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup
|
10
|
+
warn "#{name}" if ENV['TESTOPTS'] == '-v'
|
11
|
+
end
|
12
|
+
|
13
|
+
def fake_model
|
14
|
+
Class.new do
|
15
|
+
@connected = false
|
16
|
+
@executed = []
|
17
|
+
@named_scopes = []
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :connected, :executed, :named_scopes
|
21
|
+
|
22
|
+
def connection
|
23
|
+
@connected = true
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute sql
|
28
|
+
@executed << sql
|
29
|
+
end
|
30
|
+
|
31
|
+
def table_name; 'fake_model'; end
|
32
|
+
|
33
|
+
def named_scope *args
|
34
|
+
@named_scopes << args
|
35
|
+
end
|
36
|
+
|
37
|
+
def quote thing
|
38
|
+
"'#{thing}'"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestFullTextIndex < TexticleTestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
@fm = fake_model
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_initialize
|
10
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
11
|
+
name
|
12
|
+
value 'A'
|
13
|
+
end
|
14
|
+
assert_equal 'name', fti.index_columns['none'].first
|
15
|
+
assert_equal 'value', fti.index_columns['A'].first
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_destroy
|
19
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
20
|
+
name
|
21
|
+
value 'A'
|
22
|
+
end
|
23
|
+
fti.destroy
|
24
|
+
assert @fm.connected
|
25
|
+
assert_equal 1, @fm.executed.length
|
26
|
+
executed = @fm.executed.first
|
27
|
+
assert_match "DROP index IF EXISTS #{fti.instance_variable_get(:@name)}", executed
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_create
|
31
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
32
|
+
name
|
33
|
+
value 'A'
|
34
|
+
end
|
35
|
+
fti.create
|
36
|
+
assert @fm.connected
|
37
|
+
assert_equal 1, @fm.executed.length
|
38
|
+
executed = @fm.executed.first
|
39
|
+
assert_match fti.to_s, executed
|
40
|
+
assert_match "CREATE index #{fti.instance_variable_get(:@name)}", executed
|
41
|
+
assert_match "ON #{@fm.table_name}", executed
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_to_s_no_weight
|
45
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
46
|
+
name
|
47
|
+
end
|
48
|
+
assert_equal "to_tsvector('english', coalesce(#{@fm.table_name}.name, ''))", fti.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_to_s_A_weight
|
52
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
53
|
+
name 'A'
|
54
|
+
end
|
55
|
+
assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.name, '')), 'A')", fti.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_to_s_multi_weight
|
59
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
60
|
+
name 'A'
|
61
|
+
value 'A'
|
62
|
+
description 'B'
|
63
|
+
end
|
64
|
+
assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.name, '') || ' ' || coalesce(#{@fm.table_name}.value, '')), 'A') || ' ' || setweight(to_tsvector('english', coalesce(#{@fm.table_name}.description, '')), 'B')", fti.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_mixed_weight
|
68
|
+
fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
|
69
|
+
name
|
70
|
+
value 'A'
|
71
|
+
end
|
72
|
+
assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.value, '')), 'A') || ' ' || to_tsvector('english', coalesce(#{@fm.table_name}.name, ''))", fti.to_s
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTexticle < TexticleTestCase
|
4
|
+
def test_index_method
|
5
|
+
x = fake_model
|
6
|
+
x.class_eval do
|
7
|
+
extend Texticle
|
8
|
+
index do
|
9
|
+
name
|
10
|
+
end
|
11
|
+
end
|
12
|
+
assert_equal 1, x.full_text_indexes.length
|
13
|
+
assert_equal 1, x.named_scopes.length
|
14
|
+
|
15
|
+
x.full_text_indexes.first.create
|
16
|
+
assert_match "#{x.table_name}_fts_idx", x.executed.first
|
17
|
+
assert_equal :search, x.named_scopes.first.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_named_index
|
21
|
+
x = fake_model
|
22
|
+
x.class_eval do
|
23
|
+
extend Texticle
|
24
|
+
index('awesome') do
|
25
|
+
name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
assert_equal 1, x.full_text_indexes.length
|
29
|
+
assert_equal 1, x.named_scopes.length
|
30
|
+
|
31
|
+
x.full_text_indexes.first.create
|
32
|
+
assert_match "#{x.table_name}_awesome_fts_idx", x.executed.first
|
33
|
+
assert_equal :search_awesome, x.named_scopes.first.first
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_named_scope_select
|
37
|
+
x = fake_model
|
38
|
+
x.class_eval do
|
39
|
+
extend Texticle
|
40
|
+
index('awesome') do
|
41
|
+
name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
ns = x.named_scopes.first[1].call('foo')
|
45
|
+
assert_match(/^#{x.table_name}\.\*/, ns[:select])
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_double_quoted_queries
|
49
|
+
x = fake_model
|
50
|
+
x.class_eval do
|
51
|
+
extend Texticle
|
52
|
+
index('awesome') do
|
53
|
+
name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
ns = x.named_scopes.first[1].call('foo bar "foo bar"')
|
58
|
+
assert_match(/'foo' & 'bar' & 'foo bar'/, ns[:select])
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tsearch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
version: 1.0.5
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- David Harding
|
13
|
+
autorequire: texticle
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-18 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Provides easy access to PostgreSQL's tsearch full text search for your ActiveRecord models using named scopes
|
22
|
+
email: david@metalogik.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- rails/init.rb
|
31
|
+
- lib/texticle/full_text_index.rb
|
32
|
+
- lib/texticle/nodes/and_term_node.rb
|
33
|
+
- lib/texticle/nodes/boolean_term_node.rb
|
34
|
+
- lib/texticle/nodes/expression_node.rb
|
35
|
+
- lib/texticle/nodes/grouped_term_node.rb
|
36
|
+
- lib/texticle/nodes/not_term_node.rb
|
37
|
+
- lib/texticle/nodes/or_term_node.rb
|
38
|
+
- lib/texticle/nodes/query_node.rb
|
39
|
+
- lib/texticle/nodes/quoted_term_node.rb
|
40
|
+
- lib/texticle/nodes/term_node.rb
|
41
|
+
- lib/texticle/nodes/word_node.rb
|
42
|
+
- lib/texticle/parser.rb
|
43
|
+
- lib/texticle/tasks.rb
|
44
|
+
- lib/texticle/tquery.rb
|
45
|
+
- lib/texticle.rb
|
46
|
+
- test/helper.rb
|
47
|
+
- test/test_full_text_index.rb
|
48
|
+
- test/test_texticle.rb
|
49
|
+
- lib/texticle/tquery.treetop
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: http://github.com/dharding/texticle
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: tsearch
|
76
|
+
rubygems_version: 1.3.6
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Provides easy access to PostgreSQL's tsearch full text search for your ActiveRecord models
|
80
|
+
test_files: []
|
81
|
+
|