[Groonga-commit] groonga/groonga at e2b5485 [master] grn_ts: support sorting Int, Float and Time

Back to archive index

Susumu Yata null+****@clear*****
Fri Nov 27 03:44:08 JST 2015


Susumu Yata	2015-11-27 03:44:08 +0900 (Fri, 27 Nov 2015)

  New Revision: e2b5485e5fd13e6391729a7aac35bad7f783eb2a
  https://github.com/groonga/groonga/commit/e2b5485e5fd13e6391729a7aac35bad7f783eb2a

  Message:
    grn_ts: support sorting Int, Float and Time
    
    GitHub: #429

  Modified files:
    lib/ts/ts_sorter.c
    lib/ts/ts_sorter.h

  Modified: lib/ts/ts_sorter.c (+350 -73)
===================================================================
--- lib/ts/ts_sorter.c    2015-11-26 21:33:17 +0900 (1018d31)
+++ lib/ts/ts_sorter.c    2015-11-27 03:44:08 +0900 (fa1c4a8)
@@ -34,6 +34,7 @@ grn_ts_sorter_node_init(grn_ctx *ctx, grn_ts_sorter_node *node)
 {
   memset(node, 0, sizeof(*node));
   node->expr = NULL;
+  grn_ts_buf_init(ctx, &node->buf);
   node->next = NULL;
 }
 
@@ -41,6 +42,7 @@ grn_ts_sorter_node_init(grn_ctx *ctx, grn_ts_sorter_node *node)
 static void
 grn_ts_sorter_node_fin(grn_ctx *ctx, grn_ts_sorter_node *node)
 {
+  grn_ts_buf_fin(ctx, &node->buf);
   if (node->expr) {
     grn_ts_expr_close(ctx, node->expr);
   }
@@ -111,15 +113,24 @@ grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node,
                         size_t offset, size_t limit,
                         grn_ts_record *recs, size_t n_recs);
 
-/* grn_ts_swap_recs() swaps records. */
-static void
-grn_ts_swap_recs(grn_ts_record *lhs, grn_ts_record *rhs)
+/* grn_ts_rec_swap() swaps records. */
+inline static void
+grn_ts_rec_swap(grn_ts_record *lhs, grn_ts_record *rhs)
 {
   grn_ts_record tmp = *lhs;
   *lhs = *rhs;
   *rhs = tmp;
 }
 
+/* grn_ts_int_swap() swaps Int values. */
+inline static void
+grn_ts_int_swap(grn_ts_int *lhs, grn_ts_int *rhs)
+{
+  grn_ts_int tmp = *lhs;
+  *lhs = *rhs;
+  *rhs = tmp;
+}
+
 /* FIXME: Sorting by _id does not assume ID duplicates. */
 
 /* grn_ts_move_pivot_by_id_asc() moves the pivot to the front. */
@@ -134,23 +145,23 @@ grn_ts_move_pivot_by_id_asc(grn_ts_record *recs, size_t n_recs)
     /* first < middle. */
     if (recs[middle].id < recs[last].id) {
       /* first < middle < last */
-      grn_ts_swap_recs(&recs[0], &recs[middle]);
+      grn_ts_rec_swap(&recs[0], &recs[middle]);
     } else if (recs[first].id < recs[last].id) {
       /* first < last < middle. */
-      grn_ts_swap_recs(&recs[0], &recs[last]);
+      grn_ts_rec_swap(&recs[0], &recs[last]);
     } else {
       /* last < first < middle. */
-      grn_ts_swap_recs(&recs[0], &recs[first]);
+      grn_ts_rec_swap(&recs[0], &recs[first]);
     }
   } else if (recs[last].id < recs[middle].id) {
     /* last < middle < first. */
-    grn_ts_swap_recs(&recs[0], &recs[middle]);
+    grn_ts_rec_swap(&recs[0], &recs[middle]);
   } else if (recs[last].id < recs[first].id) {
     /* middle < last < first. */
-    grn_ts_swap_recs(&recs[0], &recs[last]);
+    grn_ts_rec_swap(&recs[0], &recs[last]);
   } else {
     /* middle < first < last. */
-    grn_ts_swap_recs(&recs[0], &recs[first]);
+    grn_ts_rec_swap(&recs[0], &recs[first]);
   }
 }
 
@@ -163,7 +174,7 @@ grn_ts_isort_by_id_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
   for (size_t i = 1; i < n_recs; ++i) {
     for (size_t j = i; j > 0; --j) {
       if (recs[j].id < recs[j - 1].id) {
-        grn_ts_swap_recs(&recs[j], &recs[j - 1]);
+        grn_ts_rec_swap(&recs[j], &recs[j - 1]);
       } else {
         break;
       }
@@ -204,12 +215,12 @@ grn_ts_qsort_by_id_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
       if (left >= right) {
         break;
       }
-      grn_ts_swap_recs(&recs[left], &recs[right]);
+      grn_ts_rec_swap(&recs[left], &recs[right]);
       ++left;
     }
     /* Move the pivot to the boundary. */
     --left;
-    grn_ts_swap_recs(&recs[0], &recs[left]);
+    grn_ts_rec_swap(&recs[0], &recs[left]);
     /*
      * Use a recursive call to sort the smaller group so that the recursion
      * depth is less than log_2(n_recs).
@@ -266,23 +277,23 @@ grn_ts_move_pivot_by_id_desc(grn_ts_record *recs, size_t n_recs)
     /* first > middle. */
     if (recs[middle].id > recs[last].id) {
       /* first > middle > last */
-      grn_ts_swap_recs(&recs[0], &recs[middle]);
+      grn_ts_rec_swap(&recs[0], &recs[middle]);
     } else if (recs[first].id > recs[last].id) {
       /* first > last > middle. */
-      grn_ts_swap_recs(&recs[0], &recs[last]);
+      grn_ts_rec_swap(&recs[0], &recs[last]);
     } else {
       /* last > first > middle. */
-      grn_ts_swap_recs(&recs[0], &recs[first]);
+      grn_ts_rec_swap(&recs[0], &recs[first]);
     }
   } else if (recs[last].id > recs[middle].id) {
     /* last > middle > first. */
-    grn_ts_swap_recs(&recs[0], &recs[middle]);
+    grn_ts_rec_swap(&recs[0], &recs[middle]);
   } else if (recs[last].id > recs[first].id) {
     /* middle > last > first. */
-    grn_ts_swap_recs(&recs[0], &recs[last]);
+    grn_ts_rec_swap(&recs[0], &recs[last]);
   } else {
     /* middle > first > last. */
-    grn_ts_swap_recs(&recs[0], &recs[first]);
+    grn_ts_rec_swap(&recs[0], &recs[first]);
   }
 }
 
@@ -295,7 +306,7 @@ grn_ts_isort_by_id_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
   for (size_t i = 1; i < n_recs; ++i) {
     for (size_t j = i; j > 0; --j) {
       if (recs[j].id > recs[j - 1].id) {
-        grn_ts_swap_recs(&recs[j], &recs[j - 1]);
+        grn_ts_rec_swap(&recs[j], &recs[j - 1]);
       } else {
         break;
       }
@@ -336,12 +347,12 @@ grn_ts_qsort_by_id_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
       if (left >= right) {
         break;
       }
-      grn_ts_swap_recs(&recs[left], &recs[right]);
+      grn_ts_rec_swap(&recs[left], &recs[right]);
       ++left;
     }
     /* Move the pivot to the boundary. */
     --left;
-    grn_ts_swap_recs(&recs[0], &recs[left]);
+    grn_ts_rec_swap(&recs[0], &recs[left]);
     /*
      * Use a recursive call to sort the smaller group so that the recursion
      * depth is less than log_2(n_recs).
@@ -412,21 +423,21 @@ grn_ts_move_pivot_by_score_asc(grn_ts_record *recs, size_t n_recs)
     /* first < middle. */
     if (recs[middle].score < recs[last].score) {
       /* first < middle < last */
-      grn_ts_swap_recs(&recs[0], &recs[middle]);
+      grn_ts_rec_swap(&recs[0], &recs[middle]);
     } else if (recs[first].score < recs[last].score) {
       /* first < last < middle. */
-      grn_ts_swap_recs(&recs[0], &recs[last]);
+      grn_ts_rec_swap(&recs[0], &recs[last]);
     } else { /* last < first < middle. */
-      grn_ts_swap_recs(&recs[0], &recs[first]);
+      grn_ts_rec_swap(&recs[0], &recs[first]);
     }
   } else if (recs[last].score < recs[middle].score) {
     /* last < middle < first. */
-    grn_ts_swap_recs(&recs[0], &recs[middle]);
+    grn_ts_rec_swap(&recs[0], &recs[middle]);
   } else if (recs[last].score < recs[first].score) {
     /* middle < last < first. */
-    grn_ts_swap_recs(&recs[0], &recs[last]);
+    grn_ts_rec_swap(&recs[0], &recs[last]);
   } else { /* middle < first < last. */
-    grn_ts_swap_recs(&recs[0], &recs[first]);
+    grn_ts_rec_swap(&recs[0], &recs[first]);
   }
 }
 
@@ -439,7 +450,7 @@ grn_ts_isort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
   for (size_t i = 1; i < n_recs; ++i) {
     for (size_t j = i; j > 0; --j) {
       if (recs[j].score < recs[j - 1].score) {
-        grn_ts_swap_recs(&recs[j], &recs[j - 1]);
+        grn_ts_rec_swap(&recs[j], &recs[j - 1]);
       } else {
         break;
       }
@@ -499,7 +510,7 @@ grn_ts_qsort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
           break;
         } else if ((pivot.score <= recs[left].score) &&
                    (pivot.score >= recs[left].score)) {
-          grn_ts_swap_recs(&recs[left], &recs[pivot_left]);
+          grn_ts_rec_swap(&recs[left], &recs[pivot_left]);
           ++pivot_left;
         }
         ++left;
@@ -511,24 +522,24 @@ grn_ts_qsort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
         } else if ((recs[right].score <= pivot.score) &&
                    (recs[right].score >= pivot.score)) {
           --pivot_right;
-          grn_ts_swap_recs(&recs[right], &recs[pivot_right]);
+          grn_ts_rec_swap(&recs[right], &recs[pivot_right]);
         }
       }
       if (left >= right) {
         break;
       }
-      grn_ts_swap_recs(&recs[left], &recs[right]);
+      grn_ts_rec_swap(&recs[left], &recs[right]);
       ++left;
     }
     /* Move left pivot-equivalent entries to the left of the boundary. */
     while (pivot_left > 0) {
       --pivot_left;
       --left;
-      grn_ts_swap_recs(&recs[pivot_left], &recs[left]);
+      grn_ts_rec_swap(&recs[pivot_left], &recs[left]);
     }
     /* Move right pivot-equivalent entries to the right of the boundary. */
     while (pivot_right < n_recs) {
-      grn_ts_swap_recs(&recs[pivot_right], &recs[right]);
+      grn_ts_rec_swap(&recs[pivot_right], &recs[right]);
       ++pivot_right;
       ++right;
     }
@@ -551,7 +562,7 @@ grn_ts_qsort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
     if (left < (n_recs - right)) {
       if ((offset < left) && (left >= 2)) {
         size_t next_limit = (limit < left) ? limit : left;
-        rc = grn_ts_sorter_node_sort(ctx, node, offset, next_limit,
+        rc = grn_ts_qsort_by_score_asc(ctx, node, offset, next_limit,
                                      recs, left);
         if (rc != GRN_SUCCESS) {
           return rc;
@@ -568,8 +579,8 @@ grn_ts_qsort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node,
       if ((limit > right) && ((n_recs - right) >= 2)) {
         size_t next_offset = (offset < right) ? 0 : (offset - right);
         size_t next_limit = limit - right;
-        rc = grn_ts_sorter_node_sort(ctx, node, next_offset, next_limit,
-                                     recs + right, n_recs - right);
+        rc = grn_ts_qsort_by_score_asc(ctx, node, next_offset, next_limit,
+                                       recs + right, n_recs - right);
         if (rc != GRN_SUCCESS) {
           return rc;
         }
@@ -604,21 +615,21 @@ grn_ts_move_pivot_by_score_desc(grn_ts_record *recs, size_t n_recs)
     /* first > middle. */
     if (recs[middle].score > recs[last].score) {
       /* first > middle > last */
-      grn_ts_swap_recs(&recs[0], &recs[middle]);
+      grn_ts_rec_swap(&recs[0], &recs[middle]);
     } else if (recs[first].score > recs[last].score) {
       /* first > last > middle. */
-      grn_ts_swap_recs(&recs[0], &recs[last]);
+      grn_ts_rec_swap(&recs[0], &recs[last]);
     } else { /* last > first > middle. */
-      grn_ts_swap_recs(&recs[0], &recs[first]);
+      grn_ts_rec_swap(&recs[0], &recs[first]);
     }
   } else if (recs[last].score > recs[middle].score) {
     /* last > middle > first. */
-    grn_ts_swap_recs(&recs[0], &recs[middle]);
+    grn_ts_rec_swap(&recs[0], &recs[middle]);
   } else if (recs[last].score > recs[first].score) {
     /* middle > last > first. */
-    grn_ts_swap_recs(&recs[0], &recs[last]);
+    grn_ts_rec_swap(&recs[0], &recs[last]);
   } else { /* middle > first > last. */
-    grn_ts_swap_recs(&recs[0], &recs[first]);
+    grn_ts_rec_swap(&recs[0], &recs[first]);
   }
 }
 
@@ -631,7 +642,7 @@ grn_ts_isort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
   for (size_t i = 1; i < n_recs; ++i) {
     for (size_t j = i; j > 0; --j) {
       if (recs[j].score > recs[j - 1].score) {
-        grn_ts_swap_recs(&recs[j], &recs[j - 1]);
+        grn_ts_rec_swap(&recs[j], &recs[j - 1]);
       } else {
         break;
       }
@@ -691,7 +702,7 @@ grn_ts_qsort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
           break;
         } else if ((pivot.score <= recs[left].score) &&
                    (pivot.score >= recs[left].score)) {
-          grn_ts_swap_recs(&recs[left], &recs[pivot_left]);
+          grn_ts_rec_swap(&recs[left], &recs[pivot_left]);
           ++pivot_left;
         }
         ++left;
@@ -703,24 +714,24 @@ grn_ts_qsort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
         } else if ((recs[right].score <= pivot.score) &&
                    (recs[right].score >= pivot.score)) {
           --pivot_right;
-          grn_ts_swap_recs(&recs[right], &recs[pivot_right]);
+          grn_ts_rec_swap(&recs[right], &recs[pivot_right]);
         }
       }
       if (left >= right) {
         break;
       }
-      grn_ts_swap_recs(&recs[left], &recs[right]);
+      grn_ts_rec_swap(&recs[left], &recs[right]);
       ++left;
     }
     /* Move left pivot-equivalent entries to the left of the boundary. */
     while (pivot_left > 0) {
       --pivot_left;
       --left;
-      grn_ts_swap_recs(&recs[pivot_left], &recs[left]);
+      grn_ts_rec_swap(&recs[pivot_left], &recs[left]);
     }
     /* Move right pivot-equivalent entries to the right of the boundary. */
     while (pivot_right < n_recs) {
-      grn_ts_swap_recs(&recs[pivot_right], &recs[right]);
+      grn_ts_rec_swap(&recs[pivot_right], &recs[right]);
       ++pivot_right;
       ++right;
     }
@@ -743,8 +754,8 @@ grn_ts_qsort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
     if (left < (n_recs - right)) {
       if ((offset < left) && (left >= 2)) {
         size_t next_limit = (limit < left) ? limit : left;
-        rc = grn_ts_sorter_node_sort(ctx, node, offset, next_limit,
-                                     recs, left);
+        rc = grn_ts_qsort_by_score_desc(ctx, node, offset, next_limit,
+                                        recs, left);
         if (rc != GRN_SUCCESS) {
           return rc;
         }
@@ -760,8 +771,8 @@ grn_ts_qsort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node,
       if ((limit > right) && ((n_recs - right) >= 2)) {
         size_t next_offset = (offset < right) ? 0 : (offset - right);
         size_t next_limit = limit - right;
-        rc = grn_ts_sorter_node_sort(ctx, node, next_offset, next_limit,
-                                     recs + right, n_recs - right);
+        rc = grn_ts_qsort_by_score_desc(ctx, node, next_offset, next_limit,
+                                        recs + right, n_recs - right);
         if (rc != GRN_SUCCESS) {
           return rc;
         }
@@ -797,6 +808,288 @@ grn_ts_sorter_node_sort_by_score(grn_ctx *ctx, grn_ts_sorter_node *node,
   }
 }
 
+/* grn_ts_move_pivot_by_int() moves the pivot to the front. */
+static void
+grn_ts_move_pivot_by_int(grn_ts_sorter_node *node, grn_ts_int *vals,
+                         grn_ts_record *recs, size_t n_recs)
+{
+  /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */
+  size_t first = 1;
+  size_t middle = n_recs / 2;
+  size_t last = n_recs - 2;
+  if (vals[first] < vals[middle]) {
+    /* first < middle. */
+    if (vals[middle] < vals[last]) {
+      /* first < middle < last */
+      grn_ts_rec_swap(&recs[0], &recs[middle]);
+      grn_ts_int_swap(&vals[0], &vals[middle]);
+    } else if (vals[first] < vals[last]) {
+      /* first < last < middle. */
+      grn_ts_rec_swap(&recs[0], &recs[last]);
+      grn_ts_int_swap(&vals[0], &vals[last]);
+    } else { /* last < first < middle. */
+      grn_ts_rec_swap(&recs[0], &recs[first]);
+      grn_ts_int_swap(&vals[0], &vals[first]);
+    }
+  } else if (vals[last] < vals[middle]) {
+    /* last < middle < first. */
+    grn_ts_rec_swap(&recs[0], &recs[middle]);
+    grn_ts_int_swap(&vals[0], &vals[middle]);
+  } else if (vals[last] < vals[first]) {
+    /* middle < last < first. */
+    grn_ts_rec_swap(&recs[0], &recs[last]);
+    grn_ts_int_swap(&vals[0], &vals[last]);
+  } else { /* middle < first < last. */
+    grn_ts_rec_swap(&recs[0], &recs[first]);
+    grn_ts_int_swap(&vals[0], &vals[first]);
+  }
+}
+
+/* grn_ts_isort_by_int() sorts records. */
+static grn_rc
+grn_ts_isort_by_int(grn_ctx *ctx, grn_ts_sorter_node *node,
+                    size_t offset, size_t limit,
+                    grn_ts_int *vals, grn_ts_record *recs, size_t n_recs)
+{
+  for (size_t i = 1; i < n_recs; ++i) {
+    for (size_t j = i; j > 0; --j) {
+      if (vals[j] < vals[j - 1]) {
+        grn_ts_rec_swap(&recs[j], &recs[j - 1]);
+        grn_ts_int_swap(&vals[j], &vals[j - 1]);
+      } else {
+        break;
+      }
+    }
+  }
+  /* Apply the next sorting if there are score duplicates. */
+  if (node->next) {
+    grn_rc rc;
+    size_t begin = 0;
+    for (size_t i = 1; i < n_recs; ++i) {
+      if (vals[i] != vals[begin]) {
+        if ((i - begin) >= 2) {
+          rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin,
+                                       recs + begin, i - begin);
+          if (rc != GRN_SUCCESS) {
+            return rc;
+          }
+        }
+        begin = i;
+      }
+    }
+    if ((n_recs - begin) >= 2) {
+      rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin,
+                                   recs + begin, n_recs - begin);
+      if (rc != GRN_SUCCESS) {
+        return rc;
+      }
+    }
+  }
+  return GRN_SUCCESS;
+}
+
+/* grn_ts_qsort_by_int() sorts records. */
+static grn_rc
+grn_ts_qsort_by_int(grn_ctx *ctx, grn_ts_sorter_node *node,
+                    size_t offset, size_t limit,
+                    grn_ts_int *vals, grn_ts_record *recs, size_t n_recs)
+{
+  grn_rc rc;
+  /*
+   * FIXME: Currently, the threshold is 16.
+   *        This value should be optimized and replaced with a named constant.
+   */
+  while (n_recs >= 16) {
+    grn_ts_move_pivot_by_int(node, vals, recs, n_recs);
+    grn_ts_int pivot = vals[0];
+    size_t left = 1, right = n_recs;
+    size_t pivot_left = 1, pivot_right = n_recs;
+    for ( ; ; ) {
+      /*
+       * Prior entries are moved to left. Less prior entries are moved to
+       * right. Entries which equal to the pivot are moved to the edges.
+       */
+      while (left < right) {
+        if (pivot < vals[left]) {
+          break;
+        } else if (pivot == vals[left]) {
+          grn_ts_rec_swap(&recs[left], &recs[pivot_left]);
+          grn_ts_int_swap(&vals[left], &vals[pivot_left]);
+          ++pivot_left;
+        }
+        ++left;
+      }
+      while (left < right) {
+        --right;
+        if (vals[right] < pivot) {
+          break;
+        } else if (vals[right] == pivot) {
+          --pivot_right;
+          grn_ts_rec_swap(&recs[right], &recs[pivot_right]);
+          grn_ts_int_swap(&vals[right], &vals[pivot_right]);
+        }
+      }
+      if (left >= right) {
+        break;
+      }
+      grn_ts_rec_swap(&recs[left], &recs[right]);
+      grn_ts_int_swap(&vals[left], &vals[right]);
+      ++left;
+    }
+    /* Move left pivot-equivalent entries to the left of the boundary. */
+    while (pivot_left > 0) {
+      --pivot_left;
+      --left;
+      grn_ts_rec_swap(&recs[pivot_left], &recs[left]);
+      grn_ts_int_swap(&vals[pivot_left], &vals[left]);
+    }
+    /* Move right pivot-equivalent entries to the right of the boundary. */
+    while (pivot_right < n_recs) {
+      grn_ts_rec_swap(&recs[pivot_right], &recs[right]);
+      grn_ts_int_swap(&vals[pivot_right], &vals[right]);
+      ++pivot_right;
+      ++right;
+    }
+    /* Apply the next sort condition to the pivot-equivalent recs. */
+    if (node->next) {
+      if (((right - left) >= 2) && (offset < right) && (limit > left)) {
+        size_t next_offset = (offset < left) ? 0 : (offset - left);
+        size_t next_limit = ((limit > right) ? right : limit) - left;
+        rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit,
+                                     recs + left, right - left);
+        if (rc != GRN_SUCCESS) {
+          return rc;
+        }
+      }
+    }
+    /*
+     * Use a recursive call to sort the smaller group so that the recursion
+     * depth is less than log_2(n_recs).
+     */
+    if (left < (n_recs - right)) {
+      if ((offset < left) && (left >= 2)) {
+        size_t next_limit = (limit < left) ? limit : left;
+        rc = grn_ts_qsort_by_int(ctx, node, offset, next_limit,
+                                 vals, recs, left);
+        if (rc != GRN_SUCCESS) {
+          return rc;
+        }
+      }
+      if (limit <= right) {
+        return GRN_SUCCESS;
+      }
+      vals += right;
+      recs += right;
+      n_recs -= right;
+      offset = (offset < right) ? 0 : (offset - right);
+      limit -= right;
+    } else {
+      if ((limit > right) && ((n_recs - right) >= 2)) {
+        size_t next_offset = (offset < right) ? 0 : (offset - right);
+        size_t next_limit = limit - right;
+        rc = grn_ts_qsort_by_int(ctx, node, next_offset, next_limit,
+                                 vals + right, recs + right, n_recs - right);
+        if (rc != GRN_SUCCESS) {
+          return rc;
+        }
+      }
+      if (offset >= left) {
+        return GRN_SUCCESS;
+      }
+      n_recs = left;
+      if (limit > left) {
+        limit = left;
+      }
+    }
+  }
+  if (n_recs >= 2) {
+    rc = grn_ts_isort_by_int(ctx, node, offset, limit, vals, recs, n_recs);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
+  return GRN_SUCCESS;
+}
+
+/* grn_ts_sorter_node_sort_by_var() sorts records. */
+static grn_rc
+grn_ts_sorter_node_sort_by_var(grn_ctx *ctx, grn_ts_sorter_node *node,
+                               size_t offset, size_t limit,
+                               grn_ts_record *recs, size_t n_recs)
+{
+  size_t i;
+  grn_rc rc;
+  switch (node->expr->data_kind) {
+    case GRN_TS_INT: {
+      grn_ts_int *vals;
+      rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs,
+                                       &node->buf);
+      if (rc != GRN_SUCCESS) {
+        return rc;
+      }
+      vals = (grn_ts_int *)node->buf.ptr;
+      if (node->reverse) {
+        for (i = 0; i < n_recs; i++) {
+          vals[i] = -1 - vals[i];
+        }
+      }
+      return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs);
+    }
+    case GRN_TS_FLOAT: {
+      grn_ts_int *vals;
+      rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs,
+                                       &node->buf);
+      if (rc != GRN_SUCCESS) {
+        return rc;
+      }
+      vals = (grn_ts_int *)node->buf.ptr;
+      if (node->reverse) {
+        for (i = 0; i < n_recs; i++) {
+          if (vals[i] < 0) {
+            vals[i] = (vals[i] ^ INT64_MAX) + 1;
+          }
+          vals[i] = -1 - vals[i];
+        }
+      } else {
+        for (i = 0; i < n_recs; i++) {
+          if (vals[i] < 0) {
+            vals[i] = (vals[i] ^ INT64_MAX) + 1;
+          }
+        }
+      }
+      return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs);
+    }
+    case GRN_TS_TIME: {
+      grn_ts_int *vals;
+      rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs,
+                                       &node->buf);
+      if (rc != GRN_SUCCESS) {
+        return rc;
+      }
+      vals = (grn_ts_int *)node->buf.ptr;
+      if (node->reverse) {
+        for (i = 0; i < n_recs; i++) {
+          vals[i] = -1 - vals[i];
+        }
+      }
+      return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs);
+    }
+    case GRN_TS_TEXT:
+    case GRN_TS_INT_VECTOR:
+    case GRN_TS_FLOAT_VECTOR:
+    case GRN_TS_TIME_VECTOR:
+    case GRN_TS_TEXT_VECTOR: {
+      // TODO
+      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, "not supported yet");
+    }
+    default: {
+      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
+                        node->expr->data_kind);
+    }
+  }
+  return GRN_FUNCTION_NOT_IMPLEMENTED;
+}
+
 /* grn_ts_sorter_node_sort() sorts records. */
 static grn_rc
 grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node,
@@ -820,6 +1113,8 @@ grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node,
                                      n_recs);
     }
     case GRN_TS_EXPR_VARIABLE: {
+      return grn_ts_sorter_node_sort_by_var(ctx, node, offset, limit,
+                                            recs, n_recs);
       break;
     }
     default: {
@@ -827,26 +1122,6 @@ grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node,
                         node->expr->type);
     }
   }
-  switch (node->expr->data_kind) {
-    case GRN_TS_INT:
-    case GRN_TS_FLOAT:
-    case GRN_TS_TIME: {
-      // TODO
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, "not supported yet");
-    }
-    case GRN_TS_TEXT:
-    case GRN_TS_INT_VECTOR:
-    case GRN_TS_FLOAT_VECTOR:
-    case GRN_TS_TIME_VECTOR:
-    case GRN_TS_TEXT_VECTOR: {
-      // TODO
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, "not supported yet");
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                        node->expr->data_kind);
-    }
-  }
 }
 
 /*-------------------------------------------------------------
@@ -1011,7 +1286,9 @@ grn_ts_sorter_complete(grn_ctx *ctx, grn_ts_sorter *sorter,
   }
   limit = sorter->limit;
   if (limit > (n_recs - sorter->offset)) {
-    limit = n_recs - sorter->offset;
+    limit = n_recs;
+  } else {
+    limit += sorter->offset;
   }
   if (sorter->partial) {
     // FIXME: If there was no input. Partial sorting is not required.

  Modified: lib/ts/ts_sorter.h (+1 -0)
===================================================================
--- lib/ts/ts_sorter.h    2015-11-26 21:33:17 +0900 (b4101a2)
+++ lib/ts/ts_sorter.h    2015-11-27 03:44:08 +0900 (b97db13)
@@ -34,6 +34,7 @@ extern "C" {
 typedef struct grn_ts_sorter_node {
   grn_ts_expr *expr;               /* Expression. */
   grn_ts_bool reverse;             /* Reverse order or not. */
+  grn_ts_buf buf;                  /* Buffer for values. */
   struct grn_ts_sorter_node *next; /* Next node. */
 } grn_ts_sorter_node;
 
-------------- next part --------------
HTML����������������������������...
Download 



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