droonga-engine 1.0.1
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/.dir-locals.el +3 -0
- data/.gitignore +6 -0
- data/.travis.yml +15 -0
- data/.yardopts +7 -0
- data/Gemfile +66 -0
- data/LICENSE.txt +14 -0
- data/README.md +17 -0
- data/Rakefile +64 -0
- data/benchmark/benchmark.rb +123 -0
- data/benchmark/utils.rb +246 -0
- data/benchmark/watch/benchmark-notify.rb +143 -0
- data/benchmark/watch/benchmark-notify.sh +20 -0
- data/benchmark/watch/benchmark-publish.rb +120 -0
- data/benchmark/watch/benchmark-scan.rb +213 -0
- data/bin/droonga-catalog-generate +103 -0
- data/bin/droonga-engine +20 -0
- data/bin/droonga-engine-service +20 -0
- data/doc/text/news.md +106 -0
- data/droonga-engine.gemspec +52 -0
- data/lib/droonga/adapter.rb +48 -0
- data/lib/droonga/adapter_runner.rb +104 -0
- data/lib/droonga/catalog/base.rb +41 -0
- data/lib/droonga/catalog/collection_volume.rb +106 -0
- data/lib/droonga/catalog/dataset.rb +69 -0
- data/lib/droonga/catalog/errors.rb +113 -0
- data/lib/droonga/catalog/schema.rb +186 -0
- data/lib/droonga/catalog/single_volume.rb +28 -0
- data/lib/droonga/catalog/slice.rb +41 -0
- data/lib/droonga/catalog/version1.rb +427 -0
- data/lib/droonga/catalog/version2.rb +96 -0
- data/lib/droonga/catalog/version2_validator.rb +63 -0
- data/lib/droonga/catalog/volume.rb +33 -0
- data/lib/droonga/catalog/volume_collection.rb +56 -0
- data/lib/droonga/catalog_generator.rb +156 -0
- data/lib/droonga/catalog_loader.rb +56 -0
- data/lib/droonga/catalog_observer.rb +83 -0
- data/lib/droonga/collector.rb +38 -0
- data/lib/droonga/collector_message.rb +71 -0
- data/lib/droonga/collector_runner.rb +64 -0
- data/lib/droonga/collectors/and.rb +26 -0
- data/lib/droonga/collectors/or.rb +26 -0
- data/lib/droonga/collectors/sum.rb +26 -0
- data/lib/droonga/collectors.rb +18 -0
- data/lib/droonga/dispatcher.rb +326 -0
- data/lib/droonga/distributed_command_planner.rb +179 -0
- data/lib/droonga/distributor.rb +87 -0
- data/lib/droonga/engine/command/droonga_engine.rb +441 -0
- data/lib/droonga/engine/version.rb +20 -0
- data/lib/droonga/engine.rb +80 -0
- data/lib/droonga/engine_state.rb +79 -0
- data/lib/droonga/error.rb +73 -0
- data/lib/droonga/error_messages.rb +33 -0
- data/lib/droonga/event_loop.rb +46 -0
- data/lib/droonga/farm.rb +58 -0
- data/lib/droonga/fluent_message_receiver.rb +191 -0
- data/lib/droonga/fluent_message_sender.rb +140 -0
- data/lib/droonga/forwarder.rb +119 -0
- data/lib/droonga/handler.rb +49 -0
- data/lib/droonga/handler_message.rb +61 -0
- data/lib/droonga/handler_messenger.rb +119 -0
- data/lib/droonga/handler_runner.rb +125 -0
- data/lib/droonga/input_message.rb +51 -0
- data/lib/droonga/job_protocol.rb +20 -0
- data/lib/droonga/job_pusher.rb +179 -0
- data/lib/droonga/job_receiver.rb +70 -0
- data/lib/droonga/loggable.rb +29 -0
- data/lib/droonga/logger.rb +142 -0
- data/lib/droonga/message_matcher.rb +109 -0
- data/lib/droonga/output_message.rb +55 -0
- data/lib/droonga/planner.rb +47 -0
- data/lib/droonga/pluggable.rb +31 -0
- data/lib/droonga/plugin/metadata/adapter_input_message.rb +39 -0
- data/lib/droonga/plugin/metadata/adapter_output_message.rb +39 -0
- data/lib/droonga/plugin/metadata/collector_message.rb +39 -0
- data/lib/droonga/plugin/metadata/handler_action.rb +39 -0
- data/lib/droonga/plugin/metadata/input_message.rb +54 -0
- data/lib/droonga/plugin.rb +43 -0
- data/lib/droonga/plugin_loader.rb +63 -0
- data/lib/droonga/plugin_registry.rb +66 -0
- data/lib/droonga/plugins/basic.rb +54 -0
- data/lib/droonga/plugins/crud.rb +145 -0
- data/lib/droonga/plugins/dump.rb +97 -0
- data/lib/droonga/plugins/error.rb +51 -0
- data/lib/droonga/plugins/groonga/column_create.rb +123 -0
- data/lib/droonga/plugins/groonga/column_list.rb +124 -0
- data/lib/droonga/plugins/groonga/column_remove.rb +65 -0
- data/lib/droonga/plugins/groonga/column_rename.rb +67 -0
- data/lib/droonga/plugins/groonga/delete.rb +117 -0
- data/lib/droonga/plugins/groonga/generic_command.rb +105 -0
- data/lib/droonga/plugins/groonga/generic_response.rb +43 -0
- data/lib/droonga/plugins/groonga/select.rb +236 -0
- data/lib/droonga/plugins/groonga/table_create.rb +111 -0
- data/lib/droonga/plugins/groonga/table_list.rb +120 -0
- data/lib/droonga/plugins/groonga/table_remove.rb +57 -0
- data/lib/droonga/plugins/groonga.rb +37 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +407 -0
- data/lib/droonga/plugins/search.rb +146 -0
- data/lib/droonga/plugins/watch.rb +178 -0
- data/lib/droonga/processor.rb +63 -0
- data/lib/droonga/reducer.rb +169 -0
- data/lib/droonga/replier.rb +49 -0
- data/lib/droonga/schema_applier.rb +167 -0
- data/lib/droonga/searcher/mecab_filter.rb +67 -0
- data/lib/droonga/searcher.rb +733 -0
- data/lib/droonga/server.rb +45 -0
- data/lib/droonga/session.rb +99 -0
- data/lib/droonga/single_step.rb +68 -0
- data/lib/droonga/single_step_definition.rb +54 -0
- data/lib/droonga/slice.rb +122 -0
- data/lib/droonga/status_code.rb +25 -0
- data/lib/droonga/step_runner.rb +64 -0
- data/lib/droonga/sweeper.rb +42 -0
- data/lib/droonga/test/stub_handler.rb +37 -0
- data/lib/droonga/test/stub_handler_message.rb +35 -0
- data/lib/droonga/test/stub_handler_messenger.rb +34 -0
- data/lib/droonga/test/stub_planner.rb +31 -0
- data/lib/droonga/test.rb +21 -0
- data/lib/droonga/watch_schema.rb +92 -0
- data/lib/droonga/watcher.rb +257 -0
- data/lib/droonga/worker.rb +61 -0
- data/sample/cluster/catalog.json +42 -0
- data/sample/mecab_filter/data.grn +7 -0
- data/sample/mecab_filter/ddl.grn +7 -0
- data/sample/mecab_filter/search_with_mecab_filter.json +21 -0
- data/sample/mecab_filter/search_without_mecab_filter.json +21 -0
- data/test/command/config/default/catalog.json +85 -0
- data/test/command/config/default/fluentd.conf +11 -0
- data/test/command/config/version1/catalog.json +68 -0
- data/test/command/config/version1/fluentd.conf +11 -0
- data/test/command/fixture/documents.jsons +208 -0
- data/test/command/fixture/event.jsons +41 -0
- data/test/command/fixture/user-table-array.jsons +38 -0
- data/test/command/fixture/user-table.jsons +47 -0
- data/test/command/run-test.rb +34 -0
- data/test/command/suite/add/dimension/column.catalog.json +28 -0
- data/test/command/suite/add/dimension/column.expected +41 -0
- data/test/command/suite/add/dimension/column.test +51 -0
- data/test/command/suite/add/dimension/integer.catalog.json +19 -0
- data/test/command/suite/add/dimension/integer.expected +41 -0
- data/test/command/suite/add/dimension/integer.test +51 -0
- data/test/command/suite/add/error/invalid-integer.expected +46 -0
- data/test/command/suite/add/error/invalid-integer.test +12 -0
- data/test/command/suite/add/error/invalid-time.expected +46 -0
- data/test/command/suite/add/error/invalid-time.test +12 -0
- data/test/command/suite/add/error/missing-key.expected +25 -0
- data/test/command/suite/add/error/missing-key.test +16 -0
- data/test/command/suite/add/error/missing-table.expected +25 -0
- data/test/command/suite/add/error/missing-table.test +16 -0
- data/test/command/suite/add/error/unknown-column.expected +46 -0
- data/test/command/suite/add/error/unknown-column.test +12 -0
- data/test/command/suite/add/error/unknown-table.expected +25 -0
- data/test/command/suite/add/error/unknown-table.test +17 -0
- data/test/command/suite/add/minimum.expected +6 -0
- data/test/command/suite/add/minimum.test +11 -0
- data/test/command/suite/add/with-values.expected +6 -0
- data/test/command/suite/add/with-values.test +17 -0
- data/test/command/suite/add/without-key.expected +6 -0
- data/test/command/suite/add/without-key.test +16 -0
- data/test/command/suite/groonga/column_create/scalar.expected +26 -0
- data/test/command/suite/groonga/column_create/scalar.test +17 -0
- data/test/command/suite/groonga/column_create/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_create/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_create/vector.expected +26 -0
- data/test/command/suite/groonga/column_create/vector.test +18 -0
- data/test/command/suite/groonga/column_list/success.expected +86 -0
- data/test/command/suite/groonga/column_list/success.test +24 -0
- data/test/command/suite/groonga/column_list/unknown-table.expected +13 -0
- data/test/command/suite/groonga/column_list/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_remove/success.expected +39 -0
- data/test/command/suite/groonga/column_remove/success.test +25 -0
- data/test/command/suite/groonga/column_remove/unknown-column.expected +27 -0
- data/test/command/suite/groonga/column_remove/unknown-column.test +16 -0
- data/test/command/suite/groonga/column_remove/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_remove/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_rename/success.expected +39 -0
- data/test/command/suite/groonga/column_rename/success.test +26 -0
- data/test/command/suite/groonga/column_rename/unknown-column.expected +27 -0
- data/test/command/suite/groonga/column_rename/unknown-column.test +16 -0
- data/test/command/suite/groonga/column_rename/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_rename/unknown-table.test +7 -0
- data/test/command/suite/groonga/delete/duplicated-identifiers.expected +27 -0
- data/test/command/suite/groonga/delete/duplicated-identifiers.test +17 -0
- data/test/command/suite/groonga/delete/filter.expected +19 -0
- data/test/command/suite/groonga/delete/filter.test +19 -0
- data/test/command/suite/groonga/delete/invalid-filter.expected +14 -0
- data/test/command/suite/groonga/delete/invalid-filter.test +9 -0
- data/test/command/suite/groonga/delete/no-identifier.expected +27 -0
- data/test/command/suite/groonga/delete/no-identifier.test +15 -0
- data/test/command/suite/groonga/delete/success.expected +19 -0
- data/test/command/suite/groonga/delete/success.test +19 -0
- data/test/command/suite/groonga/delete/unknown-table.expected +14 -0
- data/test/command/suite/groonga/delete/unknown-table.test +7 -0
- data/test/command/suite/groonga/select/minimum.expected +22 -0
- data/test/command/suite/groonga/select/minimum.test +8 -0
- data/test/command/suite/groonga/table_create/array.expected +14 -0
- data/test/command/suite/groonga/table_create/array.test +8 -0
- data/test/command/suite/groonga/table_create/hash.expected +13 -0
- data/test/command/suite/groonga/table_create/hash.test +8 -0
- data/test/command/suite/groonga/table_list/success.expected +71 -0
- data/test/command/suite/groonga/table_list/success.test +15 -0
- data/test/command/suite/groonga/table_remove/success.expected +13 -0
- data/test/command/suite/groonga/table_remove/success.test +8 -0
- data/test/command/suite/groonga/table_remove/unknown-table.expected +14 -0
- data/test/command/suite/groonga/table_remove/unknown-table.test +7 -0
- data/test/command/suite/message/error/missing-dataset.expected +9 -0
- data/test/command/suite/message/error/missing-dataset.test +5 -0
- data/test/command/suite/message/error/unknown-dataset.expected +9 -0
- data/test/command/suite/message/error/unknown-dataset.test +6 -0
- data/test/command/suite/message/error/unknown-type.expected +9 -0
- data/test/command/suite/message/error/unknown-type.test +6 -0
- data/test/command/suite/search/adjusters/multiple.catalog.json +38 -0
- data/test/command/suite/search/adjusters/multiple.expected +19 -0
- data/test/command/suite/search/adjusters/multiple.test +75 -0
- data/test/command/suite/search/adjusters/one.catalog.json +38 -0
- data/test/command/suite/search/adjusters/one.expected +19 -0
- data/test/command/suite/search/adjusters/one.test +66 -0
- data/test/command/suite/search/attributes/array.expected +21 -0
- data/test/command/suite/search/attributes/array.test +28 -0
- data/test/command/suite/search/attributes/hash.expected +30 -0
- data/test/command/suite/search/attributes/hash.test +36 -0
- data/test/command/suite/search/complex.expected +48 -0
- data/test/command/suite/search/complex.test +23 -0
- data/test/command/suite/search/condition/nested.expected +15 -0
- data/test/command/suite/search/condition/nested.test +27 -0
- data/test/command/suite/search/condition/query/nonexistent_column.catalog.json +37 -0
- data/test/command/suite/search/condition/query/nonexistent_column.expected +48 -0
- data/test/command/suite/search/condition/query/nonexistent_column.test +33 -0
- data/test/command/suite/search/condition/query/syntax_error.catalog.json +36 -0
- data/test/command/suite/search/condition/query/syntax_error.expected +48 -0
- data/test/command/suite/search/condition/query/syntax_error.test +33 -0
- data/test/command/suite/search/condition/query.expected +24 -0
- data/test/command/suite/search/condition/query.test +23 -0
- data/test/command/suite/search/condition/script.expected +24 -0
- data/test/command/suite/search/condition/script.test +26 -0
- data/test/command/suite/search/error/cyclic-source.expected +14 -0
- data/test/command/suite/search/error/cyclic-source.test +12 -0
- data/test/command/suite/search/error/deeply-cyclic-source.expected +17 -0
- data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
- data/test/command/suite/search/error/missing-source-parameter.expected +13 -0
- data/test/command/suite/search/error/missing-source-parameter.test +11 -0
- data/test/command/suite/search/error/no-query.expected +9 -0
- data/test/command/suite/search/error/no-query.test +7 -0
- data/test/command/suite/search/error/unknown-source.expected +52 -0
- data/test/command/suite/search/error/unknown-source.test +12 -0
- data/test/command/suite/search/group/count.expected +10 -0
- data/test/command/suite/search/group/count.test +18 -0
- data/test/command/suite/search/group/limit.expected +15 -0
- data/test/command/suite/search/group/limit.test +20 -0
- data/test/command/suite/search/group/string.expected +32 -0
- data/test/command/suite/search/group/string.test +40 -0
- data/test/command/suite/search/group/subrecord/with-sort.catalog.json +33 -0
- data/test/command/suite/search/group/subrecord/with-sort.expected +30 -0
- data/test/command/suite/search/group/subrecord/with-sort.test +81 -0
- data/test/command/suite/search/multiple/chained.expected +41 -0
- data/test/command/suite/search/multiple/chained.test +39 -0
- data/test/command/suite/search/multiple/parallel.expected +35 -0
- data/test/command/suite/search/multiple/parallel.test +35 -0
- data/test/command/suite/search/output/attributes/invalid.catalog.json +13 -0
- data/test/command/suite/search/output/attributes/invalid.expected +44 -0
- data/test/command/suite/search/output/attributes/invalid.test +28 -0
- data/test/command/suite/search/range/only-output.expected +24 -0
- data/test/command/suite/search/range/only-output.test +23 -0
- data/test/command/suite/search/range/only-sort.expected +24 -0
- data/test/command/suite/search/range/only-sort.test +26 -0
- data/test/command/suite/search/range/sort-and-output.expected +21 -0
- data/test/command/suite/search/range/sort-and-output.test +27 -0
- data/test/command/suite/search/range/too-large-output-offset.expected +12 -0
- data/test/command/suite/search/range/too-large-output-offset.test +23 -0
- data/test/command/suite/search/range/too-large-sort-offset.expected +12 -0
- data/test/command/suite/search/range/too-large-sort-offset.test +26 -0
- data/test/command/suite/search/response/elapsed_time.catalog.json +13 -0
- data/test/command/suite/search/response/elapsed_time.expected +11 -0
- data/test/command/suite/search/response/elapsed_time.test +26 -0
- data/test/command/suite/search/response/records/value/time.expected +20 -0
- data/test/command/suite/search/response/records/value/time.test +22 -0
- data/test/command/suite/search/simple.expected +48 -0
- data/test/command/suite/search/simple.test +22 -0
- data/test/command/suite/search/sort/default-offset-limit.expected +39 -0
- data/test/command/suite/search/sort/default-offset-limit.test +24 -0
- data/test/command/suite/search/sort/invisible-column.expected +24 -0
- data/test/command/suite/search/sort/invisible-column.test +26 -0
- data/test/command/suite/watch/subscribe.expected +6 -0
- data/test/command/suite/watch/subscribe.test +9 -0
- data/test/command/suite/watch/unsubscribe.expected +6 -0
- data/test/command/suite/watch/unsubscribe.test +9 -0
- data/test/performance/run-test.rb +56 -0
- data/test/performance/watch/catalog.json +33 -0
- data/test/performance/watch/feed.json +9 -0
- data/test/performance/watch/fluentd.conf +11 -0
- data/test/performance/watch/subscribe.json +3 -0
- data/test/unit/catalog/test_collection_volume.rb +103 -0
- data/test/unit/catalog/test_dataset.rb +104 -0
- data/test/unit/catalog/test_schema.rb +226 -0
- data/test/unit/catalog/test_single_volume.rb +31 -0
- data/test/unit/catalog/test_slice.rb +92 -0
- data/test/unit/catalog/test_version1.rb +361 -0
- data/test/unit/catalog/test_version2.rb +124 -0
- data/test/unit/catalog/test_version2_validator.rb +66 -0
- data/test/unit/catalog/test_volume_collection.rb +50 -0
- data/test/unit/fixtures/array.grn +18 -0
- data/test/unit/fixtures/catalog/version1.json +40 -0
- data/test/unit/fixtures/catalog/version2.json +62 -0
- data/test/unit/fixtures/document.grn +34 -0
- data/test/unit/fixtures/reference/array.grn +11 -0
- data/test/unit/fixtures/reference/hash.grn +7 -0
- data/test/unit/helper/distributed_search_planner_helper.rb +83 -0
- data/test/unit/helper/fixture.rb +28 -0
- data/test/unit/helper/plugin_helper.rb +38 -0
- data/test/unit/helper/sandbox.rb +86 -0
- data/test/unit/helper/stub_worker.rb +27 -0
- data/test/unit/helper/watch_helper.rb +23 -0
- data/test/unit/helper.rb +28 -0
- data/test/unit/plugins/crud/test_add.rb +190 -0
- data/test/unit/plugins/groonga/select/test_adapter_input.rb +510 -0
- data/test/unit/plugins/groonga/select/test_adapter_output.rb +201 -0
- data/test/unit/plugins/groonga/test_column_create.rb +171 -0
- data/test/unit/plugins/groonga/test_column_list.rb +170 -0
- data/test/unit/plugins/groonga/test_column_remove.rb +98 -0
- data/test/unit/plugins/groonga/test_column_rename.rb +105 -0
- data/test/unit/plugins/groonga/test_delete.rb +127 -0
- data/test/unit/plugins/groonga/test_table_create.rb +147 -0
- data/test/unit/plugins/groonga/test_table_list.rb +184 -0
- data/test/unit/plugins/groonga/test_table_remove.rb +61 -0
- data/test/unit/plugins/search/planner/test_basic.rb +120 -0
- data/test/unit/plugins/search/planner/test_group_by.rb +573 -0
- data/test/unit/plugins/search/planner/test_output.rb +388 -0
- data/test/unit/plugins/search/planner/test_sort_by.rb +938 -0
- data/test/unit/plugins/search/test_collector.rb +806 -0
- data/test/unit/plugins/search/test_handler.rb +930 -0
- data/test/unit/plugins/search/test_planner.rb +174 -0
- data/test/unit/plugins/test_basic.rb +510 -0
- data/test/unit/plugins/test_groonga.rb +70 -0
- data/test/unit/plugins/test_watch.rb +211 -0
- data/test/unit/run-test.rb +56 -0
- data/test/unit/test_catalog_generator.rb +93 -0
- data/test/unit/test_message_matcher.rb +160 -0
- data/test/unit/test_schema_applier.rb +59 -0
- data/test/unit/test_sweeper.rb +95 -0
- data/test/unit/test_watch_schema.rb +57 -0
- data/test/unit/test_watcher.rb +336 -0
- metadata +759 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Copyright (C) 2013-2014 Droonga Project
|
|
2
|
+
#
|
|
3
|
+
# This library is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "droonga/plugin"
|
|
17
|
+
require "droonga/watcher"
|
|
18
|
+
require "droonga/sweeper"
|
|
19
|
+
require "droonga/watch_schema"
|
|
20
|
+
|
|
21
|
+
module Droonga
|
|
22
|
+
module Plugins
|
|
23
|
+
module Watch
|
|
24
|
+
extend Plugin
|
|
25
|
+
register("watch")
|
|
26
|
+
|
|
27
|
+
module SchemaCreatable
|
|
28
|
+
private
|
|
29
|
+
def ensure_schema_created
|
|
30
|
+
# XXX just workaround. This must be re-written.
|
|
31
|
+
# When secondary and later processes opens the database,
|
|
32
|
+
# creation processes of tables by the first process is
|
|
33
|
+
# not finished yet. Then secondary and others tries to
|
|
34
|
+
# create tables and raises errors. To avoid such a problem,
|
|
35
|
+
# the creation processes of tables is disabled on workers.
|
|
36
|
+
if $0 !~ /\AServer/
|
|
37
|
+
schema = WatchSchema.new(@context)
|
|
38
|
+
schema.ensure_created
|
|
39
|
+
else
|
|
40
|
+
until @context["Keyword"]
|
|
41
|
+
sleep 0.1
|
|
42
|
+
end
|
|
43
|
+
sleep 1
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module MessageParsable
|
|
49
|
+
private
|
|
50
|
+
def parse_message(message)
|
|
51
|
+
request = message.request
|
|
52
|
+
subscriber = request["subscriber"]
|
|
53
|
+
condition = request["condition"]
|
|
54
|
+
route = request["route"] || message["from"]
|
|
55
|
+
if condition
|
|
56
|
+
query = condition.to_json
|
|
57
|
+
else
|
|
58
|
+
query = nilondition
|
|
59
|
+
end
|
|
60
|
+
[subscriber, condition, query, route]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class SubscribeHandler < Droonga::Handler
|
|
65
|
+
include SchemaCreatable
|
|
66
|
+
include MessageParsable
|
|
67
|
+
|
|
68
|
+
def initialize(*args)
|
|
69
|
+
super
|
|
70
|
+
ensure_schema_created # TODO: REMOVE ME
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def handle(message)
|
|
74
|
+
subscriber, condition, query, route = parse_message(message)
|
|
75
|
+
normalized_request = {
|
|
76
|
+
:subscriber => subscriber,
|
|
77
|
+
:condition => condition,
|
|
78
|
+
:query => query,
|
|
79
|
+
:route => route,
|
|
80
|
+
}
|
|
81
|
+
watcher = Watcher.new(@context)
|
|
82
|
+
watcher.subscribe(normalized_request)
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
define_single_step do |step|
|
|
88
|
+
step.name = "watch.subscribe"
|
|
89
|
+
step.write = true
|
|
90
|
+
step.handler = SubscribeHandler
|
|
91
|
+
step.collector = Collectors::And
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class UnsubscribeHandler < Droonga::Handler
|
|
95
|
+
include SchemaCreatable
|
|
96
|
+
include MessageParsable
|
|
97
|
+
|
|
98
|
+
def initialize(*args)
|
|
99
|
+
super
|
|
100
|
+
ensure_schema_created # TODO: REMOVE ME
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def handle(message)
|
|
104
|
+
subscriber, condition, query, route = parse_message(message)
|
|
105
|
+
_ = route # suppress a warning
|
|
106
|
+
normalized_request = {
|
|
107
|
+
:subscriber => subscriber,
|
|
108
|
+
:condition => condition,
|
|
109
|
+
:query => query,
|
|
110
|
+
}
|
|
111
|
+
watcher = Watcher.new(@context)
|
|
112
|
+
watcher.unsubscribe(normalized_request)
|
|
113
|
+
true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
define_single_step do |step|
|
|
118
|
+
step.name = "watch.unsubscribe"
|
|
119
|
+
step.write = true
|
|
120
|
+
step.handler = UnsubscribeHandler
|
|
121
|
+
step.collector = Collectors::And
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class FeedHandler < Droonga::Handler
|
|
125
|
+
include SchemaCreatable
|
|
126
|
+
|
|
127
|
+
def initialize(*args)
|
|
128
|
+
super
|
|
129
|
+
ensure_schema_created # TODO: REMOVE ME
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def handle(message)
|
|
133
|
+
request = message.request
|
|
134
|
+
watcher = Watcher.new(@context)
|
|
135
|
+
watcher.feed(:targets => request["targets"]) do |route, subscribers|
|
|
136
|
+
published_message = {
|
|
137
|
+
"to" => subscribers,
|
|
138
|
+
"body" => request,
|
|
139
|
+
}
|
|
140
|
+
published_message = message.raw.merge(published_message)
|
|
141
|
+
messenger.forward(published_message,
|
|
142
|
+
"to" => route, "type" => "watch.publish")
|
|
143
|
+
end
|
|
144
|
+
nil
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
define_single_step do |step|
|
|
149
|
+
step.name = "watch.feed"
|
|
150
|
+
step.write = true
|
|
151
|
+
step.handler = FeedHandler
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class SweepHandler < Droonga::Handler
|
|
155
|
+
include SchemaCreatable
|
|
156
|
+
|
|
157
|
+
message.type = "watch.sweep"
|
|
158
|
+
|
|
159
|
+
def initialize(*args)
|
|
160
|
+
super
|
|
161
|
+
ensure_schema_created # TODO: REMOVE ME
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def handle(message)
|
|
165
|
+
sweeper = Sweeper.new(@context)
|
|
166
|
+
sweeper.sweep_expired_subscribers
|
|
167
|
+
nil
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
define_single_step do |step|
|
|
172
|
+
step.name = "watch.sweep"
|
|
173
|
+
step.write = true
|
|
174
|
+
step.handler = SweepHandler
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Copyright (C) 2013-2014 Droonga Project
|
|
2
|
+
#
|
|
3
|
+
# This library is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "droonga/loggable"
|
|
17
|
+
require "droonga/handler_runner"
|
|
18
|
+
|
|
19
|
+
module Droonga
|
|
20
|
+
class Processor
|
|
21
|
+
include Loggable
|
|
22
|
+
|
|
23
|
+
def initialize(loop, job_pusher, options={})
|
|
24
|
+
@loop = loop
|
|
25
|
+
@job_pusher = job_pusher
|
|
26
|
+
@options = options
|
|
27
|
+
@n_workers = @options[:n_workers] || 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def start
|
|
31
|
+
@handler_runner = HandlerRunner.new(@loop, @options)
|
|
32
|
+
@handler_runner.start
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def shutdown
|
|
36
|
+
logger.trace("shutdown: start")
|
|
37
|
+
@handler_runner.shutdown
|
|
38
|
+
logger.trace("shutdown: done")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def process(message)
|
|
42
|
+
logger.trace("process: start")
|
|
43
|
+
type = message["type"]
|
|
44
|
+
if @handler_runner.processable?(type)
|
|
45
|
+
logger.trace("process: handlable: #{type}")
|
|
46
|
+
synchronous = @handler_runner.prefer_synchronous?(type)
|
|
47
|
+
if @n_workers.zero? or synchronous
|
|
48
|
+
@handler_runner.process(message)
|
|
49
|
+
else
|
|
50
|
+
@job_pusher.push(message)
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
logger.trace("process: ignore #{type}")
|
|
54
|
+
end
|
|
55
|
+
logger.trace("process: done")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
def log_tag
|
|
60
|
+
"processor"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Copyright (C) 2014 Droonga Project
|
|
2
|
+
#
|
|
3
|
+
# This library is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
module Droonga
|
|
17
|
+
class Reducer
|
|
18
|
+
class << self
|
|
19
|
+
# TODO: This is right location?
|
|
20
|
+
def apply_range(items, range)
|
|
21
|
+
if items and items.is_a?(Array)
|
|
22
|
+
offset = range["offset"] || 0
|
|
23
|
+
unless offset.zero?
|
|
24
|
+
items = items[offset..-1] || []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
limit = range["limit"] || 0
|
|
28
|
+
unless limit == UNLIMITED
|
|
29
|
+
items = items[0...limit]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
items
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# XXX: We has ULIMITED defined
|
|
37
|
+
# lib/droonga/plugins/search/distributed_search_planner.rb. We
|
|
38
|
+
# should unify it.
|
|
39
|
+
UNLIMITED = -1
|
|
40
|
+
|
|
41
|
+
def initialize(deal)
|
|
42
|
+
@deal = deal # TODO: deal is good name?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reduce(left_value, right_value)
|
|
46
|
+
if left_value.nil? or right_value.nil?
|
|
47
|
+
return right_value || left_value
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
reduced_value = nil
|
|
51
|
+
|
|
52
|
+
case @deal["type"]
|
|
53
|
+
when "and"
|
|
54
|
+
reduced_value = (left_value and right_value)
|
|
55
|
+
when "or"
|
|
56
|
+
reduced_value = (left_value or right_value)
|
|
57
|
+
when "sum"
|
|
58
|
+
reduced_value = sum(left_value, right_value)
|
|
59
|
+
reduced_value = self.class.apply_range(reduced_value,
|
|
60
|
+
"limit" => @deal["limit"])
|
|
61
|
+
when "average"
|
|
62
|
+
reduced_value = (left_value.to_f + right_value.to_f) / 2
|
|
63
|
+
when "sort"
|
|
64
|
+
reduced_value = merge(left_value,
|
|
65
|
+
right_value,
|
|
66
|
+
:operators => @deal["operators"],
|
|
67
|
+
:key_column => @deal["key_column"])
|
|
68
|
+
reduced_value = self.class.apply_range(reduced_value,
|
|
69
|
+
"limit" => @deal["limit"])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
reduced_value
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
def sum(x, y)
|
|
77
|
+
return x || y if x.nil? or y.nil?
|
|
78
|
+
|
|
79
|
+
if x.is_a?(Hash) and y.is_a?(Hash)
|
|
80
|
+
x.merge(y)
|
|
81
|
+
else
|
|
82
|
+
x + y
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def merge(x, y, options={})
|
|
87
|
+
operators = options[:operators] = normalize_operators(options[:operators])
|
|
88
|
+
|
|
89
|
+
unify_by_key!(x, y, options)
|
|
90
|
+
|
|
91
|
+
index = 0
|
|
92
|
+
y.each do |_y|
|
|
93
|
+
loop do
|
|
94
|
+
_x = x[index]
|
|
95
|
+
break unless _x
|
|
96
|
+
break if compare(_y, _x, operators)
|
|
97
|
+
index += 1
|
|
98
|
+
end
|
|
99
|
+
x.insert(index, _y)
|
|
100
|
+
index += 1
|
|
101
|
+
end
|
|
102
|
+
return x
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def normalize_operators(operators)
|
|
106
|
+
operators ||= []
|
|
107
|
+
operators.collect do |operator|
|
|
108
|
+
if operator.is_a?(String)
|
|
109
|
+
{ "operator" => operator }
|
|
110
|
+
else
|
|
111
|
+
operator
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def compare(x, y, operators)
|
|
117
|
+
operators.each_with_index do |operator, index|
|
|
118
|
+
column = operator["column"] || index
|
|
119
|
+
operator = operator["operator"]
|
|
120
|
+
_x = x[column]
|
|
121
|
+
_y = y[column]
|
|
122
|
+
return true if _x.__send__(operator, _y)
|
|
123
|
+
end
|
|
124
|
+
return false
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def unify_by_key!(base_items, unified_items, options={})
|
|
128
|
+
key_column_index = options[:key_column]
|
|
129
|
+
return unless key_column_index
|
|
130
|
+
|
|
131
|
+
# The unified records must be smaller than the base, because
|
|
132
|
+
# I sort unified records at last. I want to sort only smaller array.
|
|
133
|
+
if base_items.size < unified_items.size
|
|
134
|
+
base_items, unified_items = unified_items, base_items
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
unified_key_map = {}
|
|
138
|
+
unified_items.each do |unified_item|
|
|
139
|
+
unified_key_map[unified_item[key_column_index]] = unified_item
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
unified = false
|
|
143
|
+
base_items.reject! do |base_item|
|
|
144
|
+
key = base_item[key_column_index]
|
|
145
|
+
unified_item = unified_key_map[key]
|
|
146
|
+
if unified_item
|
|
147
|
+
base_item.each_with_index do |value, column_index|
|
|
148
|
+
next if column_index == key_column_index
|
|
149
|
+
unified_item[column_index] += value
|
|
150
|
+
end
|
|
151
|
+
unified = true
|
|
152
|
+
true
|
|
153
|
+
else
|
|
154
|
+
false
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
if unified
|
|
159
|
+
unified_items.sort! do |a, b|
|
|
160
|
+
if compare(a, b, options[:operators])
|
|
161
|
+
-1
|
|
162
|
+
else
|
|
163
|
+
1
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright (C) 2013 Droonga Project
|
|
2
|
+
#
|
|
3
|
+
# This library is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "droonga/loggable"
|
|
17
|
+
require "droonga/status_code"
|
|
18
|
+
|
|
19
|
+
module Droonga
|
|
20
|
+
class Replier
|
|
21
|
+
include Loggable
|
|
22
|
+
|
|
23
|
+
def initialize(forwarder)
|
|
24
|
+
@forwarder = forwarder
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def reply(message)
|
|
28
|
+
logger.trace("reply: start")
|
|
29
|
+
destination = message["replyTo"]
|
|
30
|
+
reply_message = {
|
|
31
|
+
"inReplyTo" => message["id"],
|
|
32
|
+
"statusCode" => message["statusCode"] || StatusCode::OK,
|
|
33
|
+
"type" => destination["type"],
|
|
34
|
+
"body" => message["body"],
|
|
35
|
+
}
|
|
36
|
+
if message.include?("errors")
|
|
37
|
+
errors = message["errors"]
|
|
38
|
+
reply_message["errors"] = errors unless errors.empty?
|
|
39
|
+
end
|
|
40
|
+
@forwarder.forward(reply_message, destination)
|
|
41
|
+
logger.trace("reply: done")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
def log_tag
|
|
46
|
+
"[#{Process.ppid}][#{Process.pid}] replier"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Copyright (C) 2014 Droonga Project
|
|
2
|
+
#
|
|
3
|
+
# This library is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "droonga/loggable"
|
|
17
|
+
|
|
18
|
+
module Droonga
|
|
19
|
+
class SchemaApplier
|
|
20
|
+
include Loggable
|
|
21
|
+
|
|
22
|
+
def initialize(context, schema)
|
|
23
|
+
@context = context
|
|
24
|
+
@schema = schema
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def apply
|
|
28
|
+
# TODO: Support migration
|
|
29
|
+
Groonga::Schema.define(:context => @context) do |schema|
|
|
30
|
+
create_tables(schema)
|
|
31
|
+
create_reference_columns(schema)
|
|
32
|
+
create_index_columns(schema)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
def each_table
|
|
38
|
+
reference_tables = []
|
|
39
|
+
@schema.tables.each_value do |table|
|
|
40
|
+
if reference_table?(table)
|
|
41
|
+
reference_tables << table
|
|
42
|
+
else
|
|
43
|
+
yield(table)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
reference_tables.each do |table|
|
|
47
|
+
yield(table)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def reference_table?(table)
|
|
52
|
+
table.type != "Array" and !type_names.include?(table.key_type_groonga)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def each_column(table)
|
|
56
|
+
table.columns.each_value do |column|
|
|
57
|
+
yield(column)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def normal_column?(column)
|
|
62
|
+
column.type != "Index" and type_names.include?(column.value_type_groonga)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def reference_column?(column)
|
|
66
|
+
column.type != "Index" and !type_names.include?(column.value_type_groonga)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def index_column?(column)
|
|
70
|
+
column.type == "Index"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def types
|
|
74
|
+
@types ||= collect_available_types
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def type_names
|
|
78
|
+
@type_names ||= types.collect(&:name)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def collect_available_types
|
|
82
|
+
each_options = {
|
|
83
|
+
:ignore_missing_object => true
|
|
84
|
+
}
|
|
85
|
+
@context.database.each(each_options).find_all do |object|
|
|
86
|
+
object.is_a?(Groonga::Type)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def create_tables(schema)
|
|
91
|
+
each_table do |table|
|
|
92
|
+
create_table(schema, table)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def create_table(schema, table)
|
|
97
|
+
options = {
|
|
98
|
+
:type => table.type_symbol,
|
|
99
|
+
:key_type => table.key_type_groonga,
|
|
100
|
+
:default_tokenizer => table.tokenizer,
|
|
101
|
+
:normalizer => table.normalizer,
|
|
102
|
+
}
|
|
103
|
+
schema.create_table(table.name, options) do |table_definition|
|
|
104
|
+
each_column(table) do |column|
|
|
105
|
+
next unless normal_column?(column)
|
|
106
|
+
create_data_column(table_definition, column)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def create_data_column(table_definition, column)
|
|
112
|
+
options = {
|
|
113
|
+
:type => column.type_symbol,
|
|
114
|
+
}
|
|
115
|
+
if options[:type] == :vector
|
|
116
|
+
options[:with_weight] = true if column.vector_options.weight
|
|
117
|
+
end
|
|
118
|
+
table_definition.column(column.name, column.value_type_groonga, options)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def create_reference_columns(schema)
|
|
122
|
+
each_table do |table|
|
|
123
|
+
reference_columns = []
|
|
124
|
+
each_column(table) do |column|
|
|
125
|
+
reference_columns << column if reference_column?(column)
|
|
126
|
+
end
|
|
127
|
+
next if reference_columns.empty?
|
|
128
|
+
|
|
129
|
+
schema.change_table(table.name) do |table_definition|
|
|
130
|
+
reference_columns.each do |column|
|
|
131
|
+
create_data_column(table_definition, column)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def create_index_columns(schema)
|
|
138
|
+
each_table do |table|
|
|
139
|
+
index_columns = []
|
|
140
|
+
each_column(table) do |column|
|
|
141
|
+
index_columns << column if index_column?(column)
|
|
142
|
+
end
|
|
143
|
+
next if index_columns.empty?
|
|
144
|
+
|
|
145
|
+
schema.change_table(table.name) do |table_definition|
|
|
146
|
+
index_columns.each do |column|
|
|
147
|
+
create_index_column(table_definition, column)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def create_index_column(table_definition, column)
|
|
154
|
+
sources = column.index_options.sources || []
|
|
155
|
+
options = {
|
|
156
|
+
:with_section => column.index_options.section,
|
|
157
|
+
:with_weight => column.index_options.weight,
|
|
158
|
+
:with_position => column.index_options.position,
|
|
159
|
+
}
|
|
160
|
+
table_definition.index(column.value_type_groonga, *sources, options)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def log_tag
|
|
164
|
+
"schema_applier"
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
|
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 "MeCab"
|
|
19
|
+
|
|
20
|
+
module Droonga
|
|
21
|
+
class Searcher
|
|
22
|
+
class QuerySearcher
|
|
23
|
+
class MeCabTokenizer
|
|
24
|
+
def initialize
|
|
25
|
+
@mecab = MeCab::Tagger.new("-Owakati")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tokenize(text)
|
|
29
|
+
tokens = @mecab.parse(text).force_encoding("utf-8").split(/\s+/)
|
|
30
|
+
tokens.reject do |token|
|
|
31
|
+
token.empty?
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def apply_mecab_filter(condition)
|
|
37
|
+
return unless condition.is_a?(Hash)
|
|
38
|
+
return unless condition["useMeCabFilter"]
|
|
39
|
+
query = condition["query"]
|
|
40
|
+
return if query.nil?
|
|
41
|
+
match_columns = condition["matchTo"]
|
|
42
|
+
return unless match_columns.is_a?(Array)
|
|
43
|
+
return if match_columns.size != 1
|
|
44
|
+
match_column = match_columns.first
|
|
45
|
+
|
|
46
|
+
tokenizer = MeCabTokenizer.new
|
|
47
|
+
|
|
48
|
+
@records.open_cursor do |cursor|
|
|
49
|
+
count = 0
|
|
50
|
+
cursor.each do |record|
|
|
51
|
+
match_target = record[match_column]
|
|
52
|
+
body_terms = tokenizer.tokenize(match_target)
|
|
53
|
+
unless body_terms.include?(query)
|
|
54
|
+
record.delete
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
alias_method :original_apply_condition!, :apply_condition!
|
|
61
|
+
def apply_condition!(condition)
|
|
62
|
+
original_apply_condition!(condition)
|
|
63
|
+
apply_mecab_filter(condition)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|