[groonga-commit:4248] ranguba/rroonga [master] add Groonga::Command::Builder.escape_value.

null+ranguba at clear-code.com null+ranguba at clear-code.com
Mon Jan 30 02:16:38 EST 2012


Kouhei Sutou	2012-01-30 16:16:38 +0900 (Mon, 30 Jan 2012)

  New Revision: 234dc4512b9492572d8a6fe6d8c86c371dc7ae29

  Log:
    add Groonga::Command::Builder.escape_value.

  Added files:
    lib/groonga/command.rb
  Modified files:
    lib/groonga/context.rb
  Renamed files:
    test/test-command-select.rb
      (from test/test-context-select.rb)

  Added: lib/groonga/command.rb (+169 -0) 100644
===================================================================
--- /dev/null
+++ lib/groonga/command.rb    2012-01-30 16:16:38 +0900 (430a974)
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2012  Kouhei Sutou <kou at clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+module Groonga
+  module Command
+    class Builder
+      class << self
+        def escape_value(value)
+          escaped_value = value.to_s.gsub(/"/, '\\"')
+          "\"#{escaped_value}\""
+        end
+      end
+
+      attr_reader :command, :arguments
+      def initialize(command, arguments={})
+        @command = command
+        @arguments = arguments
+      end
+
+      def [](key)
+        @arguments[key]
+      end
+
+      def []=(key, value)
+        @arguments[key] = value
+      end
+
+      def build
+        query = "#{@command} "
+        @arguments.each do |key, value|
+          value = value.join(", ") if value.is_a?(::Array)
+          escaped_value = self.class.escape_value(value)
+          query << " --#{key} #{escaped_value}"
+        end
+        query
+      end
+    end
+
+    class Select
+      def initialize(context, table, options)
+        @context = context
+        @table = table
+        @options = normalize_options(options)
+      end
+
+      def exec
+        request_id = @context.send(query)
+        loop do
+          response_id, result = @context.receive
+          if request_id == response_id
+            drill_down_keys = @options["drilldown"]
+            if drill_down_keys.is_a?(String)
+              drill_down_keys = drill_down_keys.split(/(?:\s+|\s*,\s*)/)
+            end
+            return Result.parse(result, drill_down_keys)
+          end
+          # raise if request_id < response_id
+        end
+      end
+
+      private
+      def normalize_options(options)
+        normalized_options = {}
+        options.each do |key, value|
+          normalized_options[normalize_option_name(key)] = value
+        end
+        normalized_options
+      end
+
+      def normalize_option_name(name)
+        name = name.to_s.gsub(/-/, "_").gsub(/drill_down/, "drilldown")
+        name.gsub(/sort_by/, 'sortby')
+      end
+
+      def query
+        if @table.is_a?(String)
+          table_name = @table
+        else
+          table_name = @table.name
+        end
+        builder = Builder.new("select", @options.merge(:table => table_name))
+        builder.build
+      end
+
+      class Result < Struct.new(:n_hits, :columns, :values, :drill_down)
+        class << self
+          def parse(json, drill_down_keys)
+            select_result, *drill_down_results = JSON.parse(json)
+            result = new
+            n_hits, columns, values = extract_result(select_result)
+            result.n_hits = n_hits
+            result.columns = columns
+            result.values = values
+            if drill_down_results
+              result.drill_down = parse_drill_down_results(drill_down_results,
+                                                           drill_down_keys)
+            end
+            result
+          end
+
+          def create_records(columns, values)
+            records = []
+            values.each do |value|
+              record = {}
+              columns.each_with_index do |(name, type), i|
+                record[name] = convert_value(value[i], type)
+              end
+              records << record
+            end
+            records
+          end
+
+          private
+          def parse_drill_down_results(results, keys)
+            named_results = {}
+            results.each_with_index do |drill_down, i|
+              n_hits, columns, values = extract_result(drill_down)
+              drill_down_result = DrillDownResult.new
+              drill_down_result.n_hits = n_hits
+              drill_down_result.columns = columns
+              drill_down_result.values = values
+              named_results[keys[i]] = drill_down_result
+            end
+            named_results
+          end
+
+          def extract_result(result)
+            meta_data, columns, *values = result
+            n_hits, = meta_data
+            [n_hits, columns, values]
+          end
+
+          def convert_value(value, type)
+            case type
+            when "Time"
+              Time.at(value)
+            else
+              value
+            end
+          end
+        end
+
+        def records
+          @records ||= self.class.create_records(columns, values)
+        end
+
+        class DrillDownResult < Struct.new(:n_hits, :columns, :values)
+          def records
+            @records ||= Result.create_records(columns, values)
+          end
+        end
+      end
+    end
+  end
+end

  Modified: lib/groonga/context.rb (+4 -124)
===================================================================
--- lib/groonga/context.rb    2012-01-26 15:25:41 +0900 (ac00b83)
+++ lib/groonga/context.rb    2012-01-30 16:16:38 +0900 (896fca1)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011  Kouhei Sutou <kou at clear-code.com>
+# Copyright (C) 2010-2012  Kouhei Sutou <kou at clear-code.com>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,8 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+require "groonga/command"
+
 module Groonga
   class Context
     # _path_ にある既存のデータベースを開く。ブロックを指定した場
@@ -70,130 +72,8 @@ module Groonga
     # @option options [Array] XXX TODO
     #   TODO
     def select(table, options={})
-      select = SelectCommand.new(self, table, options)
+      select = Command::Select.new(self, table, options)
       select.exec
     end
-
-    class SelectResult < Struct.new(:n_hits, :columns, :values,
-                                    :drill_down)
-      class << self
-        def parse(json, drill_down_keys)
-          select_result, *drill_down_results = JSON.parse(json)
-          result = new
-          n_hits, columns, values = extract_result(select_result)
-          result.n_hits = n_hits
-          result.columns = columns
-          result.values = values
-          if drill_down_results
-            result.drill_down = parse_drill_down_results(drill_down_results,
-                                                         drill_down_keys)
-          end
-          result
-        end
-
-        def create_records(columns, values)
-          records = []
-          values.each do |value|
-            record = {}
-            columns.each_with_index do |(name, type), i|
-              record[name] = convert_value(value[i], type)
-            end
-            records << record
-          end
-          records
-        end
-
-        private
-        def parse_drill_down_results(results, keys)
-          named_results = {}
-          results.each_with_index do |drill_down, i|
-            n_hits, columns, values = extract_result(drill_down)
-            drill_down_result = DrillDownResult.new
-            drill_down_result.n_hits = n_hits
-            drill_down_result.columns = columns
-            drill_down_result.values = values
-            named_results[keys[i]] = drill_down_result
-          end
-          named_results
-        end
-
-        def extract_result(result)
-          meta_data, columns, *values = result
-          n_hits, = meta_data
-          [n_hits, columns, values]
-        end
-
-        def convert_value(value, type)
-          case type
-          when "Time"
-            Time.at(value)
-          else
-            value
-          end
-        end
-      end
-
-      def records
-        @records ||= self.class.create_records(columns, values)
-      end
-
-      class DrillDownResult < Struct.new(:n_hits, :columns, :values)
-        def records
-          @records ||= SelectResult.create_records(columns, values)
-        end
-      end
-    end
-
-    class SelectCommand
-      def initialize(context, table, options)
-        @context = context
-        @table = table
-        @options = normalize_options(options)
-      end
-
-      def exec
-        request_id = @context.send(query)
-        loop do
-          response_id, result = @context.receive
-          if request_id == response_id
-            drill_down_keys = @options["drilldown"]
-            if drill_down_keys.is_a?(String)
-              drill_down_keys = drill_down_keys.split(/(?:\s+|\s*,\s*)/)
-            end
-            return SelectResult.parse(result, drill_down_keys)
-          end
-          # raise if request_id < response_id
-        end
-      end
-
-      private
-      def normalize_options(options)
-        normalized_options = {}
-        options.each do |key, value|
-          normalized_options[normalize_option_name(key)] = value
-        end
-        normalized_options
-      end
-
-      def normalize_option_name(name)
-        name = name.to_s.gsub(/-/, "_").gsub(/drill_down/, "drilldown")
-        name.gsub(/sort_by/, 'sortby')
-      end
-
-      def query
-        if @table.is_a?(String)
-          table_name = @table
-        else
-          table_name = @table.name
-        end
-        _query = "select #{table_name}"
-        @options.each do |key, value|
-          value = value.join(", ") if value.is_a?(::Array)
-          escaped_value = value.to_s.gsub(/"/, '\\"')
-          _query << " --#{key} \"#{escaped_value}\""
-        end
-        _query
-      end
-    end
   end
 end

  Renamed: test/test-command-select.rb (+3 -3) 96%
===================================================================
--- test/test-context-select.rb    2012-01-26 15:25:41 +0900 (f2b713b)
+++ test/test-command-select.rb    2012-01-30 16:16:38 +0900 (5383a08)
@@ -1,4 +1,4 @@
-# Copyright (C) 2010  Kouhei Sutou <kou at clear-code.com>
+# Copyright (C) 2010-2012  Kouhei Sutou <kou at clear-code.com>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -13,7 +13,7 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-class ContextSelectTest < Test::Unit::TestCase
+class CommandSelectTest < Test::Unit::TestCase
   include GroongaTestUtils
 
   setup :setup_database
@@ -100,7 +100,7 @@ class ContextSelectTest < Test::Unit::TestCase
 
   def test_drill_down_with_no_hit
     result = context.select(@users,
-                            :filter => "_key == \"no hit\"",
+                            :filter => "_key == \"no\\ hit\"",
                             :output_columns => ["_key"],
                             :drill_down => ["_key", "book"],
                             :drill_down_output_columns => "_key",



More information about the groonga-commit mailing list