Author: dcreager
Date: Fri Feb 25 16:19:42 2011
New Revision: 1074614

URL: http://svn.apache.org/viewvc?rev=1074614&view=rev
Log:
AVRO-762. C: Promotion of values during schema resolution

The avro_resolver_new function now takes into the schema promotion
rules: an int can be read as a long, float, or double; a long can be
read as a float or double; and a float can be read as a double.  The
test_avro_data test program includes test cases for each of these
promotions.

Modified:
    avro/trunk/lang/c/src/resolver.c
    avro/trunk/lang/c/src/schema.c
    avro/trunk/lang/c/tests/test_avro_data.c

Modified: avro/trunk/lang/c/src/resolver.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/resolver.c?rev=1074614&r1=1074613&r2=1074614&view=diff
==============================================================================
--- avro/trunk/lang/c/src/resolver.c (original)
+++ avro/trunk/lang/c/src/resolver.c Fri Feb 25 16:19:42 2011
@@ -154,7 +154,7 @@ avro_resolver_get_real_dest(avro_resolve
  */
 
 #define check_non_union(wschema, rschema, check_func)          \
-{                                                              \
+do {                                                           \
        avro_resolver_t  *self = NULL;                          \
        int  rc = check_func(&self, wschema, rschema,           \
                             rschema);                          \
@@ -171,7 +171,7 @@ avro_resolver_get_real_dest(avro_resolve
         if (rc) {                                              \
                return NULL;                                    \
        }                                                       \
-    }
+} while (0)
 
 
 /**
@@ -183,7 +183,7 @@ avro_resolver_get_real_dest(avro_resolve
  */
 
 #define check_reader_union(wschema, rschema, check_func)               \
-{                                                                      \
+do {                                                                   \
        if (!is_avro_union(rschema)) {                                  \
                break;                                                  \
        }                                                               \
@@ -213,7 +213,7 @@ avro_resolver_get_real_dest(avro_resolve
        }                                                               \
                                                                        \
        debug("No reader union branches match");                        \
-}
+} while (0)
 
 /**
  * A helper macro that defines wraps together check_non_union and
@@ -221,16 +221,16 @@ avro_resolver_get_real_dest(avro_resolve
  */
 
 #define check_simple_writer(wschema, rschema, type_name)               \
-{                                                                      \
+do {                                                                   \
        check_non_union(wschema, rschema, try_##type_name);             \
        check_reader_union(wschema, rschema, try_##type_name);          \
        debug("Writer %s doesn't match reader %s",                      \
              avro_schema_type_name(wschema),                           \
              avro_schema_type_name(rschema));                          \
-       avro_set_error("Cannot store a " #type_name " into schema %s",  \
+       avro_set_error("Cannot store " #type_name " into %s",           \
                       avro_schema_type_name(rschema));                 \
        return NULL;                                                    \
-}
+} while (0)
 
 
 /*-----------------------------------------------------------------------
@@ -332,6 +332,17 @@ avro_resolver_float_value(avro_consumer_
 }
 
 static int
+avro_resolver_float_double_value(avro_consumer_t *consumer, float value,
+                                void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %e into %p (promoting float to double)", value, dest);
+       return avro_double_set(dest, value);
+}
+
+static int
 try_float(avro_resolver_t **resolver,
          avro_schema_t wschema, avro_schema_t rschema,
          avro_schema_t root_rschema)
@@ -340,6 +351,10 @@ try_float(avro_resolver_t **resolver,
                *resolver = avro_resolver_create(wschema, root_rschema);
                (*resolver)->parent.float_value = avro_resolver_float_value;
        }
+       else if (is_avro_double(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.float_value = 
avro_resolver_float_double_value;
+       }
        return 0;
 }
 
@@ -356,6 +371,39 @@ avro_resolver_int_value(avro_consumer_t 
 }
 
 static int
+avro_resolver_int_long_value(avro_consumer_t *consumer, int32_t value,
+                            void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %" PRId32 " into %p (promoting int to long)", value, 
dest);
+       return avro_int64_set(dest, value);
+}
+
+static int
+avro_resolver_int_double_value(avro_consumer_t *consumer, int32_t value,
+                              void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %" PRId32 " into %p (promoting int to double)", value, 
dest);
+       return avro_double_set(dest, value);
+}
+
+static int
+avro_resolver_int_float_value(avro_consumer_t *consumer, int32_t value,
+                             void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %" PRId32 " into %p (promoting int to float)", value, 
dest);
+       return avro_float_set(dest, value);
+}
+
+static int
 try_int(avro_resolver_t **resolver,
        avro_schema_t wschema, avro_schema_t rschema,
        avro_schema_t root_rschema)
@@ -364,6 +412,18 @@ try_int(avro_resolver_t **resolver,
                *resolver = avro_resolver_create(wschema, root_rschema);
                (*resolver)->parent.int_value = avro_resolver_int_value;
        }
+       else if (is_avro_int64(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.int_value = avro_resolver_int_long_value;
+       }
+       else if (is_avro_double(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.int_value = avro_resolver_int_double_value;
+       }
+       else if (is_avro_float(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.int_value = avro_resolver_int_float_value;
+       }
        return 0;
 }
 
@@ -380,6 +440,28 @@ avro_resolver_long_value(avro_consumer_t
 }
 
 static int
+avro_resolver_long_float_value(avro_consumer_t *consumer, int64_t value,
+                              void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %" PRId64 " into %p (promoting long to float)", value, 
dest);
+       return avro_float_set(dest, value);
+}
+
+static int
+avro_resolver_long_double_value(avro_consumer_t *consumer, int64_t value,
+                               void *user_data)
+{
+       avro_resolver_t  *resolver = (avro_resolver_t *) consumer;
+       avro_datum_t  ud_dest = user_data;
+       avro_datum_t  dest = avro_resolver_get_real_dest(resolver, ud_dest);
+       debug("Storing %" PRId64 " into %p (promoting long to double)", value, 
dest);
+       return avro_double_set(dest, value);
+}
+
+static int
 try_long(avro_resolver_t **resolver,
         avro_schema_t wschema, avro_schema_t rschema,
         avro_schema_t root_rschema)
@@ -388,6 +470,14 @@ try_long(avro_resolver_t **resolver,
                *resolver = avro_resolver_create(wschema, root_rschema);
                (*resolver)->parent.long_value = avro_resolver_long_value;
        }
+       else if (is_avro_double(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.long_value = 
avro_resolver_long_double_value;
+       }
+       else if (is_avro_float(rschema)) {
+               *resolver = avro_resolver_create(wschema, root_rschema);
+               (*resolver)->parent.long_value = avro_resolver_long_float_value;
+       }
        return 0;
 }
 

Modified: avro/trunk/lang/c/src/schema.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/schema.c?rev=1074614&r1=1074613&r2=1074614&view=diff
==============================================================================
--- avro/trunk/lang/c/src/schema.c (original)
+++ avro/trunk/lang/c/src/schema.c Fri Feb 25 16:19:42 2011
@@ -1333,9 +1333,9 @@ const char *avro_schema_type_name(const 
  } else if (is_avro_map(schema)) {
    return "map";
  } else if (is_avro_int32(schema)) {
-   return "int32";
+   return "int";
  } else if (is_avro_int64(schema)) {
-   return "int64";
+   return "long";
  } else if (is_avro_float(schema)) {
    return "float";
  } else if (is_avro_double(schema)) {

Modified: avro/trunk/lang/c/tests/test_avro_data.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/test_avro_data.c?rev=1074614&r1=1074613&r2=1074614&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/test_avro_data.c (original)
+++ avro/trunk/lang/c/tests/test_avro_data.c Fri Feb 25 16:19:42 2011
@@ -83,8 +83,8 @@ int32_t rand_int32(void)
 }
 
 void
-write_read_check(avro_schema_t writers_schema,
-                avro_schema_t readers_schema, avro_datum_t datum, char *type)
+write_read_check(avro_schema_t writers_schema, avro_datum_t datum,
+                avro_schema_t readers_schema, avro_datum_t expected, char 
*type)
 {
        avro_datum_t datum_out;
        int validate;
@@ -94,6 +94,10 @@ write_read_check(avro_schema_t writers_s
                reader = avro_reader_memory(buf, sizeof(buf));
                writer = avro_writer_memory(buf, sizeof(buf));
 
+               if (!expected) {
+                       expected = datum;
+               }
+
                /* Validating read/write */
                if (avro_write_data
                    (writer, validate ? writers_schema : NULL, datum)) {
@@ -117,7 +121,7 @@ write_read_check(avro_schema_t writers_s
                        fprintf(stderr, "  %s\n", avro_strerror());
                        exit(EXIT_FAILURE);
                }
-               if (!avro_datum_equal(datum, datum_out)) {
+               if (!avro_datum_equal(expected, datum_out)) {
                        fprintf(stderr,
                                "Unable to encode/decode %s validate=%d\n",
                                type, validate);
@@ -153,7 +157,7 @@ static int test_string(void)
        avro_schema_t writer_schema = avro_schema_string();
        for (i = 0; i < sizeof(strings) / sizeof(strings[0]); i++) {
                avro_datum_t datum = avro_givestring(strings[i], NULL);
-               write_read_check(writer_schema, NULL, datum, "string");
+               write_read_check(writer_schema, datum, NULL, NULL, "string");
                avro_datum_decref(datum);
        }
 
@@ -180,7 +184,7 @@ static int test_bytes(void)
        avro_datum_t expected_datum;
 
        datum = avro_givebytes(bytes, sizeof(bytes), NULL);
-       write_read_check(writer_schema, NULL, datum, "bytes");
+       write_read_check(writer_schema, datum, NULL, NULL, "bytes");
        test_json(datum, "\"\\u00de\\u00ad\\u00be\\u00ef\"");
        avro_datum_decref(datum);
        avro_schema_decref(writer_schema);
@@ -211,10 +215,26 @@ static int test_int32(void)
 {
        int i;
        avro_schema_t writer_schema = avro_schema_int();
+       avro_schema_t long_schema = avro_schema_long();
+       avro_schema_t float_schema = avro_schema_float();
+       avro_schema_t double_schema = avro_schema_double();
        for (i = 0; i < 100; i++) {
-               avro_datum_t datum = avro_int32(rand_int32());
-               write_read_check(writer_schema, NULL, datum, "int");
+               int32_t  value = rand_int32();
+               avro_datum_t datum = avro_int32(value);
+               avro_datum_t long_datum = avro_int64(value);
+               avro_datum_t float_datum = avro_float(value);
+               avro_datum_t double_datum = avro_double(value);
+               write_read_check(writer_schema, datum, NULL, NULL, "int");
+               write_read_check(writer_schema, datum,
+                                long_schema, long_datum, "int->long");
+               write_read_check(writer_schema, datum,
+                                float_schema, float_datum, "int->float");
+               write_read_check(writer_schema, datum,
+                                double_schema, double_datum, "int->double");
                avro_datum_decref(datum);
+               avro_datum_decref(long_datum);
+               avro_datum_decref(float_datum);
+               avro_datum_decref(double_datum);
        }
 
        avro_datum_t  datum = avro_int32(10000);
@@ -222,6 +242,9 @@ static int test_int32(void)
        avro_datum_decref(datum);
 
        avro_schema_decref(writer_schema);
+       avro_schema_decref(long_schema);
+       avro_schema_decref(float_schema);
+       avro_schema_decref(double_schema);
        return 0;
 }
 
@@ -229,10 +252,21 @@ static int test_int64(void)
 {
        int i;
        avro_schema_t writer_schema = avro_schema_long();
+       avro_schema_t float_schema = avro_schema_float();
+       avro_schema_t double_schema = avro_schema_double();
        for (i = 0; i < 100; i++) {
-               avro_datum_t datum = avro_int64(rand_int64());
-               write_read_check(writer_schema, NULL, datum, "long");
+               int64_t  value = rand_int64();
+               avro_datum_t datum = avro_int64(value);
+               avro_datum_t float_datum = avro_float(value);
+               avro_datum_t double_datum = avro_double(value);
+               write_read_check(writer_schema, datum, NULL, NULL, "long");
+               write_read_check(writer_schema, datum,
+                                float_schema, float_datum, "long->float");
+               write_read_check(writer_schema, datum,
+                                double_schema, double_datum, "long->double");
                avro_datum_decref(datum);
+               avro_datum_decref(float_datum);
+               avro_datum_decref(double_datum);
        }
 
        avro_datum_t  datum = avro_int64(10000);
@@ -240,6 +274,8 @@ static int test_int64(void)
        avro_datum_decref(datum);
 
        avro_schema_decref(writer_schema);
+       avro_schema_decref(float_schema);
+       avro_schema_decref(double_schema);
        return 0;
 }
 
@@ -249,7 +285,7 @@ static int test_double(void)
        avro_schema_t schema = avro_schema_double();
        for (i = 0; i < 100; i++) {
                avro_datum_t datum = avro_double(rand_number(-1.0E10, 1.0E10));
-               write_read_check(schema, NULL, datum, "double");
+               write_read_check(schema, datum, NULL, NULL, "double");
                avro_datum_decref(datum);
        }
 
@@ -265,10 +301,16 @@ static int test_float(void)
 {
        int i;
        avro_schema_t schema = avro_schema_float();
+       avro_schema_t double_schema = avro_schema_double();
        for (i = 0; i < 100; i++) {
-               avro_datum_t datum = avro_float(rand_number(-1.0E10, 1.0E10));
-               write_read_check(schema, NULL, datum, "float");
+               float  value = rand_number(-1.0E10, 1.0E10);
+               avro_datum_t datum = avro_float(value);
+               avro_datum_t double_datum = avro_double(value);
+               write_read_check(schema, datum, NULL, NULL, "float");
+               write_read_check(schema, datum,
+                                double_schema, double_datum, "float->double");
                avro_datum_decref(datum);
+               avro_datum_decref(double_datum);
        }
 
        avro_datum_t  datum = avro_float(2000.0);
@@ -276,6 +318,7 @@ static int test_float(void)
        avro_datum_decref(datum);
 
        avro_schema_decref(schema);
+       avro_schema_decref(double_schema);
        return 0;
 }
 
@@ -286,7 +329,7 @@ static int test_boolean(void)
        avro_schema_t schema = avro_schema_boolean();
        for (i = 0; i <= 1; i++) {
                avro_datum_t datum = avro_boolean(i);
-               write_read_check(schema, NULL, datum, "boolean");
+               write_read_check(schema, datum, NULL, NULL, "boolean");
                test_json(datum, expected_json[i]);
                avro_datum_decref(datum);
        }
@@ -298,7 +341,7 @@ static int test_null(void)
 {
        avro_schema_t schema = avro_schema_null();
        avro_datum_t datum = avro_null();
-       write_read_check(schema, NULL, datum, "null");
+       write_read_check(schema, datum, NULL, NULL, "null");
        test_json(datum, "null");
        avro_datum_decref(datum);
        return 0;
@@ -319,7 +362,7 @@ static int test_record(void)
        avro_record_set(datum, "name", name_datum);
        avro_record_set(datum, "age", age_datum);
 
-       write_read_check(schema, NULL, datum, "record");
+       write_read_check(schema, datum, NULL, NULL, "record");
        test_json(datum, "{\"name\": \"Joseph Campbell\", \"age\": 83}");
 
        int  rc;
@@ -367,7 +410,7 @@ static int test_enum(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, datum, "enum");
+       write_read_check(schema, datum, NULL, NULL, "enum");
        test_json(datum, "\"C\"");
 
        avro_enum_set(datum, AVRO_CPP);
@@ -376,7 +419,7 @@ static int test_enum(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, datum, "enum");
+       write_read_check(schema, datum, NULL, NULL, "enum");
        test_json(datum, "\"C++\"");
 
        avro_enum_set_name(datum, "Python");
@@ -385,7 +428,7 @@ static int test_enum(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, datum, "enum");
+       write_read_check(schema, datum, NULL, NULL, "enum");
        test_json(datum, "\"Python\"");
 
        avro_datum_decref(datum);
@@ -413,7 +456,7 @@ static int test_array(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, datum, "array");
+       write_read_check(schema, datum, NULL, NULL, "array");
        test_json(datum, "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
        avro_datum_decref(datum);
        avro_schema_decref(schema);
@@ -451,7 +494,7 @@ static int test_map(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, datum, "map");
+       write_read_check(schema, datum, NULL, NULL, "map");
        test_json(datum,
                  "{\"zero\": 0, \"one\": 1, \"two\": 2, \"three\": 3, "
                  "\"four\": 4, \"five\": 5, \"six\": 6}");
@@ -494,7 +537,7 @@ static int test_union(void)
                exit(EXIT_FAILURE);
        }
 
-       write_read_check(schema, NULL, union_datum, "union");
+       write_read_check(schema, union_datum, NULL, NULL, "union");
        test_json(union_datum, "{\"string\": \"Follow your bliss.\"}");
 
        avro_datum_decref(datum);
@@ -516,7 +559,7 @@ static int test_fixed(void)
        avro_datum_t expected_datum;
 
        datum = avro_givefixed(schema, bytes, sizeof(bytes), NULL);
-       write_read_check(schema, NULL, datum, "fixed");
+       write_read_check(schema, datum, NULL, NULL, "fixed");
        test_json(datum, "\"\\r\\n\\r\\n\\u000b\\n\\u000b\\n\"");
        avro_datum_decref(datum);
 


Reply via email to