[Commits] Rev 3522: Dynamic columns insert. in file:///home/bell/maria/bzr/work-maria-5.5-cassandra/

sanja at montyprogram.com sanja at montyprogram.com
Wed Sep 26 22:09:26 EEST 2012


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

------------------------------------------------------------
revno: 3522
revision-id: sanja at montyprogram.com-20120926190923-oxdeydkyu12bmx1m
parent: sanja at montyprogram.com-20120925151828-0b5m3mp0h4jeqhut
committer: sanja at montyprogram.com
branch nick: work-maria-5.5-cassandra
timestamp: Wed 2012-09-26 22:09:23 +0300
message:
  Dynamic columns insert.
-------------- next part --------------
=== modified file 'include/ma_dyncol.h'
--- a/include/ma_dyncol.h	2012-09-25 15:18:28 +0000
+++ b/include/ma_dyncol.h	2012-09-26 19:09:23 +0000
@@ -175,13 +175,17 @@ dynamic_column_json(DYNAMIC_COLUMN *str,
 /* 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);
+                       CHARSET_INFO *cs, 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);
 
 
+enum enum_dyncol_func_result
+dynamic_column_vals(DYNAMIC_COLUMN *str,
+                    DYNAMIC_ARRAY *names, DYNAMIC_ARRAY *vals,
+                    char **free_names);
 
 /***************************************************************************
  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 15:18:28 +0000
+++ b/mysql-test/r/cassandra.result	2012-09-26 19:09:23 +0000
@@ -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 DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) 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
@@ -373,3 +373,13 @@ CREATE TABLE t2 (rowkey bigint PRIMARY K
 thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
 delete from t2;
 drop table t2;
+#
+# Dynamic column insert
+#
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+insert into t2 values (1, column_create("dyn1", 1, "dyn2", "two"));
+select rowkey, column_json(dyn) from t2;
+rowkey	column_json(dyn)
+1	[{"dyn1":"1"},{"dyn2":"two"}]
+delete from t2;
+drop table t2;

=== modified file 'mysql-test/t/cassandra.test'
--- a/mysql-test/t/cassandra.test	2012-09-25 15:18:28 +0000
+++ b/mysql-test/t/cassandra.test	2012-09-26 19:09:23 +0000
@@ -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 DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) 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;
 
@@ -473,6 +473,15 @@ CREATE TABLE t2 (rowkey bigint PRIMARY K
 delete from t2;
 drop table t2;
 
+--echo #
+--echo # Dynamic column insert
+--echo #
+CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
+insert into t2 values (1, column_create("dyn1", 1, "dyn2", "two")); 
+select rowkey, column_json(dyn) from t2;
+delete from t2;
+drop table t2;
+
 ############################################################################
 ## Cassandra cleanup
 ############################################################################

=== modified file 'mysys/ma_dyncol.c'
--- a/mysys/ma_dyncol.c	2012-09-25 15:18:28 +0000
+++ b/mysys/ma_dyncol.c	2012-09-26 19:09:23 +0000
@@ -3443,7 +3443,7 @@ end:
 
 enum enum_dyncol_func_result
 dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
-                       my_bool quote)
+                       CHARSET_INFO *cs, my_bool quote)
 {
   char buff[40];
   int len;
@@ -3473,24 +3473,22 @@ dynamic_column_val_str(DYNAMIC_STRING *s
         char *alloc= NULL;
         char *from= val->x.string.value.str;
         uint bufflen;
-        my_bool conv= !my_charset_same(val->x.string.charset,
-                                       &my_charset_utf8_general_ci);
+        my_bool conv= !my_charset_same(val->x.string.charset, cs);
         my_bool rc;
         len= val->x.string.value.length;
-        bufflen= (len * (conv ? my_charset_utf8_general_ci.mbmaxlen : 1));
+        bufflen= (len * (conv ? cs->mbmaxlen : 1));
         if (dynstr_realloc(str, bufflen))
             return ER_DYNCOL_RESOURCE;
 
         // guaranty UTF-8 string for value
-        if (!my_charset_same(val->x.string.charset,
-                             &my_charset_utf8_general_ci))
+        if (!my_charset_same(val->x.string.charset, cs))
         {
           uint dummy_errors;
           if (!quote)
           {
             /* convert to the destination */
             str->length+= copy_and_convert_extended(str->str, bufflen,
-                                                    &my_charset_utf8_general_ci,
+                                                    cs,
                                                     from, len,
                                                     val->x.string.charset,
                                                     &dummy_errors);
@@ -3499,8 +3497,7 @@ dynamic_column_val_str(DYNAMIC_STRING *s
           if ((alloc= (char *)my_malloc(bufflen, MYF(0))))
           {
             len=
-              copy_and_convert_extended(alloc, bufflen,
-                                        &my_charset_utf8_general_ci,
+              copy_and_convert_extended(alloc, bufflen, cs,
                                         from, len, val->x.string.charset,
                                         &dummy_errors);
             from= alloc;
@@ -3774,7 +3771,8 @@ dynamic_column_json(DYNAMIC_COLUMN *str,
     }
     json->str[json->length++]= '"';
     json->str[json->length++]= ':';
-    if ((rc= dynamic_column_val_str(json, &val, TRUE)) < 0 ||
+    if ((rc= dynamic_column_val_str(json, &val,
+                                    &my_charset_utf8_general_ci, TRUE)) < 0 ||
         dynstr_append_mem(json, "}", 1))
       goto err;
   }
@@ -3809,6 +3807,7 @@ dynamic_column_vals(DYNAMIC_COLUMN *str,
   uint i;
   enum enum_dyncol_func_result rc;
 
+  *free_names= 0;
   bzero(names, sizeof(DYNAMIC_ARRAY));        /* In case of errors */
   bzero(vals, sizeof(DYNAMIC_ARRAY));         /* In case of errors */
   if (str->length == 0)

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-06-14 18:05:31 +0000
+++ b/sql/sql_base.cc	2012-09-26 19:09:23 +0000
@@ -9773,6 +9773,7 @@ int dynamic_column_error_message(enum_dy
   switch (rc) {
   case ER_DYNCOL_YES:
   case ER_DYNCOL_OK:
+  case ER_DYNCOL_TRUNCATED:
     break; // it is not an error
   case ER_DYNCOL_FORMAT:
     my_error(ER_DYN_COL_WRONG_FORMAT, MYF(0));

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2012-05-16 15:44:17 +0000
+++ b/sql/sql_base.h	2012-09-26 19:09:23 +0000
@@ -272,6 +272,7 @@ bool rename_temporary_table(THD* thd, TA
 			    const char *table_name);
 bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
 
+class Open_tables_backup;
 /* Functions to work with system tables. */
 bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
                                  Open_tables_backup *backup);

=== modified file 'storage/cassandra/ha_cassandra.cc'
--- a/storage/cassandra/ha_cassandra.cc	2012-09-25 15:18:28 +0000
+++ b/storage/cassandra/ha_cassandra.cc	2012-09-26 19:09:23 +0000
@@ -31,6 +31,7 @@ static handler *cassandra_create_handler
                                        TABLE_SHARE *table,
                                        MEM_ROOT *mem_root);
 
+extern int dynamic_column_error_message(enum_dyncol_func_result rc);
 
 handlerton *cassandra_hton;
 
@@ -811,7 +812,7 @@ static int convert_hex_digit(const char
 
 const char map2number[]="0123456789abcdef";
 
-static void convert_uuid2string (char *str, const char *cass_data)
+static void convert_uuid2string(char *str, const char *cass_data)
 {
   char *ptr= str;
   /* UUID arrives as 16-byte number in network byte order */
@@ -825,6 +826,29 @@ static void convert_uuid2string (char *s
   *ptr= 0;
 }
 
+static bool convert_string2uuid(char *buf, const char *str)
+{
+  int lower, upper;
+  for (uint i= 0; i < 16; i++)
+  {
+    if ((upper= convert_hex_digit(str[0])) == -1 ||
+        (lower= convert_hex_digit(str[1])) == -1)
+    {
+      return true;
+    }
+    buf[i]= lower | (upper << 4);
+    str += 2;
+    if (i == 3 || i == 5 || i == 7 || i == 9)
+    {
+      if (str[0] != '-')
+        return true;
+      str++;
+    }
+  }
+  return false;
+}
+
+
 class UuidDataConverter : public ColumnDataConverter
 {
   char buf[16]; /* Binary UUID representation */
@@ -842,29 +866,12 @@ public:
   bool mariadb_to_cassandra(char **cass_data, int *cass_data_len)
   {
     String *uuid_str= field->val_str(&str_buf);
-    char *pstr= (char*)uuid_str->c_ptr();
 
-    if (uuid_str->length() != 36) 
+    if (uuid_str->length() != 36)
+      return true;
+
+    if (convert_string2uuid(buf, (char*)uuid_str->c_ptr()))
       return true;
-    
-    int lower, upper;
-    for (uint i=0; i < 16; i++)
-    {
-      if ((upper= convert_hex_digit(pstr[0])) == -1 ||
-          (lower= convert_hex_digit(pstr[1])) == -1)
-      {
-        return true;
-      }
-      buf[i]= lower | (upper << 4);
-      pstr += 2;
-      if (i == 3 || i == 5 || i == 7 || i == 9)
-      {
-        if (pstr[0] != '-')
-          return true;
-        pstr++;
-      }
-    }
-     
     *cass_data= buf;
     *cass_data_len= 16;
     return false;
@@ -887,6 +894,27 @@ bool cassandra_to_dyncol_intLong(const c
 #endif
   return 0;
 }
+
+bool dyncol_to_cassandraLong(DYNAMIC_COLUMN_VALUE *value,
+                             char **cass_data, int *cass_data_len,
+                             void* buff, void **freemem)
+{
+  longlong *tmp= (longlong *) buff;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_long(tmp, value);
+  if (rc < 0)
+    return true;
+  *cass_data_len= sizeof(longlong);
+#ifdef WORDS_BIGENDIAN
+  *cass_data= (char *)buff;
+#else
+  flip64((char *)buff, (char *)buff + sizeof(longlong));
+  *cass_data= (char *)buff + sizeof(longlong);
+#endif
+  *freemem= NULL;
+  return false;
+}
+
 bool cassandra_to_dyncol_intInt32(const char *cass_data,
                                   int cass_data_len __attribute__((unused)),
                                   DYNAMIC_COLUMN_VALUE *value)
@@ -901,18 +929,57 @@ bool cassandra_to_dyncol_intInt32(const
   value->x.long_value= tmp;
   return 0;
 }
+
+
+bool dyncol_to_cassandraInt32(DYNAMIC_COLUMN_VALUE *value,
+                              char **cass_data, int *cass_data_len,
+                              void* buff, void **freemem)
+{
+  longlong *tmp= (longlong *) ((char *)buff + sizeof(longlong));
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_long(tmp, value);
+  if (rc < 0)
+    return true;
+  *cass_data_len= sizeof(int32);
+  *cass_data= (char *)buff;
+#ifdef WORDS_BIGENDIAN
+  *((int32 *) buff) = (int32) *tmp;
+#else
+  {
+    int32 tmp2= (int32) *tmp;
+    flip32((char *)&tmp2, (char *)buff);
+  }
+#endif
+  *freemem= NULL;
+  return false;
+}
+
+
 bool cassandra_to_dyncol_intCounter(const char *cass_data,
                                     int cass_data_len __attribute__((unused)),
                                     DYNAMIC_COLUMN_VALUE *value)
 {
   value->type= DYN_COL_INT;
-#ifdef WORDS_BIGENDIAN
-  flip64(cass_data, &value->x.long_value);
-#else
   value->x.long_value= *((longlong *)cass_data);
-#endif
   return 0;
 }
+
+
+bool dyncol_to_cassandraCounter(DYNAMIC_COLUMN_VALUE *value,
+                                char **cass_data, int *cass_data_len,
+                                void* buff, void **freemem)
+{
+  longlong *tmp= (longlong *)buff;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_long(tmp, value);
+  if (rc < 0)
+    return true;
+  *cass_data_len= sizeof(longlong);
+  *cass_data= (char *)buff;
+  *freemem= NULL;
+  return false;
+}
+
 bool cassandra_to_dyncol_doubleFloat(const char *cass_data,
                                      int cass_data_len __attribute__((unused)),
                                      DYNAMIC_COLUMN_VALUE *value)
@@ -921,6 +988,23 @@ bool cassandra_to_dyncol_doubleFloat(con
   value->x.double_value= *((float *)cass_data);
   return 0;
 }
+
+bool dyncol_to_cassandraFloat(DYNAMIC_COLUMN_VALUE *value,
+                              char **cass_data, int *cass_data_len,
+                              void* buff, void **freemem)
+{
+  double tmp;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_double(&tmp, value);
+  if (rc < 0)
+    return true;
+  *((float *)buff)= (float) tmp;
+  *cass_data_len= sizeof(float);
+  *cass_data= (char *)buff;
+  *freemem= NULL;
+  return false;
+}
+
 bool cassandra_to_dyncol_doubleDouble(const char *cass_data,
                                       int cass_data_len __attribute__((unused)),
                                       DYNAMIC_COLUMN_VALUE *value)
@@ -929,6 +1013,22 @@ bool cassandra_to_dyncol_doubleDouble(co
   value->x.double_value= *((double *)cass_data);
   return 0;
 }
+
+bool dyncol_to_cassandraDouble(DYNAMIC_COLUMN_VALUE *value,
+                               char **cass_data, int *cass_data_len,
+                               void* buff, void **freemem)
+{
+  double *tmp= (double *)buff;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_double(tmp, value);
+  if (rc < 0)
+    return true;
+  *cass_data_len= sizeof(double);
+  *cass_data= (char *)buff;
+  *freemem= NULL;
+  return false;
+}
+
 bool cassandra_to_dyncol_strStr(const char *cass_data,
                                 int cass_data_len,
                                 DYNAMIC_COLUMN_VALUE *value,
@@ -941,6 +1041,27 @@ bool cassandra_to_dyncol_strStr(const ch
   value->x.string.nonfreeable= TRUE; // do not try to free
   return 0;
 }
+
+bool dyncol_to_cassandraStr(DYNAMIC_COLUMN_VALUE *value,
+                            char **cass_data, int *cass_data_len,
+                            void* buff, void **freemem, CHARSET_INFO *cs)
+{
+  DYNAMIC_STRING tmp;
+  if (init_dynamic_string(&tmp, NULL, 1024, 1024))
+    return 1;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_str(&tmp, value, cs, FALSE);
+  if (rc < 0)
+  {
+    dynstr_free(&tmp);
+    return 1;
+  }
+  *cass_data_len= tmp.length;
+  *(cass_data)= tmp.str;
+  *freemem= tmp.str;
+  return 0;
+}
+
 bool cassandra_to_dyncol_strBytes(const char *cass_data,
                                   int cass_data_len,
                                   DYNAMIC_COLUMN_VALUE *value)
@@ -948,6 +1069,15 @@ bool cassandra_to_dyncol_strBytes(const
   return cassandra_to_dyncol_strStr(cass_data, cass_data_len, value,
                                     &my_charset_bin);
 }
+
+bool dyncol_to_cassandraBytes(DYNAMIC_COLUMN_VALUE *value,
+                              char **cass_data, int *cass_data_len,
+                              void* buff, void **freemem)
+{
+  return dyncol_to_cassandraStr(value, cass_data, cass_data_len,
+                                buff, freemem, &my_charset_bin);
+}
+
 bool cassandra_to_dyncol_strAscii(const char *cass_data,
                                   int cass_data_len,
                                   DYNAMIC_COLUMN_VALUE *value)
@@ -955,6 +1085,15 @@ bool cassandra_to_dyncol_strAscii(const
   return cassandra_to_dyncol_strStr(cass_data, cass_data_len, value,
                                     &my_charset_latin1_bin);
 }
+
+bool dyncol_to_cassandraAscii(DYNAMIC_COLUMN_VALUE *value,
+                              char **cass_data, int *cass_data_len,
+                              void* buff, void **freemem)
+{
+  return dyncol_to_cassandraStr(value, cass_data, cass_data_len,
+                                buff, freemem, &my_charset_latin1_bin);
+}
+
 bool cassandra_to_dyncol_strUTF8(const char *cass_data,
                                  int cass_data_len,
                                  DYNAMIC_COLUMN_VALUE *value)
@@ -963,6 +1102,14 @@ bool cassandra_to_dyncol_strUTF8(const c
                                     &my_charset_utf8_unicode_ci);
 }
 
+bool dyncol_to_cassandraUTF8(DYNAMIC_COLUMN_VALUE *value,
+                             char **cass_data, int *cass_data_len,
+                             void* buff, void **freemem)
+{
+  return dyncol_to_cassandraStr(value, cass_data, cass_data_len,
+                                buff, freemem, &my_charset_utf8_unicode_ci);
+}
+
 bool cassandra_to_dyncol_strUUID(const char *cass_data,
                                  int cass_data_len,
                                  DYNAMIC_COLUMN_VALUE *value)
@@ -982,6 +1129,27 @@ bool cassandra_to_dyncol_strUUID(const c
   return 0;
 }
 
+bool dyncol_to_cassandraUUID(DYNAMIC_COLUMN_VALUE *value,
+                             char **cass_data, int *cass_data_len,
+                             void* buff, void **freemem)
+{
+  DYNAMIC_STRING tmp;
+  if (init_dynamic_string(&tmp, NULL, 1024, 1024))
+    return true;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_str(&tmp, value, &my_charset_latin1_bin, FALSE);
+  if (rc < 0 || tmp.length != 36 || convert_string2uuid((char *)buff, tmp.str))
+  {
+    dynstr_free(&tmp);
+    return true;
+  }
+
+  *cass_data_len= tmp.length;
+  *(cass_data)= tmp.str;
+  *freemem= tmp.str;
+  return 0;
+}
+
 bool cassandra_to_dyncol_intBool(const char *cass_data,
                                  int cass_data_len,
                                  DYNAMIC_COLUMN_VALUE *value)
@@ -991,6 +1159,23 @@ bool cassandra_to_dyncol_intBool(const c
   return 0;
 }
 
+bool dyncol_to_cassandraBool(DYNAMIC_COLUMN_VALUE *value,
+                             char **cass_data, int *cass_data_len,
+                             void* buff, void **freemem)
+{
+  longlong tmp;
+  enum enum_dyncol_func_result rc=
+    dynamic_column_val_long(&tmp, value);
+  if (rc < 0)
+    return true;
+  ((char *)buff)[0]= (tmp ? 1 : 0);
+  *cass_data_len= 1;
+  *(cass_data)= (char *)buff;
+  *freemem= 0;
+  return 0;
+}
+
+
 const char * const validator_bigint=  "org.apache.cassandra.db.marshal.LongType";
 const char * const validator_int=     "org.apache.cassandra.db.marshal.Int32Type";
 const char * const validator_counter= "org.apache.cassandra.db.marshal.CounterColumnType";
@@ -1016,47 +1201,58 @@ static CASSANDRA_TYPE_DEF cassandra_type
 {
   {
     validator_bigint,
-    &cassandra_to_dyncol_intLong
+    &cassandra_to_dyncol_intLong,
+    &dyncol_to_cassandraLong
   },
   {
     validator_int,
-    &cassandra_to_dyncol_intInt32
+    &cassandra_to_dyncol_intInt32,
+    &dyncol_to_cassandraInt32
   },
   {
     validator_counter,
-    cassandra_to_dyncol_intCounter
+    cassandra_to_dyncol_intCounter,
+    &dyncol_to_cassandraCounter
   },
   {
     validator_float,
-    &cassandra_to_dyncol_doubleFloat
+    &cassandra_to_dyncol_doubleFloat,
+    &dyncol_to_cassandraFloat
   },
   {
     validator_double,
-    &cassandra_to_dyncol_doubleDouble
+    &cassandra_to_dyncol_doubleDouble,
+    &dyncol_to_cassandraDouble
   },
   {
     validator_blob,
-    &cassandra_to_dyncol_strBytes
+    &cassandra_to_dyncol_strBytes,
+    &dyncol_to_cassandraBytes
   },
   {
     validator_ascii,
-    &cassandra_to_dyncol_strAscii
+    &cassandra_to_dyncol_strAscii,
+    &dyncol_to_cassandraAscii
   },
   {
     validator_text,
-    &cassandra_to_dyncol_strUTF8
+    &cassandra_to_dyncol_strUTF8,
+    &dyncol_to_cassandraUTF8
   },
   {
     validator_timestamp,
-    &cassandra_to_dyncol_intLong
+    &cassandra_to_dyncol_intLong,
+    &dyncol_to_cassandraLong
   },
   {
     validator_uuid,
-    &cassandra_to_dyncol_strUUID
+    &cassandra_to_dyncol_strUUID,
+    &dyncol_to_cassandraUUID
   },
   {
     validator_boolean,
-    &cassandra_to_dyncol_intBool
+    &cassandra_to_dyncol_intBool,
+    &dyncol_to_cassandraBool
   }
 };
 
@@ -1446,6 +1642,23 @@ void free_strings(DYNAMIC_COLUMN_VALUE *
 }
 
 
+CASSANDRA_TYPE_DEF * ha_cassandra::get_cassandra_field_def(char *cass_name,
+                                                           int cass_name_len)
+{
+  CASSANDRA_TYPE_DEF *type= default_type_def;
+  for(uint i= 0; i < n_special_type_fields; i++)
+  {
+    if (cass_name_len == (int)special_type_field_names[i].length &&
+        memcmp(cass_name, special_type_field_names[i].str,
+               cass_name_len) == 0)
+    {
+      type= special_type_field_converters + i;
+      break;
+    }
+  }
+  return type;
+}
+
 int ha_cassandra::read_cassandra_columns(bool unpack_pk)
 {
   char *cass_name;
@@ -1496,18 +1709,8 @@ int ha_cassandra::read_cassandra_columns
     {
       DYNAMIC_COLUMN_VALUE val;
       LEX_STRING nm;
-      CASSANDRA_TYPE_DEF *type= default_type_def;
-      for(uint i= 0; i < n_special_type_fields; i++)
-      {
-        if (cass_name_len == (int)special_type_field_names[i].length &&
-            memcmp(cass_name, special_type_field_names[i].str,
-                   cass_name_len) == 0)
-        {
-          type= special_type_field_converters + i;
-          break;
-        }
-      }
-
+      CASSANDRA_TYPE_DEF *type= get_cassandra_field_def(cass_name,
+                                                        cass_name_len);
       nm.str= cass_name;
       nm.length= cass_name_len;
       if ((*(type->cassandra_to_dynamic))(cass_value, cass_value_len, &val) ||
@@ -1569,6 +1772,69 @@ err:
   return res;
 }
 
+int ha_cassandra::write_dynamic_row()
+{
+  DYNAMIC_ARRAY vals, names;
+  String valcol, *strcol;
+  DYNAMIC_COLUMN col;
+  char *free_names;
+  uint i;
+  enum enum_dyncol_func_result rc;
+  DBUG_ENTER("ha_cassandra::write_dynamic_row");
+  DBUG_ASSERT(dyncol_set);
+
+  Field *field= table->field[dyncol_field];
+  DBUG_ASSERT(field->type() == MYSQL_TYPE_BLOB);
+  /* It is blob and it does not use buffer */
+  strcol= field->val_str(NULL, &valcol);
+  /*
+    dynamic_column_vals only read the string so we can
+    cheat here with assignment
+  */
+  bzero(&col, sizeof(col));
+  col.str= (char *)strcol->ptr();
+  col.length= strcol->length();
+  if ((rc= dynamic_column_vals(&col, &names, &vals, &free_names)) < 0)
+  {
+    dynamic_column_error_message(rc);
+    DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+  }
+  DBUG_ASSERT(names.elements == vals.elements);
+  for (i= 0; i < names.elements; i++)
+  {
+    char buff[16], stringname[256];
+    CASSANDRA_TYPE_DEF *type;
+    void *freemem= NULL;
+    char *cass_data;
+    int cass_data_len;
+    LEX_STRING *name= dynamic_element(&names, i, LEX_STRING*);
+    DYNAMIC_COLUMN_VALUE *val= dynamic_element(&vals, i, DYNAMIC_COLUMN_VALUE*);
+
+    DBUG_PRINT("info", ("field %*s", (int)name->length, name->str));
+    type= get_cassandra_field_def(name->str, (int) name->length);
+    if ((*type->dynamic_to_cassandra)(val, &cass_data, &cass_data_len,
+                                      buff, &freemem))
+    {
+      my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
+               name->str, insert_lineno);
+      DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+    }
+    /* prepare \0 ending name */
+    DBUG_ASSERT(name->length < sizeof(stringname) - 1);
+    memcpy(stringname, (name->str), name->length);
+    stringname[name->length]= '\0';
+    se->add_insert_column(stringname,
+                          cass_data, cass_data_len);
+    if (freemem)
+      my_free(freemem);
+  }
+
+  delete_dynamic(&names);
+  delete_dynamic(&vals);
+  if (free_names)
+    my_free(free_names);
+  DBUG_RETURN(0);
+}
 
 int ha_cassandra::write_row(uchar *buf)
 {
@@ -1599,15 +1865,26 @@ int ha_cassandra::write_row(uchar *buf)
   {
     char *cass_data;
     int cass_data_len;
-    if (field_converters[i]->mariadb_to_cassandra(&cass_data, &cass_data_len))
+    if (dyncol_set && dyncol_field == i)
     {
-      my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
-               field_converters[i]->field->field_name, insert_lineno);
-      dbug_tmp_restore_column_map(table->read_set, old_map);
-      DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+      int rc;
+      DBUG_ASSERT(field_converters[i] == NULL);
+      if ((rc= write_dynamic_row()))
+        return rc;
+    }
+    else
+    {
+      if (field_converters[i]->mariadb_to_cassandra(&cass_data,
+                                                    &cass_data_len))
+      {
+        my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
+                 field_converters[i]->field->field_name, insert_lineno);
+        dbug_tmp_restore_column_map(table->read_set, old_map);
+        DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+      }
+      se->add_insert_column(field_converters[i]->field->field_name,
+                            cass_data, cass_data_len);
     }
-    se->add_insert_column(field_converters[i]->field->field_name, 
-                          cass_data, cass_data_len);
   }
 
   dbug_tmp_restore_column_map(table->read_set, old_map);

=== modified file 'storage/cassandra/ha_cassandra.h'
--- a/storage/cassandra/ha_cassandra.h	2012-09-25 10:56:58 +0000
+++ b/storage/cassandra/ha_cassandra.h	2012-09-26 19:09:23 +0000
@@ -46,10 +46,15 @@ struct st_dynamic_column_value;
 typedef bool (* CAS2DYN_CONVERTER)(const char *cass_data,
                                    int cass_data_len,
                                    struct st_dynamic_column_value *value);
+typedef bool (* DYN2CAS_CONVERTER)(struct st_dynamic_column_value *value,
+                                   char **cass_data,
+                                   int *cass_data_len,
+                                   void *buf, void **freemem);
 struct cassandra_type_def
 {
   const char *name;
   CAS2DYN_CONVERTER cassandra_to_dynamic;
+  DYN2CAS_CONVERTER dynamic_to_cassandra;
 };
 
 typedef struct cassandra_type_def CASSANDRA_TYPE_DEF;
@@ -222,6 +227,9 @@ private:
   bool source_exhausted;
   bool mrr_start_read();
   int check_field_options(Field **fields);
+  int write_dynamic_row();
+  CASSANDRA_TYPE_DEF * get_cassandra_field_def(char *cass_name,
+                                               int cass_name_length);
 public:
 
   /*



More information about the commits mailing list