[Groonga-commit] groonga/groonga [master] revert select XML format change.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 7月 13日 (火) 10:57:11 JST


Kouhei Sutou	2010-07-13 01:57:11 +0000 (Tue, 13 Jul 2010)

  New Revision: 32614676ac70826e65f16acf91a5b4a04d80ed9d

  Log:
    revert select XML format change.

  Modified files:
    src/groonga.c

  Modified: src/groonga.c (+278 -29)
===================================================================
--- src/groonga.c    2010-07-13 01:56:58 +0000 (8bfd1d4)
+++ src/groonga.c    2010-07-13 01:57:11 +0000 (b3c4405)
@@ -21,6 +21,7 @@
 #include "lib/ql.h"
 #include "lib/proc.h"
 #include "lib/db.h"
+#include "lib/util.h"
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -207,6 +208,235 @@ typedef enum {
   grn_http_request_type_post
 } grn_http_request_type;
 
+typedef enum {
+  XML_START,
+  XML_START_ELEMENT,
+  XML_END_ELEMENT,
+  XML_TEXT
+} xml_status;
+
+typedef enum {
+  XML_PLACE_NONE,
+  XML_PLACE_COLUMN,
+  XML_PLACE_HIT
+} xml_place;
+
+static void
+transform_xml(grn_ctx *ctx, grn_obj *output, grn_obj *transformed)
+{
+  char *s, *e;
+  xml_status status = XML_START;
+  xml_place place = XML_PLACE_NONE;
+  grn_obj buf, name, columns, *expr;
+  unsigned int len;
+  int offset = 0, limit = 0, record_n = 0;
+  int column_n, column_text_n, result_set_n = -1;
+  int in_vector = 0;
+
+  s = GRN_TEXT_VALUE(output);
+  e = GRN_BULK_CURR(output);
+  GRN_TEXT_INIT(&buf, 0);
+  GRN_TEXT_INIT(&name, 0);
+  GRN_TEXT_INIT(&columns, 0);
+
+  expr = ctx->impl->curr_expr;
+
+#define EQUAL_NAME_P(_name) \
+  (GRN_TEXT_LEN(&name) == strlen(_name) && \
+   !memcmp(GRN_TEXT_VALUE(&name), _name, strlen(_name)))
+
+  while (s < e) {
+    switch (*s) {
+    case '<' :
+      s++;
+      switch (*s) {
+      case '/' :
+        status = XML_END_ELEMENT;
+        s++;
+        break;
+      default :
+        status = XML_START_ELEMENT;
+        break;
+      }
+      GRN_BULK_REWIND(&name);
+      break;
+    case '>' :
+      switch (status) {
+      case XML_START_ELEMENT :
+        if (EQUAL_NAME_P("COLUMN")) {
+          place = XML_PLACE_COLUMN;
+          column_text_n = 0;
+        } else if (EQUAL_NAME_P("HIT")) {
+          place = XML_PLACE_HIT;
+          column_n = 0;
+          if (result_set_n == 0) {
+            GRN_TEXT_PUTS(ctx, transformed, "<HIT NO=\"");
+            grn_text_itoa(ctx, transformed, record_n++);
+            GRN_TEXT_PUTS(ctx, transformed, "\">\n");
+          } else {
+            GRN_TEXT_PUTS(ctx, transformed, "<NAVIGATIONELEMENT ");
+          }
+        } else if (EQUAL_NAME_P("RESULTSET")) {
+          GRN_BULK_REWIND(&columns);
+          result_set_n++;
+          if (result_set_n == 0) {
+          } else {
+            GRN_TEXT_PUTS(ctx, transformed, "<NAVIGATIONENTRY>");
+          }
+        } else if (EQUAL_NAME_P("VECTOR")) {
+          in_vector = 1;
+        }
+        break;
+      case XML_END_ELEMENT :
+        if (EQUAL_NAME_P("HIT")) {
+          place = XML_PLACE_NONE;
+          if (result_set_n == 0) {
+            GRN_TEXT_PUTS(ctx, transformed, "</HIT>\n");
+          } else {
+            GRN_TEXT_PUTS(ctx, transformed, "/>");
+          }
+        } else if (EQUAL_NAME_P("RESULTSET")) {
+          place = XML_PLACE_NONE;
+          if (result_set_n == 0) {
+            GRN_TEXT_PUTS(ctx, transformed, "</RESULTSET>\n");
+          } else {
+            GRN_TEXT_PUTS(ctx, transformed,
+                          "</NAVIGATIONELEMENTS>"
+                          "</NAVIGATIONENTRY>");
+          }
+        } else if (EQUAL_NAME_P("RESULT")) {
+          GRN_TEXT_PUTS(ctx, transformed,
+                        "</RESULTPAGE>\n"
+                        "</SEGMENT>\n"
+                        "</SEGMENTS>\n");
+        } else if (EQUAL_NAME_P("VECTOR")) {
+          in_vector = 0;
+        } else {
+          switch (place) {
+          case XML_PLACE_HIT :
+            {
+              int i = column_n;
+              char *c = GRN_TEXT_VALUE(&columns);
+              while (i--) {
+                while (*c) {
+                  c++;
+                }
+                c++;
+              }
+              if (result_set_n == 0) {
+                GRN_TEXT_PUTS(ctx, transformed, "<FIELD NAME=\"");
+                GRN_TEXT_PUTS(ctx, transformed, c);
+                GRN_TEXT_PUTS(ctx, transformed, "\">");
+                if (!in_vector) {
+                  GRN_TEXT_PUT(ctx, transformed,
+                               GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
+                }
+                GRN_TEXT_PUTS(ctx, transformed, "</FIELD>\n");
+              } else {
+                GRN_TEXT_PUTS(ctx, transformed, c);
+                GRN_TEXT_PUTS(ctx, transformed, "=\"");
+                GRN_TEXT_PUT(ctx, transformed,
+                             GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
+                GRN_TEXT_PUTS(ctx, transformed, "\" ");
+              }
+            }
+            column_n++;
+            break;
+          default :
+            if (EQUAL_NAME_P("NHITS")) {
+              if (result_set_n == 0) {
+                uint32_t nhits;
+                grn_obj *offset_value, *limit_value;
+
+                nhits = grn_atoui(GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf),
+                                  NULL);
+                offset_value = grn_expr_get_var(ctx, expr,
+                                                "offset", strlen("offset"));
+                limit_value = grn_expr_get_var(ctx, expr,
+                                               "limit", strlen("limit"));
+                if (GRN_TEXT_LEN(offset_value)) {
+                  offset = grn_atoi(GRN_TEXT_VALUE(offset_value),
+                                    GRN_BULK_CURR(offset_value),
+                                    NULL);
+                } else {
+                  offset = 0;
+                }
+                if (GRN_TEXT_LEN(limit_value)) {
+                  limit = grn_atoi(GRN_TEXT_VALUE(limit_value),
+                                   GRN_BULK_CURR(limit_value),
+                                   NULL);
+                } else {
+#define DEFAULT_LIMIT 10
+                  limit = DEFAULT_LIMIT;
+#undef DEFAULT_LIMIT
+                }
+                grn_normalize_offset_and_limit(ctx, nhits, &offset, &limit);
+                record_n = offset + 1;
+                GRN_TEXT_PUTS(ctx, transformed,
+                              "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+                              "<SEGMENTS>\n"
+                              "<SEGMENT>\n"
+                              "<RESULTPAGE>\n"
+                              "<RESULTSET OFFSET=\"");
+                grn_text_lltoa(ctx, transformed, offset);
+                GRN_TEXT_PUTS(ctx, transformed, "\" LIMIT=\"");
+                grn_text_lltoa(ctx, transformed, limit);
+                GRN_TEXT_PUTS(ctx, transformed, "\" NHITS=\"");
+                grn_text_lltoa(ctx, transformed, nhits);
+                GRN_TEXT_PUTS(ctx, transformed, "\">\n");
+              } else {
+                GRN_TEXT_PUTS(ctx, transformed,
+                              "<NAVIGATIONELEMENTS COUNT=\"");
+                GRN_TEXT_PUT(ctx, transformed,
+                             GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
+                GRN_TEXT_PUTS(ctx, transformed,
+                              "\">");
+              }
+            } else if (EQUAL_NAME_P("TEXT")) {
+              switch (place) {
+              case XML_PLACE_COLUMN :
+                if (column_text_n == 0) {
+                  GRN_TEXT_PUT(ctx, &columns,
+                               GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
+                  GRN_TEXT_PUTC(ctx, &columns, '\0');
+                }
+                column_text_n++;
+                break;
+              default :
+                break;
+              }
+            }
+          }
+        }
+      default :
+        break;
+      }
+      s++;
+      GRN_BULK_REWIND(&buf);
+      status = XML_TEXT;
+      break;
+    default :
+      len = grn_charlen(ctx, s, e);
+      switch (status) {
+      case XML_START_ELEMENT :
+      case XML_END_ELEMENT :
+        GRN_TEXT_PUT(ctx, &name, s, len);
+        break;
+      default :
+        GRN_TEXT_PUT(ctx, &buf, s, len);
+        break;
+      }
+      s += len;
+      break;
+    }
+  }
+#undef EQUAL_NAME_P
+
+  GRN_OBJ_FIN(ctx, &buf);
+  GRN_OBJ_FIN(ctx, &name);
+  GRN_OBJ_FIN(ctx, &columns);
+}
+
 static void
 print_return_code(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj *foot)
 {
@@ -277,38 +507,57 @@ print_return_code(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj
     GRN_TEXT_PUTS(ctx, foot, "\nEND");
     break;
   case GRN_CONTENT_XML:
-    GRN_TEXT_PUTS(ctx, head, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RESULT CODE=\"");
-    grn_text_itoa(ctx, head, rc);
-    GRN_TEXT_PUTS(ctx, head, "\" UP=\"");
     {
-      double dv;
-      grn_timeval tv;
-      grn_timeval_now(ctx, &tv);
-      dv = ctx->impl->tv.tv_sec;
-      dv += ctx->impl->tv.tv_usec / 1000000.0;
-      grn_text_ftoa(ctx, head, dv);
-      dv = (tv.tv_sec - ctx->impl->tv.tv_sec);
-      dv += (tv.tv_usec - ctx->impl->tv.tv_usec) / 1000000.0;
-      GRN_TEXT_PUTS(ctx, head, "\" ELAPSED=\"");
-      grn_text_ftoa(ctx, head, dv);
-      GRN_TEXT_PUTS(ctx, head, "\">");
-    }
-    if (rc != GRN_SUCCESS) {
-      GRN_TEXT_PUTS(ctx, head, "<ERROR>");
-      grn_text_escape_xml(ctx, head, ctx->errbuf, strlen(ctx->errbuf));
-      if (ctx->errfunc && ctx->errfile) {
-        /* TODO: output backtrace */
-        GRN_TEXT_PUTS(ctx, head, "<INFO FUNC=\"");
-        grn_text_escape_xml(ctx, head, ctx->errfunc, strlen(ctx->errfunc));
-        GRN_TEXT_PUTS(ctx, head, "\" FILE=\"");
-        grn_text_escape_xml(ctx, head, ctx->errfile, strlen(ctx->errfile));
-        GRN_TEXT_PUTS(ctx, head, "\" LINE=\"");
-        grn_text_itoa(ctx, head, ctx->errline);
-        GRN_TEXT_PUTS(ctx, head, "\">");
+      char buf[GRN_TABLE_MAX_KEY_SIZE];
+      int is_select = 0;
+      if (!rc && ctx->impl->curr_expr) {
+        int len = grn_obj_name(ctx, ctx->impl->curr_expr,
+                               buf, GRN_TABLE_MAX_KEY_SIZE);
+        buf[len] = '\0';
+        is_select = strcmp(buf, "select") == 0;
+      }
+      if (is_select) {
+        grn_obj transformed;
+        GRN_TEXT_INIT(&transformed, 0);
+        transform_xml(ctx, body, &transformed);
+        GRN_TEXT_SET(ctx, body,
+                     GRN_TEXT_VALUE(&transformed), GRN_TEXT_LEN(&transformed));
+        GRN_OBJ_FIN(ctx, &transformed);
+      } else {
+        GRN_TEXT_PUTS(ctx, head, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RESULT CODE=\"");
+        grn_text_itoa(ctx, head, rc);
+        GRN_TEXT_PUTS(ctx, head, "\" UP=\"");
+        {
+          double dv;
+          grn_timeval tv;
+          grn_timeval_now(ctx, &tv);
+          dv = ctx->impl->tv.tv_sec;
+          dv += ctx->impl->tv.tv_usec / 1000000.0;
+          grn_text_ftoa(ctx, head, dv);
+          dv = (tv.tv_sec - ctx->impl->tv.tv_sec);
+          dv += (tv.tv_usec - ctx->impl->tv.tv_usec) / 1000000.0;
+          GRN_TEXT_PUTS(ctx, head, "\" ELAPSED=\"");
+          grn_text_ftoa(ctx, head, dv);
+          GRN_TEXT_PUTS(ctx, head, "\">");
+        }
+        if (rc != GRN_SUCCESS) {
+          GRN_TEXT_PUTS(ctx, head, "<ERROR>");
+          grn_text_escape_xml(ctx, head, ctx->errbuf, strlen(ctx->errbuf));
+          if (ctx->errfunc && ctx->errfile) {
+            /* TODO: output backtrace */
+            GRN_TEXT_PUTS(ctx, head, "<INFO FUNC=\"");
+            grn_text_escape_xml(ctx, head, ctx->errfunc, strlen(ctx->errfunc));
+            GRN_TEXT_PUTS(ctx, head, "\" FILE=\"");
+            grn_text_escape_xml(ctx, head, ctx->errfile, strlen(ctx->errfile));
+            GRN_TEXT_PUTS(ctx, head, "\" LINE=\"");
+            grn_text_itoa(ctx, head, ctx->errline);
+            GRN_TEXT_PUTS(ctx, head, "\">");
+          }
+          GRN_TEXT_PUTS(ctx, head, "</ERROR>");
+        }
+        GRN_TEXT_PUTS(ctx, foot, "</RESULT>");
       }
-      GRN_TEXT_PUTS(ctx, head, "</ERROR>");
     }
-    GRN_TEXT_PUTS(ctx, foot, "</RESULT>");
     break;
   case GRN_CONTENT_MSGPACK:
     // todo




Groonga-commit メーリングリストの案内
Back to archive index