[glom/sqlbuilder2] Use Gnome::Gda::SqlBuilder



commit 27fea3531c4f16972ca9a302bdba8b6c7ba7319e
Author: Murray Cumming <murrayc murrayc com>
Date:   Sat Feb 27 15:17:09 2010 +0100

    Use Gnome::Gda::SqlBuilder
    
    * several files: Use Gnome::Gda::SqlBuilder to simplify query building and to
    make it safer.
    Much of this work was actually by Johannes Schmid for Openismus.

 ChangeLog                                          |    8 +
 glom/base_db.cc                                    |  609 +++++++++++++-------
 glom/base_db.h                                     |   34 +-
 glom/base_db_table_data.cc                         |   30 +-
 glom/base_db_table_data.h                          |    2 +-
 glom/glom_privs.cc                                 |   50 ++-
 glom/libglom/connectionpool_backends/sqlite.cc     |   32 +-
 glom/libglom/python_embed/py_glom_record.cc        |   38 +-
 glom/libglom/python_embed/py_glom_related.cc       |   13 +-
 glom/libglom/python_embed/py_glom_relatedrecord.cc |  184 +++---
 glom/libglom/python_embed/py_glom_relatedrecord.h  |    4 +-
 glom/mode_data/box_data_calendar_related.cc        |   18 +-
 glom/mode_data/box_data_portal.cc                  |   18 +-
 glom/mode_design/dialog_database_preferences.cc    |   39 +-
 glom/mode_design/fields/box_db_table_definition.cc |   26 +-
 glom/report_builder.cc                             |    4 +-
 glom/utility_widgets/db_adddel/db_adddel.cc        |    5 -
 .../utility_widgets/db_adddel/glom_db_treemodel.cc |   14 +-
 18 files changed, 712 insertions(+), 416 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d589430..02dad9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2010-02-27  Murray Cumming  <murrayc murrayc com>
 
+	Use Gnome::Gda::SqlBuilder
+
+	* several files: Use Gnome::Gda::SqlBuilder to simplify query building and to 
+	make it safer.
+	Much of this work was actually by Johannes Schmid for Openismus.
+	
+2010-02-27  Murray Cumming  <murrayc murrayc com>
+
   Increase required version of libgdamm.
   
 	* configure.ac: Increase libgdamm dependency to the last one that doesn't 
diff --git a/glom/base_db.cc b/glom/base_db.cc
index eafcaf2..7e7d421 100644
--- a/glom/base_db.cc
+++ b/glom/base_db.cc
@@ -212,54 +212,108 @@ Glib::RefPtr<Gnome::Gda::DataModel> Base_DB::query_execute_select(const Glib::us
   const App_Glom* app = App_Glom::get_application();
   if(stmt && app && app->get_show_sql_debug())
   {
+    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
+    std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
+  }
+
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-    try
-    {
-      const Glib::ustring full_query = stmt->to_sql(params);
-      std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
-    }
-    catch(const Glib::Exception& ex)
-    {
-      std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
-    }
+  try
+  {
+    result = gda_connection->statement_execute_select(stmt, params);
+  }
+  catch(const Gnome::Gda::ConnectionError& ex)
+  {
+    std::cout << "debug: Base_DB::query_execute_select(): ConnectionError: exception from statement_execute_select(): " << ex.what() << std::endl;
+  }
+  catch(const Gnome::Gda::ServerProviderError& ex)
+  {
+    std::cout << "debug: Base_DB::query_execute_select(): ServerProviderError exception from statement_execute_select(): code=" << ex.code() << ", message=" << ex.what() << std::endl;
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cout << "debug: Base_DB::query_execute_select(): Error exception from statement_execute_select(): " << ex.what() << std::endl;
+  }
 #else
-      const Glib::ustring full_query = stmt->to_sql(params, ex);
-      std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
-      if (ex.get())
-        std::cout << "Debug: query string could not be converted to std::cout: " << ex->what() << std::endl;
+  result = gda_connection->statement_execute_select(stmt, params, ex);
+  if(ex.get())
+    std::cout << "debug: Base_DB::query_execute_select(): Glib::Error from statement_execute_select(): " << ex->what() << std::endl;
+#endif //GLIBMM_EXCEPTIONS_ENABLED
 
+  if(!result)
+  {
+    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
+    std::cerr << "Glom  Base_DB::query_execute_select(): Error while executing SQL" << std::endl <<
+      "  " <<  full_query << std::endl;
+    handle_error();
+  }
+
+  return result;
+}
+
+//static:
+Glib::RefPtr<Gnome::Gda::DataModel> Base_DB::query_execute_select(const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
+                                                                  const Glib::RefPtr<const Gnome::Gda::Set>& params)
+{
+  Glib::RefPtr<Gnome::Gda::DataModel> result;
+
+  //TODO: BusyCursor busy_cursor(get_app_window());
+
+#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())
+  {
+    g_warning("Base_DB::query_execute_select() failed (query was: %s): %s", strQuery.c_str(), error->what());
+    // TODO: Rethrow?
+  }
 #endif
+  if(!sharedconnection)
+  {
+    std::cerr << "Base_DB::query_execute_select(): No connection yet." << std::endl;
+    return result;
   }
 
+  Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
 
+  //Debug output:
+  const App_Glom* app = App_Glom::get_application();
+  if(app && app->get_show_sql_debug())
+  {
+    const std::string full_query = sqlbuilder_get_full_query(builder, params);
+    std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
+  }
+  
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
   {
-    result = gda_connection->statement_execute_select(stmt, params);
+    result = gda_connection->statement_execute_select_builder(builder, params);
   }
   catch(const Gnome::Gda::ConnectionError& ex)
   {
-    std::cout << "debug: Base_DB::query_execute_select(): ConnectionError: exception from statement_execute_select(): " << ex.what() << std::endl;
+    std::cerr << "debug: Base_DB::query_execute_select(): ConnectionError: exception from statement_execute_select_builder(): " << ex.what() << std::endl;
   }
   catch(const Gnome::Gda::ServerProviderError& ex)
   {
-    std::cout << "debug: Base_DB::query_execute_select(): ServerProviderError: exception from statement_execute_select(): code=" << ex.code() << "message=" << ex.what() << std::endl;
+    std::cerr << "debug: Base_DB::query_execute_select(): ServerProviderError: exception from statement_execute_select_builder(): code=" << ex.code() << "message=" << ex.what() << std::endl;
   }
   catch(const Glib::Error& ex)
   {
-    std::cout << "debug: Base_DB::query_execute_select(): Error: exception from statement_execute_select(): " << ex.what() << std::endl;
+    std::cerr << "debug: Base_DB::query_execute_select(): Error: exception from statement_execute_select_builder(): " << ex.what() << std::endl;
   }
 
 #else
-  result = gda_connection->statement_execute_select(stmt, params, ex);
+  result = gda_connection->statement_execute_select_builder(builder, params, ex);
   if(ex.get())
-    std::cout << "debug: Base_DB::query_execute_select(): Glib::Error from statement_execute_select(): " << ex->what() << std::endl;
+    std::cerr << "debug: Base_DB::query_execute_select(): Glib::Error from statement_execute_select_builder(): " << ex->what() << std::endl;
 #endif //GLIBMM_EXCEPTIONS_ENABLED
 
   if(!result)
   {
-    std::cerr << "Glom  Base_DB::query_execute_select(): Error while executing SQL" << std::endl <<
-      "  " <<  strQuery << std::endl;
+    const std::string full_query = sqlbuilder_get_full_query(builder, params);
+    std::cerr << "Glom  Base_DB::query_execute_select(): Error while executing SQL: " 
+      << std::endl << "  " << full_query << std::endl << std::endl;
     handle_error();
   }
 
@@ -315,24 +369,8 @@ bool Base_DB::query_execute(const Glib::ustring& strQuery,
   const App_Glom* app = App_Glom::get_application();
   if(stmt && app && app->get_show_sql_debug())
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-    try
-    {
-      //TODO: full_query still seems to contain ## parameter names,
-      //though it works for our SELECT queries in query_execute_select():
-      const Glib::ustring full_query = stmt->to_sql(params);
-      std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
-    }
-    catch(const Glib::Exception& ex)
-    {
-      std::cerr << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
-    }
-#else
-    const Glib::ustring full_query = stmt->to_sql(params, sql_error);
+    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
     std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
-    if (sql_error.get())
-      std::cerr << "Debug: query string could not be converted to std::cout: " << sql_error->what() << std::endl;
-#endif
   }
 
 
@@ -345,7 +383,7 @@ bool Base_DB::query_execute(const Glib::ustring& strQuery,
   catch(const Glib::Error& error)
   {
     std::cerr << "BaseDB::query_execute: ConnectionError: " << error.what() << std::endl;
-    const Glib::ustring full_query = stmt->to_sql(params);
+    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
     std::cerr << "  full_query: " << full_query << std::endl;
     return false;
   }
@@ -355,7 +393,66 @@ bool Base_DB::query_execute(const Glib::ustring& strQuery,
   if(exec_error.get())
   {
     std::cerr << "BaseDB::query_execute: ConnectionError: " << exec_error->what() << std::endl;
-    const Glib::ustring full_query = stmt->to_sql(params, exec_error);
+    const std::string full_query = sqlbuilder_get_full_query(gda_connection, stmt, params);
+    std::cerr << "  full_query: " << full_query << std::endl;
+    return false;
+  }
+#endif
+  return (exec_retval >= 0);
+}
+
+//static:
+bool Base_DB::query_execute(const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
+                            const Glib::RefPtr<const Gnome::Gda::Set>& params)
+{
+  #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())
+  {
+    g_warning("Base_DB::query_execute() failed (query was: %s): %s", strQuery.c_str(), error->what());
+    // TODO: Rethrow?
+  }
+#endif
+  if(!sharedconnection)
+  {
+    std::cerr << "Base_DB::query_execute(): No connection yet." << std::endl;
+    return false;
+  }
+
+  Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
+  
+  //Debug output:
+  const App_Glom* app = App_Glom::get_application();
+  if(app && app->get_show_sql_debug())
+  {
+    const std::string full_query = sqlbuilder_get_full_query(builder, params);
+    std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
+  }
+
+
+  int exec_retval = -1;
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+  {
+    exec_retval = gda_connection->statement_execute_non_select_builder(builder, params);
+  }
+  catch(const Glib::Error& error)
+  {
+    std::cerr << "BaseDB::query_execute: ConnectionError: " << error.what() << std::endl;
+    const std::string full_query = sqlbuilder_get_full_query(builder, params);
+    std::cerr << "  full_query: " << full_query << std::endl;
+    return false;
+  }
+#else
+  std::auto_ptr<Glib::Error> exec_error;
+  exec_retval = gda_connection->statement_execute_non_select_builder(builder, params, exec_error);
+  if(exec_error.get())
+  {
+    std::cerr << "BaseDB::query_execute: ConnectionError: " << exec_error->what() << std::endl;
+    const std::string full_query = sqlbuilder_get_full_query(builder, params);
     std::cerr << "  full_query: " << full_query << std::endl;
     return false;
   }
@@ -892,25 +989,34 @@ Gnome::Gda::Value Base_DB::auto_increment_insert_first_if_necessary(const Glib::
     //This should not happen:
     std::cerr << "Glom: Base_DB::auto_increment_insert_first_if_necessary(): The current user may not edit the autoincrements table. Any user who has create rights for a table should have edit rights to the autoincrements table." << std::endl;
   }
-  Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-  params->add_holder("table_name", table_name);
-  params->add_holder("field_name", field_name);
-
-  const Glib::ustring sql_query = "SELECT \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\".\"next_value\" FROM \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\""
-   " WHERE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME "\" = ##table_name::gchararray AND "
-          "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME "\" = ##field_name::gchararray";
 
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query, params);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field("next_value", GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->select_add_target(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_AND,
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME),
+        builder->add_expr(table_name)),
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME),
+        builder->add_expr(field_name))));
+
+  const Glib::RefPtr<const Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
   if(!datamodel || (datamodel->get_n_rows() == 0))
   {
     //Start with zero:
+    builder.reset();
 
     //Insert the row if it's not there.
-    const Glib::ustring sql_query = "INSERT INTO \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\" ("
-      GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME ", " GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME ", " GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE
-      ") VALUES (##table_name::gchararray, ##field_name::gchararray, 0)";
+    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_INSERT);
+    builder->set_table(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+    builder->add_field_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME, table_name);
+    builder->add_field_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME, field_name);
+    builder->add_field_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE, 0);
 
-    const bool test = query_execute(sql_query, params);
+    const bool test = query_execute(builder);
     if(!test)
       std::cerr << "Base_DB::auto_increment_insert_first_if_necessary(): INSERT of new row failed." << std::endl;
 
@@ -944,8 +1050,13 @@ void Base_DB::recalculate_next_auto_increment_value(const Glib::ustring& table_n
   auto_increment_insert_first_if_necessary(table_name, field_name);
 
   //Get the max key value in the database:
-  const Glib::ustring sql_query = "SELECT MAX(\"" + table_name + "\".\"" + field_name + "\") FROM \"" + table_name + "\"";
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  std::list<guint> args;
+  args.push_back(builder->add_id(table_name + "." + field_name));
+  builder->add_field_id(builder->add_function("MAX", args));
+  builder->select_add_target(table_name);
+
+  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
   if(datamodel && datamodel->get_n_rows() && datamodel->get_n_columns())
   {
     //Increment it:
@@ -960,12 +1071,20 @@ void Base_DB::recalculate_next_auto_increment_value(const Glib::ustring& table_n
 
     //Set it in the glom system table:
     const Gnome::Gda::Value next_value = Conversions::parse_value(num_max);
-    const Glib::ustring sql_query = "UPDATE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\" SET "
-      "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE "\" = " + next_value.to_string() + //TODO: Don't use to_string().
-      " WHERE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME "\" = '" + table_name + "' AND "
-      "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME "\" = '" + field_name + "'";
 
-    const bool test = query_execute(sql_query);
+    builder.reset();
+    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+    builder->set_table(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+    builder->add_field_value_as_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE, next_value);
+    builder->set_where(builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_AND,
+                                         builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                                           builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME),
+                                                           builder->add_expr(table_name)),
+                                         builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                                           builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME),
+                                                           builder->add_expr(field_name))));
+
+    const bool test = query_execute(builder);
     if(!test)
       std::cerr << "Base_DB::recalculate_next_auto_increment_value(): UPDATE failed." << std::endl;
   }
@@ -982,16 +1101,18 @@ Gnome::Gda::Value Base_DB::get_next_auto_increment_value(const Glib::ustring& ta
   //Increment the next_value:
   ++num_result;
   const Gnome::Gda::Value next_value = Conversions::parse_value(num_result);
-  Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-  params->add_holder("table_name", table_name);
-  params->add_holder("field_name", field_name);
-  params->add_holder("next_value", next_value);
-  const Glib::ustring sql_query = "UPDATE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\" SET "
-      "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE "\" = ##next_value::gchararray"
-      " WHERE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME "\" = ##table_name::gchararray AND "
-            "\""  GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME "\" = ##field_name::gchararray";
-
-  const bool test = query_execute(sql_query, params);
+
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+  builder->set_table(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->add_field_value_as_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE, next_value);
+  builder->set_where(builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_AND,
+                                       builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                                         builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME),
+                                                         builder->add_expr(table_name)),
+                                       builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                                         builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME),
+                                                         builder->add_expr(field_name))));
+  const bool test = query_execute(builder);
   if(!test)
     std::cerr << "Base_DB::get_next_auto_increment_value(): Increment failed." << std::endl;
 
@@ -1012,27 +1133,34 @@ SystemPrefs Base_DB::get_database_preferences() const
 
   const bool optional_org_logo = get_field_exists_in_database(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME, GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO);
 
-  const Glib::ustring sql_query = "SELECT "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_NAME "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_NAME "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET2 "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_TOWN "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTY "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTRY "\", "
-      "\"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_POSTCODE "\""
-      + Glib::ustring(optional_org_logo ? ", \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO "\"" : "") +
-      " FROM \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\"";
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+        Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_NAME, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_NAME, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET2, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_TOWN, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTY, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTRY, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_POSTCODE, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+
+  if(optional_org_logo)
+  {
+    builder->select_add_field(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO, GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  }
+
+  builder->select_add_target(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
 
   int attempts = 0;
   while(attempts < 2)
   {
     bool succeeded = true;
-    #ifdef GLIBMM_EXCEPTIONS_ENABLED
-    try
+    std::string full_query = sqlbuilder_get_full_query(builder);
+    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
+    if(datamodel && (datamodel->get_n_rows() != 0))
     {
-      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
-      if(datamodel && (datamodel->get_n_rows() != 0))
+      #ifdef GLIBMM_EXCEPTIONS_ENABLED
+      try
       {
         result.m_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(0, 0));
         result.m_org_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(1, 0));
@@ -1047,24 +1175,18 @@ SystemPrefs Base_DB::get_database_preferences() const
         if(optional_org_logo)
           result.m_org_logo = datamodel->get_value_at(8, 0);
       }
-      else
+      catch(const Glib::Exception& ex)
+      {
+        std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
         succeeded = false;
-    }
-    catch(const Glib::Exception& ex)
-    {
-      std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
-      succeeded = false;
-    }
-    catch(const std::exception& ex)
-    {
-      std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
-      succeeded = false;
-    }
-    #else // GLIBMM_EXCEPTIONS_ENABLED
-    std::auto_ptr<Glib::Error> error;
-    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
-    if(datamodel && (datamodel->get_n_rows() != 0))
-    {
+      }
+      catch(const std::exception& ex)
+      {
+        std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
+        succeeded = false;
+      }
+      #else // GLIBMM_EXCEPTIONS_ENABLED
+      std::auto_ptr<Glib::Error> error;
       result.m_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(0, 0, error));
       result.m_org_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(1, 0, error));
       result.m_org_address_street = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(2, 0, error));
@@ -1077,16 +1199,17 @@ SystemPrefs Base_DB::get_database_preferences() const
       //We need to be more clever about these column indexes if we add more new fields:
       if(optional_org_logo)
         result.m_org_logo = datamodel->get_value_at(8, 0, error);
+
+      if(error.get())
+      {
+        std::cerr << "Error: " << error->what() << std::endl;
+        succeeded = false;
+      }
+      #endif
     }
     else
       succeeded = false;
 
-    if (error.get())
-    {
-      std::cerr << "Error: " << error->what() << std::endl;
-      succeeded = false;
-    }
-    #endif
     //Return the result, or try again:
     if(succeeded)
       return result;
@@ -1121,7 +1244,10 @@ bool Base_DB::add_standard_tables() const
       if(test)
       {
         //Add the single record:
-        const bool test = query_execute("INSERT INTO \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\" (\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ID "\") VALUES (1)");
+        Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_INSERT);
+        builder->set_table(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+        builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ID, 1);
+        const bool test = query_execute(builder);
         if(!test)
           std::cerr << "Base_DB::add_standard_tables(): INSERT failed." << std::endl;
 
@@ -1129,7 +1255,13 @@ bool Base_DB::add_standard_tables() const
         const Glib::ustring system_name = get_document()->get_database_title();
         if(!system_name.empty())
         {
-          const bool test = query_execute("UPDATE \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\" SET  " "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_NAME "\" = '" + system_name + "' WHERE \"" GLOM_STANDARD_TABLE_PREFS_FIELD_ID "\" = 1");
+          Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+          builder->set_table(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+          builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_NAME, system_name);
+          builder->set_where(builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                               builder->add_id(GLOM_STANDARD_TABLE_PREFS_FIELD_ID),
+                                               builder->add_expr(1)));
+          const bool test = query_execute(builder);
           if(!test)
             std::cerr << "Base_DB::add_standard_tables(): UPDATE failed." << std::endl;
         }
@@ -1290,37 +1422,26 @@ void Base_DB::set_database_preferences(const SystemPrefs& prefs)
   if(get_userlevel() == AppState::USERLEVEL_DEVELOPER)
     add_standard_tables();
 
-  Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-  params->add_holder("name", prefs.m_name);
-  params->add_holder("street", prefs.m_org_address_street);
-  params->add_holder("street2", prefs.m_org_address_street2);
-  params->add_holder("town", prefs.m_org_address_town);
-  params->add_holder("county", prefs.m_org_address_county);
-  params->add_holder("country", prefs.m_org_address_country);
-  params->add_holder("postcode", prefs.m_org_address_postcode);
-
   //The logo field was introduced in a later version of Glom.
   //If the user is not in developer mode then the new field has not yet been added:
-  Glib::ustring optional_part_logo;
+
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+  builder->set_table(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_NAME, prefs.m_name);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET, prefs.m_org_address_street);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET2, prefs.m_org_address_street2);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_TOWN, prefs.m_org_address_town);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTY, prefs.m_org_address_county);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTRY, prefs.m_org_address_country);
+  builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_POSTCODE, prefs.m_org_address_postcode);
   if(get_field_exists_in_database(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME, GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO))
   {
-    params->add_holder("org_logo", prefs.m_org_logo);
-    optional_part_logo =  "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO "\" = ##org_logo::GDA_TYPE_BINARY, ";
+    builder->add_field_value(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO, prefs.m_org_logo);
   }
-  const Glib::ustring sql_query = "UPDATE \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\" SET "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_NAME "\" = ##name::gchararray, "
-      + optional_part_logo +
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET "\" = ##street::gchararray, "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET2 "\" = ##street2::gchararray, "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_TOWN "\" = ##town::gchararray, "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTY "\" = ##county::gchararray, "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTRY "\" = ##country::gchararray, "
-      "\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_POSTCODE "\" = ##postcode::gchararray"
-      " WHERE \"" GLOM_STANDARD_TABLE_PREFS_FIELD_ID "\" = 1";
-
-  bool test = false;
-  test = query_execute(sql_query, params);
-
+  builder->set_where(builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                       builder->add_id(GLOM_STANDARD_TABLE_PREFS_FIELD_ID),
+                                       builder->add_expr(1)));                                 
+  const bool test = query_execute(builder);
   if(!test)
     std::cerr << "Base_DB::set_database_preferences(): UPDATE failed." << std::endl;
 
@@ -1746,18 +1867,12 @@ bool Base_DB::insert_example_data(const Glib::ustring& table_name) const
 
     //std::cout << "DEBUG: row_data size = " << row_data.size() << ", (fields size= " << vec_fields.size() << " )" << std::endl;
 
-    Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
     ParameterNameGenerator generator;
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_INSERT);
+    builder->set_table(table_name);
+
     for(unsigned int i = 0; i < row_data.size(); ++i) //TODO_Performance: Avoid calling size() so much.
     {
-      //std::cout << "  DEBUG: i=" << i << ", row_data.size()=" << row_data.size() << std::endl;
-
-      if(i > 0)
-      {
-        strVals += ", ";
-        strNames += ", ";
-      }
-
       sharedptr<Field> field = vec_fields[i];
       if(!field)
       {
@@ -1765,35 +1880,21 @@ bool Base_DB::insert_example_data(const Glib::ustring& table_name) const
         break;
       }
 
-      strNames += field->get_name();
-
-      Gnome::Gda::Value value = row_data[i];
-      //std::cout << "  DEBUG: example: field=" << field->get_name() << ", value=" << value.to_string() << std::endl;
-
-      //Add a SQL parameter for the value:
-      guint id = 0;
-      const Field::glom_field_type glom_type = field->get_glom_type();
-      Glib::RefPtr<Gnome::Gda::Holder> holder =
-        Gnome::Gda::Holder::create( Field::get_gda_type_for_glom_type(glom_type),
-          generator.get_next_name(id));
-
-      holder->set_not_null(false);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-      holder->set_value_as_value(value);
-#else
-      std::auto_ptr<Glib::Error> holder_error;
-      holder->set_value_as_value(value, holder_error);
-#endif
-      params->add_holder(holder);
-
-      strVals += "##" + generator.get_name_from_id(id) + "::" + vec_fields[i]->get_gda_type_name();
+      const Gnome::Gda::Value& value = row_data[i];
+      if(!value.is_null()) //TODO: Remove this check when libgda allows this.
+      {
+        /*
+        std::cout << "debug: field=" << field->get_name() << ", value=" << value.to_string() << std::endl;
+        if(value.get_value_type() == GDA_TYPE_NULL)
+          std::cout << "  (GDA_TYPE_NULL)" << std::endl;
+        else
+          std::cout << "  value.get_value_type()=" << value.get_value_type() << std::endl;
+        */
+        builder->add_field_value_as_value(field->get_name(), value);
+      }
     }
-
-    //Create and parse the SQL query:
-    //After this, the Parser will know how many SQL parameters there are in
-    //the query, and allow us to set their values.
-    const Glib::ustring strQuery = "INSERT INTO \"" + table_name + "\" (" + strNames + ") VALUES (" + strVals + ")";
-    insert_succeeded = query_execute(strQuery, params);
+    
+    insert_succeeded = query_execute(builder);
     if(!insert_succeeded)
       break;
   }
@@ -2445,8 +2546,11 @@ void Base_DB::calculate_field_in_all_records(const Glib::ustring& table_name, co
 {
 
   //Get primary key values for every record:
-  const Glib::ustring query = "SELECT \"" + table_name + "\".\"" + primary_key->get_name() + "\" FROM \"" + table_name + "\"";
-  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(query);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(primary_key->get_name(), table_name);
+  builder->select_add_target(table_name);
+
+  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
   if(!data_model || !data_model->get_n_rows() || !data_model->get_n_columns())
   {
     //HandleError();
@@ -2750,19 +2854,19 @@ bool Base_DB::set_field_value_in_database(const LayoutFieldInRecord& layoutfield
   const Glib::ustring field_name = field_in_record.m_field->get_name();
   if(!field_name.empty()) //This should not happen.
   {
-    Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-    params->add_holder(field_in_record.m_field->get_holder(field_value));
-    params->add_holder(field_in_record.m_key->get_holder(field_in_record.m_key_value));
-
-    Glib::ustring strQuery = "UPDATE \"" + field_in_record.m_table_name + "\"";
-    strQuery += " SET \"" + field_in_record.m_field->get_name() + "\" = " + field_in_record.m_field->get_gda_holder_string();
-    strQuery += " WHERE \"" + field_in_record.m_key->get_name() + "\" = " + field_in_record.m_key->get_gda_holder_string();
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+    builder->set_table(field_in_record.m_table_name);
+    builder->add_field_value_as_value(field_in_record.m_field->get_name(), field_value);
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(field_in_record.m_key->get_name()),
+        builder->add_expr_as_value(field_in_record.m_key_value)));
 
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
     try //TODO: The exceptions are probably already handled by query_execute(0.
 #endif
     {
-      const bool test = query_execute(strQuery, params); //TODO: Respond to failure.
+      const bool test = query_execute(builder); //TODO: Respond to failure.
       if(!test)
       {
         std::cerr << "Box_Data::set_field_value_in_database(): UPDATE failed." << std::endl;
@@ -3081,10 +3185,6 @@ void Base_DB::do_lookups(const LayoutFieldInRecord& field_in_record, const Gtk::
 
         //Add it to the database (even if it is not shown in the view)
         set_field_value_in_database(field_in_record_to_set, row, value_converted); //Also does dependent lookups/recalcs.
-        //Glib::ustring strQuery = "UPDATE \"" + m_table_name + "\"";
-        //strQuery += " SET " + field_lookup.get_name() + " = " + field_lookup.sql(value);
-        //strQuery += " WHERE " + primary_key.get_name() + " = " + primary_key.sql(primary_key_value);
-        //query_execute(strQuery);  //TODO: Handle errors
 
         //TODO: Handle lookups triggered by these fields (recursively)? TODO: Check for infinitely looping lookups.
       }
@@ -3147,13 +3247,17 @@ Gnome::Gda::Value Base_DB::get_lookup_value(const Glib::ustring& /* table_name *
   {
     //Convert the value, in case the from and to fields have different types:
     const Gnome::Gda::Value value_to_key_field = Conversions::convert_value(key_value, to_key_field->get_glom_type());
-    Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-    params->add_holder("key", value_to_key_field);
-
-    Glib::ustring strQuery = "SELECT \"" + relationship->get_to_table() + "\".\"" + source_field->get_name() + "\" FROM \"" +  relationship->get_to_table() + "\"";
-    strQuery += " WHERE \"" + to_key_field->get_name() + "\" = ##key::" + to_key_field->get_gda_type_name();
 
-    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery, params);
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+    builder->select_add_field(source_field->get_name(), relationship->get_to_table());
+    builder->select_add_target(relationship->get_to_table());
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(to_key_field->get_name()), //TODO: It would be nice to specify the table here too.
+        builder->add_expr(value_to_key_field)));
+        
+    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
     if(data_model && data_model->get_n_rows())
     {
       //There should be only 1 row. Well, there could be more but we will ignore them.
@@ -3179,15 +3283,16 @@ bool Base_DB::get_field_value_is_unique(const Glib::ustring& table_name, const s
 
   const Glib::ustring table_name_used = field->get_table_used(table_name);
 
-  Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-  sharedptr<const Field> glom_field = field->get_full_field_details();
-  if(glom_field)
-    params->add_holder(glom_field->get_holder(value));
-
-  const Glib::ustring strQuery = "SELECT \"" + table_name_used + "\".\"" + field->get_name() + "\" FROM \"" + table_name_used + "\""
-    " WHERE \"" + field->get_name() + "\" = " + glom_field->get_gda_holder_string();
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(field->get_name(), table_name_used);
+  builder->select_add_target(table_name_used);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+      builder->add_id(field->get_name()), //TODO: It would be nice to specify the table here too.
+      builder->add_expr(value)));
 
-  Glib::RefPtr<const Gnome::Gda::DataModel> data_model = query_execute_select(strQuery, params);
+  Glib::RefPtr<const Gnome::Gda::DataModel> data_model = query_execute_select(builder);
   if(data_model)
   {
     //std::cout << "debug: Base_DB::get_field_value_is_unique(): table_name=" << table_name << ", field name=" << field->get_name() << ", value=" << value.to_string() << ", rows count=" << data_model->get_n_rows() << std::endl;
@@ -3409,6 +3514,13 @@ int Base_DB::count_rows_returned_by(const Glib::ustring& sql_query)
   //Note that the alias is just because the SQL syntax requires it - we get an error if we don't use it.
   //Be careful not to include ORDER BY clauses in this, because that would make it unnecessarily slow:
   const Glib::ustring query_count = "SELECT COUNT (*) FROM (" + sql_query + ") AS glomarbitraryalias";
+  
+  /* TODO: Use SqlBuilder when we discover how to use a sub-query, or when this function can take a Sqlbuilder.
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->add_function("count", builder->add_id("*")); //TODO: Is * allowed here?
+  builder->select_add_target(m_found_set.m_table_name);
+  */
 
   const App_Glom* app = App_Glom::get_application();
   if(app && app->get_show_sql_debug())
@@ -3738,4 +3850,101 @@ Glib::ustring Base_DB::get_active_layout_platform(Document* document)
 }
 
 
+std::string Base_DB::sqlbuilder_get_full_query(
+    const Glib::RefPtr<Gnome::Gda::Connection>& connection, 
+    const Glib::ustring& query,
+    const Glib::RefPtr<const Gnome::Gda::Set>& params)
+{
+  Glib::ustring result = "glom_query_not_parsed";
+  
+  try
+  {
+    Glib::RefPtr<Gnome::Gda::SqlParser> parser = connection->create_parser();
+    if(parser)
+    {
+      Glib::RefPtr<Gnome::Gda::Statement> stmt = parser->parse_string(query);
+      if(stmt)
+        result = stmt->to_sql(params);
+    }
+  }
+  catch(const Glib::Exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while parsing query: " << ex.what() << std::endl;
+  }
+  catch(const std::exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while parsing query: " << ex.what() << std::endl;
+  }
+  
+  //Convert to something that std::cout should be able to handle.
+  const Glib::ScopedPtr<char> buf(g_convert_with_fallback(
+    result.raw().data(), result.raw().size(), 
+    "ISO-8859-1", "UTF-8", 
+    (char*)"?", 
+    0, 0, 0));
+  return std::string(buf.get());
+}
+
+std::string Base_DB::sqlbuilder_get_full_query(
+  const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
+  const Glib::RefPtr<const Gnome::Gda::Set>& params)
+{
+  Glib::ustring result = "glom_query_not_parsed";
+  
+  try
+  {
+    Glib::RefPtr<Gnome::Gda::Statement> stmt = builder->get_statement();
+    if(stmt)
+      result = stmt->to_sql(params);
+  }
+  catch(const Glib::Exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while getting query: " << ex.what() << std::endl;
+  }
+  catch(const std::exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while getting query: " << ex.what() << std::endl;
+  }
+  
+  //Convert to something that std::cout should be able to handle.
+  const Glib::ScopedPtr<char> buf(g_convert_with_fallback(
+    result.raw().data(), result.raw().size(), 
+    "ISO-8859-1", "UTF-8", 
+    (char*)"?", 
+    0, 0, 0));
+  return std::string(buf.get());
+}
+
+std::string Base_DB::sqlbuilder_get_full_query(
+  const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder)
+{
+  Glib::ustring result = "glom_query_not_parsed";
+  
+  try
+  {
+    Glib::RefPtr<Gnome::Gda::Statement> stmt = builder->get_statement();
+    if(stmt)
+      result = stmt->to_sql();
+  }
+  catch(const Glib::Exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while getting query: " << ex.what() << std::endl;
+  }
+  catch(const std::exception& ex)
+  {
+    std::cerr << "sqlbuilder_get_full_query(): exception while getting query: " << ex.what() << std::endl;
+  }
+  
+  //Convert to something that std::cout should be able to handle.
+  const Glib::ScopedPtr<char> buf(g_convert_with_fallback(
+    result.raw().data(), result.raw().size(), 
+    "ISO-8859-1", "UTF-8", 
+    (char*)"?", 
+    0, 0, 0));
+  return std::string(buf.get());
+}
+  
+  
+
+
 } //namespace Glom
diff --git a/glom/base_db.h b/glom/base_db.h
index 6fce311..bfa0b08 100644
--- a/glom/base_db.h
+++ b/glom/base_db.h
@@ -36,6 +36,9 @@
 #include <libglom/document/bakery/view/view.h>
 #include <glom/bakery/busy_cursor.h>
 
+#include <libgdamm/set.h>
+#include <libgdamm/sqlbuilder.h>
+
 namespace Glom
 {
 
@@ -81,8 +84,12 @@ public:
   /** Execute a SQL Select command, returning the result.
    * This method handles any Gda exceptions caused by executing the command.
    */
-  static Glib::RefPtr<Gnome::Gda::DataModel> query_execute_select(const Glib::ustring& strQuery, 
-                                                                  const Glib::RefPtr<Gnome::Gda::Set>& params = Glib::RefPtr<Gnome::Gda::Set>(0));
+  static Glib::RefPtr<Gnome::Gda::DataModel> query_execute_select(
+    const Glib::ustring& strQuery, 
+    const Glib::RefPtr<Gnome::Gda::Set>& params = Glib::RefPtr<Gnome::Gda::Set>(0));
+  static Glib::RefPtr<Gnome::Gda::DataModel> query_execute_select(
+     const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder, 
+     const Glib::RefPtr<const Gnome::Gda::Set>& params = Glib::RefPtr<const Gnome::Gda::Set>(0));
 
 
   /** Execute a SQL non-select command, returning true if it succeeded.
@@ -90,9 +97,11 @@ public:
    */
   static bool query_execute(const Glib::ustring& strQuery,
                             const Glib::RefPtr<Gnome::Gda::Set>& params = Glib::RefPtr<Gnome::Gda::Set>(0));
-
+  static bool query_execute(const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
+                            const Glib::RefPtr<const Gnome::Gda::Set>& params = Glib::RefPtr<const Gnome::Gda::Set>(0));
+  
   static int count_rows_returned_by(const Glib::ustring& sql_query);
-
+  
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   bool add_standard_groups();
   bool add_standard_tables() const;
@@ -428,7 +437,24 @@ protected:
   static void handle_error(const Glib::Exception& ex);
   static void handle_error(const std::exception& ex); //TODO_port: This is probably useless now.
   static bool handle_error();
+  
+private:
+  /// Get the full query string suitable for use with std::cout.
+  static std::string sqlbuilder_get_full_query(
+    const Glib::RefPtr<Gnome::Gda::Connection>& connection, 
+    const Glib::ustring& query,
+    const Glib::RefPtr<const Gnome::Gda::Set>& params);
+    
+  /// Get the full query string suitable for use with std::cout.
+  static std::string sqlbuilder_get_full_query(
+    const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
+    const Glib::RefPtr<const Gnome::Gda::Set>& params);
+    
+  /// Get the full query string suitable for use with std::cout.
+  static std::string sqlbuilder_get_full_query(
+    const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder);
 
+protected:
   type_field_calcs m_FieldsCalculationInProgress; //Prevent circular calculations and recalculations.
 };
 
diff --git a/glom/base_db_table_data.cc b/glom/base_db_table_data.cc
index be5ac82..c72a1ce 100644
--- a/glom/base_db_table_data.cc
+++ b/glom/base_db_table_data.cc
@@ -262,7 +262,7 @@ bool Base_DB_Table_Data::record_new(bool use_entered_data, const Gnome::Gda::Val
 }
 
 
-bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relationship>& relationship, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
+bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relationship>& relationship, const Gnome::Gda::Value& key_value)
 {
   BusyCursor cursor(App_Glom::get_application());
 
@@ -277,9 +277,17 @@ bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relatio
   const Glib::ustring to_field = relationship->get_to_field();
   const Glib::ustring related_table = relationship->get_to_table();
 
-  //TODO_Performance: Is this the best way to just find out whether there is one record that meets this criteria?
-  const Glib::ustring query = "SELECT \"" + to_field + "\" FROM \"" + relationship->get_to_table() + "\" WHERE \"" + related_table + "\".\"" + to_field + "\" = " + key_field->sql(key_value);
-  Glib::RefPtr<Gnome::Gda::DataModel> records = query_execute_select(query);
+  //TODO_Performance: Is this the best way to just find out whether there is one record that meets this criteria? 
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(to_field, related_table);
+  builder->select_add_target(related_table);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+      builder->add_id(to_field), //TODO: It would be nice to specify the table here too.
+      builder->add_expr(key_value)));
+                                               
+  Glib::RefPtr<Gnome::Gda::DataModel> records = query_execute_select(builder);
   if(!records)
     handle_error();
   else
@@ -300,7 +308,7 @@ bool Base_DB_Table_Data::add_related_record_for_field(const sharedptr<const Layo
 {
   Gnome::Gda::Value primary_key_value = primary_key_value_provided;
 
-  const bool related_record_exists = get_related_record_exists(relationship, primary_key_field, primary_key_value);
+  const bool related_record_exists = get_related_record_exists(relationship, primary_key_value);
   if(related_record_exists)
   {
     //No problem, the SQL command below will update this value in the related table.
@@ -413,6 +421,18 @@ bool Base_DB_Table_Data::add_related_record_for_field(const sharedptr<const Layo
             params->add_holder(parent_primary_key_field->get_holder(parent_primary_key_value));
             const Glib::ustring strQuery = "UPDATE \"" + relationship->get_from_table() + "\" SET \"" + relationship->get_from_field() + "\" = " + primary_key_field->get_gda_holder_string() +
               " WHERE \"" + relationship->get_from_table() + "\".\"" + parent_primary_key_field->get_name() + "\" = " +  parent_primary_key_field->get_gda_holder_string();
+              
+            /* TODO: Use SqlBuilder when can know how to specify the related field properly in the condition:
+            Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = 
+              Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+            builder->set_table(relationship->get_from_table());
+            builder->add_field_value_as_value(relationship->get_from_field(), primary_key_value);
+            builder->set_where(
+              builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                builder->add_id("\"" + relationship->get_from_table() + "\".\"" + parent_primary_key_field->get_name() + "\""),
+                builder->add_expr(parent_primary_key_value)),
+            */
+          
             const bool test = query_execute(strQuery, params);
             if(!test)
             {
diff --git a/glom/base_db_table_data.h b/glom/base_db_table_data.h
index ce6882a..ea4f5cd 100644
--- a/glom/base_db_table_data.h
+++ b/glom/base_db_table_data.h
@@ -95,7 +95,7 @@ protected:
   type_signal_record_changed m_signal_record_changed;
     
 private:
-  bool get_related_record_exists(const sharedptr<const Relationship>& relationship, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value);
+  bool get_related_record_exists(const sharedptr<const Relationship>& relationship, const Gnome::Gda::Value& key_value);
 };
 
 } //namespace Glom
diff --git a/glom/glom_privs.cc b/glom/glom_privs.cc
index 1c08d69..79b62e3 100644
--- a/glom/glom_privs.cc
+++ b/glom/glom_privs.cc
@@ -33,8 +33,12 @@ Privs::type_vec_strings Privs::get_database_groups()
 {
   type_vec_strings result;
 
-  const Glib::ustring strQuery = "SELECT \"pg_group\".\"groname\" FROM \"pg_group\"";
-  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field("groname", "pg_group");
+  builder->select_add_target("pg_group");
+  
+  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
   if(data_model)
   {
     const int rows_count = data_model->get_n_rows();
@@ -101,8 +105,12 @@ Privs::type_vec_strings Privs::get_database_users(const Glib::ustring& group_nam
   if(group_name.empty())
   {
     //pg_shadow contains the users. pg_users is a view of pg_shadow without the password.
-    const Glib::ustring strQuery = "SELECT \"pg_shadow\".\"usename\" FROM \"pg_shadow\"";
-    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery);
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+    builder->select_add_field("usename", "pg_shadow");
+    builder->select_add_target("pg_shadow");
+  
+    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
     if(data_model)
     {
       const int rows_count = data_model->get_n_rows();
@@ -121,8 +129,16 @@ Privs::type_vec_strings Privs::get_database_users(const Glib::ustring& group_nam
   }
   else
   {
-    const Glib::ustring strQuery = "SELECT \"pg_group\".\"groname\", \"pg_group\".\"grolist\" FROM \"pg_group\" WHERE \"pg_group\".\"groname\" = '" + group_name + "'";
-    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery);
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+    builder->select_add_field("groname", "pg_group");
+    builder->select_add_field("grolist", "pg_group");
+    builder->select_add_target("pg_group");
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id("groname"), //TODO: It would be nice to specify the table here too.
+        builder->add_expr(group_name)));
+    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
     if(data_model && data_model->get_n_rows())
     {
       const int rows_count = data_model->get_n_rows();
@@ -144,8 +160,15 @@ Privs::type_vec_strings Privs::get_database_users(const Glib::ustring& group_nam
         for(type_vec_strings::const_iterator iter = vecUserIds.begin(); iter != vecUserIds.end(); ++iter)
         {
           //TODO_Performance: Can we do this in one SQL SELECT?
-          const Glib::ustring strQuery = "SELECT \"pg_user\".\"usename\" FROM \"pg_user\" WHERE \"pg_user\".\"usesysid\" = '" + *iter + "'";
-          Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery);
+          Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+            Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+          builder->select_add_field("usename", "pg_user");
+          builder->select_add_target("pg_user");
+          builder->set_where(
+            builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+              builder->add_id("usesysid"), //TODO: It would be nice to specify the table here too.
+              builder->add_expr(*iter)));
+          Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
           if(data_model)
           {
 #ifdef GLIBMM_EXCEPTIONS_ENABLED          
@@ -253,8 +276,15 @@ Privileges Privs::get_table_privileges(const Glib::ustring& group_name, const Gl
   }
 
   //Get the permissions:
-  Glib::ustring strQuery = "SELECT \"pg_class\".\"relacl\" FROM \"pg_class\" WHERE \"pg_class\".\"relname\" = '" + table_name + "'";
-  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(strQuery);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field("relacl", "pg_class");
+  builder->select_add_target("pg_class");
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+      builder->add_id("relname"), //TODO: It would be nice to specify the table here too.
+      builder->add_expr(table_name)));
+  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(builder);
   if(data_model && data_model->get_n_rows())
   {
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
diff --git a/glom/libglom/connectionpool_backends/sqlite.cc b/glom/libglom/connectionpool_backends/sqlite.cc
index 01df7bc..2b3e5ac 100644
--- a/glom/libglom/connectionpool_backends/sqlite.cc
+++ b/glom/libglom/connectionpool_backends/sqlite.cc
@@ -226,21 +226,21 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
       {
       case Field::TYPE_TEXT:
         if(column->gtype == G_TYPE_BOOLEAN)
-	  trans_fields += Glib::ustring("(CASE WHEN ") + column->column_name + " = 1 THEN 'true' "
-                                              "WHEN "  + column->column_name + " = 0 THEN 'false' "
-                                              "WHEN "  + column->column_name + " IS NULL THEN 'false' END)";
+	  trans_fields += Glib::ustring("(CASE WHEN \"") + column->column_name + "\" = 1 THEN 'true' "
+                                              "WHEN \""  + column->column_name + "\" = 0 THEN 'false' "
+                                              "WHEN \""  + column->column_name + "\" IS NULL THEN 'false' END)";
 	else if(column->gtype == GDA_TYPE_BLOB)
 	  trans_fields += "''";
 	else
           // Make sure we don't insert NULL strings, as we ignore that concept in Glom.
-          trans_fields += Glib::ustring("(CASE WHEN ") + column->column_name + " IS NULL THEN '' "
-                                              "WHEN "  + column->column_name + " IS NOT NULL THEN " + column->column_name + " END)";
+          trans_fields += Glib::ustring("(CASE WHEN \"") + column->column_name + "\" IS NULL THEN '' "
+                                              "WHEN \""  + column->column_name + "\" IS NOT NULL THEN \"" + column->column_name + "\" END)";
 	break;
       case Field::TYPE_NUMERIC:
         if(column->gtype == G_TYPE_BOOLEAN)
-          trans_fields += Glib::ustring("(CASE WHEN ") + column->column_name + " = 0 THEN 0 "
-                                              "WHEN "  + column->column_name + " != 0 THEN 1 "
-                                              "WHEN "  + column->column_name + " IS NULL THEN 0 END)";
+          trans_fields += Glib::ustring("(CASE WHEN \"") + column->column_name + "\" = 0 THEN 0 "
+                                              "WHEN \""  + column->column_name + "\" != 0 THEN 1 "
+                                              "WHEN \""  + column->column_name + "\" IS NULL THEN 0 END)";
         else if(column->gtype == GDA_TYPE_BLOB || column->gtype == G_TYPE_DATE || column->gtype == GDA_TYPE_TIME)
           trans_fields += '0';
         else
@@ -248,13 +248,13 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
         break;
       case Field::TYPE_BOOLEAN:
         if(column->gtype == G_TYPE_STRING)
-          trans_fields += Glib::ustring("(CASE WHEN ") + column->column_name + " = 'true' THEN 1 "
-                                              "WHEN "  + column->column_name + " = 'false' THEN 0 "
-                                              "WHEN "  + column->column_name + " IS NULL THEN 0 END)";
+          trans_fields += Glib::ustring("(CASE WHEN \"") + column->column_name + "\" = 'true' THEN 1 "
+                                              "WHEN \""  + column->column_name + "\" = 'false' THEN 0 "
+                                              "WHEN \""  + column->column_name + "\" IS NULL THEN 0 END)";
         else if(column->gtype == G_TYPE_DOUBLE)
-          trans_fields += Glib::ustring("(CASE WHEN ") + column->column_name + " = 0 THEN 0 "
-                                              "WHEN "  + column->column_name + " != 0 THEN 1 "
-                                              "WHEN "  + column->column_name + " IS NULL THEN 0 END)";
+          trans_fields += Glib::ustring("(CASE WHEN \"") + column->column_name + "\" = 0 THEN 0 "
+                                              "WHEN \""  + column->column_name + "\" != 0 THEN 1 "
+                                              "WHEN \""  + column->column_name + "\" IS NULL THEN 0 END)";
         else if(column->gtype == G_TYPE_BOOLEAN)
           trans_fields += column->column_name;
         else
@@ -334,11 +334,11 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
 
   if(perform_server_operation(connection->get_provider(), connection, operation, error))
   {
-    if(trans_fields.empty() || query_execute(connection, Glib::ustring("INSERT INTO ") + TEMPORARY_TABLE_NAME + " SELECT " + trans_fields + " FROM " + table_name, error))
+    if(trans_fields.empty() || query_execute(connection, Glib::ustring("INSERT INTO \"") + TEMPORARY_TABLE_NAME + "\" SELECT " + trans_fields + " FROM \"" + table_name + "\"", error))
     {
       if(query_execute(connection, "DROP TABLE " + table_name, error))
       {
-        if(query_execute(connection, Glib::ustring("ALTER TABLE ") + TEMPORARY_TABLE_NAME + " RENAME TO " + table_name, error))
+        if(query_execute(connection, Glib::ustring("ALTER TABLE \"") + TEMPORARY_TABLE_NAME + "\" RENAME TO \"" + table_name + "\"", error))
         {
           if(commit_transaction(connection, TRANSACTION_NAME, error))
           {
diff --git a/glom/libglom/python_embed/py_glom_record.cc b/glom/libglom/python_embed/py_glom_record.cc
index a989659..f62c396 100644
--- a/glom/libglom/python_embed/py_glom_record.cc
+++ b/glom/libglom/python_embed/py_glom_record.cc
@@ -167,41 +167,27 @@ void PyGlomRecord::setitem(const boost::python::object& key, const boost::python
   params->add_holder(field->get_holder(field_value));
   params->add_holder(m_key_field->get_holder(m_key_field_value));
 
-  Glib::ustring strQuery = "UPDATE \"" + m_table_name + "\"";
-  strQuery += " SET \"" + field->get_name() + "\" = " + field->get_gda_holder_string();
-  strQuery += " WHERE \"" + m_key_field->get_name() + "\" = " + m_key_field->get_gda_holder_string();
-
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = 
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+  builder->set_table(m_table_name);
+  builder->add_field_value_as_value(field->get_name(), field_value);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+      builder->add_id(m_key_field->get_name()),
+      builder->add_expr(m_key_field_value)));
+ 
   bool updated = false;
-  Glib::RefPtr<Gnome::Gda::Statement> stmt;
   try
   {
-    Glib::RefPtr<Gnome::Gda::SqlParser> parser = m_connection->create_parser();
-    stmt = parser->parse_string(strQuery);
-
+    updated = m_connection->statement_execute_non_select_builder(builder);
   }
   catch(const Glib::Exception& ex)
   {
-    std::cerr << "PyGlomRecord::setitem(): exception while parsing query: " << ex.what() << std::endl;
+    std::cerr << "PyGlomRecord::setitem(): exception while executing query: " << ex.what() << std::endl;
   }
   catch(const std::exception& ex)
   {
-    std::cerr << "PyGlomRecord::setitem(): exception while parsing query: " << ex.what() << std::endl;
-  }
-
-  if(stmt)
-  {
-    try
-    {
-      updated = m_connection->statement_execute_non_select(stmt, params);
-    }
-    catch(const Glib::Exception& ex)
-    {
-      std::cerr << "PyGlomRecord::setitem(): exception while executing query: " << ex.what() << std::endl;
-    }
-    catch(const std::exception& ex)
-    {
-      std::cerr << "PyGlomRecord::setitem(): exception while executing query: " << ex.what() << std::endl;
-    }
+    std::cerr << "PyGlomRecord::setitem(): exception while executing query: " << ex.what() << std::endl;
   }
 
   if(!updated)
diff --git a/glom/libglom/python_embed/py_glom_related.cc b/glom/libglom/python_embed/py_glom_related.cc
index 1676d38..2f49217 100644
--- a/glom/libglom/python_embed/py_glom_related.cc
+++ b/glom/libglom/python_embed/py_glom_related.cc
@@ -86,17 +86,10 @@ boost::python::object PyGlomRelated::getitem(const boost::python::object& cppite
 
               //TODO_Performance:
               //Get the full field details so we can sqlize its value:
-              sharedptr<Field> from_key_field;
-              from_key_field = record->m_document->get_field(record->m_table_name, from_key);
+              sharedptr<const Field> from_key_field = record->m_document->get_field(record->m_table_name, from_key);
               if(from_key_field)
-              {
-                Glib::ustring key_value_sqlized;
-                //std::cout << "from_key_field=" << from_key_field->get_name() << ", from_key_value=" << from_key_value.to_string() << std::endl;
-
-                if(!Conversions::value_is_empty(from_key_value)) //Do not link on null-values. That would cause us to link on 0, or "0".
-                  key_value_sqlized = from_key_field->sql(from_key_value);
-
-                PyGlomRelatedRecord_SetRelationship(pyRelatedRecord, iterFind->second, key_value_sqlized, record->m_document);
+              { 
+                PyGlomRelatedRecord_SetRelationship(pyRelatedRecord, iterFind->second, from_key_value, record->m_document);
 
                 //Store it in the cache:
                 boost::python::object objectRelatedRecord(pyRelatedRecord);
diff --git a/glom/libglom/python_embed/py_glom_relatedrecord.cc b/glom/libglom/python_embed/py_glom_relatedrecord.cc
index 59c5949..396a6d9 100644
--- a/glom/libglom/python_embed/py_glom_relatedrecord.cc
+++ b/glom/libglom/python_embed/py_glom_relatedrecord.cc
@@ -22,6 +22,7 @@
 #include <libglom/python_embed/py_glom_record.h>
 #include <libglom/python_embed/pygdavalue_conversions.h> //For pygda_value_as_pyobject().
 #include <libglom/connectionpool.h>
+#include <libglom/data_structure/glomconversions.h>
 
 #include <libglom/data_structure/field.h>
 #include <glibmm/ustring.h>
@@ -61,91 +62,94 @@ boost::python::object PyGlomRelatedRecord::getitem(const boost::python::object&
     //If the value has already been stored, then just return it again:
     return glom_pygda_value_as_boost_pyobject(iterFind->second);
   }
+  
+  const Glib::ustring related_table = m_relationship->get_to_table();
+
+  //Check whether the field exists in the table.
+  //TODO_Performance: Do this without the useless Field information?
+  sharedptr<const Field> field = m_document->get_field(m_relationship->get_to_table(), field_name);
+  if(!field)
+  {
+    g_warning("PyGlomRelatedRecord::setitem(): field %s not found in table %s", field_name.c_str(), m_relationship->get_to_table().c_str());
+    PyErr_SetString(PyExc_IndexError, "field not found");
+    return boost::python::object();
+  }
   else
   {
-    const Glib::ustring related_table = m_relationship->get_to_table();
-
-    //Check whether the field exists in the table.
-    //TODO_Performance: Do this without the useless Field information?
-    sharedptr<const Field> field = m_document->get_field(m_relationship->get_to_table(), field_name);
-    if(!field)
-      g_warning("RelatedRecord_tp_as_mapping_getitem: field %s not found in table %s", field_name.c_str(), m_relationship->get_to_table().c_str());
-    else
-    {
-      //Try to get the value from the database:
-      //const Glib::ustring parent_key_name;
+    //Try to get the value from the database:
+    //const Glib::ustring parent_key_name;
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-      sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect();
+    sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect();
 #else
-      std::auto_ptr<ExceptionConnection> conn_error;
-      sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect(conn_error);
-      // Ignore error, sharedconnection presence is checked below
+    std::auto_ptr<ExceptionConnection> conn_error;
+    sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect(conn_error);
+    // Ignore error, sharedconnection presence is checked below
 #endif
-      if(sharedconnection)
-      {
-        Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
-
-        const Glib::ustring related_key_name = m_relationship->get_to_field();
-
-        //Do not try to get a value based on a null key value:
-        if(m_from_key_value_sqlized.empty())
-          return boost::python::object();
-
-        //Get the single value from the related records:
-        const Glib::ustring sql_query = "SELECT \"" + related_table + "\".\"" + field_name + "\" FROM \"" + related_table + "\""
-          + " WHERE \"" + related_table + "\".\"" + related_key_name + "\" = " + m_from_key_value_sqlized;
-
-        /* TODO: Fix linking problems
-        const App_Glom* app = App_Glom::get_application();
-        if(app && app->get_show_sql_debug())
-        {
-          try
-          {
-            std::cout << "Debug: RelatedRecord_tp_as_mapping_getitem():  " << sql_query << std::endl;
-          }
-          catch(const Glib::Exception& ex)
-          {
-            std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
-          }
-        }*/
+    if(!sharedconnection)
+    {
+      PyErr_SetString(PyExc_IndexError, "connection not found");
+      return boost::python::object();
+    }
+  
+    Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-        // TODO: Does this behave well if this throws an exception?
-        Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select(sql_query);
-#else
-        std::auto_ptr<Glib::Error> error;
-        Glib::RefPtr<Gnome::Gda::DataModel> datamodel =  gda_connection->statement_execute_select(sql_query, Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, error);
-        // Ignore error, datamodel return value is checked below
-#endif
-        if(datamodel && datamodel->get_n_rows())
-        {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-          Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
-#else
-          Gnome::Gda::Value value = datamodel->get_value_at(0, 0, error);
-#endif
-          //g_warning("RelatedRecord_tp_as_mapping_getitem(): value from datamodel = %s", value.to_string().c_str());
-
-          //Cache it, in case it's asked-for again.
-          m_map_field_values[field_name] = value;
-          return glom_pygda_value_as_boost_pyobject(value);
-        }
-        else if(!datamodel)
-        {
-          g_warning("RelatedRecord_tp_as_mapping_getitem(): The datamodel was null.");
-          ConnectionPool::handle_error_cerr_only();
-          RelatedRecord_HandlePythonError();
-        }
-        else
-        {
-          g_warning("RelatedRecord_tp_as_mapping_getitem(): No related records exist yet for relationship %s.",  m_relationship->get_name().c_str());
-        }
+    const Glib::ustring related_key_name = m_relationship->get_to_field();
+
+    //Do not try to get a value based on a null key value:
+    if(Conversions::value_is_empty(m_from_key_value))
+    {
+      PyErr_SetString(PyExc_IndexError, "connection not found");
+      return boost::python::object();
+    }
+
+    //Get the single value from the related records:
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+    builder->select_add_field(field_name, related_table);
+    builder->select_add_target(related_table);
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(related_key_name), //TODO: It would nice to specify the table name here too.
+        builder->add_expr(m_from_key_value)));
+        
+    /* TODO: Fix linking problems
+    const App_Glom* app = App_Glom::get_application();
+    if(app && app->get_show_sql_debug())
+    {
+      try
+      {
+        std::cout << "Debug: PyGlomRelatedRecord::setitem()():  " << sql_query << std::endl;
       }
+      catch(const Glib::Exception& ex)
+      {
+        std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
+      }
+    }*/
+    
+    // TODO: Does this behave well if this throws an exception?
+    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select_builder(builder);
+    if(datamodel && datamodel->get_n_rows())
+    {
+      const Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
+      //g_warning("PyGlomRelatedRecord::setitem()(): value from datamodel = %s", value.to_string().c_str());
+
+      //Cache it, in case it's asked-for again.
+      m_map_field_values[field_name] = value;
+      return glom_pygda_value_as_boost_pyobject(value);
+    }
+    else if(!datamodel)
+    {
+      g_warning("PyGlomRelatedRecord::setitem()(): The datamodel was null.");
+      ConnectionPool::handle_error_cerr_only();
+      RelatedRecord_HandlePythonError();
+    }
+    else
+    {
+      g_warning("PyGlomRelatedRecord::setitem()(): No related records exist yet for relationship %s.",  m_relationship->get_name().c_str());
     }
   }
 
-  g_warning("RelatedRecord_tp_as_mapping_getitem(): return null.");
-  PyErr_SetString(PyExc_IndexError, "field not found");
+  g_warning("PyGlomRelatedRecord::setitem()(): return null.");
   return boost::python::object();
 }
 
@@ -182,32 +186,30 @@ boost::python::object PyGlomRelatedRecord::generic_aggregate(const std::string&
   const Glib::ustring related_key_name = m_relationship->get_to_field();
 
   //Do not try to get a value based on a null key value:
-  if(m_from_key_value_sqlized.empty())
+  if(Conversions::value_is_empty(m_from_key_value))
   {
     return boost::python::object();
   }
 
   //Get the aggregate value from the related records:
-  const Glib::ustring sql_query = "SELECT " + aggregate + "(\"" + related_table + "\".\"" + field_name + "\") FROM \"" + related_table + "\""
-    + " WHERE \"" + related_table + "\".\"" + related_key_name + "\" = " + m_from_key_value_sqlized;
-
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->add_function(aggregate, builder->add_id(field_name)); //TODO: It would be nice to specify the table here too.
+  builder->select_add_target(related_table);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+      builder->add_id(related_key_name), //TODO: It would nice to specify the table name here too.
+      builder->add_expr(m_from_key_value)));
+
+ 
   //std::cout << "PyGlomRelatedRecord: Executing:  " << sql_query << std::endl;
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select(sql_query);
-#else
-  std::auto_ptr<Glib::Error> error;
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select(sql_query, Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, error);
+  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select_builder(builder);
 
   // Ignore the error: The case that the command execution didn't return
   // a datamodel is handled below.
-#endif
   if(datamodel && datamodel->get_n_rows())
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
-#else
-    Gnome::Gda::Value value = datamodel->get_value_at(0, 0, error);
-#endif
     //g_warning("RelatedRecord_generic_aggregate(): value from datamodel = %s", value.to_string().c_str());
 
     //Cache it, in case it's asked-for again.
@@ -248,11 +250,11 @@ boost::python::object PyGlomRelatedRecord::max(const std::string& field_name) co
   return generic_aggregate(field_name, "max");
 }
 
-void PyGlomRelatedRecord_SetRelationship(PyGlomRelatedRecord* self, const sharedptr<const Relationship>& relationship, const Glib::ustring& from_key_value_sqlized,  Document* document)
+void PyGlomRelatedRecord_SetRelationship(PyGlomRelatedRecord* self, const sharedptr<const Relationship>& relationship, const Gnome::Gda::Value& from_key_value,  Document* document)
 {
   self->m_relationship = relationship;
 
-  self->m_from_key_value_sqlized = from_key_value_sqlized;
+  self->m_from_key_value = from_key_value;
 
   self->m_document = document;
 }
diff --git a/glom/libglom/python_embed/py_glom_relatedrecord.h b/glom/libglom/python_embed/py_glom_relatedrecord.h
index c4dad58..7c92734 100644
--- a/glom/libglom/python_embed/py_glom_relatedrecord.h
+++ b/glom/libglom/python_embed/py_glom_relatedrecord.h
@@ -56,14 +56,14 @@ public:
   Document* m_document;
 
   sharedptr<const Relationship> m_relationship;
-  Glib::ustring m_from_key_value_sqlized;
+  Gnome::Gda::Value m_from_key_value;
 
   //Available, for instance, in python via record["name_first"]
   typedef std::map<Glib::ustring, Gnome::Gda::Value> type_map_field_values;
   mutable type_map_field_values m_map_field_values; //A cache.
 };
 
-void PyGlomRelatedRecord_SetRelationship(PyGlomRelatedRecord* self, const sharedptr<const Relationship>& relationship, const Glib::ustring& from_key_value_sqlized, Document* document);
+void PyGlomRelatedRecord_SetRelationship(PyGlomRelatedRecord* self, const sharedptr<const Relationship>& relationship, const Gnome::Gda::Value& from_key_value, Document* document);
 
 /*
 void PyGlomRelatedRecord_SetConnection(PyGlomRelatedRecord* self, const Glib::RefPtr<Gnome::Gda::Connection>& connection);
diff --git a/glom/mode_data/box_data_calendar_related.cc b/glom/mode_data/box_data_calendar_related.cc
index bf919c8..327e93f 100644
--- a/glom/mode_data/box_data_calendar_related.cc
+++ b/glom/mode_data/box_data_calendar_related.cc
@@ -285,14 +285,16 @@ void Box_Data_Calendar_Related::on_record_added(const Gnome::Gda::Value& primary
 
     //Create the link by setting the foreign key
     if(m_key_field && m_portal)
-    {
-      Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-      params->add_holder(m_key_field->get_holder(m_key_value));
-      params->add_holder(field_primary_key->get_holder(primary_key_value));
-      Glib::ustring strQuery = "UPDATE \"" + m_portal->get_table_used(Glib::ustring() /* not relevant */) + "\"";
-      strQuery += " SET \"" +  /* get_table_name() + "." +*/ m_key_field->get_name() + "\" = " + m_key_field->get_gda_holder_string();
-      strQuery += " WHERE \"" + get_table_name() + "\".\"" + field_primary_key->get_name() + "\" = " + field_primary_key->get_gda_holder_string();
-      const bool test = query_execute(strQuery, params);
+    {      
+      Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+      builder->set_table(m_portal->get_table_used(Glib::ustring() /* not relevant */));
+      builder->add_field_value_as_value(m_key_field->get_name(), m_key_value);
+      builder->set_where(
+        builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+          builder->add_id(field_primary_key->get_name()),
+          builder->add_expr_as_value(primary_key_value)));
+      
+      const bool test = query_execute(builder);
       if(test)
       {
         //Show it on the view, if it's visible:
diff --git a/glom/mode_data/box_data_portal.cc b/glom/mode_data/box_data_portal.cc
index feef1a2..7d653c9 100644
--- a/glom/mode_data/box_data_portal.cc
+++ b/glom/mode_data/box_data_portal.cc
@@ -108,17 +108,19 @@ void Box_Data_Portal::make_record_related(const Gnome::Gda::Value& related_recor
     std::cerr << "Box_Data_Portal::make_record_related(): m_portal was null." << std::endl;
   } 
 
-  Glib::RefPtr<Gnome::Gda::Set> params = Gnome::Gda::Set::create();
-  params->add_holder(m_key_field->get_holder(m_key_value));
-  params->add_holder(field_primary_key->get_holder(related_record_primary_key_value));
-  Glib::ustring strQuery = "UPDATE \"" + m_portal->get_table_used(Glib::ustring() /* not relevant */) + "\"";
-  strQuery += " SET \"" +  /* get_table_name() + "." +*/ m_key_field->get_name() + "\" = " + m_key_field->get_gda_holder_string();
-  strQuery += " WHERE \"" + get_table_name() + "\".\"" + field_primary_key->get_name() + "\" = " + field_primary_key->get_gda_holder_string();
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+    builder->set_table(m_portal->get_table_used(Glib::ustring() /* not relevant */));
+    builder->add_field_value_as_value(m_key_field->get_name(), m_key_value);
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+        builder->add_id(field_primary_key->get_name()),
+        builder->add_expr_as_value(related_record_primary_key_value)));
+          
   //std::cout << "Box_Data_Portal::make_record_related(): setting value in db=" << primary_key_value.to_string() << std::endl;
-  const bool test = query_execute(strQuery, params);
+  const bool test = query_execute(builder);
   if(!test)
   {
-    std::cerr << "Box_Data_Portal::make_record_related(): SQL query failed: " << strQuery << std::endl;
+    std::cerr << "Box_Data_Portal::make_record_related(): SQL query failed." << std::endl;
   }
 }
 
diff --git a/glom/mode_design/dialog_database_preferences.cc b/glom/mode_design/dialog_database_preferences.cc
index b515147..0867aa4 100644
--- a/glom/mode_design/dialog_database_preferences.cc
+++ b/glom/mode_design/dialog_database_preferences.cc
@@ -94,13 +94,20 @@ void Dialog_Database_Preferences::on_treeview_cell_edited_next_value(const Glib:
     const Glib::ustring field_name = row[m_columns.m_col_field];
 
     const Gnome::Gda::Value next_value = Conversions::parse_value(new_value);
-
-    const Glib::ustring sql_query = "UPDATE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\" SET "
-        "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE "\" = " + next_value.to_string() +
-        " WHERE \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME "\" = '" + table_name + "' AND "
-               "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME "\" = '" + field_name +"'";
-
-    const bool test = query_execute(sql_query);
+               
+    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+    builder->set_table(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+    builder->add_field_value_as_value(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE, next_value);
+    builder->set_where(
+      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_AND,
+        builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+          builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME),
+          builder->add_expr(table_name)),
+        builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+          builder->add_id(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME),
+          builder->add_expr(field_name))));
+
+    const bool test = query_execute(builder);
     if(!test)
       std::cerr << "Dialog_Database_Preferences::on_treeview_cell_edited_next_value(): UPDATE failed." << std::endl;
   }
@@ -132,15 +139,19 @@ void Dialog_Database_Preferences::load_from_document()
   //Show the auto-increment values:
   m_model_autoincrements->clear();
 
-  const Glib::ustring sql_query = "SELECT "
-    "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME "\", "
-    "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME "\", "
-    "\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE "\""
-    " FROM \"" GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME "\"";
-
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_TABLE_NAME,
+    GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_FIELD_NAME,
+    GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->select_add_field(GLOM_STANDARD_TABLE_AUTOINCREMENTS_FIELD_NEXT_VALUE,
+    GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  builder->select_add_target(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
+  
   NumericFormat numeric_format; //ignored
 
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
+  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
   if(!datamodel)
   {
     std::cerr << "Dialog_Database_Preferences::load_from_document(): Gda::DataModel is NULL." << std::endl;
diff --git a/glom/mode_design/fields/box_db_table_definition.cc b/glom/mode_design/fields/box_db_table_definition.cc
index 3dd85c7..df7cc93 100644
--- a/glom/mode_design/fields/box_db_table_definition.cc
+++ b/glom/mode_design/fields/box_db_table_definition.cc
@@ -623,14 +623,18 @@ void Box_DB_Table_Definition::fill_fields()
 
 bool Box_DB_Table_Definition::field_has_null_values(const sharedptr<const Field>& field)
 {
-  //TODO: Use SQL paramters?
   //Note that "= Null" doesn't work, though it doesn't error either.
   //Note also that SELECT COUNT always returns 0 if all the values are NULL, so we can't use that to be more efficient.
-  const Glib::ustring sql_query = "SELECT \"" + field->get_name() + "\" FROM \"" + m_table_name + "\" WHERE \"" + m_table_name + "\".\"" + field->get_name() + "\" IS NULL LIMIT 1";
-  //std::cout << "sql_query: " << sql_query << std::endl;
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_field(field->get_name(), m_table_name);
+  builder->select_add_target(m_table_name);
+  builder->set_where(
+    builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_ISNULL,
+      builder->add_id(field->get_name()))); //TODO: It would nice to specify the table name here too.
 
   long null_count = 0;
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
+  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
   if(datamodel)
   {
     if(datamodel->get_n_rows() && datamodel->get_n_columns())
@@ -641,7 +645,7 @@ bool Box_DB_Table_Definition::field_has_null_values(const sharedptr<const Field>
   }
   else
   {
-    std::cerr << "Box_DB_Table_Definition::field_has_null_values(): query failed: " << sql_query << std::endl;
+    std::cerr << "Box_DB_Table_Definition::field_has_null_values(): query failed." << std::endl;
   }
 
   return null_count > 0; 
@@ -652,7 +656,8 @@ bool Box_DB_Table_Definition::field_has_non_unique_values(const sharedptr<const
   long count_distinct = 0;
   long count_all = 0;
 
-  //Count the distint rows:
+  //TODO: Use SqlBuilder. I asked on the mailing list about how to use DISTINCT with it. murrayc.
+  //Count the distinct rows:
   const Glib::ustring sql_query_distinct = "SELECT DISTINCT \"" + field->get_name() + "\" FROM \"" + m_table_name + "\"";
   
   Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query_distinct);
@@ -667,9 +672,12 @@ bool Box_DB_Table_Definition::field_has_non_unique_values(const sharedptr<const
   }
 
   //Count all rows, to compare. TODO_performance: Is there a more efficient way to do this? Maybe count(*), which apparently doesn't ignore NULL rows like count(somefield) would.
-  const Glib::ustring sql_query_all = "SELECT \"" + field->get_name() + "\" FROM \"" + m_table_name + "\"";
-  
-  datamodel = query_execute_select(sql_query_all);
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder_query_all =
+    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder_query_all->select_add_field(field->get_name(), m_table_name);
+  builder_query_all->select_add_target(m_table_name);
+      
+  datamodel = query_execute_select(builder_query_all);
   if(datamodel)
   {
     count_all = datamodel->get_n_rows();
diff --git a/glom/report_builder.cc b/glom/report_builder.cc
index d1257fb..0052d98 100644
--- a/glom/report_builder.cc
+++ b/glom/report_builder.cc
@@ -175,6 +175,7 @@ void ReportBuilder::report_build_groupby(const FoundSet& found_set_parent, xmlpp
     fill_full_field_details(found_set_parent.m_table_name, field_group_by);
 
     //Get the possible group values, ignoring repeats by using GROUP BY.
+    //TODO: Use SqlBuilder:
     const Glib::ustring group_field_table_name = field_group_by->get_table_used(found_set_parent.m_table_name);
     Glib::ustring sql_query = "SELECT \"" + group_field_table_name + "\".\"" + field_group_by->get_name() + "\""
       " FROM \"" + group_field_table_name + "\"";
@@ -182,7 +183,7 @@ void ReportBuilder::report_build_groupby(const FoundSet& found_set_parent, xmlpp
     if(!found_set_parent.m_where_clause.empty())
       sql_query += " WHERE " + found_set_parent.m_where_clause;
 
-    sql_query += " GROUP BY " + field_group_by->get_name(); //rTODO: And restrict to the current found set.
+    sql_query += " GROUP BY " + field_group_by->get_name(); //TODO: And restrict to the current found set.
 
     Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
     if(datamodel)
@@ -384,6 +385,7 @@ void ReportBuilder::report_build_records_field(const FoundSet& found_set, xmlpp:
   {
     //In this case it can only be a system preferences field.
     //So let's get that data here:
+    //TODO: Use SqlBuilder when we know how to use LIMIT with it. I asked on the libgda mailing list. murrayc.
     const Glib::ustring table_used = field->get_table_used(found_set.m_table_name);
     const Glib::ustring query = "SELECT \"" + table_used + "\".\"" + field->get_name() + "\" FROM \""+ table_used + "\" LIMIT 1";
     Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(query);
diff --git a/glom/utility_widgets/db_adddel/db_adddel.cc b/glom/utility_widgets/db_adddel/db_adddel.cc
index 279b729..9ffce98 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.cc
+++ b/glom/utility_widgets/db_adddel/db_adddel.cc
@@ -2551,11 +2551,6 @@ void DbAddDel::user_changed(const Gtk::TreeModel::iterator& row, guint col)
 
 
       const bool bTest = set_field_value_in_database(field_in_record, row, field_value, false /* don't use current calculations */, window);
-
-      //Glib::ustring strQuery = "UPDATE \"" + table_name + "\"";
-      //strQuery += " SET " +  /* table_name + "." + postgres does not seem to like the table name here */ strFieldName + " = " + field.sql(field_value, connection);
-      //strQuery += " WHERE " + table_name + "." + primary_key_field.get_name() + " = " + primary_key_field.sql(primary_key_value, connection);
-      //bool bTest = query_execute(strQuery);
       if(!bTest)
       {
         //Update failed.
diff --git a/glom/utility_widgets/db_adddel/glom_db_treemodel.cc b/glom/utility_widgets/db_adddel/glom_db_treemodel.cc
index a83dc17..8fa203a 100644
--- a/glom/utility_widgets/db_adddel/glom_db_treemodel.cc
+++ b/glom/utility_widgets/db_adddel/glom_db_treemodel.cc
@@ -958,15 +958,17 @@ void DbTreeModel::get_record_counts(gulong& total, gulong& found) const
     {
       //Ask the database how many records there are in the whole table:
       //TODO: Apparently, this is very slow:
-      const Glib::ustring sql_query = "SELECT count(*) FROM \"" + m_found_set.m_table_name + "\"";
-      Glib::RefPtr<Gnome::Gda::SqlParser> parser = m_connection->get_gda_connection()->create_parser();
+      
+      Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
+        Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+      builder->add_function("count", builder->add_id("*")); //TODO: Is * allowed here?
+      builder->select_add_target(m_found_set.m_table_name);
+
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-      Glib::RefPtr<Gnome::Gda::Statement> stmt = parser->parse_string(sql_query);
-      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = m_connection->get_gda_connection()->statement_execute_select(stmt);
+      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = m_connection->get_gda_connection()->statement_execute_select_builder(builder);
 #else
       std::auto_ptr<Glib::Error> error;
-      Glib::RefPtr<Gnome::Gda::Statement> stmt = parser->parse_string(sql_query, error);
-      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = m_connection->get_gda_connection()->statement_execute_select(stmt, Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, error);
+      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = m_connection->get_gda_connection()->statement_execute_select_builder(builder, Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, error);
       // Ignore error, datamodel presence is checked below
 #endif //GLIBMM_EXCEPTIONS_ENABLED
 



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