[Commits] Rev 3521: change syntax of cassandra dynamic columns tag. in file:///home/bell/maria/bzr/work-maria-5.5-cassandra/

sanja at montyprogram.com sanja at montyprogram.com
Tue Sep 25 18:18:29 EEST 2012


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

------------------------------------------------------------
revno: 3521
revision-id: sanja at montyprogram.com-20120925151828-0b5m3mp0h4jeqhut
parent: sanja at montyprogram.com-20120925105658-4l9jctn5jd4io9fa
committer: sanja at montyprogram.com
branch nick: work-maria-5.5-cassandra
timestamp: Tue 2012-09-25 18:18:28 +0300
message:
  change syntax of cassandra dynamic columns tag.
  
  added conversion functions to dyncmic column library
  
  added reading all names and values
-------------- next part --------------
=== modified file 'include/ma_dyncol.h'
--- a/include/ma_dyncol.h	2012-09-25 10:56:58 +0000
+++ b/include/ma_dyncol.h	2012-09-25 15:18:28 +0000
@@ -50,7 +50,8 @@ enum enum_dyncol_func_result
   ER_DYNCOL_LIMIT=  -2,            /* Some limit reached */
   ER_DYNCOL_RESOURCE= -3,          /* Out of resourses */
   ER_DYNCOL_DATA= -4,              /* Incorrect input data */
-  ER_DYNCOL_UNKNOWN_CHARSET= -5    /* Unknown character set */
+  ER_DYNCOL_UNKNOWN_CHARSET= -5,   /* Unknown character set */
+  ER_DYNCOL_TRUNCATED= 2           /* OK, but data was truncated */
 };
 
 typedef DYNAMIC_STRING DYNAMIC_COLUMN;
@@ -171,6 +172,17 @@ dynamic_column_json(DYNAMIC_COLUMN *str,
 #define dynamic_column_initialize(A) memset((A), 0, sizeof(*(A)))
 #define dynamic_column_column_free(V) dynstr_free(V)
 
+/* conversion of values to 3 base types */
+enum enum_dyncol_func_result
+dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
+                       my_bool quote);
+enum enum_dyncol_func_result
+dynamic_column_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val);
+enum enum_dyncol_func_result
+dynamic_column_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val);
+
+
+
 /***************************************************************************
  Internal functions, don't use if you don't know what you are doing...
 ***************************************************************************/

=== modified file 'mysql-test/r/cassandra.result'
--- a/mysql-test/r/cassandra.result	2012-09-25 10:56:58 +0000
+++ b/mysql-test/r/cassandra.result	2012-09-25 15:18:28 +0000
@@ -346,13 +346,13 @@ drop table t2;
 #
 # Dynamic columns support
 #
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 drop table t2;
 #error: dynamic column is not a blob
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 ERROR 42000: Incorrect column specifier for column 'uuidcol'
 #error: double dynamic column
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNCOL=1, textcol blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1, textcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 ERROR 42000: Incorrect column specifier for column 'textcol'
 #
 # Dynamic column read
@@ -363,7 +363,7 @@ delete from t2;
 insert into t2 values(1,'9b5658dc-f32f-11e1-94cd-f46d046e9f09');
 insert into t2 values(2,'9b5658dc-f32f-11e1-94cd-f46d046e9f0a');
 drop table t2;
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 select rowkey, column_list(dyn), column_get(dyn, 'uuidcol' as char) from t2;
 rowkey	column_list(dyn)	column_get(dyn, 'uuidcol' as char)
 1	`uuidcol`	9b5658dc-f32f-11e1-94cd-f46d046e9f09

=== modified file 'mysql-test/t/cassandra.test'
--- a/mysql-test/t/cassandra.test	2012-09-25 10:56:58 +0000
+++ b/mysql-test/t/cassandra.test	2012-09-25 15:18:28 +0000
@@ -440,16 +440,16 @@ drop table t2;
 --echo #
 --echo # Dynamic columns support
 --echo #
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 drop table t2;
 
 --echo #error: dynamic column is not a blob
 --error ER_WRONG_FIELD_SPEC
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 
 --echo #error: double dynamic column
 --error ER_WRONG_FIELD_SPEC
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNCOL=1, textcol blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1, textcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 
 --echo #
 --echo # Dynamic column read
@@ -463,7 +463,7 @@ insert into t2 values(2,'9b5658dc-f32f-1
 drop table t2;
 
 #test dynamic column read
-CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNCOL=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 select rowkey, column_list(dyn), column_get(dyn, 'uuidcol' as char) from t2;
 drop table t2;
 

=== modified file 'mysys/ma_dyncol.c'
--- a/mysys/ma_dyncol.c	2012-09-25 10:56:58 +0000
+++ b/mysys/ma_dyncol.c	2012-09-25 15:18:28 +0000
@@ -68,6 +68,8 @@ uint32 copy_and_convert(char *to, uint32
 
 #define MAX_OFFSET_LENGTH  5
 
+#define DYNCOL_NUM_CHAR 6
+
 my_bool dynamic_column_has_names(DYNAMIC_COLUMN *str)
 {
   if (str->length < 1)
@@ -1764,7 +1766,7 @@ static my_bool
 find_column(DYN_HEADER *hdr, uint numkey, LEX_STRING *strkey)
 {
   LEX_STRING nmkey;
-  char nmkeybuff[6]; /* to fit max 2 bytes number */
+  char nmkeybuff[DYNCOL_NUM_CHAR]; /* to fit max 2 bytes number */
   DBUG_ASSERT(hdr->header != NULL);
 
   if (hdr->header + hdr->header_size > hdr->data_end)
@@ -2172,10 +2174,10 @@ dynamic_column_list_str(DYNAMIC_COLUMN *
     if (header.format == DYNCOL_FMT_NUM)
     {
       uint nm= uint2korr(read);
-      tmp.str= my_malloc(6, MYF(0));
+      tmp.str= my_malloc(DYNCOL_NUM_CHAR, MYF(0));
       if (!tmp.str)
         return ER_DYNCOL_RESOURCE;
-      tmp.length= snprintf(tmp.str, 6, "%u", nm);
+      tmp.length= snprintf(tmp.str, DYNCOL_NUM_CHAR, "%u", nm);
     }
     else
     {
@@ -2211,7 +2213,7 @@ find_place(DYN_HEADER *hdr, void *key, m
   uint mid, start, end, val;
   int flag;
   LEX_STRING str;
-  char buff[6];
+  char buff[DYNCOL_NUM_CHAR];
   my_bool need_conversion= ((string_keys ? DYNCOL_FMT_STR : DYNCOL_FMT_NUM) !=
                             hdr->format);
   LINT_INIT(flag);                              /* 100 % safe */
@@ -2428,7 +2430,7 @@ dynamic_column_update_copy(DYNAMIC_COLUM
       size_t offs;
       uint nm;
       DYNAMIC_COLUMN_TYPE tp;
-      char buff[6];
+      char buff[DYNCOL_NUM_CHAR];
 
       if (hdr->format == DYNCOL_FMT_NUM)
       {
@@ -3546,6 +3548,155 @@ dynamic_column_val_str(DYNAMIC_STRING *s
   return(ER_DYNCOL_OK);
 }
 
+
+enum enum_dyncol_func_result
+dynamic_column_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val)
+{
+  enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
+  *ll= 0;
+  switch (val->type) {
+  case DYN_COL_INT:
+      *ll= val->x.long_value;
+      break;
+    case DYN_COL_UINT:
+      *ll= (longlong)val->x.ulong_value;
+      if (val->x.ulong_value > ULONGLONG_MAX)
+         rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_DOUBLE:
+      *ll= (longlong)val->x.double_value;
+      if (((double) *ll) != val->x.double_value)
+        rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_STRING:
+      {
+        longlong i= 0, sign= 1;
+        char *src= val->x.string.value.str;
+        uint len= val->x.string.value.length;
+
+        while (len && my_isspace(&my_charset_latin1, *src)) src++,len--;
+
+        if (len)
+        {
+          if (*src == '-')
+          {
+            sign= -1;
+            src++;
+          } else if (*src == '-')
+            src++;
+          while(len && my_isdigit(&my_charset_latin1, *src))
+          {
+            i= i * 10 + (*src - '0');
+            src++;
+          }
+        }
+        else
+          rc= ER_DYNCOL_TRUNCATED;
+        if (len)
+          rc= ER_DYNCOL_TRUNCATED;
+        *ll= i * sign;
+        break;
+      }
+    case DYN_COL_DECIMAL:
+      if (decimal2longlong(&val->x.decimal.value, ll) != E_DEC_OK)
+        rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_DATETIME:
+      *ll= (val->x.time_value.year * 10000000000L +
+            val->x.time_value.month * 100000000L +
+            val->x.time_value.day * 1000000 +
+            val->x.time_value.hour * 10000 +
+            val->x.time_value.minute * 100 +
+            val->x.time_value.second) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_DATE:
+      *ll= (val->x.time_value.year * 10000 +
+            val->x.time_value.month * 100 +
+            val->x.time_value.day) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_TIME:
+      *ll= (val->x.time_value.hour * 10000 +
+            val->x.time_value.minute * 100 +
+            val->x.time_value.second) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_NULL:
+      rc= ER_DYNCOL_TRUNCATED;
+      break;
+    default:
+      return(ER_DYNCOL_FORMAT);
+  }
+  return(rc);
+}
+
+
+enum enum_dyncol_func_result
+dynamic_column_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val)
+{
+  enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
+  *dbl= 0;
+  switch (val->type) {
+  case DYN_COL_INT:
+      *dbl= (double)val->x.long_value;
+      if (((longlong) *dbl) != val->x.long_value)
+        rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_UINT:
+      *dbl= (double)val->x.ulong_value;
+      if (((ulonglong) *dbl) != val->x.ulong_value)
+        rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_DOUBLE:
+      *dbl= val->x.double_value;
+      break;
+    case DYN_COL_STRING:
+      {
+        char *str, *end;
+        if ((str= malloc(val->x.string.value.length + 1)))
+          return ER_DYNCOL_RESOURCE;
+        memcpy(str, val->x.string.value.str, val->x.string.value.length);
+        str[val->x.string.value.length]= '\0';
+        *dbl= strtod(str, &end);
+        if (*end != '\0')
+          rc= ER_DYNCOL_TRUNCATED;
+      }
+    case DYN_COL_DECIMAL:
+      if (decimal2double(&val->x.decimal.value, dbl) != E_DEC_OK)
+        rc= ER_DYNCOL_TRUNCATED;
+      break;
+    case DYN_COL_DATETIME:
+      *dbl= (double)(val->x.time_value.year * 10000000000L +
+                     val->x.time_value.month * 100000000L +
+                     val->x.time_value.day * 1000000 +
+                     val->x.time_value.hour * 10000 +
+                     val->x.time_value.minute * 100 +
+                     val->x.time_value.second) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_DATE:
+      *dbl= (double)(val->x.time_value.year * 10000 +
+                     val->x.time_value.month * 100 +
+                     val->x.time_value.day) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_TIME:
+      *dbl= (double)(val->x.time_value.hour * 10000 +
+                     val->x.time_value.minute * 100 +
+                     val->x.time_value.second) *
+        (val->x.time_value.neg ? -1 : 1);
+      break;
+    case DYN_COL_NULL:
+      rc= ER_DYNCOL_TRUNCATED;
+      break;
+    default:
+      return(ER_DYNCOL_FORMAT);
+  }
+  return(rc);
+}
+
+
 /**
   Convert to JSON
 
@@ -3605,10 +3756,11 @@ dynamic_column_json(DYNAMIC_COLUMN *str,
     if (header.format == DYNCOL_FMT_NUM)
     {
       uint nm= uint2korr(header.entry);
-      if (dynstr_realloc(json, 6 + 3))
+      if (dynstr_realloc(json, DYNCOL_NUM_CHAR + 3))
         goto err;
       json->str[json->length++]= '"';
-      json->length+= (snprintf(json->str + json->length, 6, "%u", nm));
+      json->length+= (snprintf(json->str + json->length,
+                               DYNCOL_NUM_CHAR, "%u", nm));
     }
     else
     {
@@ -3634,3 +3786,98 @@ err:
   json->length= 0;
   return rc;
 }
+
+
+/**
+  Convert to DYNAMIC_COLUMN_VALUE values and names (LEX_STING) dynamic array
+
+  @param str             The packed string
+  @param names           Where to put names
+  @param vals            Where to put values
+  @param free_names      pointer to free names buffer if there is it.
+
+  @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+dynamic_column_vals(DYNAMIC_COLUMN *str,
+                    DYNAMIC_ARRAY *names, DYNAMIC_ARRAY *vals,
+                    char **free_names)
+{
+  DYN_HEADER header;
+  char *nm;
+  uint i;
+  enum enum_dyncol_func_result rc;
+
+  bzero(names, sizeof(DYNAMIC_ARRAY));        /* In case of errors */
+  bzero(vals, sizeof(DYNAMIC_ARRAY));         /* 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_array(names, sizeof(LEX_STRING),
+                         header.column_count, 0) ||
+      init_dynamic_array(vals, sizeof(DYNAMIC_COLUMN_VALUE),
+                         header.column_count, 0) ||
+      (header.format == DYNCOL_FMT_NUM &&
+       !(*free_names= (char *)malloc(DYNCOL_NUM_CHAR * header.column_count))))
+  {
+    rc= ER_DYNCOL_RESOURCE;
+    goto err;
+  }
+  nm= *free_names;
+
+  for (i= 0, header.entry= header.header;
+       i < header.column_count;
+       i++, header.entry+= header.entry_size)
+  {
+    DYNAMIC_COLUMN_VALUE val;
+    LEX_STRING name;
+    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)
+      goto err;
+
+    if (header.format == DYNCOL_FMT_NUM)
+    {
+      uint num= uint2korr(header.entry);
+      name.str= nm;
+      name.length= snprintf(nm, DYNCOL_NUM_CHAR, "%u", num);
+      nm+= name.length + 1;
+    }
+    else
+    {
+      name.length= header.entry[0];
+      name.str= (char *)header.nmpool + uint2korr(header.entry + 1);
+    }
+    /* following is preallocated and so do not fail */
+    (void) insert_dynamic(names, (uchar *)&name);
+    (void) insert_dynamic(vals, (uchar *)&val);
+  }
+  return ER_DYNCOL_OK;
+
+err:
+  delete_dynamic(names);
+  delete_dynamic(vals);
+  if (*free_names)
+    my_free(*free_names);
+  *free_names= 0;
+  return rc;
+}

=== modified file 'storage/cassandra/ha_cassandra.cc'
--- a/storage/cassandra/ha_cassandra.cc	2012-09-25 10:56:58 +0000
+++ b/storage/cassandra/ha_cassandra.cc	2012-09-25 15:18:28 +0000
@@ -90,7 +90,7 @@ ha_create_table_option cassandra_field_o
     the valid values are YES/NO, ON/OFF, 1/0.
     The default is 0, that is true, yes, on.
   */
-  HA_FOPTION_BOOL("DYNCOL", dyncol_field, 0),
+  HA_FOPTION_BOOL("DYNAMIC_COLUMN_STORAGE", dyncol_field, 0),
   HA_FOPTION_END
 };
 



More information about the commits mailing list