glom r1762 - in trunk: . glom glom/libglom glom/libglom/connectionpool_backends glom/libglom/data_structure glom/utility_widgets



Author: arminb
Date: Fri Nov 28 16:55:06 2008
New Revision: 1762
URL: http://svn.gnome.org/viewvc/glom?rev=1762&view=rev

Log:
2008-11-28  Armin Burgmeier  <armin openismus com>

	* glom/libglom/data_structure/field.h:
	* glom/libglom/data_structure/field.cc: Added a sql_format
	enumeration, and added a format paramater to sql() and from_sql().
	This is needed for sqlite because it does not understand the
	E'binarydata'::bytea representation for binary data, which is a
	postgres extension.

	* glom/libglom/connectionpool.h:
	* glom/libglom/connectionpool.cc:
	* glom/libglom/connectionpool_backends/postgres_central.h:
	* glom/libglom/connectionpool_backends/postgres_self.h:
	* glom/libglom/connectionpool_backends/sqlite.h: Added a
	get_sql_format() virtual method that returns the SQL format of the
	backend.

	* glom/libglom/data_structure/fieldtypes.cc
	(get_string_name_for_gdavaluetype): Added some fallbacks for types
	sqlite does not support. This means we are storing numerics as
	doubles, and dates and times as strings in sqlite.

	* glom/libglom/data_structure/glomconversions.cc
	(get_double_for_gda_value_numeric): Handle the value being a double,
	since we use this when the database system doesn't has a "numeric"
	type.

	* glom/dialog_import_csv.cc:
	* glom/dialog_import_csv_progress.cc:
	* glom/frame_glom.cc: Export/Import data always in postgres format,
	because this is what we used to do.

	* glom/base_db.cc (add_standard_groups): Make this a no-op in case the
	database system doesn't support users.
	(insert_example_data): Convert data from the example file from
	postgres format to the format the current database backend uses before
	importing.
	(count_rows_returned_by): For sqlite the result of the SELECT COUNT
	query is int, not int64, so handle that case as well.

	* glom/glom_privs.cc (get_current_privs): Assume we have all possible
	privileges in case the database system doesn't support users.

	* glom/utility_widgets/filechooserdialog_saveextras.cc
	(set_extra_newdb_hosting_mode): Fixed central hosting/self hosting
	mismatch (the default option in the dialog was wrong).


Modified:
   trunk/ChangeLog
   trunk/glom/application.cc
   trunk/glom/base_db.cc
   trunk/glom/dialog_import_csv.cc
   trunk/glom/dialog_import_csv_progress.cc
   trunk/glom/frame_glom.cc
   trunk/glom/glom_privs.cc
   trunk/glom/libglom/connectionpool.cc
   trunk/glom/libglom/connectionpool.h
   trunk/glom/libglom/connectionpool_backends/postgres_central.h
   trunk/glom/libglom/connectionpool_backends/postgres_self.h
   trunk/glom/libglom/connectionpool_backends/sqlite.h
   trunk/glom/libglom/data_structure/field.cc
   trunk/glom/libglom/data_structure/field.h
   trunk/glom/libglom/data_structure/fieldtypes.cc
   trunk/glom/libglom/data_structure/glomconversions.cc
   trunk/glom/utility_widgets/filechooserdialog_saveextras.cc

Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc	(original)
+++ trunk/glom/application.cc	Fri Nov 28 16:55:06 2008
@@ -1976,7 +1976,7 @@
 #ifdef GLOM_ENABLE_MAEMO
   //TODO: Put the browse button on the initial dialog for Maemo, 
   //because Hildon::FileChooserDialog does not allow extra widgets.
-  Hildon::FileChooserDialog fileChooser_Open(Gtk::FILE_CHOOSER_ACTION_OPEN));
+  Hildon::FileChooserDialog fileChooser_Open(Gtk::FILE_CHOOSER_ACTION_OPEN);
 #else
   Gtk::FileChooserDialog fileChooser_Open(gettext("Open Document"), Gtk::FILE_CHOOSER_ACTION_OPEN);
   fileChooser_Open.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);

Modified: trunk/glom/base_db.cc
==============================================================================
--- trunk/glom/base_db.cc	(original)
+++ trunk/glom/base_db.cc	Fri Nov 28 16:55:06 2008
@@ -729,54 +729,74 @@
   //Add the glom_developer group if it does not exist:
   const Glib::ustring devgroup = GLOM_STANDARD_GROUP_NAME_DEVELOPER;
 
-  const type_vecStrings vecGroups = Privs::get_database_groups();
-  type_vecStrings::const_iterator iterFind = std::find(vecGroups.begin(), vecGroups.end(), devgroup);
-  if(iterFind == vecGroups.end())
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  sharedptr<SharedConnection> sharedconnection = connect_to_server();
+#else
+  std::auto_ptr<ExceptionConnection> error;
+  sharedptr<SharedConnection> sharedconnection = connect_to_server(0, error);
+  if(error.get())
   {
-    bool test = query_execute("CREATE GROUP \"" GLOM_STANDARD_GROUP_NAME_DEVELOPER "\"");
-    if(!test)
-    {
-      std::cerr << "Glom Base_DB::add_standard_groups(): CREATE GROUP failed when adding the developer group." << std::endl;
-      return false;
-    }
+    g_warning("Base_DB::add_standard_groups: Failed to connect: %s", error->what());
+    // TODO: Rethrow? 
+  }
+#endif
 
-    //Make sure the current user is in the developer group.
-    //(If he is capable of creating these groups then he is obviously a developer, and has developer rights on the postgres server.)
-    const Glib::ustring current_user = ConnectionPool::get_instance()->get_user();
-    Glib::ustring strQuery = "ALTER GROUP \"" GLOM_STANDARD_GROUP_NAME_DEVELOPER "\" ADD USER \"" + current_user + "\"";
-    test = query_execute(strQuery);
-    if(!test)
+  // If the connection doesn't support users we can skip this step
+  if(sharedconnection->get_gda_connection()->supports_feature(Gnome::Gda::CONNECTION_FEATURE_USERS))
+  {
+    const type_vecStrings vecGroups = Privs::get_database_groups();
+    type_vecStrings::const_iterator iterFind = std::find(vecGroups.begin(), vecGroups.end(), devgroup);
+    if(iterFind == vecGroups.end())
     {
-      std::cerr << "Glom Base_DB::add_standard_groups(): ALTER GROUP failed when adding the user to the developer group." << std::endl;
-      return false;
-    }
+      bool test = query_execute("CREATE GROUP \"" GLOM_STANDARD_GROUP_NAME_DEVELOPER "\"");
+      if(!test)
+      {
+        std::cerr << "Glom Base_DB::add_standard_groups(): CREATE GROUP failed when adding the developer group." << std::endl;
+        return false;
+      }
 
-    std::cout << "DEBUG: Added user " << current_user << " to glom developer group on postgres server." << std::endl;
+      //Make sure the current user is in the developer group.
+      //(If he is capable of creating these groups then he is obviously a developer, and has developer rights on the postgres server.)
+      const Glib::ustring current_user = ConnectionPool::get_instance()->get_user();
+      Glib::ustring strQuery = "ALTER GROUP \"" GLOM_STANDARD_GROUP_NAME_DEVELOPER "\" ADD USER \"" + current_user + "\"";
+      test = query_execute(strQuery);
+      if(!test)
+      {
+        std::cerr << "Glom Base_DB::add_standard_groups(): ALTER GROUP failed when adding the user to the developer group." << std::endl;
+        return false;
+      }
 
-    Privileges priv_devs;
-    priv_devs.m_view = true;
-    priv_devs.m_edit = true;
-    priv_devs.m_create = true;
-    priv_devs.m_delete = true;
+      std::cout << "DEBUG: Added user " << current_user << " to glom developer group on postgres server." << std::endl;
 
-    Document_Glom::type_listTableInfo table_list = get_document()->get_tables(true /* including system prefs */);
+      Privileges priv_devs;
+      priv_devs.m_view = true;
+      priv_devs.m_edit = true;
+      priv_devs.m_create = true;
+      priv_devs.m_delete = true;
 
-    for(Document_Glom::type_listTableInfo::const_iterator iter = table_list.begin(); iter != table_list.end(); ++iter)
-    {
-      sharedptr<const TableInfo> table_info = *iter;
-      if(table_info)
+      Document_Glom::type_listTableInfo table_list = get_document()->get_tables(true /* including system prefs */);
+
+      for(Document_Glom::type_listTableInfo::const_iterator iter = table_list.begin(); iter != table_list.end(); ++iter)
       {
-        const Glib::ustring table_name = table_info->get_name();
-        if(get_table_exists_in_database(table_name)) //Maybe the table has not been created yet.
-          Privs::set_table_privileges(devgroup, table_name, priv_devs, true /* developer privileges */);
+        sharedptr<const TableInfo> table_info = *iter;
+        if(table_info)
+        {
+          const Glib::ustring table_name = table_info->get_name();
+          if(get_table_exists_in_database(table_name)) //Maybe the table has not been created yet.
+            Privs::set_table_privileges(devgroup, table_name, priv_devs, true /* developer privileges */);
+        }
       }
-    }
 
-    //Make sure that it is in the database too:
-    GroupInfo group_info;
-    group_info.set_name(GLOM_STANDARD_GROUP_NAME_DEVELOPER);
-    group_info.m_developer = true;
-    get_document()->set_group(group_info);
+      //Make sure that it is in the database too:
+      GroupInfo group_info;
+      group_info.set_name(GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+      group_info.m_developer = true;
+      get_document()->set_group(group_info);
+    }
+  }
+  else
+  {
+    std::cout << "DEBUG: Connection does not support users" << std::endl;
   }
 
   return true;
@@ -1208,6 +1228,8 @@
     strNames += "\"" + (*iter)->get_name() + "\"";
   }
 
+  const ConnectionPool* connection_pool = ConnectionPool::get_instance();
+
   if(strNames.empty())
   {
     g_warning("Base_DB::insert_example_data(): strNames is empty.");
@@ -1234,9 +1256,37 @@
 	{
           //Do not allow any unescaped newlines in the row data.
           //Note that this is checking for newlines ("\n"), not escaped newlines ("\\n").
+          Glib::ustring converted_row_data;
+          const Glib::ustring* actual_row_data = &row_data;
           if(row_data.find("\n") == Glib::ustring::npos) 
           {
-            const Glib::ustring strQuery = "INSERT INTO \"" + table_name + "\" (" + strNames + ") VALUES (" + row_data + ")";
+            // All data is stored in postgres format in the examples file
+            // (for historical reasons). Convert to the format the backend
+            // requires, if necessary.
+            if(connection_pool->get_sql_format() != Field::SQL_FORMAT_POSTGRES)
+            {
+              for(unsigned int i = 0; i < vec_values.size(); ++i)
+              {
+                if(i > 0)
+                  converted_row_data += ", ";
+                // If there are more fields than data values, then simply
+                // omit the excess values.
+                if(i >= vec_fields.size())
+                  break;
+
+                bool success;
+                const Gnome::Gda::Value value = vec_fields[i]->from_sql(vec_values[i], Field::SQL_FORMAT_POSTGRES, success);
+
+		if(success)
+                  converted_row_data += vec_fields[i]->sql(value, connection_pool->get_sql_format());
+		else
+		  converted_row_data += "''";
+              }
+
+              actual_row_data = &converted_row_data;
+            }
+
+            const Glib::ustring strQuery = "INSERT INTO \"" + table_name + "\" (" + strNames + ") VALUES (" + *actual_row_data + ")";
             //std::cout << "debug: before query: " << strQuery << std::endl;
             if(query_execute(strQuery))
               //std::cout << "debug: after query: " << strQuery << std::endl;
@@ -2754,7 +2804,11 @@
     {
       Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
       //This showed me that this contains a gint64: std::cerr << "DEBUG: value type=" << G_VALUE_TYPE_NAME(value.gobj()) << std::endl;
-      result = (int)value.get_int64();
+      //For sqlite, this is an integer
+      if(value.get_value_type() == G_TYPE_INT64)
+        result = (int)value.get_int64();
+      else
+        result = value.get_int();
     }
   }
   catch(const Glib::Exception& ex)

Modified: trunk/glom/dialog_import_csv.cc
==============================================================================
--- trunk/glom/dialog_import_csv.cc	(original)
+++ trunk/glom/dialog_import_csv.cc	Fri Nov 28 16:55:06 2008
@@ -902,7 +902,8 @@
 
       if(field->get_glom_type() != Field::TYPE_IMAGE)
       {
-        Gnome::Gda::Value value = field->from_sql(orig_text, success);
+        /* Exported data is always stored in postgres format */
+        Gnome::Gda::Value value = field->from_sql(orig_text, Field::SQL_FORMAT_POSTGRES, success);
         
         if(!success) text = _("<Import Failure>");
         else text = Glom::Conversions::get_text_for_gda_value(field->get_glom_type(), value);

Modified: trunk/glom/dialog_import_csv_progress.cc
==============================================================================
--- trunk/glom/dialog_import_csv_progress.cc	(original)
+++ trunk/glom/dialog_import_csv_progress.cc	Fri Nov 28 16:55:06 2008
@@ -143,7 +143,10 @@
     if(field)
     {
       bool success;
-      Gnome::Gda::Value value = field->from_sql(m_data_source->get_data(m_current_row, i), success);
+
+      // We always assume exported data was stored in postgres format, since
+      // we do export it this way.
+      Gnome::Gda::Value value = field->from_sql(m_data_source->get_data(m_current_row, i), Field::SQL_FORMAT_POSTGRES, success);
 
       if(success)
       {

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Fri Nov 28 16:55:06 2008
@@ -435,8 +435,16 @@
     if(document)
     {
       //Check whether the current user has developer privileges:
-      const ConnectionPool* connection_pool = ConnectionPool::get_instance();
-      bool test = Privs::get_user_is_in_group(connection_pool->get_user(), GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+      ConnectionPool* connection_pool = ConnectionPool::get_instance();
+      sharedptr<SharedConnection> sharedconnection = connection_pool->connect();
+
+      // Default to true; if we don't support users, we always have
+      // priviliges to change things in developer mode.
+      bool test = true;
+
+      if(sharedconnection && sharedconnection->get_gda_connection()->supports_feature(Gnome::Gda::CONNECTION_FEATURE_USERS))
+        Privs::get_user_is_in_group(connection_pool->get_user(), GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+
       if(test)
       {
         std::cout << "DEBUG: User=" << connection_pool->get_user() << " _is_ in the developer group on the server." << std::endl;
@@ -597,7 +605,7 @@
               row_string += ",";
 
             //Output data in canonical SQL format, ignoring the user's locale, and ignoring the layout formatting:
-            row_string += layout_item->get_full_field_details()->sql(value);
+            row_string += layout_item->get_full_field_details()->sql(value, Field::SQL_FORMAT_POSTGRES);
 
             //if(layout_item->m_field.get_glom_type() == Field::TYPE_IMAGE) //This is too much data.
             //{
@@ -649,7 +657,7 @@
               row_string += ",";
 
             //Output data in canonical SQL format, ignoring the user's locale, and ignoring the layout formatting:
-            row_string += layout_item->get_full_field_details()->sql(value);
+            row_string += layout_item->get_full_field_details()->sql(value, Field::SQL_FORMAT_POSTGRES);
 
             if(layout_item->get_glom_type() == Field::TYPE_IMAGE) //This is too much data.
             {

Modified: trunk/glom/glom_privs.cc
==============================================================================
--- trunk/glom/glom_privs.cc	(original)
+++ trunk/glom/glom_privs.cc	Fri Nov 28 16:55:06 2008
@@ -338,23 +338,35 @@
   }
   */
 
-  //Get the "true" rights for any groups that the user is in:
-  type_vecStrings groups = get_groups_of_user(current_user);
-  for(type_vecStrings::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
+  sharedptr<SharedConnection> sharedconnection = connection_pool->connect();
+  if(sharedconnection && sharedconnection->get_gda_connection()->supports_feature(Gnome::Gda::CONNECTION_FEATURE_USERS))
   {
-    Privileges privs = get_table_privileges(*iter, table_name);
-
-    if(privs.m_view)
-      result.m_view = true;
-
-    if(privs.m_edit)
-      result.m_edit = true;
-
-    if(privs.m_create)
-      result.m_create = true;
-
-    if(privs.m_delete)
-      result.m_delete = true;
+    //Get the "true" rights for any groups that the user is in:
+    type_vecStrings groups = get_groups_of_user(current_user);
+    for(type_vecStrings::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
+    {
+      Privileges privs = get_table_privileges(*iter, table_name);
+
+      if(privs.m_view)
+        result.m_view = true;
+
+      if(privs.m_edit)
+        result.m_edit = true;
+
+      if(privs.m_create)
+        result.m_create = true;
+
+      if(privs.m_delete)
+        result.m_delete = true;
+    }
+  }
+  else
+  {
+    // If the database doesn't support users we have privileges to do everything
+    result.m_view = true;
+    result.m_edit = true;
+    result.m_create = true;
+    result.m_delete = true;
   }
 
   return result;

Modified: trunk/glom/libglom/connectionpool.cc
==============================================================================
--- trunk/glom/libglom/connectionpool.cc	(original)
+++ trunk/glom/libglom/connectionpool.cc	Fri Nov 28 16:55:06 2008
@@ -427,7 +427,7 @@
 
 Glib::ustring ConnectionPool::get_password() const
 {
-return m_password;
+  return m_password;
 }
 
 Glib::ustring ConnectionPool::get_database() const
@@ -435,6 +435,12 @@
   return m_database;
 }
 
+Field::sql_format ConnectionPool::get_sql_format() const
+{
+  g_assert(m_backend.get());
+  return m_backend->get_sql_format();
+}
+
 const FieldTypes* ConnectionPool::get_field_types() const
 {
   return m_pFieldTypes;

Modified: trunk/glom/libglom/connectionpool.h
==============================================================================
--- trunk/glom/libglom/connectionpool.h	(original)
+++ trunk/glom/libglom/connectionpool.h	Fri Nov 28 16:55:06 2008
@@ -24,6 +24,7 @@
 #include <libgdamm.h>
 #include <glom/libglom/sharedptr.h>
 #include <glom/libglom/data_structure/fieldtypes.h>
+#include <glom/libglom/data_structure/field.h>
 
 #include <memory> // For std::auto_ptr
 
@@ -111,6 +112,10 @@
   /* TODO: Merge create_database() and initialize() into a single function?
    */
 
+  /* This method specifies the format of values in SQL expressions.
+   */
+  virtual Field::sql_format get_sql_format() const = 0;
+
   /* This method is called for one-time initialization of the database
    * storage. No need to implement this function if the data is centrally
    * hosted, not managed by Glom. */
@@ -205,6 +210,7 @@
   Glib::ustring get_password() const;
   Glib::ustring get_database() const;
 
+  Field::sql_format get_sql_format() const;
   const FieldTypes* get_field_types() const;
 
 #if 0

Modified: trunk/glom/libglom/connectionpool_backends/postgres_central.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_central.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_central.h	Fri Nov 28 16:55:06 2008
@@ -66,6 +66,8 @@
   static Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::RefPtr<Gnome::Gda::Client>& client, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, float& postgres_server_version, std::auto_ptr<ExceptionConnection>& error);
 
 protected:
+  virtual Field::sql_format get_sql_format() const { return Field::SQL_FORMAT_POSTGRES; }
+
   virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 
   /** Creates a new database.

Modified: trunk/glom/libglom/connectionpool_backends/postgres_self.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_self.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_self.h	Fri Nov 28 16:55:06 2008
@@ -74,6 +74,8 @@
   static bool install_postgres(Gtk::Window* parent_window);
 
 protected:
+  virtual Field::sql_format get_sql_format() const { return Field::SQL_FORMAT_POSTGRES; }
+
   virtual bool initialize(Gtk::Window* parent_window, const Glib::ustring& initial_username, const Glib::ustring& password);
 
   virtual bool startup(Gtk::Window* parent_window);

Modified: trunk/glom/libglom/connectionpool_backends/sqlite.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/sqlite.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/sqlite.h	Fri Nov 28 16:55:06 2008
@@ -41,6 +41,8 @@
   const std::string& get_database_directory_uri() const;
 
 protected:
+  virtual Field::sql_format get_sql_format() const { return Field::SQL_FORMAT_SQLITE; }
+
   virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 
   /** Creates a new database.

Modified: trunk/glom/libglom/data_structure/field.cc
==============================================================================
--- trunk/glom/libglom/data_structure/field.cc	(original)
+++ trunk/glom/libglom/data_structure/field.cc	Fri Nov 28 16:55:06 2008
@@ -319,7 +319,7 @@
   return result;
 }
 
-Glib::ustring Field::sql(const Gnome::Gda::Value& value) const
+Glib::ustring Field::sql(const Gnome::Gda::Value& value, sql_format format) const
 {
   //g_warning("Field::sql: glom_type=%d", get_glom_type());
 
@@ -403,15 +403,20 @@
         if(buffer && buffer_length > 0)
         {
           //Get the escaped text that represents the binary data:
-	  const std::string escaped_binary_data = Conversions::get_escaped_binary_data((guint8*)buffer, buffer_length);
+          const std::string escaped_binary_data = Conversions::get_escaped_binary_data((guint8*)buffer, buffer_length);
           //Now escape that text (to convert \ to \\, for instance):
-	  //The E prefix indicates ""escape" string constants, which are an extension to the SQL standard"
+          //The E prefix indicates ""escape" string constants, which are an extension to the SQL standard"
           //Otherwise, we get a warning when using large escaped strings:
-          str = "E" + glom_escape_text(escaped_binary_data) /* has quotes */ + "::bytea";
+          if(format == SQL_FORMAT_POSTGRES)
+            str = "E" + glom_escape_text(escaped_binary_data) /* has quotes */ + "::bytea";
+          else
+            str = glom_escape_text(escaped_binary_data);
         }
       }
       else
+      {
         g_warning("Field::sql(): glom_type is TYPE_IMAGE but gda type is not VALUE_TYPE_BINARY");
+      }
 
       break;
     }
@@ -428,7 +433,13 @@
   return str;
 }
 
-Gnome::Gda::Value Field::from_sql(const Glib::ustring& str, bool& success) const
+Glib::ustring Field::sql(const Gnome::Gda::Value& value) const
+{
+  sql_format format = ConnectionPool::get_instance()->get_sql_format();
+  return sql(value, format);
+}
+
+Gnome::Gda::Value Field::from_sql(const Glib::ustring& str, sql_format format, bool& success) const
 {
   success = true;
   switch(m_glom_type)
@@ -467,17 +478,31 @@
       // We operate on the raw std::string since access into the Glib::ustring
       // is expensive, and we only check for ASCII stuff anyway.
       const std::string& raw = str.raw();
-      if(raw.length() >= 10 &&
-         raw.compare(0, 2, "E'") == 0 && raw.compare(raw.length() - 8, 8, "'::bytea") == 0)
-      {
-        std::string unescaped = glom_unescape_text(raw.substr(1, raw.length() - 8));
-        NumericFormat format_ignored; //Because we use ISO format.
-        return Conversions::parse_value(m_glom_type, unescaped, format_ignored, success, true);
-      }
-      else
+
+      switch(format)
       {
-        success = false;
-        return Gnome::Gda::Value();
+      case SQL_FORMAT_POSTGRES:
+        if(raw.length() >= 10 &&
+           raw.compare(0, 2, "E'") == 0 && raw.compare(raw.length() - 8, 8, "'::bytea") == 0)
+        {
+          std::string unescaped = glom_unescape_text(raw.substr(1, raw.length() - 8));
+          NumericFormat format_ignored; //Because we use ISO format.
+          return Conversions::parse_value(m_glom_type, unescaped, format_ignored, success, true);
+        }
+        else
+        {
+          success = false;
+          return Gnome::Gda::Value();
+        }
+      case SQL_FORMAT_SQLITE:
+        {
+          std::string unescaped = glom_unescape_text(raw);
+          NumericFormat format_ignored; //Because we use ISO format.
+          return Conversions::parse_value(m_glom_type, unescaped, format_ignored, success, true);
+        }
+      default:
+        g_assert_not_reached();
+        break;
       }
     }
   default:

Modified: trunk/glom/libglom/data_structure/field.h
==============================================================================
--- trunk/glom/libglom/data_structure/field.h	(original)
+++ trunk/glom/libglom/data_structure/field.h	Fri Nov 28 16:55:06 2008
@@ -71,6 +71,15 @@
 class Field : public TranslatableItem
 {
 public:
+  /* Possible formats when converting from/to SQL representation.
+   * TODO: Maybe we should move the code that does the conversion between gda
+   * type and SQL into the connectionpool backends. */
+  enum sql_format
+  {
+    SQL_FORMAT_POSTGRES,
+    SQL_FORMAT_SQLITE
+  };
+
   enum glom_field_type
   {
     TYPE_INVALID,
@@ -151,17 +160,18 @@
 
   Glib::ustring get_sql_type() const;
 
-  /** Escape the string so that it can be used in a SQL command.
+  /** Escape the value so that it can be used in a SQL command.
    */
-  //Glib::ustring sql(const Glib::ustring& str) const;
+  Glib::ustring sql(const Gnome::Gda::Value& value, sql_format format) const;
 
   /** Escape the value so that it can be used in a SQL command.
+   * Uses the sql_format of the current connectionpool backend.
    */
   Glib::ustring sql(const Gnome::Gda::Value& value) const;
 
   /** Unescape the value again.
    */
-  Gnome::Gda::Value from_sql(const Glib::ustring& str, bool& success) const;
+  Gnome::Gda::Value from_sql(const Glib::ustring& str, sql_format format, bool& success) const;
 
   /** Escape the value so that it can be used in a SQL command for a find.
    */

Modified: trunk/glom/libglom/data_structure/fieldtypes.cc
==============================================================================
--- trunk/glom/libglom/data_structure/fieldtypes.cc	(original)
+++ trunk/glom/libglom/data_structure/fieldtypes.cc	Fri Nov 28 16:55:06 2008
@@ -116,12 +116,21 @@
   type_mapGdaTypesToSchemaStrings::const_iterator iterFind = m_mapGdaTypesToSchemaStrings.find(field_type);
   if(iterFind == m_mapGdaTypesToSchemaStrings.end())
   {
-    g_warning("FieldTypes::get_string_name_for_gdavaluetype(): returning unknowntype for field_type=%ld", static_cast<long>(field_type));
+    // Fallback for a few types if the database system does not support
+    // them directly:
+    if(field_type == GDA_TYPE_NUMERIC)
+      return get_string_name_for_gdavaluetype(G_TYPE_DOUBLE);
+    if(field_type == G_TYPE_DATE)
+      return get_string_name_for_gdavaluetype(G_TYPE_STRING);
+    if(field_type == GDA_TYPE_TIME)
+      return get_string_name_for_gdavaluetype(G_TYPE_STRING);
+
+    g_warning("FieldTypes::get_string_name_for_gdavaluetype(): returning unknowntype for field_type=%ld (%s)", static_cast<long>(field_type), g_type_name(field_type));
 
     g_warning("  possible types are: ");
     for(type_mapGdaTypesToSchemaStrings::const_iterator iter = m_mapGdaTypesToSchemaStrings.begin(); iter != m_mapGdaTypesToSchemaStrings.end(); ++iter)
     {
-      g_warning("    gdatype=%ld, sqltype=%s", static_cast<long>(iter->first), iter->second.c_str());
+      g_warning("    gdatype=%ld (%s), sqltype=%s", static_cast<long>(iter->first), g_type_name(iter->first), iter->second.c_str());
     }
     
     return "unknowntype";

Modified: trunk/glom/libglom/data_structure/glomconversions.cc
==============================================================================
--- trunk/glom/libglom/data_structure/glomconversions.cc	(original)
+++ trunk/glom/libglom/data_structure/glomconversions.cc	Fri Nov 28 16:55:06 2008
@@ -268,6 +268,12 @@
 {
   if(value.get_value_type() != 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;
   }

Modified: trunk/glom/utility_widgets/filechooserdialog_saveextras.cc
==============================================================================
--- trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	(original)
+++ trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	Fri Nov 28 16:55:06 2008
@@ -114,6 +114,7 @@
   m_radiobutton_server_sqlite.set_group(group);
   vbox->pack_start(m_radiobutton_server_sqlite);
   m_radiobutton_server_sqlite.show();
+  m_radiobutton_server_postgres_selfhosted.set_active(true); // Default
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
 
@@ -133,10 +134,10 @@
   switch(mode)
   {
   case Document_Glom::POSTGRES_CENTRAL_HOSTED:
-    m_radiobutton_server_postgres_selfhosted.set_active();
+    m_radiobutton_server_postgres_central.set_active();
     break;
   case Document_Glom::POSTGRES_SELF_HOSTED:
-    m_radiobutton_server_postgres_central.set_active();
+    m_radiobutton_server_postgres_selfhosted.set_active();
     break;
   case Document_Glom::SQLITE_HOSTED:
     m_radiobutton_server_sqlite.set_active();



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