rroonga 0.9.2-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +5 -0
- data/NEWS.ja.rdoc +114 -0
- data/NEWS.rdoc +116 -0
- data/README.ja.rdoc +65 -0
- data/README.rdoc +66 -0
- data/Rakefile +206 -0
- data/benchmark/common.rb +49 -0
- data/benchmark/read-write-many-small-items.rb +144 -0
- data/benchmark/write-many-small-items.rb +135 -0
- data/example/bookmark.rb +161 -0
- data/example/index-html.rb +89 -0
- data/example/search/config.ru +230 -0
- data/example/search/public/css/groonga.css +122 -0
- data/ext/.gitignore +2 -0
- data/ext/groonga/extconf.rb +93 -0
- data/ext/groonga/rb-grn-accessor.c +52 -0
- data/ext/groonga/rb-grn-array-cursor.c +36 -0
- data/ext/groonga/rb-grn-array.c +210 -0
- data/ext/groonga/rb-grn-column.c +573 -0
- data/ext/groonga/rb-grn-context.c +662 -0
- data/ext/groonga/rb-grn-database.c +472 -0
- data/ext/groonga/rb-grn-encoding-support.c +64 -0
- data/ext/groonga/rb-grn-encoding.c +257 -0
- data/ext/groonga/rb-grn-exception.c +1110 -0
- data/ext/groonga/rb-grn-expression-builder.c +75 -0
- data/ext/groonga/rb-grn-expression.c +731 -0
- data/ext/groonga/rb-grn-fix-size-column.c +166 -0
- data/ext/groonga/rb-grn-hash-cursor.c +38 -0
- data/ext/groonga/rb-grn-hash.c +294 -0
- data/ext/groonga/rb-grn-index-column.c +488 -0
- data/ext/groonga/rb-grn-logger.c +504 -0
- data/ext/groonga/rb-grn-object.c +1369 -0
- data/ext/groonga/rb-grn-operation.c +198 -0
- data/ext/groonga/rb-grn-patricia-trie-cursor.c +39 -0
- data/ext/groonga/rb-grn-patricia-trie.c +488 -0
- data/ext/groonga/rb-grn-procedure.c +52 -0
- data/ext/groonga/rb-grn-query.c +260 -0
- data/ext/groonga/rb-grn-record.c +40 -0
- data/ext/groonga/rb-grn-snippet.c +334 -0
- data/ext/groonga/rb-grn-table-cursor-key-support.c +69 -0
- data/ext/groonga/rb-grn-table-cursor.c +247 -0
- data/ext/groonga/rb-grn-table-key-support.c +714 -0
- data/ext/groonga/rb-grn-table.c +1977 -0
- data/ext/groonga/rb-grn-type.c +181 -0
- data/ext/groonga/rb-grn-utils.c +769 -0
- data/ext/groonga/rb-grn-variable-size-column.c +36 -0
- data/ext/groonga/rb-grn-variable.c +108 -0
- data/ext/groonga/rb-grn-view-accessor.c +53 -0
- data/ext/groonga/rb-grn-view-cursor.c +35 -0
- data/ext/groonga/rb-grn-view-record.c +41 -0
- data/ext/groonga/rb-grn-view.c +421 -0
- data/ext/groonga/rb-grn.h +698 -0
- data/ext/groonga/rb-groonga.c +107 -0
- data/extconf.rb +130 -0
- data/html/bar.svg +153 -0
- data/html/developer.html +117 -0
- data/html/developer.svg +469 -0
- data/html/download.svg +253 -0
- data/html/favicon.ico +0 -0
- data/html/favicon.xcf +0 -0
- data/html/footer.html.erb +28 -0
- data/html/head.html.erb +4 -0
- data/html/header.html.erb +17 -0
- data/html/index.html +147 -0
- data/html/install.svg +636 -0
- data/html/logo.xcf +0 -0
- data/html/ranguba.css +250 -0
- data/html/tutorial.svg +559 -0
- data/lib/1.8/groonga.so +0 -0
- data/lib/1.9/groonga.so +0 -0
- data/lib/groonga.rb +90 -0
- data/lib/groonga/context.rb +184 -0
- data/lib/groonga/expression-builder.rb +324 -0
- data/lib/groonga/patricia-trie.rb +85 -0
- data/lib/groonga/record.rb +311 -0
- data/lib/groonga/schema.rb +1191 -0
- data/lib/groonga/view-record.rb +56 -0
- data/license/GPL +340 -0
- data/license/LGPL +504 -0
- data/license/RUBY +59 -0
- data/misc/grnop2ruby.rb +49 -0
- data/pkg-config.rb +333 -0
- data/rroonga-build.rb +57 -0
- data/test-unit/Rakefile +40 -0
- data/test-unit/TODO +5 -0
- data/test-unit/bin/testrb +5 -0
- data/test-unit/html/classic.html +15 -0
- data/test-unit/html/index.html +25 -0
- data/test-unit/html/index.html.ja +27 -0
- data/test-unit/lib/test/unit.rb +323 -0
- data/test-unit/lib/test/unit/assertionfailederror.rb +25 -0
- data/test-unit/lib/test/unit/assertions.rb +1230 -0
- data/test-unit/lib/test/unit/attribute.rb +125 -0
- data/test-unit/lib/test/unit/autorunner.rb +360 -0
- data/test-unit/lib/test/unit/collector.rb +36 -0
- data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
- data/test-unit/lib/test/unit/collector/dir.rb +108 -0
- data/test-unit/lib/test/unit/collector/load.rb +144 -0
- data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
- data/test-unit/lib/test/unit/color-scheme.rb +102 -0
- data/test-unit/lib/test/unit/color.rb +96 -0
- data/test-unit/lib/test/unit/diff.rb +724 -0
- data/test-unit/lib/test/unit/error.rb +130 -0
- data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
- data/test-unit/lib/test/unit/failure.rb +136 -0
- data/test-unit/lib/test/unit/fixture.rb +176 -0
- data/test-unit/lib/test/unit/notification.rb +129 -0
- data/test-unit/lib/test/unit/omission.rb +191 -0
- data/test-unit/lib/test/unit/pending.rb +150 -0
- data/test-unit/lib/test/unit/priority.rb +180 -0
- data/test-unit/lib/test/unit/runner/console.rb +52 -0
- data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
- data/test-unit/lib/test/unit/runner/tap.rb +8 -0
- data/test-unit/lib/test/unit/testcase.rb +476 -0
- data/test-unit/lib/test/unit/testresult.rb +89 -0
- data/test-unit/lib/test/unit/testsuite.rb +110 -0
- data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
- data/test-unit/lib/test/unit/ui/console/testrunner.rb +466 -0
- data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +63 -0
- data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
- data/test-unit/lib/test/unit/ui/testrunner.rb +28 -0
- data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
- data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
- data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
- data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
- data/test-unit/lib/test/unit/util/observable.rb +90 -0
- data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
- data/test-unit/lib/test/unit/version.rb +7 -0
- data/test-unit/sample/adder.rb +13 -0
- data/test-unit/sample/subtracter.rb +12 -0
- data/test-unit/sample/test_adder.rb +20 -0
- data/test-unit/sample/test_subtracter.rb +20 -0
- data/test-unit/sample/test_user.rb +23 -0
- data/test-unit/test/collector/test-descendant.rb +133 -0
- data/test-unit/test/collector/test-load.rb +442 -0
- data/test-unit/test/collector/test_dir.rb +406 -0
- data/test-unit/test/collector/test_objectspace.rb +100 -0
- data/test-unit/test/run-test.rb +15 -0
- data/test-unit/test/test-attribute.rb +86 -0
- data/test-unit/test/test-color-scheme.rb +67 -0
- data/test-unit/test/test-color.rb +47 -0
- data/test-unit/test/test-diff.rb +518 -0
- data/test-unit/test/test-emacs-runner.rb +60 -0
- data/test-unit/test/test-fixture.rb +287 -0
- data/test-unit/test/test-notification.rb +33 -0
- data/test-unit/test/test-omission.rb +81 -0
- data/test-unit/test/test-pending.rb +70 -0
- data/test-unit/test/test-priority.rb +119 -0
- data/test-unit/test/test-testcase.rb +544 -0
- data/test-unit/test/test_assertions.rb +1151 -0
- data/test-unit/test/test_error.rb +26 -0
- data/test-unit/test/test_failure.rb +33 -0
- data/test-unit/test/test_testresult.rb +113 -0
- data/test-unit/test/test_testsuite.rb +129 -0
- data/test-unit/test/testunit-test-util.rb +14 -0
- data/test-unit/test/ui/test_testrunmediator.rb +20 -0
- data/test-unit/test/util/test-method-owner-finder.rb +38 -0
- data/test-unit/test/util/test_backtracefilter.rb +41 -0
- data/test-unit/test/util/test_observable.rb +102 -0
- data/test-unit/test/util/test_procwrapper.rb +36 -0
- data/test/.gitignore +1 -0
- data/test/groonga-test-utils.rb +134 -0
- data/test/run-test.rb +58 -0
- data/test/test-array.rb +90 -0
- data/test/test-column.rb +316 -0
- data/test/test-context-select.rb +93 -0
- data/test/test-context.rb +73 -0
- data/test/test-database.rb +113 -0
- data/test/test-encoding.rb +33 -0
- data/test/test-exception.rb +93 -0
- data/test/test-expression-builder.rb +217 -0
- data/test/test-expression.rb +134 -0
- data/test/test-fix-size-column.rb +65 -0
- data/test/test-gqtp.rb +72 -0
- data/test/test-hash.rb +305 -0
- data/test/test-index-column.rb +81 -0
- data/test/test-logger.rb +37 -0
- data/test/test-patricia-trie.rb +205 -0
- data/test/test-procedure.rb +37 -0
- data/test/test-query.rb +22 -0
- data/test/test-record.rb +243 -0
- data/test/test-remote.rb +54 -0
- data/test/test-schema-view.rb +90 -0
- data/test/test-schema.rb +459 -0
- data/test/test-snippet.rb +130 -0
- data/test/test-table-cursor.rb +153 -0
- data/test/test-table-offset-and-limit.rb +102 -0
- data/test/test-table-select-normalize.rb +53 -0
- data/test/test-table-select.rb +150 -0
- data/test/test-table.rb +594 -0
- data/test/test-type.rb +71 -0
- data/test/test-variable-size-column.rb +98 -0
- data/test/test-variable.rb +28 -0
- data/test/test-vector-column.rb +76 -0
- data/test/test-version.rb +31 -0
- data/test/test-view.rb +72 -0
- data/text/TUTORIAL.ja.rdoc +392 -0
- data/text/expression.rdoc +284 -0
- metadata +276 -0
data/lib/1.8/groonga.so
ADDED
Binary file
|
data/lib/1.9/groonga.so
ADDED
Binary file
|
data/lib/groonga.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require 'pathname'
|
19
|
+
|
20
|
+
base_dir = Pathname.new(__FILE__).dirname.dirname.expand_path
|
21
|
+
local_groonga_dir = base_dir + "vendor" + "local"
|
22
|
+
local_groonga_bin_dir = local_groonga_dir + "bin"
|
23
|
+
if local_groonga_bin_dir.exist?
|
24
|
+
prepend_path = Proc.new do |environment_name, separator|
|
25
|
+
paths = (ENV[environment_name] || '').split(/#{separator}/)
|
26
|
+
dir = local_groonga_bin_dir.to_s
|
27
|
+
dir = dir.gsub(/\//, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
|
28
|
+
unless paths.include?(dir)
|
29
|
+
paths = [dir] + paths
|
30
|
+
ENV[environment_name] = paths.join(separator)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
case RUBY_PLATFORM
|
35
|
+
when /mingw|mswin/
|
36
|
+
prepend_path.call("PATH", ";")
|
37
|
+
when /cygwin/
|
38
|
+
prepend_path.call("PATH", ":")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'groonga/view-record'
|
43
|
+
require 'groonga/record'
|
44
|
+
require 'groonga/expression-builder'
|
45
|
+
require 'groonga.so'
|
46
|
+
|
47
|
+
##
|
48
|
+
# Ruby/groonga用のネームスペース。Ruby/groongaのクラスやメソッ
|
49
|
+
# ドなどはこのモジュール以下に定義される。
|
50
|
+
module Groonga
|
51
|
+
class << self
|
52
|
+
##
|
53
|
+
# BUILD_VERSIONを"."で結合して<tt>"メジャーバージョン.マ
|
54
|
+
# イナーバージョン.マイクロバージョン"</tt>という形式の
|
55
|
+
# 文字列にしたもの。
|
56
|
+
def build_version
|
57
|
+
BUILD_VERSION.join(".")
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# VERSIONを"."で結合して<tt>"メジャーバージョン.マイナー
|
62
|
+
# バージョン.マイクロバージョン"</tt>という形式の文字列に
|
63
|
+
# したもの。
|
64
|
+
def version
|
65
|
+
VERSION.join(".")
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# BINDINGS_VERSIONを"."で結合して<tt>"メジャーバージョン.マ
|
70
|
+
# イナーバージョン.マイクロバージョン"</tt>という形式の文
|
71
|
+
# 字列にしたもの。
|
72
|
+
def bindings_version
|
73
|
+
BINDINGS_VERSION.join(".")
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# call-seq:
|
78
|
+
# Groonga[name] -> Groonga::Object or nil
|
79
|
+
# Groonga[id] -> Groonga::Object or nil
|
80
|
+
#
|
81
|
+
# 便利メソッド。Groonga::Context.default[name]と同じ。
|
82
|
+
def [](name)
|
83
|
+
Context.default[name]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
require 'groonga/context'
|
89
|
+
require 'groonga/patricia-trie'
|
90
|
+
require 'groonga/schema'
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
module Groonga
|
19
|
+
class Context
|
20
|
+
# call-seq:
|
21
|
+
# context.select(table, options={}) -> SelectResult
|
22
|
+
#
|
23
|
+
# _table_から指定した条件にマッチするレコードの値を取得
|
24
|
+
# する。_table_はテーブル名かテーブルオブジェクトを指定
|
25
|
+
# する。
|
26
|
+
#
|
27
|
+
# _options_に指定できるキーは以下の通り。
|
28
|
+
#
|
29
|
+
# [_output_columns_] 値を取得するカラムを指定する。
|
30
|
+
# [_XXX_] TODO
|
31
|
+
#
|
32
|
+
# 例:
|
33
|
+
# TODO
|
34
|
+
def select(table, options={})
|
35
|
+
select = SelectCommand.new(self, table, options)
|
36
|
+
select.exec
|
37
|
+
end
|
38
|
+
|
39
|
+
class SelectResult < Struct.new(:return_code, :start_time, :elapsed,
|
40
|
+
:error_message,
|
41
|
+
:n_hits, :columns, :values,
|
42
|
+
:drill_down)
|
43
|
+
class << self
|
44
|
+
def parse(json, drill_down_keys)
|
45
|
+
status, (select_result, *drill_down_results) = parse_json(json)
|
46
|
+
result = new
|
47
|
+
return_code, start_time, elapsed, error_message = status
|
48
|
+
result.return_code = return_code
|
49
|
+
result.start_time = Time.at(start_time)
|
50
|
+
result.elapsed = elapsed
|
51
|
+
result.error_message = error_message
|
52
|
+
n_hits, columns, values = extract_result(select_result)
|
53
|
+
result.n_hits = n_hits
|
54
|
+
result.columns = columns
|
55
|
+
result.values = values
|
56
|
+
if drill_down_results
|
57
|
+
result.drill_down = parse_drill_down_results(drill_down_results,
|
58
|
+
drill_down_keys)
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_records(columns, values)
|
64
|
+
records = []
|
65
|
+
values.each do |value|
|
66
|
+
record = {}
|
67
|
+
columns.each_with_index do |(name, type), i|
|
68
|
+
record[name] = convert_value(value[i], type)
|
69
|
+
end
|
70
|
+
records << record
|
71
|
+
end
|
72
|
+
records
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def parse_drill_down_results(results, keys)
|
77
|
+
named_results = {}
|
78
|
+
results.each_with_index do |drill_down, i|
|
79
|
+
n_hits, columns, values = extract_result(drill_down)
|
80
|
+
drill_down_result = DrillDownResult.new
|
81
|
+
drill_down_result.n_hits = n_hits
|
82
|
+
drill_down_result.columns = columns
|
83
|
+
drill_down_result.values = values
|
84
|
+
named_results[keys[i]] = drill_down_result
|
85
|
+
end
|
86
|
+
named_results
|
87
|
+
end
|
88
|
+
|
89
|
+
def extract_result(result)
|
90
|
+
meta_data, columns, *values = result
|
91
|
+
n_hits, = meta_data
|
92
|
+
[n_hits, columns, values]
|
93
|
+
end
|
94
|
+
|
95
|
+
def convert_value(value, type)
|
96
|
+
case type
|
97
|
+
when "Time"
|
98
|
+
Time.at(value)
|
99
|
+
else
|
100
|
+
value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
require 'json'
|
106
|
+
def parse_json(json)
|
107
|
+
JSON.parse(json)
|
108
|
+
end
|
109
|
+
rescue LoadError
|
110
|
+
require 'yaml'
|
111
|
+
def parse_json(json)
|
112
|
+
YAML.load(json)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def records
|
118
|
+
@records ||= self.class.create_records(columns, values)
|
119
|
+
end
|
120
|
+
|
121
|
+
def success?
|
122
|
+
return_code.zero?
|
123
|
+
end
|
124
|
+
|
125
|
+
class DrillDownResult < Struct.new(:n_hits, :columns, :values)
|
126
|
+
def records
|
127
|
+
@records ||= SelectResult.create_records(columns, values)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class SelectCommand
|
133
|
+
def initialize(context, table, options)
|
134
|
+
@context = context
|
135
|
+
@table = table
|
136
|
+
@options = normalize_options(options)
|
137
|
+
end
|
138
|
+
|
139
|
+
def exec
|
140
|
+
request_id = @context.send(query)
|
141
|
+
loop do
|
142
|
+
response_id, result = @context.receive
|
143
|
+
if request_id == response_id
|
144
|
+
drill_down_keys = @options["drilldown"]
|
145
|
+
if drill_down_keys.is_a?(String)
|
146
|
+
drill_down_keys = drill_down_keys.split(/(?:\s+|\s*,\s*)/)
|
147
|
+
end
|
148
|
+
return SelectResult.parse(result, drill_down_keys)
|
149
|
+
end
|
150
|
+
# raise if request_id < response_id
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
def normalize_options(options)
|
156
|
+
normalized_options = {}
|
157
|
+
options.each do |key, value|
|
158
|
+
normalized_options[normalize_option_name(key)] = value
|
159
|
+
end
|
160
|
+
normalized_options
|
161
|
+
end
|
162
|
+
|
163
|
+
def normalize_option_name(name)
|
164
|
+
name = name.to_s.gsub(/-/, "_").gsub(/drill_down/, "drilldown")
|
165
|
+
name.gsub(/sort_by/, 'sortby')
|
166
|
+
end
|
167
|
+
|
168
|
+
def query
|
169
|
+
if @table.is_a?(String)
|
170
|
+
table_name = @table
|
171
|
+
else
|
172
|
+
table_name = @table.name
|
173
|
+
end
|
174
|
+
_query = "select #{table_name}"
|
175
|
+
@options.each do |key, value|
|
176
|
+
value = value.join(", ") if value.is_a?(::Array)
|
177
|
+
escaped_value = value.to_s.gsub(/"/, '\\"')
|
178
|
+
_query << " --#{key} \"#{escaped_value}\""
|
179
|
+
end
|
180
|
+
_query
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,324 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
module Groonga
|
19
|
+
module ExpressionBuildable # :nodoc:
|
20
|
+
attr_reader :table
|
21
|
+
attr_accessor :query
|
22
|
+
attr_accessor :syntax
|
23
|
+
attr_accessor :allow_pragma
|
24
|
+
attr_accessor :allow_column
|
25
|
+
attr_accessor :allow_update
|
26
|
+
attr_accessor :default_column
|
27
|
+
|
28
|
+
VALID_COLUMN_NAME_RE = /\A[a-zA-Z\d_]+\z/
|
29
|
+
|
30
|
+
def initialize(*args)
|
31
|
+
@table = nil
|
32
|
+
@name = nil
|
33
|
+
@query = nil
|
34
|
+
@syntax = nil
|
35
|
+
@allow_pragma = nil
|
36
|
+
@allow_column = nil
|
37
|
+
@allow_update = nil
|
38
|
+
@default_column = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def build
|
42
|
+
expression = Expression.new(:name => @name)
|
43
|
+
variable = expression.define_variable(:domain => @table)
|
44
|
+
|
45
|
+
builder = nil
|
46
|
+
builder = match(@query, default_parse_options) if @query
|
47
|
+
if block_given?
|
48
|
+
if builder
|
49
|
+
builder &= yield(self)
|
50
|
+
else
|
51
|
+
builder = yield(self)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if builder.nil? or builder == self
|
55
|
+
expression.append_constant(1)
|
56
|
+
expression.append_constant(1)
|
57
|
+
expression.append_operation(Groonga::Operation::OR, 2)
|
58
|
+
else
|
59
|
+
builder.build(expression, variable)
|
60
|
+
end
|
61
|
+
|
62
|
+
expression.compile
|
63
|
+
expression
|
64
|
+
end
|
65
|
+
|
66
|
+
def &(other)
|
67
|
+
other
|
68
|
+
end
|
69
|
+
|
70
|
+
def |(other)
|
71
|
+
other
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def default_parse_options
|
76
|
+
{
|
77
|
+
:syntax => @syntax,
|
78
|
+
:allow_pragma => @allow_pragma,
|
79
|
+
:allow_column => @allow_column,
|
80
|
+
:allow_update => @allow_update,
|
81
|
+
:default_column => @default_column,
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
class ExpressionBuilder # :nodoc:
|
86
|
+
def initialize
|
87
|
+
super()
|
88
|
+
end
|
89
|
+
|
90
|
+
def &(other)
|
91
|
+
AndExpressionBuilder.new(self, other)
|
92
|
+
end
|
93
|
+
|
94
|
+
def |(other)
|
95
|
+
OrExpressionBuilder.new(self, other)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class SetExpressionBuilder < ExpressionBuilder # :nodoc:
|
100
|
+
def initialize(operation, *expression_builders)
|
101
|
+
super()
|
102
|
+
@operation = operation
|
103
|
+
@expression_builders = expression_builders
|
104
|
+
end
|
105
|
+
|
106
|
+
def build(expression, variable)
|
107
|
+
return if @expression_builders.empty?
|
108
|
+
@expression_builders.each do |builder|
|
109
|
+
builder.build(expression, variable)
|
110
|
+
end
|
111
|
+
expression.append_operation(@operation, @expression_builders.size)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class AndExpressionBuilder < SetExpressionBuilder # :nodoc:
|
116
|
+
def initialize(*expression_builders)
|
117
|
+
super(Groonga::Operation::AND, *expression_builders)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class OrExpressionBuilder < SetExpressionBuilder # :nodoc:
|
122
|
+
def initialize(*expression_builders)
|
123
|
+
super(Groonga::Operation::OR, *expression_builders)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class BinaryExpressionBuilder < ExpressionBuilder # :nodoc:
|
128
|
+
def initialize(operation, column, value)
|
129
|
+
super()
|
130
|
+
@operation = operation
|
131
|
+
@default_column = column
|
132
|
+
@value = value
|
133
|
+
end
|
134
|
+
|
135
|
+
def build(expression, variable)
|
136
|
+
expression.append_object(variable)
|
137
|
+
if @default_column.is_a?(String)
|
138
|
+
expression.append_constant(@default_column)
|
139
|
+
else
|
140
|
+
expression.append_object(@default_column)
|
141
|
+
end
|
142
|
+
expression.append_operation(Groonga::Operation::GET_VALUE, 2)
|
143
|
+
expression.append_constant(@value)
|
144
|
+
expression.append_operation(@operation, 2)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class EqualExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
149
|
+
def initialize(column, value)
|
150
|
+
super(Groonga::Operation::EQUAL, column, value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class MatchExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
155
|
+
def initialize(column, value)
|
156
|
+
super(Groonga::Operation::MATCH, column, value)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class LessExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
161
|
+
def initialize(column, value)
|
162
|
+
super(Groonga::Operation::LESS, column, value)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class LessEqualExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
167
|
+
def initialize(column, value)
|
168
|
+
super(Groonga::Operation::LESS_EQUAL, column, value)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
class GreaterExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
173
|
+
def initialize(column, value)
|
174
|
+
super(Groonga::Operation::GREATER, column, value)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class GreaterEqualExpressionBuilder < BinaryExpressionBuilder # :nodoc:
|
179
|
+
def initialize(column, value)
|
180
|
+
super(Groonga::Operation::GREATER_EQUAL, column, value)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class SubExpressionBuilder < ExpressionBuilder # :nodoc:
|
185
|
+
def initialize(query, options)
|
186
|
+
super()
|
187
|
+
@query = query
|
188
|
+
@options = options
|
189
|
+
end
|
190
|
+
|
191
|
+
def build(expression, variable)
|
192
|
+
expression.parse(@query, @options)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class RecordExpressionBuilder # :nodoc:
|
198
|
+
include ExpressionBuildable
|
199
|
+
|
200
|
+
def initialize(table, name)
|
201
|
+
super()
|
202
|
+
@table = table
|
203
|
+
@name = name
|
204
|
+
end
|
205
|
+
|
206
|
+
def [](name)
|
207
|
+
column = @table.column(name)
|
208
|
+
if column.nil?
|
209
|
+
message = "unknown column <#{name.inspect}> " +
|
210
|
+
"for table <#{@table.inspect}>"
|
211
|
+
raise ArgumentError, message
|
212
|
+
end
|
213
|
+
ColumnExpressionBuilder.new(column, nil, nil,
|
214
|
+
:table => @table,
|
215
|
+
:column_name => name)
|
216
|
+
end
|
217
|
+
|
218
|
+
def id
|
219
|
+
self["_id"]
|
220
|
+
end
|
221
|
+
|
222
|
+
def key
|
223
|
+
self["_key"]
|
224
|
+
end
|
225
|
+
|
226
|
+
def score
|
227
|
+
self["_score"]
|
228
|
+
end
|
229
|
+
|
230
|
+
def n_sub_records
|
231
|
+
self["_nsubrecs"]
|
232
|
+
end
|
233
|
+
|
234
|
+
def match(query, options_or_default_column={})
|
235
|
+
if options_or_default_column.is_a?(String)
|
236
|
+
options = {:default_column => options_or_default_column}
|
237
|
+
else
|
238
|
+
options = options_or_default_column
|
239
|
+
end
|
240
|
+
options = options.dup
|
241
|
+
options[:syntax] ||= :query
|
242
|
+
SubExpressionBuilder.new(query, options)
|
243
|
+
end
|
244
|
+
|
245
|
+
private
|
246
|
+
def method_missing(name, *args, &block)
|
247
|
+
return super if block
|
248
|
+
return super unless args.empty?
|
249
|
+
if VALID_COLUMN_NAME_RE =~ name.to_s
|
250
|
+
self[name]
|
251
|
+
else
|
252
|
+
super
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class ColumnExpressionBuilder # :nodoc:
|
258
|
+
include ExpressionBuildable
|
259
|
+
|
260
|
+
def initialize(column, name, query, options={})
|
261
|
+
super()
|
262
|
+
@table = options[:table] || column.table
|
263
|
+
@default_column = column
|
264
|
+
@column_name = options[:column_name] || @default_column.local_name
|
265
|
+
@range = @default_column.range
|
266
|
+
@name = name
|
267
|
+
@query = query
|
268
|
+
end
|
269
|
+
|
270
|
+
def ==(other)
|
271
|
+
EqualExpressionBuilder.new(@default_column, normalize(other))
|
272
|
+
end
|
273
|
+
|
274
|
+
def =~(other)
|
275
|
+
if other.nil?
|
276
|
+
full_column_name = "#{@table.name}.#{@column_name}"
|
277
|
+
raise ArgumentError, "match word should not be nil: #{full_column_name}"
|
278
|
+
end
|
279
|
+
MatchExpressionBuilder.new(@default_column, normalize(other))
|
280
|
+
end
|
281
|
+
|
282
|
+
def <(other)
|
283
|
+
LessExpressionBuilder.new(@default_column, normalize(other))
|
284
|
+
end
|
285
|
+
|
286
|
+
def <=(other)
|
287
|
+
LessEqualExpressionBuilder.new(@default_column, normalize(other))
|
288
|
+
end
|
289
|
+
|
290
|
+
def >(other)
|
291
|
+
GreaterExpressionBuilder.new(@default_column, normalize(other))
|
292
|
+
end
|
293
|
+
|
294
|
+
def >=(other)
|
295
|
+
GreaterEqualExpressionBuilder.new(@default_column, normalize(other))
|
296
|
+
end
|
297
|
+
|
298
|
+
def match(query, options={})
|
299
|
+
options = options.dup
|
300
|
+
options[:syntax] ||= :query
|
301
|
+
options[:default_column] = @column_name
|
302
|
+
SubExpressionBuilder.new(query, options)
|
303
|
+
end
|
304
|
+
|
305
|
+
private
|
306
|
+
def normalize(other)
|
307
|
+
if @range.is_a?(Groonga::Table) and other.is_a?(Integer)
|
308
|
+
Groonga::Record.new(@range, other)
|
309
|
+
else
|
310
|
+
other
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def method_missing(name, *args, &block)
|
315
|
+
return super if block
|
316
|
+
return super unless args.empty?
|
317
|
+
if VALID_COLUMN_NAME_RE =~ name.to_s
|
318
|
+
RecordExpressionBuilder.new(@table, @name)["#{@column_name}.#{name}"]
|
319
|
+
else
|
320
|
+
super
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|