[Groonga-commit] groonga/groonga at 5e3f08c [master] mrb: support optimize for "X > 0 && X < 10"

Back to archive index

Kouhei Sutou null+****@clear*****
Fri Sep 12 23:34:57 JST 2014


Kouhei Sutou	2014-09-12 23:34:57 +0900 (Fri, 12 Sep 2014)

  New Revision: 5e3f08ccd013359c55904cf0dbdea2792b935334
  https://github.com/groonga/groonga/commit/5e3f08ccd013359c55904cf0dbdea2792b935334

  Message:
    mrb: support optimize for "X > 0 && X < 10"
    
        X > 0 && X < 10
        ->
        between(X, 0, "exclude", 10, "exclude")
    
        X >= 0 && X < 10
        ->
        between(X, 0, "include", 10, "exclude")
    
        X > 0 && X <= 10
        ->
        between(X, 0, "exclude", 10, "include")
    
        X >= 0 && X <= 10
        ->
        between(X, 0, "include", 10, "include")

  Added files:
    test/command/suite/select/filter/range/less_than_and_greater_than.expected
    test/command/suite/select/filter/range/less_than_and_greater_than.test
    test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.expected
    test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.test
    test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.expected
    test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.test
    test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.expected
    test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.test
  Modified files:
    lib/mrb/scripts/scan_info_builder.rb

  Modified: lib/mrb/scripts/scan_info_builder.rb (+98 -1)
===================================================================
--- lib/mrb/scripts/scan_info_builder.rb    2014-09-12 23:34:08 +0900 (0d88f40)
+++ lib/mrb/scripts/scan_info_builder.rb    2014-09-12 23:34:57 +0900 (55a6476)
@@ -123,7 +123,7 @@ module Groonga
         put_logical_op(@operator, n_codes)
       end
 
-      @data_list
+      optimize
     end
 
     private
@@ -239,5 +239,102 @@ module Groonga
         end
       end
     end
+
+    def optimize
+      optimized_data_list = []
+      i = 0
+      n = @data_list.size
+      while i < n
+        data = @data_list[i]
+        next_data = @data_list[i + 1]
+        i += 1
+        if next_data.nil?
+          optimized_data_list << data
+          next
+        end
+        if range_operations?(data, next_data)
+          between_data = create_between_data(data, next_data)
+          optimized_data_list << between_data
+          next
+        end
+        optimized_data_list << data
+      end
+      optimized_data_list
+    end
+
+    def range_operations?(data, next_data)
+      return false unless next_data.logical_op == Operator::AND
+
+      op, next_op = data.op, next_data.op
+      return false if !(lower_condition?(op) or lower_condition?(next_op))
+      return false if !(upper_condition?(op) or upper_condition?(next_op))
+
+      data.args[0] == next_data.args[0] and data.indexes == next_data.indexes
+    end
+
+    def lower_condition?(operator)
+      case operator
+      when Operator::GREATER, Operator::GREATER_EQUAL
+        true
+      else
+        false
+      end
+    end
+
+    def upper_condition?(operator)
+      case operator
+      when Operator::LESS, Operator::LESS_EQUAL
+        true
+      else
+        false
+      end
+    end
+
+    def create_between_data(data, next_data)
+      between_data = ScanInfoData.new(data.start)
+      between_data.end = next_data.end
+      between_data.op = Operator::CALL
+      between_data.logical_op = data.logical_op
+      between_data.args = create_between_data_args(data, next_data)
+      between_data.indexes = data.indexes
+      between_data
+    end
+
+    def create_between_data_args(data, next_data)
+      between = Context.instance["between"]
+      @expression.take_object(between)
+      column = data.args[0]
+      op, next_op = data.op, next_data.op
+      if lower_condition?(op)
+        min = data.args[1]
+        min_operator = op
+        max = next_data.args[1]
+        max_operator = next_op
+      else
+        min = next_data.args[1]
+        min_operator = next_op
+        max = data.args[1]
+        max_operator = op
+      end
+      if min_operator == Operator::GREATER
+        min_border = "exclude"
+      else
+        min_border = "include"
+      end
+      if max_operator == Operator::LESS
+        max_border = "exclude"
+      else
+        max_border = "include"
+      end
+
+      [
+        between,
+        column,
+        min,
+        @expression.allocate_constant(min_border),
+        max,
+        @expression.allocate_constant(max_border),
+      ]
+    end
   end
 end

  Added: test/command/suite/select/filter/range/less_than_and_greater_than.expected (+51 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_and_greater_than.expected    2014-09-12 23:34:57 +0900 (48702b1)
@@ -0,0 +1,51 @@
+table_create Users TABLE_HASH_KEY ShortText
+[[0,0.0,0.0],true]
+column_create Users age COLUMN_SCALAR Int32
+[[0,0.0,0.0],true]
+table_create Ages TABLE_PAT_KEY Int32
+[[0,0.0,0.0],true]
+column_create Ages users_age COLUMN_INDEX Users age
+[[0,0.0,0.0],true]
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+[[0,0.0,0.0],5]
+select Users --filter 'age > 18 && age < 20'
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        1
+      ],
+      [
+        [
+          "_id",
+          "UInt32"
+        ],
+        [
+          "_key",
+          "ShortText"
+        ],
+        [
+          "age",
+          "Int32"
+        ]
+      ],
+      [
+        3,
+        "calros",
+        19
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/select/filter/range/less_than_and_greater_than.test (+16 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_and_greater_than.test    2014-09-12 23:34:57 +0900 (660895c)
@@ -0,0 +1,16 @@
+table_create Users TABLE_HASH_KEY ShortText
+column_create Users age COLUMN_SCALAR Int32
+
+table_create Ages TABLE_PAT_KEY Int32
+column_create Ages users_age COLUMN_INDEX Users age
+
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+
+select Users --filter 'age > 18 && age < 20'

  Added: test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.expected (+56 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.expected    2014-09-12 23:34:57 +0900 (368c754)
@@ -0,0 +1,56 @@
+table_create Users TABLE_HASH_KEY ShortText
+[[0,0.0,0.0],true]
+column_create Users age COLUMN_SCALAR Int32
+[[0,0.0,0.0],true]
+table_create Ages TABLE_PAT_KEY Int32
+[[0,0.0,0.0],true]
+column_create Ages users_age COLUMN_INDEX Users age
+[[0,0.0,0.0],true]
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+[[0,0.0,0.0],5]
+select Users --filter 'age > 18 && age <= 20'
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        2
+      ],
+      [
+        [
+          "_id",
+          "UInt32"
+        ],
+        [
+          "_key",
+          "ShortText"
+        ],
+        [
+          "age",
+          "Int32"
+        ]
+      ],
+      [
+        3,
+        "calros",
+        19
+      ],
+      [
+        4,
+        "dave",
+        20
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.test (+16 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_and_greater_than_or_equal.test    2014-09-12 23:34:57 +0900 (ef75d7c)
@@ -0,0 +1,16 @@
+table_create Users TABLE_HASH_KEY ShortText
+column_create Users age COLUMN_SCALAR Int32
+
+table_create Ages TABLE_PAT_KEY Int32
+column_create Ages users_age COLUMN_INDEX Users age
+
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+
+select Users --filter 'age > 18 && age <= 20'

  Added: test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.expected (+56 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.expected    2014-09-12 23:34:57 +0900 (72a7342)
@@ -0,0 +1,56 @@
+table_create Users TABLE_HASH_KEY ShortText
+[[0,0.0,0.0],true]
+column_create Users age COLUMN_SCALAR Int32
+[[0,0.0,0.0],true]
+table_create Ages TABLE_PAT_KEY Int32
+[[0,0.0,0.0],true]
+column_create Ages users_age COLUMN_INDEX Users age
+[[0,0.0,0.0],true]
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+[[0,0.0,0.0],5]
+select Users --filter 'age >= 18 && age < 20'
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        2
+      ],
+      [
+        [
+          "_id",
+          "UInt32"
+        ],
+        [
+          "_key",
+          "ShortText"
+        ],
+        [
+          "age",
+          "Int32"
+        ]
+      ],
+      [
+        2,
+        "bob",
+        18
+      ],
+      [
+        3,
+        "calros",
+        19
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.test (+16 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_or_equal_and_greater_than.test    2014-09-12 23:34:57 +0900 (5e4b273)
@@ -0,0 +1,16 @@
+table_create Users TABLE_HASH_KEY ShortText
+column_create Users age COLUMN_SCALAR Int32
+
+table_create Ages TABLE_PAT_KEY Int32
+column_create Ages users_age COLUMN_INDEX Users age
+
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+
+select Users --filter 'age >= 18 && age < 20'

  Added: test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.expected (+61 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.expected    2014-09-12 23:34:57 +0900 (d303a23)
@@ -0,0 +1,61 @@
+table_create Users TABLE_HASH_KEY ShortText
+[[0,0.0,0.0],true]
+column_create Users age COLUMN_SCALAR Int32
+[[0,0.0,0.0],true]
+table_create Ages TABLE_PAT_KEY Int32
+[[0,0.0,0.0],true]
+column_create Ages users_age COLUMN_INDEX Users age
+[[0,0.0,0.0],true]
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+[[0,0.0,0.0],5]
+select Users --filter 'age >= 18 && age <= 20'
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        3
+      ],
+      [
+        [
+          "_id",
+          "UInt32"
+        ],
+        [
+          "_key",
+          "ShortText"
+        ],
+        [
+          "age",
+          "Int32"
+        ]
+      ],
+      [
+        2,
+        "bob",
+        18
+      ],
+      [
+        3,
+        "calros",
+        19
+      ],
+      [
+        4,
+        "dave",
+        20
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.test (+16 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/filter/range/less_than_or_equal_and_greater_than_or_equal.test    2014-09-12 23:34:57 +0900 (49ace87)
@@ -0,0 +1,16 @@
+table_create Users TABLE_HASH_KEY ShortText
+column_create Users age COLUMN_SCALAR Int32
+
+table_create Ages TABLE_PAT_KEY Int32
+column_create Ages users_age COLUMN_INDEX Users age
+
+load --table Users
+[
+{"_key": "alice",  "age": 17},
+{"_key": "bob",    "age": 18},
+{"_key": "calros", "age": 19},
+{"_key": "dave",   "age": 20},
+{"_key": "eric",   "age": 21}
+]
+
+select Users --filter 'age >= 18 && age <= 20'
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index