db_text_search 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +1 -1
- data/lib/db_text_search/case_insensitive_eq/abstract_adapter.rb +4 -1
- data/lib/db_text_search/case_insensitive_eq/collate_nocase_adapter.rb +7 -9
- data/lib/db_text_search/case_insensitive_eq/insensitive_column_adapter.rb +2 -0
- data/lib/db_text_search/case_insensitive_eq/lower_adapter.rb +12 -14
- data/lib/db_text_search/case_insensitive_eq.rb +16 -7
- data/lib/db_text_search/full_text_search/abstract_adapter.rb +7 -20
- data/lib/db_text_search/full_text_search/mysql_adapter.rb +11 -8
- data/lib/db_text_search/full_text_search/postgres_adapter.rb +13 -14
- data/lib/db_text_search/full_text_search/sqlite_adapter.rb +12 -7
- data/lib/db_text_search/full_text_search.rb +24 -10
- data/lib/db_text_search/query_building.rb +21 -0
- data/lib/db_text_search/version.rb +2 -1
- data/lib/db_text_search.rb +5 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c4d97cd16283ff2c47726a56e36fee85c3eb922
|
4
|
+
data.tar.gz: 06b3ca789b57a423f9ffc33840903e8028377263
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1ef0f9d45289ed1623f73cded6a2bd3c2f7ad88928364af7b7e94077eb79bcb93c5842c9f772e64b003d5039c64d3028242395d4263ad7574ebdf41e7854231
|
7
|
+
data.tar.gz: 027a5ebcfc61f1d017aee0bd61b66e7327132667085556d60fe3453b92f266093bad59e9f248dde4ec9ff1e6539716a468b3e8805f9a3f8957cf3335c592acb6
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@ require 'db_text_search/query_building'
|
|
2
2
|
module DbTextSearch
|
3
3
|
class CaseInsensitiveEq
|
4
4
|
# A base class for CaseInsensitiveStringFinder adapters.
|
5
|
+
# @abstract
|
6
|
+
# @api private
|
5
7
|
class AbstractAdapter
|
6
8
|
include ::DbTextSearch::QueryBuilding
|
7
9
|
|
@@ -25,7 +27,8 @@ module DbTextSearch
|
|
25
27
|
# @param table_name [String, Symbol]
|
26
28
|
# @param column_name [String, Symbol]
|
27
29
|
# @param options [Hash] passed down to ActiveRecord::ConnectionAdapters::SchemaStatements#add_index.
|
28
|
-
# @
|
30
|
+
# @option options name [String] index name
|
31
|
+
# @option options unique [Boolean] default: false
|
29
32
|
# @abstract
|
30
33
|
def self.add_index(connection, table_name, column_name, options = {})
|
31
34
|
fail 'abstract'
|
@@ -1,25 +1,23 @@
|
|
1
1
|
require 'db_text_search/case_insensitive_eq/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class CaseInsensitiveEq
|
4
|
+
# Provides case-insensitive string-in-set querying via COLLATE NOCASE.
|
5
|
+
# @api private
|
4
6
|
class CollateNocaseAdapter < AbstractAdapter
|
5
7
|
# (see AbstractAdapter#find)
|
6
8
|
def find(values)
|
7
9
|
conn = @scope.connection
|
8
|
-
@scope.where
|
9
|
-
#{quoted_scope_column} COLLATE NOCASE IN (#{values.map { |v| conn.quote(v.to_s) }.join(', ')})
|
10
|
-
SQL
|
10
|
+
@scope.where "#{quoted_scope_column} COLLATE NOCASE IN (#{values.map { |v| conn.quote(v.to_s) }.join(', ')})"
|
11
11
|
end
|
12
12
|
|
13
13
|
# (see AbstractAdapter.add_index)
|
14
14
|
def self.add_index(connection, table_name, column_name, options = {})
|
15
15
|
# TODO: Switch to the native Rails solution once it's landed, as the current one requires SQL dump format.
|
16
16
|
# https://github.com/rails/rails/pull/18499
|
17
|
-
options.
|
18
|
-
|
19
|
-
connection.
|
20
|
-
|
21
|
-
(#{connection.quote_column_name(column_name)} COLLATE NOCASE);
|
22
|
-
SQL
|
17
|
+
options = options.dup
|
18
|
+
options[:name] ||= "#{column_name}_nocase"
|
19
|
+
options[:expression] = "(#{connection.quote_column_name(column_name)} COLLATE NOCASE)"
|
20
|
+
connection.exec_query quoted_create_index(connection, table_name, **options)
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'db_text_search/case_insensitive_eq/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class CaseInsensitiveEq
|
4
|
+
# Provides case-insensitive string-in-set querying for case-insensitive columns.
|
5
|
+
# @api private
|
4
6
|
class InsensitiveColumnAdapter < AbstractAdapter
|
5
7
|
# (see AbstractAdapter#find)
|
6
8
|
def find(values)
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'db_text_search/case_insensitive_eq/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class CaseInsensitiveEq
|
4
|
+
# Provides case-insensitive string-in-set querying by applying the database LOWER function.
|
5
|
+
# @api private
|
4
6
|
class LowerAdapter < AbstractAdapter
|
5
7
|
# (see AbstractAdapter#find)
|
6
8
|
def find(values)
|
7
9
|
conn = @scope.connection
|
8
|
-
@scope.where
|
9
|
-
LOWER(#{quoted_scope_column}) IN (#{values.map { |v| "LOWER(#{conn.quote(v.to_s)})" }.join(', ')})
|
10
|
-
SQL
|
10
|
+
@scope.where "LOWER(#{quoted_scope_column}) IN (#{values.map { |v| "LOWER(#{conn.quote(v.to_s)})" }.join(', ')})"
|
11
11
|
end
|
12
12
|
|
13
13
|
# (see AbstractAdapter.add_index)
|
@@ -15,21 +15,19 @@ module DbTextSearch
|
|
15
15
|
if connection.adapter_name =~ /postgres/i
|
16
16
|
# TODO: Switch to native Rails support once it lands.
|
17
17
|
# https://github.com/rails/rails/pull/18499
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
options = options.dup
|
19
|
+
options[:name] ||= "#{table_name}_#{column_name}_lower"
|
20
|
+
options[:expression] = "(LOWER(#{connection.quote_column_name(column_name)}))"
|
21
|
+
if defined?(::SchemaPlus)
|
22
|
+
connection.add_index(table_name, column_name, options)
|
22
23
|
else
|
23
|
-
|
24
|
-
connection.exec_query <<-SQL.strip
|
25
|
-
CREATE #{'UNIQUE ' if options[:unique]}INDEX #{index_name} ON #{connection.quote_table_name(table_name)}
|
26
|
-
(LOWER(#{connection.quote_column_name(column_name)}));
|
27
|
-
SQL
|
24
|
+
connection.exec_query quoted_create_index(connection, table_name, **options)
|
28
25
|
end
|
29
26
|
elsif connection.adapter_name =~ /mysql/i
|
30
|
-
fail 'MySQL case-insensitive index creation for case-sensitive columns is not supported.'
|
27
|
+
fail ArgumentError.new('MySQL case-insensitive index creation for case-sensitive columns is not supported.')
|
31
28
|
else
|
32
|
-
fail
|
29
|
+
fail ArgumentError.new(
|
30
|
+
"Cannot create a case-insensitive index for case-sensitive column on #{connection.adapter_name}.")
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
@@ -5,14 +5,15 @@ require 'db_text_search/case_insensitive_eq/collate_nocase_adapter'
|
|
5
5
|
module DbTextSearch
|
6
6
|
# Provides case-insensitive string-in-set querying, and CI index creation.
|
7
7
|
class CaseInsensitiveEq
|
8
|
-
#
|
8
|
+
# @param scope [ActiveRecord::Relation, Class<ActiveRecord::Base>]
|
9
|
+
# @param column [Symbol] name
|
9
10
|
def initialize(scope, column)
|
10
11
|
@adapter = self.class.adapter_class(scope.connection, scope.table_name, column).new(scope, column)
|
11
12
|
@scope = scope
|
12
13
|
end
|
13
14
|
|
14
15
|
# @param value_or_values [String, Array<String>]
|
15
|
-
# @return
|
16
|
+
# @return [ActiveRecord::Relation]
|
16
17
|
def find(value_or_values)
|
17
18
|
values = Array(value_or_values)
|
18
19
|
return @scope.none if values.empty?
|
@@ -23,14 +24,14 @@ module DbTextSearch
|
|
23
24
|
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
24
25
|
# @param table_name [String, Symbol]
|
25
26
|
# @param column_name [String, Symbol]
|
26
|
-
# @param options [Hash]
|
27
|
+
# @param options [Hash] passed to ActiveRecord::ConnectionAdapters::SchemaStatements#add_index
|
27
28
|
def self.add_ci_text_column(connection, table_name, column_name, options = {})
|
28
29
|
case connection.adapter_name.downcase
|
29
30
|
when /mysql/
|
30
31
|
connection.add_column(table_name, column_name, :text, options)
|
31
32
|
when /postgres/
|
32
33
|
connection.enable_extension 'citext'
|
33
|
-
if ActiveRecord::VERSION::
|
34
|
+
if ActiveRecord::VERSION::STRING >= '4.2.0'
|
34
35
|
connection.add_column(table_name, column_name, :citext, options)
|
35
36
|
else
|
36
37
|
connection.add_column(table_name, column_name, 'CITEXT', options)
|
@@ -42,11 +43,18 @@ module DbTextSearch
|
|
42
43
|
connection.add_column(table_name, column_name, 'TEXT COLLATE NOCASE', options)
|
43
44
|
end
|
44
45
|
else
|
45
|
-
fail "Unsupported adapter #{connection.adapter_name}"
|
46
|
+
fail ArgumentError.new("Unsupported adapter #{connection.adapter_name}")
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
#
|
50
|
+
# Add an index for case-insensitive string search.
|
51
|
+
#
|
52
|
+
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
53
|
+
# @param table_name [String, Symbol]
|
54
|
+
# @param column_name [String, Symbol]
|
55
|
+
# @param options [Hash]
|
56
|
+
# @option options name [String] index name
|
57
|
+
# @option options unique [Boolean] default: false
|
50
58
|
def self.add_index(connection, table_name, column_name, options = {})
|
51
59
|
adapter_class(connection, table_name, column_name).add_index(connection, table_name, column_name, options)
|
52
60
|
end
|
@@ -55,6 +63,7 @@ module DbTextSearch
|
|
55
63
|
# @param table_name [String, Symbol]
|
56
64
|
# @param column_name [String, Symbol]
|
57
65
|
# @return [Class<AbstractAdapter>]
|
66
|
+
# @api private
|
58
67
|
def self.adapter_class(connection, table_name, column_name)
|
59
68
|
if connection.adapter_name.downcase =~ /sqlite/
|
60
69
|
# Always use COLLATE NOCASE for SQLite, as we can't check if the column is case-sensitive.
|
@@ -81,7 +90,7 @@ module DbTextSearch
|
|
81
90
|
when /postgres/
|
82
91
|
column.sql_type !~ /citext/i
|
83
92
|
else
|
84
|
-
fail "Unsupported adapter #{connection.adapter_name}"
|
93
|
+
fail ArgumentError.new("Unsupported adapter #{connection.adapter_name}")
|
85
94
|
end
|
86
95
|
end
|
87
96
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module DbTextSearch
|
2
2
|
class FullTextSearch
|
3
3
|
# A base class for FullTextSearch adapters.
|
4
|
+
# @abstract
|
5
|
+
# @api private
|
4
6
|
class AbstractAdapter
|
5
7
|
include ::DbTextSearch::QueryBuilding
|
6
|
-
DEFAULT_PG_TS_CONFIG = %q('english')
|
7
8
|
|
8
9
|
# @param scope [ActiveRecord::Relation, Class<ActiveRecord::Base>]
|
9
10
|
# @param column [Symbol] name
|
@@ -13,17 +14,10 @@ module DbTextSearch
|
|
13
14
|
end
|
14
15
|
|
15
16
|
# @param terms [Array<String>]
|
17
|
+
# @param pg_ts_config [String] a pg text search config
|
16
18
|
# @return [ActiveRecord::Relation]
|
17
|
-
def find(terms)
|
18
|
-
@scope.where(*where_args(terms))
|
19
|
-
end
|
20
|
-
|
21
|
-
# @param terms [Array<String>]
|
22
|
-
# @param options [Hash]
|
23
|
-
# @option options pg_ts_config [String] a pg text search config. Default: 'english'
|
24
|
-
# @return [query fragment, binds]
|
25
19
|
# @abstract
|
26
|
-
def
|
20
|
+
def find(terms, pg_ts_config:)
|
27
21
|
fail 'abstract'
|
28
22
|
end
|
29
23
|
|
@@ -32,19 +26,12 @@ module DbTextSearch
|
|
32
26
|
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
33
27
|
# @param table_name [String, Symbol]
|
34
28
|
# @param column_name [String, Symbol]
|
35
|
-
# @param
|
36
|
-
# @
|
29
|
+
# @param name [String, Symbol] index name
|
30
|
+
# @param pg_ts_config [String] for Postgres, the TS config to use; ignored for non-postgres.
|
37
31
|
# @abstract
|
38
|
-
def self.add_index(connection, table_name, column_name,
|
32
|
+
def self.add_index(connection, table_name, column_name, name:, pg_ts_config:)
|
39
33
|
fail 'abstract'
|
40
34
|
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
def parse_search_options(options = {})
|
45
|
-
options.assert_valid_keys(:pg_ts_config)
|
46
|
-
options.reverse_merge(pg_ts_config: DEFAULT_PG_TS_CONFIG)
|
47
|
-
end
|
48
35
|
end
|
49
36
|
end
|
50
37
|
end
|
@@ -1,18 +1,21 @@
|
|
1
1
|
require 'db_text_search/full_text_search/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class FullTextSearch
|
4
|
+
# Provides basic FTS support for MySQL.
|
5
|
+
#
|
6
|
+
# Runs a `MATCH AGAINST` query against a `FULLTEXT` index.
|
7
|
+
#
|
8
|
+
# @note MySQL v5.6.4+ is required.
|
9
|
+
# @api private
|
4
10
|
class MysqlAdapter < AbstractAdapter
|
5
|
-
# (see AbstractAdapter#
|
6
|
-
def
|
7
|
-
|
8
|
-
conn = @scope.connection
|
9
|
-
["MATCH (#{conn.quote_table_name(@scope.table_name)}.#{conn.quote_column_name(@column)}) AGAINST (?)",
|
10
|
-
terms.uniq.join(' ')]
|
11
|
+
# (see AbstractAdapter#find)
|
12
|
+
def find(terms, pg_ts_config:)
|
13
|
+
@scope.where("MATCH (#{quoted_scope_column}) AGAINST (?)", terms.uniq.join(' '))
|
11
14
|
end
|
12
15
|
|
13
16
|
# (see AbstractAdapter.add_index)
|
14
|
-
def self.add_index(connection, table_name, column_name,
|
15
|
-
connection.add_index table_name, column_name,
|
17
|
+
def self.add_index(connection, table_name, column_name, name:, pg_ts_config:)
|
18
|
+
connection.add_index table_name, column_name, name: name, type: :fulltext
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -1,24 +1,23 @@
|
|
1
1
|
require 'db_text_search/full_text_search/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class FullTextSearch
|
4
|
+
# Provides basic FTS support for PostgreSQL.
|
5
|
+
#
|
6
|
+
# Runs a `@@ plainto_tsquery` query against a `gist(to_tsvector(...))` index.
|
7
|
+
#
|
8
|
+
# @see DbTextSearch::FullTextSearch::DEFAULT_PG_TS_CONFIG
|
9
|
+
# @api private
|
4
10
|
class PostgresAdapter < AbstractAdapter
|
5
|
-
# (see AbstractAdapter#
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
["to_tsvector(#{pg_ts_config}, #{quoted_scope_column}::text) @@ plainto_tsquery(#{pg_ts_config}, ?)",
|
10
|
-
terms.uniq.join(' ')]
|
11
|
+
# (see AbstractAdapter#find)
|
12
|
+
def find(terms, pg_ts_config:)
|
13
|
+
@scope.where("to_tsvector(#{pg_ts_config}, #{quoted_scope_column}) @@ plainto_tsquery(#{pg_ts_config}, ?)",
|
14
|
+
terms.uniq.join(' '))
|
11
15
|
end
|
12
16
|
|
13
17
|
# (see AbstractAdapter.add_index)
|
14
|
-
def self.add_index(connection, table_name, column_name,
|
15
|
-
|
16
|
-
|
17
|
-
index_name = options[:name] || "#{table_name}_#{column_name}_fts"
|
18
|
-
connection.exec_query <<-SQL.strip
|
19
|
-
CREATE INDEX #{index_name} ON #{connection.quote_table_name(table_name)}
|
20
|
-
USING gist(to_tsvector(#{pg_ts_config}, #{connection.quote_column_name column_name}))
|
21
|
-
SQL
|
18
|
+
def self.add_index(connection, table_name, column_name, name:, pg_ts_config:)
|
19
|
+
expression = "USING gist(to_tsvector(#{pg_ts_config}, #{connection.quote_column_name column_name}))"
|
20
|
+
connection.exec_query quoted_create_index(connection, table_name, name: name, expression: expression)
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -1,19 +1,24 @@
|
|
1
1
|
require 'db_text_search/full_text_search/abstract_adapter'
|
2
2
|
module DbTextSearch
|
3
3
|
class FullTextSearch
|
4
|
+
# Provides very basic FTS support for SQLite.
|
5
|
+
#
|
6
|
+
# Runs a `LIKE %term%` query for each term, joined with `AND`.
|
7
|
+
# Cannot use an index.
|
8
|
+
#
|
9
|
+
# @note .add_index is a no-op.
|
10
|
+
# @api private
|
4
11
|
class SqliteAdapter < AbstractAdapter
|
5
|
-
# (see AbstractAdapter
|
6
|
-
def
|
7
|
-
parse_search_options(options)
|
12
|
+
# (see AbstractAdapter#find)
|
13
|
+
def find(terms, pg_ts_config:)
|
8
14
|
quoted_col = quoted_scope_column
|
9
|
-
|
10
|
-
|
15
|
+
terms.map(&:downcase).uniq.inject(@scope) do |scope, term|
|
16
|
+
scope.where("#{quoted_col} COLLATE NOCASE LIKE ?", "%#{sanitize_sql_like term}%")
|
11
17
|
end
|
12
|
-
[term_args.map(&:first).join(' AND '), *term_args.map(&:second)]
|
13
18
|
end
|
14
19
|
|
15
20
|
# (see AbstractAdapter.add_index)
|
16
|
-
def self.add_index(connection, table_name, column_name,
|
21
|
+
def self.add_index(connection, table_name, column_name, name:, pg_ts_config:)
|
17
22
|
# A no-op, as we just use LIKE for sqlite.
|
18
23
|
end
|
19
24
|
end
|
@@ -3,31 +3,45 @@ require 'db_text_search/full_text_search/mysql_adapter'
|
|
3
3
|
require 'db_text_search/full_text_search/sqlite_adapter'
|
4
4
|
|
5
5
|
module DbTextSearch
|
6
|
-
# Provides
|
6
|
+
# Provides basic full-text search for a list of terms, and FTS index creation.
|
7
7
|
class FullTextSearch
|
8
|
-
#
|
8
|
+
# The default Postgres text search config.
|
9
|
+
DEFAULT_PG_TS_CONFIG = %q('english')
|
10
|
+
|
11
|
+
# @param scope [ActiveRecord::Relation, Class<ActiveRecord::Base>]
|
12
|
+
# @param column [Symbol] name
|
9
13
|
def initialize(scope, column)
|
10
14
|
@adapter = self.class.adapter_class(scope.connection, scope.table_name, column).new(scope, column)
|
11
15
|
@scope = scope
|
12
16
|
end
|
13
17
|
|
14
18
|
# @param term_or_terms [String, Array<String>]
|
15
|
-
# @
|
16
|
-
|
17
|
-
|
19
|
+
# @param pg_ts_config [String] for Postgres, the TS config to use; ignored for non-postgres.
|
20
|
+
# @return [ActiveRecord::Relation]
|
21
|
+
def find(term_or_terms, pg_ts_config: DEFAULT_PG_TS_CONFIG)
|
22
|
+
values = Array(term_or_terms)
|
18
23
|
return @scope.none if values.empty?
|
19
|
-
@adapter.find(values)
|
24
|
+
@adapter.find(values, pg_ts_config: pg_ts_config)
|
20
25
|
end
|
21
26
|
|
22
|
-
#
|
23
|
-
|
24
|
-
|
27
|
+
# Add an index for full text search.
|
28
|
+
#
|
29
|
+
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
30
|
+
# @param table_name [String, Symbol]
|
31
|
+
# @param column_name [String, Symbol]
|
32
|
+
# @param name [String, Symbol] index name
|
33
|
+
# @param pg_ts_config [String] for Postgres, the TS config to use; ignored for non-postgres.
|
34
|
+
def self.add_index(connection, table_name, column_name, name: "#{table_name}_#{column_name}_fts",
|
35
|
+
pg_ts_config: DEFAULT_PG_TS_CONFIG)
|
36
|
+
adapter_class(connection, table_name, column_name)
|
37
|
+
.add_index(connection, table_name, column_name, name: name, pg_ts_config: pg_ts_config)
|
25
38
|
end
|
26
39
|
|
27
40
|
# @param connection [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
28
41
|
# @param _table_name [String, Symbol]
|
29
42
|
# @param _column_name [String, Symbol]
|
30
43
|
# @return [Class<AbstractAdapter>]
|
44
|
+
# @api private
|
31
45
|
def self.adapter_class(connection, _table_name, _column_name)
|
32
46
|
case connection.adapter_name
|
33
47
|
when /mysql/i
|
@@ -37,7 +51,7 @@ module DbTextSearch
|
|
37
51
|
when /sqlite/i
|
38
52
|
SqliteAdapter
|
39
53
|
else
|
40
|
-
fail "
|
54
|
+
fail ArgumentError.new("Unsupported adapter #{connection.adapter_name}")
|
41
55
|
end
|
42
56
|
end
|
43
57
|
end
|
@@ -1,22 +1,43 @@
|
|
1
1
|
module DbTextSearch
|
2
|
+
# Common methods for building SQL that use @scope and @column instance variables.
|
3
|
+
# @api private
|
2
4
|
module QueryBuilding
|
5
|
+
def self.included(base) # :nodoc:
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
3
9
|
protected
|
4
10
|
|
11
|
+
# @return [String] SQL-quoted scope table name.
|
5
12
|
def quoted_scope_table
|
6
13
|
@scope.connection.quote_table_name(@scope.table_name)
|
7
14
|
end
|
8
15
|
|
16
|
+
# @return [String] SQL-quoted column (without the table name).
|
9
17
|
def quoted_column
|
10
18
|
@scope.connection.quote_column_name(@column)
|
11
19
|
end
|
12
20
|
|
21
|
+
# @return [String] SQL-quoted column fully-qualified with the scope table name.
|
13
22
|
def quoted_scope_column
|
14
23
|
"#{quoted_scope_table}.#{quoted_column}"
|
15
24
|
end
|
16
25
|
|
26
|
+
# @return [String] SQL-quoted string suitable for use in a LIKE statement, with % and _ escaped.
|
17
27
|
def sanitize_sql_like(string, escape_character = "\\")
|
18
28
|
pattern = Regexp.union(escape_character, '%', '_')
|
19
29
|
string.gsub(pattern) { |x| [escape_character, x].join }
|
20
30
|
end
|
31
|
+
|
32
|
+
# Common methods for building SQL
|
33
|
+
# @api private
|
34
|
+
module ClassMethods
|
35
|
+
protected
|
36
|
+
|
37
|
+
# @return [String] a CREATE INDEX statement
|
38
|
+
def quoted_create_index(connection, table_name, name:, expression:, unique: false)
|
39
|
+
"CREATE #{'UNIQUE ' if unique}INDEX #{name} ON #{connection.quote_table_name(table_name)} #{expression}"
|
40
|
+
end
|
41
|
+
end
|
21
42
|
end
|
22
43
|
end
|
data/lib/db_text_search.rb
CHANGED
@@ -5,5 +5,10 @@ require 'db_text_search/version'
|
|
5
5
|
require 'db_text_search/case_insensitive_eq'
|
6
6
|
require 'db_text_search/full_text_search'
|
7
7
|
|
8
|
+
# DbTextSearch provides a unified interface on top of ActiveRecord for SQLite, MySQL, and PostgreSQL to do:
|
9
|
+
# * Case-insensitive string-in-set querying, and CI index creation.
|
10
|
+
# * Basic full-text search for a list of terms, and FTS index creation.
|
11
|
+
# @see DbTextSearch::CaseInsensitiveEq
|
12
|
+
# @see DbTextSearch::FullTextSearch
|
8
13
|
module DbTextSearch
|
9
14
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: db_text_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gleb Mazovetskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -170,3 +170,4 @@ specification_version: 4
|
|
170
170
|
summary: A unified interface on top of ActiveRecord for SQLite, MySQL, and PostgreSQL
|
171
171
|
for case-insensitive string search and basic full-text search.
|
172
172
|
test_files: []
|
173
|
+
has_rdoc:
|