[glom] Python calculations: Really convert to expected types.



commit af79b02df611d5324af80404be62b6cc43ccf114
Author: Murray Cumming <murrayc murrayc com>
Date:   Sun May 2 23:36:52 2010 +0200

    Python calculations: Really convert to expected types.
    
    * glom/libglom/data_structure/glomconversions.cc:
    get_double_for_gda_value_numeric(): Handle all numeric GTypes - not just
    G_TYPE_INT..
    convert_value(): Remove the special case for G_TYPE_INT (now handled in
    get_double_for_gda_value_numeric instead). Make sure that all numeric GTypes
    are converted to GDA_TYPE_NUMERIC, making it easier for callers to check.

 ChangeLog                                          |   13 +++-
 glom/libglom/data_structure/glomconversions.cc     |   76 ++++++++++++++------
 .../test_python_execute_func_change_result_type.cc |    4 +-
 3 files changed, 69 insertions(+), 24 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b8e954f..259a4f9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-05-02  Murray Cumming  <murrayc murrayc-x61>
+
+	Python calculations: Really convert to expected types.
+	
+	* glom/libglom/data_structure/glomconversions.cc: 
+	get_double_for_gda_value_numeric(): Handle all numeric GTypes - not just 
+	G_TYPE_INT..
+	convert_value(): Remove the special case for G_TYPE_INT (now handled in 
+	get_double_for_gda_value_numeric instead). Make sure that all numeric GTypes 
+	are converted to GDA_TYPE_NUMERIC, making it easier for callers to check.
+
 2010-05-01  Murray Cumming  <murrayc murrayc com>
 
 	Add test of type conversion after python calculations.
@@ -9,7 +20,7 @@
 
 2010-05-01  Murray Cumming  <murrayc murrayc com>
 
-	Python scripts and calcuations: Test buttons now show python errors.
+	Python scripts and calculations: Test buttons now show python errors.
 	
 	* glom/python_embed/glom_python.[h|cc]: 
 	glom_execute_python_function_implementation(), 
diff --git a/glom/libglom/data_structure/glomconversions.cc b/glom/libglom/data_structure/glomconversions.cc
index 7bf57a9..ff4fe06 100644
--- a/glom/libglom/data_structure/glomconversions.cc
+++ b/glom/libglom/data_structure/glomconversions.cc
@@ -292,16 +292,32 @@ Glib::ustring Conversions::get_text_for_gda_value(Field::glom_field_type glom_ty
 
 double Conversions::get_double_for_gda_value_numeric(const Gnome::Gda::Value& value)
 {
-  if(value.get_value_type() != GDA_TYPE_NUMERIC)
+  const GType vtype = value.get_value_type();
+  if(vtype != GDA_TYPE_NUMERIC)
   {
     // Note that in case the database system does not support GdaNumeric
     // (such as sqlite) we fall back to double (see
     // FieldTypes::get_string_name_for_gdavaluetype), so try this as well.
-    if(value.get_value_type() == G_TYPE_DOUBLE)
-      return value.get_double();
-
-    std::cerr << "Conversions::get_double_for_gda_value_numeric(): expected NUMERIC but GdaValue type is: " << g_type_name(value.get_value_type()) << std::endl;
-    return 0;
+    switch(vtype)
+    {
+      case G_TYPE_DOUBLE:
+        return value.get_double();
+      case G_TYPE_INT:
+        return value.get_int();
+      case G_TYPE_UINT:
+        return value.get_uint();
+      //case G_TYPE_LONG:
+      //TODO: Add this to libgdamm:  return value.get_long();
+      case G_TYPE_ULONG:
+        return value.get_ulong();
+      case G_TYPE_INT64:
+        return value.get_int64();
+      case G_TYPE_UINT64:
+        return value.get_uint64();
+      default:
+        std::cerr << "Conversions::get_double_for_gda_value_numeric(): expected NUMERIC but GdaValue type is: " << g_type_name(value.get_value_type()) << std::endl;
+        return 0;
+    }
   }
 
   const GdaNumeric* gda_numeric = value.get_numeric();
@@ -972,29 +988,47 @@ Gnome::Gda::Value Conversions::get_example_value(Field::glom_field_type field_ty
   }
 }
 
-Gnome::Gda::Value Conversions::convert_value(const Gnome::Gda::Value& value, Field::glom_field_type target_glom_type)
+static bool vtype_is_numeric(GType vtype)
 {
-  const GType gvalue_type = value.get_value_type();
-
-  //A special case (only used for serial keys)
-  //Always convert these.
-  if(gvalue_type == G_TYPE_INT)
+  switch(vtype)
   {
-    const gint num = value.get_int();
-    return parse_value(num);
+    case G_TYPE_DOUBLE:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+    case G_TYPE_LONG:
+    case G_TYPE_ULONG:
+    case G_TYPE_INT64:
+    case G_TYPE_UINT64:
+      return true;
+    default:
+      return false;
   }
+}
 
-  const Field::glom_field_type source_glom_type = Field::get_glom_type_for_gda_type(gvalue_type);
+Gnome::Gda::Value Conversions::convert_value(const Gnome::Gda::Value& value, Field::glom_field_type target_glom_type)
+{
+  const GType gvalue_type_target = Field::get_gda_type_for_glom_type(target_glom_type);
+  const GType gvalue_type_source = value.get_value_type();
+  if(gvalue_type_source == gvalue_type_target)
+    return value; //No conversion necessary, and no loss of precision.
+  
+  const Field::glom_field_type source_glom_type = Field::get_glom_type_for_gda_type(gvalue_type_source);
   if(source_glom_type == target_glom_type)
-    return value; //No conversion necessary.
-  else
   {
-    const Glib::ustring text = get_text_for_gda_value(source_glom_type, value);
-    bool test = false;
-    return parse_value(target_glom_type, text, test, true /* iso_format */);
+    //Try to return the canonical type, 
+    //instead of just something of a similar GType:
+    if((target_glom_type == Field::TYPE_NUMERIC) && 
+      (vtype_is_numeric(gvalue_type_source)))
+    {
+      const double number = get_double_for_gda_value_numeric(value);
+      return parse_value(number);
+    }
   }
 
-  return value;
+  //Fallback for other conversions:
+  const Glib::ustring text = get_text_for_gda_value(source_glom_type, value);
+  bool test = false;
+  return parse_value(target_glom_type, text, test, true /* iso_format */);
 }
 
 } //namespace Glom
diff --git a/tests/test_python_execute_func_change_result_type.cc b/tests/test_python_execute_func_change_result_type.cc
index 2d32f8a..720cd14 100644
--- a/tests/test_python_execute_func_change_result_type.cc
+++ b/tests/test_python_execute_func_change_result_type.cc
@@ -37,7 +37,7 @@ int main()
     return EXIT_FAILURE;
   }
 
-  std::cout << "type=" << g_type_name(value.get_value_type()) << std::endl;
+  //std::cout << "type=" << g_type_name(value.get_value_type()) << std::endl;
 
   //Check that there was no python error:
   g_assert(error_message.empty());
@@ -47,7 +47,7 @@ int main()
 
   //Check that the return value is of the expected value:
   const Glib::ustring text = value.get_string();
-  std::cout << "text=" << text << std::endl;
+  //std::cout << "text=" << text << std::endl;
   g_assert(text == "4950"); //This should always be as per ISO, not according to the user's locale, because it's generally passed to the database. Presentation is separate to calculation or storage.
 
   //std::cout << "value=" << value.to_string() << std::endl;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]