[Commits] Rev 3491: dynamic column value to string conversion finction. in file:///home/bell/maria/bzr/work-maria-5.5-dnames/

sanja at askmonty.org sanja at askmonty.org
Sat Sep 22 21:58:52 EEST 2012


At file:///home/bell/maria/bzr/work-maria-5.5-dnames/

------------------------------------------------------------
revno: 3491
revision-id: sanja at askmonty.org-20120922185847-5uwcrnfwkmlby24z
parent: sanja at askmonty.org-20120920152129-l42e0zsavdrhlg54
committer: sanja at askmonty.org
branch nick: work-maria-5.5-dnames
timestamp: Sat 2012-09-22 21:58:47 +0300
message:
  dynamic column value to string conversion finction.
  
  dynamic columns record to json conversion.
-------------- next part --------------
=== modified file 'include/ma_dyncol.h'
--- a/include/ma_dyncol.h	2012-09-20 15:21:29 +0000
+++ b/include/ma_dyncol.h	2012-09-22 18:58:47 +0000
@@ -157,6 +157,9 @@ my_bool dynamic_column_has_names(DYNAMIC
 enum enum_dyncol_func_result
 dynamic_column_check(DYNAMIC_COLUMN *str);
 
+enum enum_dyncol_func_result
+dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
+
 #define dynamic_column_initialize(A) memset((A), 0, sizeof(*(A)))
 #define dynamic_column_column_free(V) dynstr_free(V)
 

=== modified file 'include/my_sys.h'
--- a/include/my_sys.h	2012-03-28 17:26:00 +0000
+++ b/include/my_sys.h	2012-09-22 18:58:47 +0000
@@ -793,6 +793,8 @@ my_bool dynstr_append_mem(DYNAMIC_STRING
 			  size_t length);
 extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append,
                                        ...);
+extern my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
+                                    const char *append, size_t len);
 extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str);
 extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size);
 extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n);

=== modified file 'mysql-test/r/dyncol.result'
--- a/mysql-test/r/dyncol.result	2012-09-20 15:21:29 +0000
+++ b/mysql-test/r/dyncol.result	2012-09-22 18:58:47 +0000
@@ -1553,3 +1553,12 @@ hex(COLUMN_CREATE(REPEAT('a',255),1))
 040100FF00FF00000061616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616102
 SELECT hex(COLUMN_CREATE(REPEAT('a',256),1));
 ERROR 22007: Illegal value used as argument of dynamic column function
+#
+# JSON conversion
+#
+select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date));
+column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" 
+[{"int":-1212},{"date":"2011-04-05"},{"time":"00:45:49.000001"},{"uint":12334},{"double":"1.23444e+50"},{"string":"gdgd\\dhdjh\"dhdhd"},{"decimal":23.344},{"datetime":"2011-04-05 00:45:49.000001"}]
+select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date));
+column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date))
+[{"1":-1212},{"2":12334},{"3":23.344},{"4":"1.23444e+50"},{"5":"gdgd\\dhdjh\"dhdhd"},{"6":"00:45:49.000001"},{"7":"2011-04-05 00:45:49.000001"},{"8":"2011-04-05"}]

=== modified file 'mysql-test/t/dyncol.test'
--- a/mysql-test/t/dyncol.test	2012-09-20 15:21:29 +0000
+++ b/mysql-test/t/dyncol.test	2012-09-22 18:58:47 +0000
@@ -658,3 +658,9 @@ SELECT COLUMN_ADD( NULL, 'val', 'col');
 SELECT hex(COLUMN_CREATE(REPEAT('a',255),1));
 --error ER_DYN_COL_DATA
 SELECT hex(COLUMN_CREATE(REPEAT('a',256),1));
+
+--echo #
+--echo # JSON conversion
+--echo #
+select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date));
+select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date));

=== modified file 'mysys/ma_dyncol.c'
--- a/mysys/ma_dyncol.c	2012-09-20 15:21:29 +0000
+++ b/mysys/ma_dyncol.c	2012-09-22 18:58:47 +0000
@@ -29,6 +29,7 @@
 #include "mysys_priv.h"
 #include <m_string.h>
 #include <ma_dyncol.h>
+#include <my_time.h>
 
 /*
   Flag byte bits
@@ -1904,6 +1905,46 @@ dynamic_column_get_fmt(DYNAMIC_COLUMN *s
                                      *((uint *)key), NULL);
 }
 
+static enum enum_dyncol_func_result
+dynamic_column_get_value(DYN_HEADER *hdr, DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+  static enum enum_dyncol_func_result rc;
+  switch ((store_it_here->type= hdr->type)) {
+  case DYN_COL_INT:
+    rc= dynamic_column_sint_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_UINT:
+    rc= dynamic_column_uint_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_DOUBLE:
+    rc= dynamic_column_double_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_STRING:
+    rc= dynamic_column_string_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_DECIMAL:
+    rc= dynamic_column_decimal_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_DATETIME:
+    rc= dynamic_column_date_time_read(store_it_here, hdr->data,
+                                      hdr->length);
+    break;
+  case DYN_COL_DATE:
+    rc= dynamic_column_date_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_TIME:
+    rc= dynamic_column_time_read(store_it_here, hdr->data, hdr->length);
+    break;
+  case DYN_COL_NULL:
+    rc= ER_DYNCOL_OK;
+    break;
+  default:
+    rc= ER_DYNCOL_FORMAT;
+    store_it_here->type= DYN_COL_NULL;
+    break;
+  }
+  return rc;
+}
 
 /**
   Get dynamic column value by number or name
@@ -1937,38 +1978,7 @@ dynamic_column_get_internal(DYNAMIC_COLU
   if (find_column(&header, num_key, str_key))
     goto err;
 
-  switch ((store_it_here->type= header.type)) {
-  case DYN_COL_INT:
-    rc= dynamic_column_sint_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_UINT:
-    rc= dynamic_column_uint_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_DOUBLE:
-    rc= dynamic_column_double_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_STRING:
-    rc= dynamic_column_string_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_DECIMAL:
-    rc= dynamic_column_decimal_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_DATETIME:
-    rc= dynamic_column_date_time_read(store_it_here, header.data,
-                                      header.length);
-    break;
-  case DYN_COL_DATE:
-    rc= dynamic_column_date_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_TIME:
-    rc= dynamic_column_time_read(store_it_here, header.data, header.length);
-    break;
-  case DYN_COL_NULL:
-    rc= ER_DYNCOL_OK;
-    break;
-  default:
-    goto err;
-  }
+  rc= dynamic_column_get_value(&header, store_it_here);
   return rc;
 
 null:
@@ -3421,3 +3431,150 @@ dynamic_column_check(DYNAMIC_COLUMN *str
 end:
   DBUG_RETURN(rc);
 }
+
+
+enum enum_dyncol_func_result
+dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val)
+{
+  char buff[40];
+  int len;
+  switch (val->type) {
+  case DYN_COL_INT:
+      len= snprintf(buff, sizeof(buff), "%lld", val->x.long_value);
+      if (dynstr_append_mem(str, buff, len))
+        return ER_DYNCOL_RESOURCE;
+      break;
+    case DYN_COL_UINT:
+      len= snprintf(buff, sizeof(buff), "%llu", val->x.ulong_value);
+      if (dynstr_append_mem(str, buff, len))
+        return ER_DYNCOL_RESOURCE;
+      break;
+    case DYN_COL_DOUBLE:
+      len= snprintf(buff, sizeof(buff), "%lg", val->x.double_value);
+      if (dynstr_realloc(str, len + 2))
+        return ER_DYNCOL_RESOURCE;
+      str->str[str->length++]= '"';
+      dynstr_append_mem(str, buff, len);
+      str->str[str->length++]= '"';
+      break;
+    case DYN_COL_STRING:
+      if (dynstr_append_quoted(str, val->x.string.value.str,
+                               val->x.string.value.length))
+        return ER_DYNCOL_RESOURCE;
+      break;
+    case DYN_COL_DECIMAL:
+      len= sizeof(buff);
+      decimal2string(&val->x.decimal.value, buff, &len,
+                     0, val->x.decimal.value.frac,
+                     '0');
+      if (dynstr_append_mem(str, buff, len))
+        return ER_DYNCOL_RESOURCE;
+      break;
+    case DYN_COL_DATETIME:
+    case DYN_COL_DATE:
+    case DYN_COL_TIME:
+      len= my_TIME_to_str(&val->x.time_value, buff, AUTO_SEC_PART_DIGITS);
+      if (dynstr_realloc(str, len + 2))
+        return ER_DYNCOL_RESOURCE;
+      str->str[str->length++]= '"';
+      dynstr_append_mem(str, buff, len);
+      str->str[str->length++]= '"';
+      break;
+    case DYN_COL_NULL:
+      if (dynstr_append_mem(str, "null", 4))
+        return ER_DYNCOL_RESOURCE;
+      break;
+    default:
+      return(ER_DYNCOL_FORMAT);
+  }
+  return(ER_DYNCOL_OK);
+}
+
+/**
+  Convert to JSON
+
+  @param str             The packed string
+  @param json            Where to put json result
+
+  @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json)
+{
+  DYN_HEADER header;
+  uint i;
+  enum enum_dyncol_func_result rc;
+
+  bzero(json, sizeof(DYNAMIC_STRING));          /* In case of errors */
+  if (str->length == 0)
+    return ER_DYNCOL_OK;                        /* no columns */
+
+  if ((rc= init_read_hdr(&header, str)) < 0)
+    return rc;
+
+  if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
+      str->length)
+    return ER_DYNCOL_FORMAT;
+
+  if (init_dynamic_string(json, NULL, str->length * 2, 100))
+    return ER_DYNCOL_RESOURCE;
+
+  if (dynstr_append_mem(json, "[", 1))
+    return ER_DYNCOL_RESOURCE;
+  rc= ER_DYNCOL_RESOURCE;
+  for (i= 0, header.entry= header.header;
+       i < header.column_count;
+       i++, header.entry+= header.entry_size)
+  {
+    DYNAMIC_COLUMN_VALUE val;
+    if (i != 0 && dynstr_append_mem(json, ",", 1))
+      goto err;
+    header.length=
+      hdr_interval_length(&header, header.entry + header.entry_size);
+    header.data= header.dtpool + header.offset;
+    /*
+      Check that the found data is withing the ranges. This can happen if
+      we get data with wrong offsets.
+    */
+    if (header.length == DYNCOL_OFFSET_ERROR ||
+        header.length > INT_MAX || header.offset > header.data_size)
+    {
+      rc= ER_DYNCOL_FORMAT;
+      goto err;
+    }
+    if ((rc= dynamic_column_get_value(&header, &val)) < 0 ||
+        dynstr_append_mem(json, "{", 1))
+      goto err;
+    if (header.format == DYNCOL_FMT_NUM)
+    {
+      uint nm= uint2korr(header.entry);
+      if (dynstr_realloc(json, 6 + 3))
+        goto err;
+      json->str[json->length++]= '"';
+      json->length+= (snprintf(json->str + json->length, 6, "%u", nm));
+    }
+    else
+    {
+      uint len= header.entry[0];
+      if (dynstr_realloc(json, len + 3))
+        goto err;
+      json->str[json->length++]= '"';
+      memcpy(json->str + json->length, (const void *)header.nmpool +
+             uint2korr(header.entry + 1), len);
+      json->length+= len;
+    }
+    json->str[json->length++]= '"';
+    json->str[json->length++]= ':';
+    if ((rc= dynamic_column_val_str(json, &val)) < 0 ||
+        dynstr_append_mem(json, "}", 1))
+      goto err;
+  }
+  if (dynstr_append_mem(json, "]", 1))
+    return ER_DYNCOL_RESOURCE;
+  return ER_DYNCOL_OK;
+
+err:
+  json->length= 0;
+  return rc;
+}

=== modified file 'mysys/string.c'
--- a/mysys/string.c	2012-01-13 14:50:02 +0000
+++ b/mysys/string.c	2012-09-22 18:58:47 +0000
@@ -175,6 +175,34 @@ my_bool dynstr_append_os_quoted(DYNAMIC_
   return ret;
 }
 
+my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
+                             const char *append, size_t len)
+{
+  uint additional= (str->alloc_increment ? str->alloc_increment : 10);
+  uint lim= additional;
+  uint i;
+  if (dynstr_realloc(str, len + additional + 2))
+    return TRUE;
+  str->str[str->length++]= '"';
+  for (i= 0; i < len; i++)
+  {
+    register char c= append[i];
+    if (c == '"' || c == '\\')
+    {
+      if (!lim)
+      {
+        if (dynstr_realloc(str, additional))
+          return TRUE;
+        lim= additional;
+      }
+      lim--;
+      str->str[str->length++]= '\\';
+    }
+    str->str[str->length++]= c;
+  }
+  str->str[str->length++]= '"';
+  return FALSE;
+}
 
 void dynstr_free(DYNAMIC_STRING *str)
 {

=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc	2012-09-20 15:21:29 +0000
+++ b/sql/item_create.cc	2012-09-22 18:58:47 +0000
@@ -5720,6 +5720,10 @@ Item *create_func_dyncol_create(THD *thd
   return new (thd->mem_root) Item_func_dyncol_create(*args, dfs);
 }
 
+Item *create_func_dyncol_json(THD *thd, Item *str)
+{
+  return new (thd->mem_root) Item_func_dyncol_json(str);
+}
 
 Item *create_func_dyncol_add(THD *thd, Item *str,
                              List<DYNCALL_CREATE_DEF> &list)

=== modified file 'sql/item_create.h'
--- a/sql/item_create.h	2012-01-13 14:50:02 +0000
+++ b/sql/item_create.h	2012-09-22 18:58:47 +0000
@@ -180,5 +180,6 @@ Item *create_func_dyncol_get(THD *thd, I
                              Cast_target cast_type,
                              const char *c_len, const char *c_dec,
                              CHARSET_INFO *cs);
+Item *create_func_dyncol_json(THD *thd, Item *str);
 #endif
 

=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc	2012-09-20 15:21:29 +0000
+++ b/sql/item_strfunc.cc	2012-09-22 18:58:47 +0000
@@ -4097,6 +4097,40 @@ void Item_func_dyncol_create::print(Stri
   str->append(')');
 }
 
+String *Item_func_dyncol_json::val_str(String *str)
+{
+  DYNAMIC_STRING json, col;
+  String *res;
+  enum enum_dyncol_func_result rc;
+
+  res= args[0]->val_str(str);
+  if (args[0]->null_value)
+    goto null;
+
+  col.str= (char *)res->ptr();
+  col.length= res->length();
+  if ((rc= dynamic_column_json(&col, &json)))
+  {
+    dynamic_column_error_message(rc);
+    goto null;
+  }
+  bzero(&col, sizeof(col));
+  {
+    /* Move result from DYNAMIC_COLUMN to str */
+    char *ptr;
+    size_t length, alloc_length;
+    dynstr_reassociate(&json, &ptr, &length, &alloc_length);
+    str->reassociate(ptr, (uint32) length, (uint32) alloc_length,
+                     &my_charset_bin);
+    null_value= FALSE;
+  }
+  return str;
+
+null:
+  bzero(&col, sizeof(col));
+  null_value= TRUE;
+  return NULL;
+}
 
 String *Item_func_dyncol_add::val_str(String *str)
 {
@@ -4108,10 +4142,10 @@ String *Item_func_dyncol_add::val_str(St
 
   /* We store the packed data last */
   res= args[arg_count - 1]->val_str(str);
-  if (args[arg_count - 1]->null_value)
+  if (args[arg_count - 1]->null_value ||
+      init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE,
+                          STRING_BUFFER_USUAL_SIZE))
     goto null;
-  init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE,
-                      STRING_BUFFER_USUAL_SIZE);
 
   col.length= res->length();
   memcpy(col.str, res->ptr(), col.length);
@@ -4139,7 +4173,6 @@ String *Item_func_dyncol_add::val_str(St
   }
 
   /* cleanup */
-  dynamic_column_column_free(&col);
   cleanup_arguments();
 
   return str;

=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h	2012-09-20 15:21:29 +0000
+++ b/sql/item_strfunc.h	2012-09-22 18:58:47 +0000
@@ -1027,6 +1027,19 @@ public:
   virtual void print(String *str, enum_query_type query_type);
 };
 
+class Item_func_dyncol_json: public Item_str_func
+{
+public:
+  Item_func_dyncol_json(Item *str) :Item_str_func(str) {}
+  const char *func_name() const{ return "column_json"; }
+  String *val_str(String *);
+  void fix_length_and_dec()
+  {
+    maybe_null= TRUE;
+    collation.set(&my_charset_bin);
+    decimals= 0;
+  }
+};
 
 /*
   The following functions is always called from an Item_cast function

=== modified file 'sql/lex.h'
--- a/sql/lex.h	2012-09-20 15:21:29 +0000
+++ b/sql/lex.h	2012-09-22 18:58:47 +0000
@@ -128,6 +128,7 @@ static SYMBOL symbols[] = {
   { "COLUMN_DELETE",    SYM(COLUMN_DELETE_SYM)},
   { "COLUMN_EXISTS",    SYM(COLUMN_EXISTS_SYM)},
   { "COLUMN_GET",       SYM(COLUMN_GET_SYM)},
+  { "COLUMN_JSON",      SYM(COLUMN_JSON_SYM)},
   { "COLUMN_LIST",      SYM(COLUMN_LIST_SYM)},
   { "COMMENT",		SYM(COMMENT_SYM)},
   { "COMMIT",		SYM(COMMIT_SYM)},

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2012-09-20 15:21:29 +0000
+++ b/sql/sql_yacc.yy	2012-09-22 18:58:47 +0000
@@ -887,6 +887,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  COLUMN_DELETE_SYM
 %token  COLUMN_EXISTS_SYM
 %token  COLUMN_GET_SYM
+%token  COLUMN_JSON_SYM
 %token  COLUMN_LIST_SYM
 %token  COLUMN_SYM                    /* SQL-2003-R */
 %token  COLUMN_NAME_SYM               /* SQL-2003-N */
@@ -8844,6 +8845,13 @@ function_call_nonkeyword:
               MYSQL_YYABORT;
           }
         |
+          COLUMN_JSON_SYM '(' expr ')'
+          {
+            $$= create_func_dyncol_json(YYTHD, $3);
+            if ($$ == NULL)
+              MYSQL_YYABORT;
+          }
+        |
           COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
           {
             LEX *lex= Lex;
@@ -12937,6 +12945,7 @@ keyword:
         | COLUMN_DELETE_SYM     {}
         | COLUMN_EXISTS_SYM     {}
         | COLUMN_GET_SYM        {}
+        | COLUMN_JSON_SYM       {}
         | COLUMN_LIST_SYM       {}
         | COMMENT_SYM           {}
         | COMMIT_SYM            {}



More information about the commits mailing list