[glom] utils: Move some functions into sql_utils.



commit cd91632e534121b06a987fba1cfa6c753e373a34
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Mar 17 10:39:12 2016 +0100

    utils: Move some functions into sql_utils.

 CMakeLists.txt                                     |    2 +
 glom/base_db.cc                                    |    1 +
 glom/base_db_table_data.cc                         |    1 +
 glom/frame_glom.cc                                 |    2 +-
 glom/libglom/db_utils.cc                           |  128 ++++
 glom/libglom/db_utils.h                            |    6 +
 glom/libglom/db_utils_export.cc                    |    1 +
 glom/libglom/filelist.am                           |    3 +
 glom/libglom/report_builder.cc                     |    1 +
 glom/libglom/sql_utils.cc                          |  574 +++++++++++++++++
 glom/libglom/sql_utils.h                           |  132 ++++
 glom/libglom/utils.cc                              |  661 --------------------
 glom/libglom/utils.h                               |   97 ---
 glom/libglom/xsl_utils.h                           |    4 -
 glom/mode_data/box_data_calendar_related.cc        |    3 +-
 glom/mode_data/box_data_details.cc                 |    1 +
 glom/mode_data/box_data_portal.cc                  |    1 +
 .../mode_data/datawidget/combo_as_radio_buttons.cc |    6 +-
 .../datawidget/combochoiceswithtreemodel.cc        |    1 +
 glom/mode_data/datawidget/dialog_choose_id.cc      |    2 +-
 glom/mode_data/datawidget/treemodel_db.cc          |    2 +-
 glom/mode_data/db_adddel/db_adddel.cc              |    2 +-
 glom/mode_data/notebook_data.cc                    |    1 +
 glom/print_layout/canvas_print_layout.cc           |    1 +
 tests/test_fake_connection.cc                      |    2 +-
 tests/test_selfhosting_new_from_example_float.cc   |    2 +-
 tests/test_selfhosting_new_then_choices.cc         |   10 +-
 tests/test_selfhosting_new_then_image.cc           |    2 +-
 tests/test_selfhosting_sqlinjection.cc             |    2 +-
 tests/test_selfhosting_utils.cc                    |    1 +
 30 files changed, 873 insertions(+), 779 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5f552f7..5b7682a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,6 +254,8 @@ set(SOURCE_FILES
         glom/libglom/translations_po.h
         glom/libglom/file_utils.cc
         glom/libglom/file_utils.h
+        glom/libglom/sql_utils.cc
+        glom/libglom/sql_utils.h
         glom/libglom/string_utils.cc
         glom/libglom/string_utils.h
         glom/libglom/utils.cc
diff --git a/glom/base_db.cc b/glom/base_db.cc
index 8eef37c..309ae24 100644
--- a/glom/base_db.cc
+++ b/glom/base_db.cc
@@ -27,6 +27,7 @@
 #include <libglom/document/document.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <glom/mode_design/layout/dialog_choose_field.h>
 
 //#ifndef GLOM_ENABLE_CLIENT_ONLY
diff --git a/glom/base_db_table_data.cc b/glom/base_db_table_data.cc
index 1282523..aa75368 100644
--- a/glom/base_db_table_data.cc
+++ b/glom/base_db_table_data.cc
@@ -25,6 +25,7 @@
 #include <glom/python_embed/glom_python.h>
 #include <glom/utils_ui.h>
 #include <libglom/db_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <sstream>
 #include <iostream>
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 1077b91..1cfe122 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -28,7 +28,7 @@
 #include <libglom/appstate.h>
 #include <libglom/db_utils_export.h>
 #include <libglom/string_utils.h>
-
+#include <libglom/sql_utils.h>
 #include <libglom/connectionpool.h>
 
 #ifdef GLOM_ENABLE_POSTGRESQL
diff --git a/glom/libglom/db_utils.cc b/glom/libglom/db_utils.cc
index ff18b82..579fd79 100644
--- a/glom/libglom/db_utils.cc
+++ b/glom/libglom/db_utils.cc
@@ -20,6 +20,7 @@
 
 #include <libglom/algorithms_utils.h>
 #include <libglom/db_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/connectionpool_backends/postgres_central.h>
@@ -2373,6 +2374,133 @@ type_map_fields get_record_field_values(const std::shared_ptr<const Document>& d
   return field_values;
 }
 
+
+type_list_values_with_second get_choice_values_all(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field)
+{
+  return get_choice_values(document, field,
+                           Gnome::Gda::Value() /* means get all with no WHERE clause */);
+}
+
+type_list_values_with_second get_choice_values(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value)
+{
+  //TODO: Reduce duplication between this and get_choice_values(field).
+
+  type_list_values_with_second result;
+
+  //We allows this, so this method can be used to get all records in a related table:
+  /*
+  if(Conversions::value_is_empty(foreign_key_value))
+  {
+    std::cout << G_STRFUNC << "debug: foreign_key_value is empty.\n";
+    return result;
+  }
+  */
+
+  const Formatting& format = field->get_formatting_used();
+  std::shared_ptr<const Relationship> choice_relationship;
+  std::shared_ptr<const LayoutItem_Field> layout_choice_first;
+  std::shared_ptr<const LayoutGroup> layout_choice_extra;
+  Formatting::type_list_sort_fields choice_sort_fields;
+  bool choice_show_all = false;
+  format.get_choices_related(choice_relationship, layout_choice_first, layout_choice_extra, 
choice_sort_fields, choice_show_all);
+
+  if(!choice_relationship)
+  {
+    std::cerr << G_STRFUNC << ": !choice_relationship.\n";
+    return result;
+  }
+
+  Utils::type_vecConstLayoutFields fields;
+  fields.emplace_back(layout_choice_first);
+
+  if(layout_choice_extra)
+  {
+    for(const auto& item : layout_choice_extra->get_items_recursive())
+    {
+      const auto& item_field = std::dynamic_pointer_cast<const LayoutItem_Field>(item);
+      if(item_field)
+        fields.emplace_back(item_field); //TODO: Don't ignore other usable items such as static text.
+    }
+  }
+
+  const Glib::ustring to_table = choice_relationship->get_to_table();
+  const auto to_field = document->get_field(to_table, choice_relationship->get_to_field());
+
+  if(!to_field)
+  {
+    std::cerr << G_STRFUNC << ": to_field is null.\n";
+  }
+
+  //Default to some sort order rather than none:
+  if(choice_sort_fields.empty())
+  {
+    choice_sort_fields.emplace_back( Formatting::type_pair_sort_field(layout_choice_first, true /* ascending 
*/));
+  }
+
+  //TODO: Support related relationships (in the UI too):
+  auto builder = Utils::build_sql_select_with_key(
+          to_table,
+          fields,
+          to_field,
+          foreign_key_value,
+          choice_sort_fields);
+
+  if(!builder)
+  {
+    std::cerr << G_STRFUNC << ": builder is null.\n";
+    return result;
+  }
+
+  //TODO: builder->select_order_by(choice_field_id);
+
+  //Connect to database and get the related values:
+  auto connection = ConnectionPool::get_instance()->connect();
+
+  if(!connection)
+  {
+    std::cerr << G_STRFUNC << ": connection is null.\n";
+    return result;
+  }
+
+  const std::string sql_query =
+          Utils::sqlbuilder_get_full_query(builder);
+  //std::cout << "debug: sql_query=" << sql_query << std::endl;
+  auto datamodel = connection->get_gda_connection()->statement_execute_select(sql_query);
+
+  if(datamodel)
+  {
+    const guint count = datamodel->get_n_rows();
+    const guint cols_count = datamodel->get_n_columns();
+    for(guint row = 0; row < count; ++row)
+    {
+
+      std::pair<Gnome::Gda::Value, type_list_values> itempair;
+      itempair.first = datamodel->get_value_at(0, row);
+
+      if(layout_choice_extra && (cols_count > 1))
+      {
+        type_list_values list_values;
+        for(guint i = 1; i < cols_count; ++i)
+        {
+          list_values.emplace_back(datamodel->get_value_at(i, row));
+        }
+
+        itempair.second = list_values;
+      }
+
+      result.emplace_back(itempair);
+    }
+  }
+  else
+  {
+    std::cerr << G_STRFUNC << ": Error while executing SQL\n" <<
+    "  " <<  sql_query << std::endl;
+    return result;
+  }
+
+  return result;
+}
+
 } //namespace DbUtils
 
 } //namespace Glom
diff --git a/glom/libglom/db_utils.h b/glom/libglom/db_utils.h
index 293e657..10cae91 100644
--- a/glom/libglom/db_utils.h
+++ b/glom/libglom/db_utils.h
@@ -228,6 +228,12 @@ type_map_fields get_record_field_values(const std::shared_ptr<const Document>& d
  */
 void set_fake_connection();
 
+typedef std::vector<Gnome::Gda::Value> type_list_values;
+typedef std::vector< std::pair<Gnome::Gda::Value, type_list_values> > type_list_values_with_second; //TODO: 
Rename this now that we have more than just 1 extra field.
+type_list_values_with_second get_choice_values_all(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field);
+
+type_list_values_with_second get_choice_values(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value);
+
 } //namespace DbUtils
 
 } //namespace Glom
diff --git a/glom/libglom/db_utils_export.cc b/glom/libglom/db_utils_export.cc
index f281ca7..16d09d1 100644
--- a/glom/libglom/db_utils_export.cc
+++ b/glom/libglom/db_utils_export.cc
@@ -22,6 +22,7 @@
 #include <libglom/db_utils_export.h>
 #include <libglom/db_utils.h>
 #include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/algorithms_utils.h>
 #include <libgdamm/metastore.h>
 #include <iostream>
diff --git a/glom/libglom/filelist.am b/glom/libglom/filelist.am
index a2de35f..c19dc82 100644
--- a/glom/libglom/filelist.am
+++ b/glom/libglom/filelist.am
@@ -27,6 +27,7 @@ libglom_toplevel_headers =                            \
        glom/libglom/utils.h                            \
        glom/libglom/db_utils.h \
        glom/libglom/db_utils_export.h \
+       glom/libglom/sql_utils.h \
        glom/libglom/report_builder.h \
        glom/libglom/translations_po.h
 
@@ -123,6 +124,8 @@ libglom_sources =                                                   \
        glom/libglom/string_utils.h \
        glom/libglom/translations_po.cc                         \
        glom/libglom/translations_po.h                          \
+       glom/libglom/sql_utils.cc \
+       glom/libglom/sql_utils.h \
        glom/libglom/utils.cc                                           \
        glom/libglom/utils.h                                            \
        glom/libglom/xsl_utils.cc                                       \
diff --git a/glom/libglom/report_builder.cc b/glom/libglom/report_builder.cc
index a9444bf..1394d5e 100644
--- a/glom/libglom/report_builder.cc
+++ b/glom/libglom/report_builder.cc
@@ -23,6 +23,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
 #include <libglom/file_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/xsl_utils.h>
 #include <libglom/xml_utils.h>
 #include <iostream>
diff --git a/glom/libglom/sql_utils.cc b/glom/libglom/sql_utils.cc
new file mode 100644
index 0000000..514d292
--- /dev/null
+++ b/glom/libglom/sql_utils.cc
@@ -0,0 +1,574 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
+#include <libglom/data_structure/glomconversions.h>
+#include <libglom/connectionpool.h>
+#include <libglom/sql_utils.h>
+#include <libglom/algorithms_utils.h>
+#include <iostream>
+
+namespace Glom
+{
+
+namespace Utils
+{
+
+template
+        <typename T_Container>
+auto find_if_uses_relationship_has_relationship(T_Container& container, const std::shared_ptr<const 
UsesRelationship> uses_relationship_name, bool first_level_only = false) -> decltype(container.begin())
+{
+  const Glib::ustring relationship_name(uses_relationship_name->get_relationship_name());
+  Glib::ustring related_relationship_name(uses_relationship_name->get_related_relationship_name());
+
+  //If first_level_only, search for relationships that have the same top-level relationship, but have no 
related relationship.
+  if(first_level_only)
+    related_relationship_name = Glib::ustring();
+
+  return find_if(container,
+                        [&relationship_name, &related_relationship_name](const typename 
T_Container::value_type& element)
+                        {
+                          //Assume that element is a shared_ptr<>.
+
+                          return (element->get_relationship_name() == relationship_name) && 
(element->get_related_relationship_name() == related_relationship_name);
+                        }
+  );
+}
+
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(const Glib::ustring& table_name, 
const type_vecLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const std::shared_ptr<const 
Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
+{
+  //TODO_Performance:
+  type_vecConstLayoutFields constFieldsToGet;
+  copy(fieldsToGet, constFieldsToGet);
+
+  return build_sql_select_with_where_clause(table_name, constFieldsToGet, where_clause, extra_join, 
sort_clause, limit);
+}
+
+/** Build a SQL query to discover how many rows a SQL query would return if it was run.
+ *
+ * This uses a COUNT * on a the @a sql_query as a sub-statement.
+ * Be careful not to include ORDER BY clauses in the supplied SQL query, because that would make it 
unnecessarily slow.
+ *
+ * @sql_query A SQL query.
+ * @result The number of rows.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_count_rows(const Glib::RefPtr<const 
Gnome::Gda::SqlBuilder>& sql_query)
+{
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> result;
+
+  if(!sql_query)
+  {
+    std::cerr << G_STRFUNC << ": sql_query was null.\n";
+    return result;
+  }
+
+  result = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+
+  //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 guint target_id = result->add_sub_select( sql_query->get_sql_statement() );
+  result->select_add_target_id(target_id, "glomarbitraryalias");
+
+  const Gnome::Gda::SqlBuilder::Id id_function = result->add_function("COUNT", result->add_id("*"));
+  result->add_field_value_id(id_function);
+
+  return result;
+}
+
+typedef std::list< std::shared_ptr<const UsesRelationship> > type_list_relationships;
+
+static void add_to_relationships_list(type_list_relationships& list_relationships, const 
std::shared_ptr<const LayoutItem_Field>& layout_item)
+{
+  g_return_if_fail(layout_item);
+
+  if(!(layout_item->get_has_relationship_name()))
+    return;
+
+  //If this is a related relationship, add the first-level relationship too, so that the related 
relationship can be defined in terms of it:
+  auto iterFind = find_if_uses_relationship_has_relationship(list_relationships, layout_item, true /* 
top_level_only */);
+  if(iterFind == list_relationships.end()) //If the table is not yet in the list:
+  {
+    auto uses_rel = std::make_shared<UsesRelationship>();
+    uses_rel->set_relationship(layout_item->get_relationship());
+    list_relationships.emplace_front(uses_rel); //These need to be at the front, so that related 
relationships can use them later in the SQL statement.
+  }
+
+  //Add the relationship to the list:
+  iterFind = find_if_uses_relationship_has_relationship(list_relationships, layout_item);
+  if(iterFind == list_relationships.end()) //If the table is not yet in the list:
+  {
+    auto uses_rel = std::make_shared<UsesRelationship>();
+    uses_rel->set_relationship(layout_item->get_relationship());
+    uses_rel->set_related_relationship(layout_item->get_related_relationship());
+    list_relationships.emplace_back(uses_rel);
+  }
+
+}
+
+static void builder_add_join(const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder, const 
std::shared_ptr<const UsesRelationship>& uses_relationship)
+{
+  auto relationship = uses_relationship->get_relationship();
+  if(!relationship->get_has_fields()) //TODO: Handle related_record has_fields.
+  {
+    if(relationship->get_has_to_table())
+    {
+      //It is a relationship that only specifies the table, without specifying linking fields:
+      builder->select_add_target(relationship->get_to_table());
+    }
+
+    return;
+  }
+
+  // Define the alias name as returned by get_sql_join_alias_name():
+
+  // Specify an alias, to avoid ambiguity when using 2 relationships to the same table.
+  const Glib::ustring alias_name = uses_relationship->get_sql_join_alias_name();
+
+  // Add the JOIN:
+  if(!uses_relationship->get_has_related_relationship_name())
+  {
+    const guint to_target_id = builder->select_add_target(relationship->get_to_table(), alias_name);
+
+    builder->select_join_targets(
+            builder->select_add_target(relationship->get_from_table()),
+            to_target_id,
+            Gnome::Gda::SQL_SELECT_JOIN_LEFT,
+            builder->add_cond(
+                    Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                    builder->add_field_id(relationship->get_from_field(), relationship->get_from_table()),
+                    builder->add_field_id(relationship->get_to_field(), alias_name)));
+  }
+  else
+  {
+    UsesRelationship parent_relationship;
+    parent_relationship.set_relationship(relationship);
+    auto related_relationship = uses_relationship->get_related_relationship();
+
+    const guint to_target_id = builder->select_add_target(related_relationship->get_to_table(), alias_name);
+
+    builder->select_join_targets(
+            builder->select_add_target(relationship->get_from_table()), //TODO: Must we use the ID from 
select_add_target_id()?
+            to_target_id,
+            Gnome::Gda::SQL_SELECT_JOIN_LEFT,
+            builder->add_cond(
+                    Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                    builder->add_field_id(related_relationship->get_from_field(), 
parent_relationship.get_sql_join_alias_name()),
+                    builder->add_field_id(related_relationship->get_to_field(), alias_name) ) );
+  }
+}
+
+void build_sql_select_add_fields_to_get(const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder, const 
Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const type_sort_clause& sort_clause, 
bool extra_join)
+{
+  //Get all relationships used in the query:
+  type_list_relationships list_relationships;
+
+  for(const auto& layout_item : fieldsToGet)
+  {
+    add_to_relationships_list(list_relationships, layout_item);
+  }
+
+  for(const auto& the_pair : sort_clause)
+  {
+    add_to_relationships_list(list_relationships, the_pair.first);
+  }
+
+
+  //LEFT OUTER JOIN will get the field values from the other tables,
+  //and give us our fields for this table even if there is no corresponding value in the other table.
+  for(const auto& uses_relationship : list_relationships)
+  {
+    builder_add_join(builder, uses_relationship);
+  }
+
+  bool one_added = false;
+  for(const auto& layout_item : fieldsToGet)
+  {
+    Glib::ustring one_sql_part;
+
+    if(!layout_item)
+    {
+      g_warn_if_reached();
+      continue;
+    }
+
+    //Get the parent, such as the table name, or the alias name for the join:
+    const Glib::ustring parent = layout_item->get_sql_table_or_join_alias_name(table_name);
+
+    //TODO: Use std::dynamic_pointer_cast?
+    const auto fieldsummary = dynamic_cast<const LayoutItem_FieldSummary*>(layout_item.get());
+    if(fieldsummary)
+    {
+      const Gnome::Gda::SqlBuilder::Id id_function = builder->add_function(
+              fieldsummary->get_summary_type_sql(),
+              builder->add_field_id(layout_item->get_name(), table_name));
+      builder->add_field_value_id(id_function);
+    }
+    else
+    {
+      const Glib::ustring field_name = layout_item->get_name();
+      if(!field_name.empty())
+      {
+        const Gnome::Gda::SqlBuilder::Id id = builder->select_add_field(field_name, parent);
+
+        //Avoid duplicate records with doubly-related fields:
+        if(extra_join)
+          builder->select_group_by(id);
+      }
+    }
+
+
+    one_added = true;
+  }
+
+  if(!one_added)
+  {
+    std::cerr << G_STRFUNC << ": No fields added: fieldsToGet.size()=" << fieldsToGet.size() << std::endl;
+    return;
+  }
+}
+
+
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(const Glib::ustring& table_name, 
const type_vecConstLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const 
std::shared_ptr<const Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
+{
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder;
+
+  //Build the whole SQL statement:
+  try
+  {
+    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+    builder->select_add_target(table_name);
+
+    //Add the fields to SELECT, plus the tables that they are selected FROM.
+    //We tell it whether extra_join is empty, so it can do an extra GROUP BY if necessary.
+    //TODO: Try to use DISTINCT instead, with a proper test case.
+    build_sql_select_add_fields_to_get(builder, table_name, fieldsToGet, sort_clause, (bool)extra_join);
+
+    if(extra_join)
+    {
+      auto uses_relationship = std::make_shared<UsesRelationship>();
+      uses_relationship->set_relationship(extra_join);
+      builder_add_join(builder, uses_relationship);
+    }
+
+    //Add the WHERE clause:
+    if(!where_clause.empty())
+    {
+      const int id = builder->import_expression(where_clause);
+      builder->set_where(id);
+    }
+
+    //Sort clause:
+    if(!sort_clause.empty())
+    {
+      for(const auto& the_pair : sort_clause)
+      {
+        auto layout_item = the_pair.first;
+        if(layout_item)
+        {
+          const auto ascending = the_pair.second;
+
+          //TODO: Avoid the need for the "."
+          builder->select_order_by(
+                  builder->add_field_id(layout_item->get_name(), 
layout_item->get_sql_table_or_join_alias_name(table_name)),
+                  ascending);
+        }
+      }
+    }
+
+    //LIMIT clause:
+    if(limit > 0)
+    {
+      builder->select_set_limit(limit);
+    }
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << G_STRFUNC << ": Exception: " << ex.what() << std::endl;
+  }
+
+  return builder;
+}
+
+
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(const Glib::ustring& table_name, const 
type_vecLayoutFields& fieldsToGet, const std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& 
key_value, const type_sort_clause& sort_clause, guint limit)
+{
+  //TODO_Performance:
+  type_vecConstLayoutFields constFieldsToGet;
+  copy(fieldsToGet, constFieldsToGet);
+
+  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value, sort_clause, limit);
+}
+
+Gnome::Gda::SqlExpr build_simple_where_expression(const Glib::ustring& table_name, const 
std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
+{
+  if(!key_field)
+  {
+    std::cerr << G_STRFUNC << ": key_field was empty\n";
+    return Gnome::Gda::SqlExpr();
+  }
+
+  auto builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_target(table_name);  //This might not be necessary.
+  const Gnome::Gda::SqlBuilder::Id id = builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
+                                                          builder->add_field_id(key_field->get_name(), 
table_name),
+                                                          builder->add_expr(key_value));
+  builder->set_where(id); //This might not be necessary.
+
+  return builder->export_expression(id);
+}
+
+Gnome::Gda::SqlExpr build_combined_where_expression(const Gnome::Gda::SqlExpr& a, const Gnome::Gda::SqlExpr& 
b, Gnome::Gda::SqlOperatorType op)
+{
+  auto builder =
+          Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+
+  const Gnome::Gda::SqlBuilder::Id id = builder->add_cond(op,
+                                                          builder->import_expression(a),
+                                                          builder->import_expression(b));
+  builder->set_where(id);
+  return builder->export_expression(id);
+}
+
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(const Glib::ustring& table_name, const 
type_vecConstLayoutFields& fieldsToGet, const std::shared_ptr<const Field>& key_field, const 
Gnome::Gda::Value& key_value, const type_sort_clause& sort_clause, guint limit)
+{
+  //We choose instead to have no where clause in this case,
+  //because that is useful to some callers:
+  //if(Conversions::value_is_empty(key_value)) //If there is a record to show:
+  //  return Glib::RefPtr<Gnome::Gda::SqlBuilder>();
+
+  Gnome::Gda::SqlExpr where_clause;
+  if(!Conversions::value_is_empty(key_value) && key_field)
+  {
+    where_clause = build_simple_where_expression(table_name, key_field, key_value);
+  }
+
+  return build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause,
+                                                   std::shared_ptr<const Relationship>(), sort_clause, 
limit);
+}
+
+
+//TODO: This is a duplicate of the one in db_utils.cc:
+//Merge all db utilities into db_utils in glom 1.24:
+static Glib::RefPtr<Gnome::Gda::Connection> get_connection()
+{
+  std::shared_ptr<SharedConnection> sharedconnection;
+  try
+  {
+    sharedconnection = ConnectionPool::get_and_connect();
+  }
+  catch(const Glib::Error& error)
+  {
+    std::cerr << G_STRFUNC << ": " << error.what() << std::endl;
+  }
+
+  if(!sharedconnection)
+  {
+    std::cerr << G_STRFUNC << ": No connection yet.\n";
+    return Glib::RefPtr<Gnome::Gda::Connection>();
+  }
+
+  auto gda_connection = sharedconnection->get_gda_connection();
+
+  return gda_connection;
+}
+
+
+std::string sqlbuilder_get_full_query(
+        const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder)
+{
+  auto connection = get_connection();
+  if(!connection)
+  {
+    //TODO: Just use the correct provider, without an actual connection?
+    std::cerr << G_STRFUNC << ": There is no connection, so the SQL statement might not be created 
correctly.\n";
+  }
+
+  Glib::ustring result = "glom_query_not_parsed";
+
+  try
+  {
+    auto stmt = builder->get_statement();
+    if(!stmt)
+    {
+      std::cerr << G_STRFUNC << ": builder->get_statement() failed.\n";
+      return result;
+    }
+
+    if(connection)
+    {
+      result = connection->statement_to_sql(stmt,
+                                            Gnome::Gda::STATEMENT_SQL_PARAMS_AS_VALUES | 
Gnome::Gda::STATEMENT_SQL_PRETTY);
+    }
+    else
+      result = stmt->to_sql();
+  }
+  catch(const Gnome::Gda::SqlError& ex)
+  {
+    std::cerr << G_STRFUNC << ": SqlError exception while getting query: " << ex.what() << std::endl;
+  }
+  catch(const Glib::Exception& ex)
+  {
+    std::cerr << G_STRFUNC << ": exception (" << typeid(ex).name() << ") while getting query: " << ex.what() 
<< std::endl;
+  }
+  catch(const std::exception& ex)
+  {
+    std::cerr << G_STRFUNC << ": exception (" << typeid(ex).name() << ") while getting query: " << ex.what() 
<< std::endl;
+  }
+
+  //Convert to something that std::cout should be able to handle.
+  const auto buf = Glib::make_unique_ptr_gfree(g_convert_with_fallback(
+          result.raw().data(), result.raw().size(),
+          "ISO-8859-1", "UTF-8",
+          (char*)"?",
+          0, 0, 0));
+
+  const Glib::ustring str = std::string(buf.get());
+  if(str.empty())
+  {
+    std::cerr << G_STRFUNC << ": Returning an empty string.\n";
+  }
+
+  return str;
+}
+
+Gnome::Gda::SqlExpr get_find_where_clause_quick(const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name, const Gnome::Gda::Value& quick_search)
+{
+  if(table_name.empty())
+  {
+    std::cerr << G_STRFUNC << ": table_name is empty.\n";
+    return Gnome::Gda::SqlExpr();
+  }
+
+  if(Conversions::value_is_empty(quick_search))
+    return Gnome::Gda::SqlExpr();
+
+  auto builder =
+          Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+  builder->select_add_target(table_name);
+
+  //We need to add some fields to select,
+  //because otherwise the SqlBuilder would not contain a valid query.
+  builder->select_add_field("*", table_name);
+
+  if(!document)
+  {
+    std::cerr << G_STRFUNC << ": document was null.\n";
+    return Gnome::Gda::SqlExpr();
+  }
+
+  //We need the connection to generate the correct SQL syntax:
+  auto connection = get_connection();
+  if(!connection)
+  {
+    std::cerr << G_STRFUNC << ": connection was null.\n";
+    return Gnome::Gda::SqlExpr();
+  }
+
+  //TODO: Cache the list of all fields, as well as caching (m_Fields) the list of all visible fields:
+  const Document::type_vec_fields fields = document->get_table_fields(table_name);
+
+  guint previous_id = 0;
+  for(const auto& field : fields)
+  {
+    Glib::ustring strClausePart;
+
+    bool use_this_field = true;
+    if(field->get_glom_type() != Field::glom_field_type::TEXT)
+    {
+      use_this_field = false;
+    }
+
+    if(use_this_field)
+    {
+      //std::cout << "Using field: " << field->get_name() << std::endl;
+      const guint eq_id = builder->add_cond(field->sql_find_operator(),
+                                            builder->add_field_id(field->get_name(), table_name),
+                                            builder->add_expr( field->sql_find(quick_search, connection) )); 
//sql_find() modifies the value for the operator.
+
+      if(previous_id)
+      {
+        const guint or_id = builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_OR,
+                                              previous_id, eq_id);
+        previous_id = or_id;
+      }
+      else
+        previous_id = eq_id;
+    }
+  }
+
+  if(previous_id)
+  {
+    builder->set_where(previous_id); //This might be unnecessary.
+    //std::cout << G_STRFUNC << ": builder: " << sqlbuilder_get_full_query(builder) << std::endl;
+    return builder->export_expression(previous_id);
+  }
+  else
+  {
+    std::cerr << G_STRFUNC << ": Returning null SqlExpr\n";
+    return Gnome::Gda::SqlExpr();
+  }
+}
+
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_update_with_where_clause(
+        const Glib::ustring& table_name,
+        const std::shared_ptr<const Field>& field, const Gnome::Gda::Value& value,
+        const Gnome::Gda::SqlExpr& where_clause)
+{
+  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder;
+
+  if(!field || field->get_name().empty())
+  {
+    std::cerr << G_STRFUNC << ": field was null or its name was empty.\n";
+    return builder;
+  }
+
+  if(table_name.empty())
+  {
+    std::cerr << G_STRFUNC << ": table_name was empty.\n";
+    return builder;
+  }
+
+  //Build the whole SQL statement:
+  try
+  {
+    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
+    builder->set_table(table_name);
+
+    builder->add_field_value_as_value(field->get_name(), value);
+
+    //Add the WHERE clause:
+    if(!where_clause.empty())
+    {
+      const int id = builder->import_expression(where_clause);
+      builder->set_where(id);
+    }
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << G_STRFUNC << ": Exception: " << ex.what() << std::endl;
+  }
+
+  return builder;
+}
+
+} //namespace Utils
+
+} //namespace Glom
+
diff --git a/glom/libglom/sql_utils.h b/glom/libglom/sql_utils.h
new file mode 100644
index 0000000..c7b852c
--- /dev/null
+++ b/glom/libglom/sql_utils.h
@@ -0,0 +1,132 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GLOM_SQL_UTILS_H
+#define GLOM_SQL_UTILS_H
+
+#include <libglom/document/document.h>
+#include <libglom/data_structure/layout/layoutitem_field.h>
+#include <libgdamm/sqlbuilder.h>
+#include <libgdamm/sqlexpr.h>
+
+
+namespace Glom
+{
+
+///field, ascending
+typedef std::pair< std::shared_ptr<const LayoutItem_Field>, bool> type_pair_sort_field;
+typedef std::vector<type_pair_sort_field> type_sort_clause;
+
+namespace Utils
+{
+
+typedef std::vector< std::shared_ptr<const LayoutItem_Field> > type_vecConstLayoutFields;
+
+//typedef Base_DB::type_vecLayoutFields type_vecLayoutFields;
+typedef std::vector< std::shared_ptr<LayoutItem_Field> > type_vecLayoutFields;
+
+// Create a Gnome::Gda::SqlExpr.
+Gnome::Gda::SqlExpr build_simple_where_expression(const Glib::ustring& table_name, const 
std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& key_value);
+
+// Create a where clause that is two other conditions combined together.
+Gnome::Gda::SqlExpr build_combined_where_expression(const Gnome::Gda::SqlExpr& a, const Gnome::Gda::SqlExpr& 
b, Gnome::Gda::SqlOperatorType op);
+
+/** Generate a SQL statement to SELECT field values,
+ * even if the fields are in related (or doubly related) records.
+ */
+void build_sql_select_add_fields_to_get(
+        const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder,
+        const Glib::ustring& table_name,
+        const type_vecConstLayoutFields& fieldsToGet,
+        const type_sort_clause& sort_clause,
+        bool extra_join);
+
+/** Generate a SQL statement to SELECT field values,
+ * even if the fields are in related (or doubly related) records,
+ * narrowing the records down with a WHERE clause.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(
+        const Glib::ustring& table_name,
+        const type_vecLayoutFields& fieldsToGet,
+        const Gnome::Gda::SqlExpr& where_clause = Gnome::Gda::SqlExpr(),
+        const std::shared_ptr<const Relationship>& extra_join = std::shared_ptr<const Relationship>(),
+        const type_sort_clause& sort_clause = type_sort_clause(),
+        guint limit = 0);
+
+/** Just a version of build_sql_select_with_where_clause() that takes a list of const fields.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(
+        const Glib::ustring& table_name,
+        const type_vecConstLayoutFields& fieldsToGet,
+        const Gnome::Gda::SqlExpr& where_clause = Gnome::Gda::SqlExpr(),
+        const std::shared_ptr<const Relationship>& extra_join = std::shared_ptr<const Relationship>(),
+        const type_sort_clause& sort_clause = type_sort_clause(),
+        guint limit = 0);
+
+/**
+ * @param key_value If this is empty then all records in the tables will be retrieved.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
+        const Glib::ustring& table_name,
+        const type_vecLayoutFields& fieldsToGet,
+        const std::shared_ptr<const Field>& key_field,
+        const Gnome::Gda::Value& key_value,
+        const type_sort_clause& sort_clause = type_sort_clause(),
+        guint limit = 0);
+
+/** Just a version of build_sql_select_with_key() that takes a list of const fields.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
+        const Glib::ustring& table_name,
+        const type_vecConstLayoutFields& fieldsToGet,
+        const std::shared_ptr<const Field>& key_field,
+        const Gnome::Gda::Value& key_value,
+        const type_sort_clause& sort_clause = type_sort_clause(),
+        guint limit = 0);
+
+//Note: This is not used by glom itself, but it is used by java-libglom.
+/** Build a SQL query to discover how many rows a SQL query would return if it was run.
+ *
+ * This uses a COUNT * on a the @a sql_query as a sub-statement.
+ * Be careful not to include ORDER BY clauses in the supplied SQL query, because that would make it 
unnecessarily slow.
+ *
+ * @param sql_query A SQL query.
+ * @result The number of rows.
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_count_rows(const Glib::RefPtr<const 
Gnome::Gda::SqlBuilder>& sql_query);
+
+Gnome::Gda::SqlExpr get_find_where_clause_quick(const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name, const Gnome::Gda::Value& quick_search);
+
+/** Generate a SQL statement to UPDATE field values,
+ */
+Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_update_with_where_clause(
+        const Glib::ustring& table_name,
+        const std::shared_ptr<const Field>& field, const Gnome::Gda::Value& value,
+        const Gnome::Gda::SqlExpr& where_clause);
+
+/// Get the full query string suitable for use with std::cout.
+std::string sqlbuilder_get_full_query(
+        const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder);
+
+} //namespace Utils
+
+} //namespace Glom
+
+#endif //GLOM_SQL_UTILS_H
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index 5216d81..702a78d 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -54,464 +54,6 @@
 namespace Glom
 {
 
-template
-<typename T_Container>
-auto find_if_uses_relationship_has_relationship(T_Container& container, const std::shared_ptr<const 
UsesRelationship> uses_relationship_name, bool first_level_only = false) -> decltype(container.begin())
-{
-  const Glib::ustring relationship_name(uses_relationship_name->get_relationship_name());
-  Glib::ustring related_relationship_name(uses_relationship_name->get_related_relationship_name());
-
-  //If first_level_only, search for relationships that have the same top-level relationship, but have no 
related relationship.
-  if(first_level_only)
-    related_relationship_name = Glib::ustring();
-
-  return Utils::find_if(container,
-    [&relationship_name, &related_relationship_name](const typename T_Container::value_type& element)
-    {
-      //Assume that element is a shared_ptr<>.
-
-      return (element->get_relationship_name() == relationship_name) && 
(element->get_related_relationship_name() == related_relationship_name);
-    }
-  );
-}
-
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_where_clause(const Glib::ustring& 
table_name, const type_vecLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const 
std::shared_ptr<const Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
-{
-  //TODO_Performance:
-  type_vecConstLayoutFields constFieldsToGet;
-  Utils::copy(fieldsToGet, constFieldsToGet);
-
-  return build_sql_select_with_where_clause(table_name, constFieldsToGet, where_clause, extra_join, 
sort_clause, limit);
-}
-
-/** Build a SQL query to discover how many rows a SQL query would return if it was run.
- *
- * This uses a COUNT * on a the @a sql_query as a sub-statement.
- * Be careful not to include ORDER BY clauses in the supplied SQL query, because that would make it 
unnecessarily slow.
- *
- * @sql_query A SQL query.
- * @result The number of rows.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_count_rows(const Glib::RefPtr<const 
Gnome::Gda::SqlBuilder>& sql_query)
-{
-  Glib::RefPtr<Gnome::Gda::SqlBuilder> result;
-
-  if(!sql_query)
-  {
-    std::cerr << G_STRFUNC << ": sql_query was null.\n";
-    return result;
-  }
-
-  result = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-
-  //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 guint target_id = result->add_sub_select( sql_query->get_sql_statement() );
-  result->select_add_target_id(target_id, "glomarbitraryalias");
-
-  const Gnome::Gda::SqlBuilder::Id id_function = result->add_function("COUNT", result->add_id("*"));
-  result->add_field_value_id(id_function);
-
-  return result;
-}
-
-typedef std::list< std::shared_ptr<const UsesRelationship> > type_list_relationships;
-
-static void add_to_relationships_list(type_list_relationships& list_relationships, const 
std::shared_ptr<const LayoutItem_Field>& layout_item)
-{
-  g_return_if_fail(layout_item);
-
-  if(!(layout_item->get_has_relationship_name()))
-    return;
-
-  //If this is a related relationship, add the first-level relationship too, so that the related 
relationship can be defined in terms of it:
-  auto iterFind = find_if_uses_relationship_has_relationship(list_relationships, layout_item, true /* 
top_level_only */);
-  if(iterFind == list_relationships.end()) //If the table is not yet in the list:
-  {
-    auto uses_rel = std::make_shared<UsesRelationship>();
-    uses_rel->set_relationship(layout_item->get_relationship());
-    list_relationships.emplace_front(uses_rel); //These need to be at the front, so that related 
relationships can use them later in the SQL statement.
-  }
-
-  //Add the relationship to the list:
-  iterFind = find_if_uses_relationship_has_relationship(list_relationships, layout_item);
-  if(iterFind == list_relationships.end()) //If the table is not yet in the list:
-  {
-    auto uses_rel = std::make_shared<UsesRelationship>();
-    uses_rel->set_relationship(layout_item->get_relationship());
-    uses_rel->set_related_relationship(layout_item->get_related_relationship());
-    list_relationships.emplace_back(uses_rel);
-  }
-
-}
-
-static void builder_add_join(const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder, const 
std::shared_ptr<const UsesRelationship>& uses_relationship)
-{
-  auto relationship = uses_relationship->get_relationship();
-  if(!relationship->get_has_fields()) //TODO: Handle related_record has_fields.
-  {
-    if(relationship->get_has_to_table())
-    {
-      //It is a relationship that only specifies the table, without specifying linking fields:
-      builder->select_add_target(relationship->get_to_table());
-    }
-
-    return;
-  }
-
-  // Define the alias name as returned by get_sql_join_alias_name():
-
-  // Specify an alias, to avoid ambiguity when using 2 relationships to the same table.
-  const Glib::ustring alias_name = uses_relationship->get_sql_join_alias_name();
-
-  // Add the JOIN:
-  if(!uses_relationship->get_has_related_relationship_name())
-  {
-    const guint to_target_id = builder->select_add_target(relationship->get_to_table(), alias_name);
-
-    builder->select_join_targets(
-      builder->select_add_target(relationship->get_from_table()),
-      to_target_id,
-      Gnome::Gda::SQL_SELECT_JOIN_LEFT,
-      builder->add_cond(
-        Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
-        builder->add_field_id(relationship->get_from_field(), relationship->get_from_table()),
-        builder->add_field_id(relationship->get_to_field(), alias_name)));
-  }
-  else
-  {
-     UsesRelationship parent_relationship;
-     parent_relationship.set_relationship(relationship);
-     auto related_relationship = uses_relationship->get_related_relationship();
-
-     const guint to_target_id = builder->select_add_target(related_relationship->get_to_table(), alias_name);
-
-     builder->select_join_targets(
-       builder->select_add_target(relationship->get_from_table()), //TODO: Must we use the ID from 
select_add_target_id()?
-       to_target_id,
-       Gnome::Gda::SQL_SELECT_JOIN_LEFT,
-       builder->add_cond(
-         Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
-         builder->add_field_id(related_relationship->get_from_field(), 
parent_relationship.get_sql_join_alias_name()),
-         builder->add_field_id(related_relationship->get_to_field(), alias_name) ) );
-  }
-}
-
-void Utils::build_sql_select_add_fields_to_get(const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder, const 
Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const type_sort_clause& sort_clause, 
bool extra_join)
-{
-  //Get all relationships used in the query:
-  type_list_relationships list_relationships;
-
-  for(const auto& layout_item : fieldsToGet)
-  {
-    add_to_relationships_list(list_relationships, layout_item);
-  }
-
-  for(const auto& the_pair : sort_clause)
-  {
-    add_to_relationships_list(list_relationships, the_pair.first);
-  }
-
-
-  //LEFT OUTER JOIN will get the field values from the other tables,
-  //and give us our fields for this table even if there is no corresponding value in the other table.
-  for(const auto& uses_relationship : list_relationships)
-  {
-    builder_add_join(builder, uses_relationship);
-  }
-
-  bool one_added = false;
-  for(const auto& layout_item : fieldsToGet)
-  {
-    Glib::ustring one_sql_part;
-
-    if(!layout_item)
-    {
-      g_warn_if_reached();
-      continue;
-    }
-
-    //Get the parent, such as the table name, or the alias name for the join:
-    const Glib::ustring parent = layout_item->get_sql_table_or_join_alias_name(table_name);
-
-    //TODO: Use std::dynamic_pointer_cast?
-    const auto fieldsummary = dynamic_cast<const LayoutItem_FieldSummary*>(layout_item.get());
-    if(fieldsummary)
-    {
-      const Gnome::Gda::SqlBuilder::Id id_function = builder->add_function(
-        fieldsummary->get_summary_type_sql(),
-        builder->add_field_id(layout_item->get_name(), table_name));
-      builder->add_field_value_id(id_function);
-    }
-    else
-    {
-      const Glib::ustring field_name = layout_item->get_name();
-      if(!field_name.empty())
-      {
-        const Gnome::Gda::SqlBuilder::Id id = builder->select_add_field(field_name, parent);
-
-        //Avoid duplicate records with doubly-related fields:
-        if(extra_join)
-          builder->select_group_by(id);
-      }
-    }
-
-
-    one_added = true;
-  }
-
-  if(!one_added)
-  {
-    std::cerr << G_STRFUNC << ": No fields added: fieldsToGet.size()=" << fieldsToGet.size() << std::endl;
-    return;
-  }
-}
-
-
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_where_clause(const Glib::ustring& 
table_name, const type_vecConstLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const 
std::shared_ptr<const Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
-{
-  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder;
-
-  //Build the whole SQL statement:
-  try
-  {
-    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-    builder->select_add_target(table_name);
-
-    //Add the fields to SELECT, plus the tables that they are selected FROM.
-    //We tell it whether extra_join is empty, so it can do an extra GROUP BY if necessary.
-    //TODO: Try to use DISTINCT instead, with a proper test case.
-    Utils::build_sql_select_add_fields_to_get(builder, table_name, fieldsToGet, sort_clause, 
(bool)extra_join);
-
-    if(extra_join)
-    {
-      auto uses_relationship = std::make_shared<UsesRelationship>();
-      uses_relationship->set_relationship(extra_join);
-      builder_add_join(builder, uses_relationship);
-    }
-
-    //Add the WHERE clause:
-    if(!where_clause.empty())
-    {
-      const int id = builder->import_expression(where_clause);
-      builder->set_where(id);
-    }
-
-    //Sort clause:
-    if(!sort_clause.empty())
-    {
-      for(const auto& the_pair : sort_clause)
-      {
-        auto layout_item = the_pair.first;
-        if(layout_item)
-        {
-          const auto ascending = the_pair.second;
-
-          //TODO: Avoid the need for the "."
-          builder->select_order_by(
-            builder->add_field_id(layout_item->get_name(), 
layout_item->get_sql_table_or_join_alias_name(table_name)),
-            ascending);
-        }
-      }
-    }
-
-    //LIMIT clause:
-    if(limit > 0)
-    {
-      builder->select_set_limit(limit);
-    }
-  }
-  catch(const Glib::Error& ex)
-  {
-    std::cerr << G_STRFUNC << ": Exception: " << ex.what() << std::endl;
-  }
-
-  return builder;
-}
-
-
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const 
type_vecLayoutFields& fieldsToGet, const std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& 
key_value, const type_sort_clause& sort_clause, guint limit)
-{
-  //TODO_Performance:
-  type_vecConstLayoutFields constFieldsToGet;
-  Utils::copy(fieldsToGet, constFieldsToGet);
-
-  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value, sort_clause, limit);
-}
-
-Gnome::Gda::SqlExpr Utils::build_simple_where_expression(const Glib::ustring& table_name, const 
std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
-{
-  if(!key_field)
-  {
-    std::cerr << G_STRFUNC << ": key_field was empty\n";
-    return Gnome::Gda::SqlExpr();
-  }
-  
-  auto builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-  builder->select_add_target(table_name);  //This might not be necessary.
-  const Gnome::Gda::SqlBuilder::Id id = builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
-    builder->add_field_id(key_field->get_name(), table_name),
-    builder->add_expr(key_value));
-  builder->set_where(id); //This might not be necessary.
-
-  return builder->export_expression(id);
-}
-
-Gnome::Gda::SqlExpr Utils::build_combined_where_expression(const Gnome::Gda::SqlExpr& a, const 
Gnome::Gda::SqlExpr& b, Gnome::Gda::SqlOperatorType op)
-{
-  auto builder =
-    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-
-  const Gnome::Gda::SqlBuilder::Id id = builder->add_cond(op,
-    builder->import_expression(a),
-    builder->import_expression(b));
-   builder->set_where(id);
-  return builder->export_expression(id);
-}
-
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const 
type_vecConstLayoutFields& fieldsToGet, const std::shared_ptr<const Field>& key_field, const 
Gnome::Gda::Value& key_value, const type_sort_clause& sort_clause, guint limit)
-{
-  //We choose instead to have no where clause in this case,
-  //because that is useful to some callers:
-  //if(Conversions::value_is_empty(key_value)) //If there is a record to show:
-  //  return Glib::RefPtr<Gnome::Gda::SqlBuilder>();
-
-  Gnome::Gda::SqlExpr where_clause;
-  if(!Conversions::value_is_empty(key_value) && key_field)
-  {
-    where_clause = build_simple_where_expression(table_name, key_field, key_value);
-  }
-
-  return Utils::build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause,
-    std::shared_ptr<const Relationship>(), sort_clause, limit);
-}
-
-Utils::type_list_values_with_second Utils::get_choice_values_all(const std::shared_ptr<const Document>& 
document, const std::shared_ptr<const LayoutItem_Field>& field)
-{
-  return get_choice_values(document, field,
-    Gnome::Gda::Value() /* means get all with no WHERE clause */);
-}
-
-Utils::type_list_values_with_second Utils::get_choice_values(const std::shared_ptr<const Document>& 
document, const std::shared_ptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value)
-{
-  //TODO: Reduce duplication between this and get_choice_values(field).
-
-  type_list_values_with_second result;
-
-  //We allows this, so this method can be used to get all records in a related table:
-  /*
-  if(Conversions::value_is_empty(foreign_key_value))
-  {
-    std::cout << G_STRFUNC << "debug: foreign_key_value is empty.\n";
-    return result;
-  }
-  */
-
-  const Formatting& format = field->get_formatting_used();
-  std::shared_ptr<const Relationship> choice_relationship;
-  std::shared_ptr<const LayoutItem_Field> layout_choice_first;
-  std::shared_ptr<const LayoutGroup> layout_choice_extra;
-  Formatting::type_list_sort_fields choice_sort_fields;
-  bool choice_show_all = false;
-  format.get_choices_related(choice_relationship, layout_choice_first, layout_choice_extra, 
choice_sort_fields, choice_show_all);
-
-  if(!choice_relationship)
-  {
-    std::cerr << G_STRFUNC << ": !choice_relationship.\n";
-    return result;
-  }
-
-  Utils::type_vecConstLayoutFields fields;
-  fields.emplace_back(layout_choice_first);
-
-  if(layout_choice_extra)
-  {
-    for(const auto& item : layout_choice_extra->get_items_recursive())
-    {
-      const auto& item_field = std::dynamic_pointer_cast<const LayoutItem_Field>(item);
-      if(item_field)
-         fields.emplace_back(item_field); //TODO: Don't ignore other usable items such as static text.
-    }
-  }
-
-  const Glib::ustring to_table = choice_relationship->get_to_table();
-  const auto to_field = document->get_field(to_table, choice_relationship->get_to_field());
-
-  if(!to_field)
-  {
-    std::cerr << G_STRFUNC << ": to_field is null.\n";
-  }
-
-  //Default to some sort order rather than none:
-  if(choice_sort_fields.empty())
-  {
-    choice_sort_fields.emplace_back( type_pair_sort_field(layout_choice_first, true /* ascending */));
-  }
-
-  //TODO: Support related relationships (in the UI too):
-  auto builder = Utils::build_sql_select_with_key(
-    to_table,
-    fields,
-    to_field,
-    foreign_key_value,
-    choice_sort_fields);
-
-  if(!builder)
-  {
-    std::cerr << G_STRFUNC << ": builder is null.\n";
-    return result;
-  }
-
-  //TODO: builder->select_order_by(choice_field_id);
-
-  //Connect to database and get the related values:
-  auto connection = ConnectionPool::get_instance()->connect();
-
-  if(!connection)
-  {
-    std::cerr << G_STRFUNC << ": connection is null.\n";
-    return result;
-  }
-
-  const std::string sql_query =
-    Utils::sqlbuilder_get_full_query(builder);
-  //std::cout << "debug: sql_query=" << sql_query << std::endl;
-  auto datamodel = connection->get_gda_connection()->statement_execute_select(sql_query);
-
-  if(datamodel)
-  {
-    const guint count = datamodel->get_n_rows();
-    const guint cols_count = datamodel->get_n_columns();
-    for(guint row = 0; row < count; ++row)
-    {
-
-      std::pair<Gnome::Gda::Value, type_list_values> itempair;
-      itempair.first = datamodel->get_value_at(0, row);
-
-      if(layout_choice_extra && (cols_count > 1))
-      {
-        type_list_values list_values;
-        for(guint i = 1; i < cols_count; ++i)
-        {
-          list_values.emplace_back(datamodel->get_value_at(i, row));
-        }
-
-        itempair.second = list_values;
-      }
-
-      result.emplace_back(itempair);
-    }
-  }
-  else
-  {
-      std::cerr << G_STRFUNC << ": Error while executing SQL\n" <<
-                   "  " <<  sql_query << std::endl;
-      return result;
-  }
-
-  return result;
-}
-
 /** Get just the first part of a locale, such as de_DE,
  * ignoring, for instance, .UTF-8 or \ euro at the end.
  */
@@ -577,209 +119,6 @@ Glib::ustring Utils::locale_language_id(const Glib::ustring& locale_id)
   }
 }
 
-//TODO: This is a duplicate of the one in db_utils.cc:
-//Merge all db utilities into db_utils in glom 1.24:
-static Glib::RefPtr<Gnome::Gda::Connection> get_connection()
-{
-  std::shared_ptr<SharedConnection> sharedconnection;
-  try
-  {
-     sharedconnection = ConnectionPool::get_and_connect();
-  }
-  catch(const Glib::Error& error)
-  {
-    std::cerr << G_STRFUNC << ": " << error.what() << std::endl;
-  }
-
-  if(!sharedconnection)
-  {
-    std::cerr << G_STRFUNC << ": No connection yet.\n";
-    return Glib::RefPtr<Gnome::Gda::Connection>();
-  }
-
-  auto gda_connection = sharedconnection->get_gda_connection();
-
-  return gda_connection;
-}
-
-std::string Utils::sqlbuilder_get_full_query(
-  const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder)
-{
-  auto connection = get_connection();
-  if(!connection)
-  {
-    //TODO: Just use the correct provider, without an actual connection?
-    std::cerr << G_STRFUNC << ": There is no connection, so the SQL statement might not be created 
correctly.\n";
-  }
-
-  Glib::ustring result = "glom_query_not_parsed";
-
-  try
-  {
-    auto stmt = builder->get_statement();
-    if(!stmt)
-    {
-      std::cerr << G_STRFUNC << ": builder->get_statement() failed.\n";
-      return result;
-    }
-
-    if(connection)
-    {
-      result = connection->statement_to_sql(stmt,
-          Gnome::Gda::STATEMENT_SQL_PARAMS_AS_VALUES | Gnome::Gda::STATEMENT_SQL_PRETTY);
-    }
-    else
-      result = stmt->to_sql();
-  }
-  catch(const Gnome::Gda::SqlError& ex)
-  {
-    std::cerr << G_STRFUNC << ": SqlError exception while getting query: " << ex.what() << std::endl;
-  }
-  catch(const Glib::Exception& ex)
-  {
-    std::cerr << G_STRFUNC << ": exception (" << typeid(ex).name() << ") while getting query: " << ex.what() 
<< std::endl;
-  }
-  catch(const std::exception& ex)
-  {
-    std::cerr << G_STRFUNC << ": exception (" << typeid(ex).name() << ") while getting query: " << ex.what() 
<< std::endl;
-  }
-
-  //Convert to something that std::cout should be able to handle.
-  const auto buf = Glib::make_unique_ptr_gfree(g_convert_with_fallback(
-    result.raw().data(), result.raw().size(),
-    "ISO-8859-1", "UTF-8",
-    (char*)"?",
-    0, 0, 0));
-
-  const Glib::ustring str = std::string(buf.get());
-  if(str.empty())
-  {
-    std::cerr << G_STRFUNC << ": Returning an empty string.\n";
-  }
-
-  return str;
-}
-
-Gnome::Gda::SqlExpr Utils::get_find_where_clause_quick(const std::shared_ptr<const Document>& document, 
const Glib::ustring& table_name, const Gnome::Gda::Value& quick_search)
-{
-  if(table_name.empty())
-  {
-    std::cerr << G_STRFUNC << ": table_name is empty.\n";
-    return Gnome::Gda::SqlExpr();
-  }
-
-  if(Conversions::value_is_empty(quick_search))
-    return Gnome::Gda::SqlExpr();
-  
-  auto builder =
-    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-  builder->select_add_target(table_name);
-
-  //We need to add some fields to select,
-  //because otherwise the SqlBuilder would not contain a valid query.
-  builder->select_add_field("*", table_name);
-
-  if(!document)
-  {
-    std::cerr << G_STRFUNC << ": document was null.\n";
-    return Gnome::Gda::SqlExpr();
-  }
-
-  //We need the connection to generate the correct SQL syntax:
-  auto connection = get_connection();
-  if(!connection)
-  {
-    std::cerr << G_STRFUNC << ": connection was null.\n";
-    return Gnome::Gda::SqlExpr();
-  }
-
-  //TODO: Cache the list of all fields, as well as caching (m_Fields) the list of all visible fields:
-  const Document::type_vec_fields fields = document->get_table_fields(table_name);
-
-  guint previous_id = 0;
-  for(const auto& field : fields)
-  {
-    Glib::ustring strClausePart;
-
-    bool use_this_field = true;
-    if(field->get_glom_type() != Field::glom_field_type::TEXT)
-    {
-      use_this_field = false;
-    }
-
-    if(use_this_field)
-    {
-      //std::cout << "Using field: " << field->get_name() << std::endl;
-      const guint eq_id = builder->add_cond(field->sql_find_operator(),
-        builder->add_field_id(field->get_name(), table_name),
-        builder->add_expr( field->sql_find(quick_search, connection) )); //sql_find() modifies the value for 
the operator.
-
-      if(previous_id)
-      {
-        const guint or_id = builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_OR,
-          previous_id, eq_id);
-        previous_id = or_id;
-      }
-      else
-        previous_id = eq_id;
-    }
-  }
-
-  if(previous_id)
-  {
-    builder->set_where(previous_id); //This might be unnecessary.
-    //std::cout << G_STRFUNC << ": builder: " << sqlbuilder_get_full_query(builder) << std::endl; 
-    return builder->export_expression(previous_id);
-  }
-  else
-  {
-    std::cerr << G_STRFUNC << ": Returning null SqlExpr\n";
-    return Gnome::Gda::SqlExpr();
-  }
-}
-
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_update_with_where_clause(
-  const Glib::ustring& table_name,
-  const std::shared_ptr<const Field>& field, const Gnome::Gda::Value& value,
-  const Gnome::Gda::SqlExpr& where_clause)
-{
-  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder;
-
-  if(!field || field->get_name().empty())
-  {
-    std::cerr << G_STRFUNC << ": field was null or its name was empty.\n";
-    return builder;
-  }
-
-  if(table_name.empty())
-  {
-    std::cerr << G_STRFUNC << ": table_name was empty.\n";
-    return builder;
-  }
-
-  //Build the whole SQL statement:
-  try
-  {
-    builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
-    builder->set_table(table_name);
-
-    builder->add_field_value_as_value(field->get_name(), value);
-
-    //Add the WHERE clause:
-    if(!where_clause.empty())
-    {
-      const int id = builder->import_expression(where_clause);
-      builder->set_where(id);
-    }
-  }
-  catch(const Glib::Error& ex)
-  {
-    std::cerr << G_STRFUNC << ": Exception: " << ex.what() << std::endl;
-  }
-
-  return builder;
-}
-
 Glib::ustring Utils::get_list_of_layout_items_for_display(const LayoutGroup::type_list_items& 
list_layout_fields)
 {
   Glib::ustring result;
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index 57b4668..f73b637 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -27,114 +27,17 @@
 #include <libglom/data_structure/layout/layoutitem_field.h>
 #include <libglom/algorithms_utils.h>
 
-#include <libgdamm/sqlexpr.h>
 #include <giomm/file.h>
 
 namespace Glom
 {
 
-///field, ascending
-typedef std::pair< std::shared_ptr<const LayoutItem_Field>, bool> type_pair_sort_field;
-typedef std::vector<type_pair_sort_field> type_sort_clause;
-
 namespace Utils
 {
 
-//typedef Base_DB::type_vecLayoutFields type_vecLayoutFields;
-typedef std::vector< std::shared_ptr<LayoutItem_Field> > type_vecLayoutFields;
 typedef std::vector< std::shared_ptr<const LayoutItem_Field> > type_vecConstLayoutFields;
 typedef std::vector< std::shared_ptr<Field> > type_vec_fields;
 
-//TODO: Move these to their own file:
-
-// Create a Gnome::Gda::SqlExpr.
-Gnome::Gda::SqlExpr build_simple_where_expression(const Glib::ustring& table_name, const 
std::shared_ptr<const Field>& key_field, const Gnome::Gda::Value& key_value);
-
-// Create a where clause that is two other conditions combined together.
-Gnome::Gda::SqlExpr build_combined_where_expression(const Gnome::Gda::SqlExpr& a, const Gnome::Gda::SqlExpr& 
b, Gnome::Gda::SqlOperatorType op);
-
-/** Generate a SQL statement to SELECT field values,
- * even if the fields are in related (or doubly related) records.
- */
-void build_sql_select_add_fields_to_get(
-  const Glib::RefPtr<Gnome::Gda::SqlBuilder>& builder,
-  const Glib::ustring& table_name,
-  const type_vecConstLayoutFields& fieldsToGet,
-  const type_sort_clause& sort_clause,
-  bool extra_join);
-
-/** Generate a SQL statement to SELECT field values,
- * even if the fields are in related (or doubly related) records,
- * narrowing the records down with a WHERE clause.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(
-  const Glib::ustring& table_name,
-  const type_vecLayoutFields& fieldsToGet,
-  const Gnome::Gda::SqlExpr& where_clause = Gnome::Gda::SqlExpr(),
-  const std::shared_ptr<const Relationship>& extra_join = std::shared_ptr<const Relationship>(),
-  const type_sort_clause& sort_clause = type_sort_clause(),
-  guint limit = 0);
-
-/** Just a version of build_sql_select_with_where_clause() that takes a list of const fields.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(
-  const Glib::ustring& table_name,
-  const type_vecConstLayoutFields& fieldsToGet,
-  const Gnome::Gda::SqlExpr& where_clause = Gnome::Gda::SqlExpr(),
-  const std::shared_ptr<const Relationship>& extra_join = std::shared_ptr<const Relationship>(),
-  const type_sort_clause& sort_clause = type_sort_clause(),
-  guint limit = 0);
-
-/**
- * @param key_value If this is empty then all records in the tables will be retrieved.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
-  const Glib::ustring& table_name,
-  const type_vecLayoutFields& fieldsToGet,
-  const std::shared_ptr<const Field>& key_field,
-  const Gnome::Gda::Value& key_value,
-  const type_sort_clause& sort_clause = type_sort_clause(),
-  guint limit = 0);
-
-/** Just a version of build_sql_select_with_key() that takes a list of const fields.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
-  const Glib::ustring& table_name,
-  const type_vecConstLayoutFields& fieldsToGet,
-  const std::shared_ptr<const Field>& key_field,
-  const Gnome::Gda::Value& key_value,
-  const type_sort_clause& sort_clause = type_sort_clause(),
-  guint limit = 0);
-
-//Note: This is not used by glom itself, but it is used by java-libglom.
-/** Build a SQL query to discover how many rows a SQL query would return if it was run.
- *
- * This uses a COUNT * on a the @a sql_query as a sub-statement.
- * Be careful not to include ORDER BY clauses in the supplied SQL query, because that would make it 
unnecessarily slow.
- *
- * @param sql_query A SQL query.
- * @result The number of rows.
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_count_rows(const Glib::RefPtr<const 
Gnome::Gda::SqlBuilder>& sql_query);
-
-Gnome::Gda::SqlExpr get_find_where_clause_quick(const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name, const Gnome::Gda::Value& quick_search);
-
-/** Generate a SQL statement to UPDATE field values,
- */
-Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_update_with_where_clause(
-  const Glib::ustring& table_name,
-  const std::shared_ptr<const Field>& field, const Gnome::Gda::Value& value,
-  const Gnome::Gda::SqlExpr& where_clause);
-
-typedef std::vector<Gnome::Gda::Value> type_list_values;
-typedef std::vector< std::pair<Gnome::Gda::Value, type_list_values> > type_list_values_with_second; //TODO: 
Rename this now that we have more than just 1 extra field.
-type_list_values_with_second get_choice_values_all(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field);
-
-type_list_values_with_second get_choice_values(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value);
-
-/// Get the full query string suitable for use with std::cout.
-std::string sqlbuilder_get_full_query(
-  const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder);
 
 /** Get just the first part of a locale, such as de_DE,
  * ignoring, for instance, .UTF-8 or \ euro at the end.
diff --git a/glom/libglom/xsl_utils.h b/glom/libglom/xsl_utils.h
index 7b6e990..0ebb8bf 100644
--- a/glom/libglom/xsl_utils.h
+++ b/glom/libglom/xsl_utils.h
@@ -31,10 +31,6 @@
 namespace Glom
 {
 
-///field, ascending
-typedef std::pair< std::shared_ptr<const LayoutItem_Field>, bool> type_pair_sort_field;
-typedef std::vector<type_pair_sort_field> type_sort_clause;
-
 namespace GlomXslUtils
 {
 
diff --git a/glom/mode_data/box_data_calendar_related.cc b/glom/mode_data/box_data_calendar_related.cc
index 580ba20..8bfcb7d 100644
--- a/glom/mode_data/box_data_calendar_related.cc
+++ b/glom/mode_data/box_data_calendar_related.cc
@@ -23,8 +23,9 @@
 #include <glom/utils_ui.h>
 #include <glom/appwindow.h>
 #include <libglom/data_structure/glomconversions.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
+#include <libglom/utils.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
 #include <glom/glade_utils.h>
 #include <giomm/menu.h>
diff --git a/glom/mode_data/box_data_details.cc b/glom/mode_data/box_data_details.cc
index 1e3cd5d..2a1d1c3 100644
--- a/glom/mode_data/box_data_details.cc
+++ b/glom/mode_data/box_data_details.cc
@@ -26,6 +26,7 @@
 #include <libglom/data_structure/relationship.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <glom/mode_design/layout/dialog_layout_details.h>
 #include <glom/glade_utils.h>
diff --git a/glom/mode_data/box_data_portal.cc b/glom/mode_data/box_data_portal.cc
index 0ad308b..cd32a2c 100644
--- a/glom/mode_data/box_data_portal.cc
+++ b/glom/mode_data/box_data_portal.cc
@@ -21,6 +21,7 @@
 #include <glom/mode_data/box_data_portal.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <glom/glade_utils.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
diff --git a/glom/mode_data/datawidget/combo_as_radio_buttons.cc 
b/glom/mode_data/datawidget/combo_as_radio_buttons.cc
index cb1de14..e693f62 100644
--- a/glom/mode_data/datawidget/combo_as_radio_buttons.cc
+++ b/glom/mode_data/datawidget/combo_as_radio_buttons.cc
@@ -24,7 +24,7 @@
 #include <glom/dialog_invalid_data.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/appwindow.h>
-#include <libglom/utils.h>
+#include <libglom/db_utils.h>
 #include <glibmm/i18n.h>
 //#include <sstream> //For stringstream
 
@@ -148,8 +148,8 @@ void ComboAsRadioButtons::set_choices_fixed(const Formatting::type_list_values&
 
 void ComboAsRadioButtons::set_choices_related(const std::shared_ptr<const Document>& document, const 
std::shared_ptr<const LayoutItem_Field>& layout_field, const Gnome::Gda::Value& foreign_key_value)
 {
-  const Utils::type_list_values_with_second list_values =
-    Utils::get_choice_values(document, layout_field, foreign_key_value);
+  const auto list_values =
+    DbUtils::get_choice_values(document, layout_field, foreign_key_value);
   set_choices_with_second(list_values);
 }
 
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc 
b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
index b025e9a..9c67490 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
@@ -22,6 +22,7 @@
 #include <glom/mode_data/datawidget/treemodel_db_withextratext.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/privs.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <glom/utils_ui.h>
 #include <glom/appwindow.h>
diff --git a/glom/mode_data/datawidget/dialog_choose_id.cc b/glom/mode_data/datawidget/dialog_choose_id.cc
index dfc5b4c..337d848 100644
--- a/glom/mode_data/datawidget/dialog_choose_id.cc
+++ b/glom/mode_data/datawidget/dialog_choose_id.cc
@@ -21,7 +21,7 @@
 #include "dialog_choose_id.h"
 #include <glom/utils_ui.h> //For bold_message()).
 #include <glom/appwindow.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
diff --git a/glom/mode_data/datawidget/treemodel_db.cc b/glom/mode_data/datawidget/treemodel_db.cc
index 1d4b5bf..cf98abb 100644
--- a/glom/mode_data/datawidget/treemodel_db.cc
+++ b/glom/mode_data/datawidget/treemodel_db.cc
@@ -23,7 +23,7 @@
 
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/glomconversions.h> //For util_build_sql
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
 #include <libgdamm/datamodel.h>
 #include <libgdamm/dataaccesswrapper.h>
diff --git a/glom/mode_data/db_adddel/db_adddel.cc b/glom/mode_data/db_adddel/db_adddel.cc
index 40163c8..a61dfe0 100644
--- a/glom/mode_data/db_adddel/db_adddel.cc
+++ b/glom/mode_data/db_adddel/db_adddel.cc
@@ -1594,7 +1594,7 @@ void DbAddDel::on_treeview_column_clicked(int model_column_index)
 
     //Set the sort clause to be used by refresh_from_database():
     m_found_set.m_sort_clause.clear();
-    m_found_set.m_sort_clause.emplace_back( type_pair_sort_field(layout_item, ascending) );
+    m_found_set.m_sort_clause.emplace_back( Formatting::type_pair_sort_field(layout_item, ascending) );
   }
 
   refresh_from_database();
diff --git a/glom/mode_data/notebook_data.cc b/glom/mode_data/notebook_data.cc
index 46c36f2..e315f7c 100644
--- a/glom/mode_data/notebook_data.cc
+++ b/glom/mode_data/notebook_data.cc
@@ -22,6 +22,7 @@
 #include <glom/signal_reemitter.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <glibmm/main.h>
 #include <glibmm/i18n.h>
 
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index 16370b6..bf9196e 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -33,6 +33,7 @@
 #include <glom/appwindow.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 
 #include <glom/glade_utils.h>
diff --git a/tests/test_fake_connection.cc b/tests/test_fake_connection.cc
index e24166a..5ba141e 100644
--- a/tests/test_fake_connection.cc
+++ b/tests/test_fake_connection.cc
@@ -20,7 +20,7 @@
 
 #include <libglom/document/document.h>
 #include <libglom/init.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
 #include <giomm/file.h>
 #include <glibmm/convert.h>
diff --git a/tests/test_selfhosting_new_from_example_float.cc 
b/tests/test_selfhosting_new_from_example_float.cc
index 3168a10..077e6e0 100644
--- a/tests/test_selfhosting_new_from_example_float.cc
+++ b/tests/test_selfhosting_new_from_example_float.cc
@@ -20,7 +20,7 @@
 
 #include "tests/test_selfhosting_utils.h"
 #include <libglom/init.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/glomconversions.h>
diff --git a/tests/test_selfhosting_new_then_choices.cc b/tests/test_selfhosting_new_then_choices.cc
index da9d1d6..0ed6f35 100644
--- a/tests/test_selfhosting_new_then_choices.cc
+++ b/tests/test_selfhosting_new_then_choices.cc
@@ -35,7 +35,7 @@
 static bool test(Glom::Document::HostingMode hosting_mode)
 {
   auto document = std::make_shared<Glom::Document>();
-  const bool recreated = 
+  const bool recreated =
     test_create_and_selfhost_from_example("example_smallbusiness.glom", document, hosting_mode);
   if(!recreated)
   {
@@ -45,7 +45,7 @@ static bool test(Glom::Document::HostingMode hosting_mode)
   
   const Glib::ustring table_name = "invoice_lines";
  
-  const auto field_with_choice = 
+  const auto field_with_choice =
     get_field_on_layout(document, table_name, table_name, "product_id");
   if(!field_with_choice)
   {
@@ -53,15 +53,15 @@ static bool test(Glom::Document::HostingMode hosting_mode)
     return false;
   }
 
-  const Glom::Utils::type_list_values_with_second values_with_second = 
-    Glom::Utils::get_choice_values_all(document, field_with_choice);
+  const auto values_with_second =
+    Glom::DbUtils::get_choice_values_all(document, field_with_choice);
   if(values_with_second.size() != 3)
   {
     std::cerr << G_STRFUNC << ": Failure: There were an unexpected number of choices.\n";
     return false;
   }
   
-  const std::pair<Gnome::Gda::Value, Glom::Utils::type_list_values> pair_values 
+  const auto pair_values
     = *(values_with_second.begin());
   if(pair_values.second.size() != 1)
   {
diff --git a/tests/test_selfhosting_new_then_image.cc b/tests/test_selfhosting_new_then_image.cc
index 6ab94d8..5b1e98d 100644
--- a/tests/test_selfhosting_new_then_image.cc
+++ b/tests/test_selfhosting_new_then_image.cc
@@ -22,7 +22,7 @@
 #include "tests/test_utils.h"
 #include "tests/test_utils_images.h"
 #include <libglom/init.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
 #include <glibmm/fileutils.h>
 #include <glibmm/miscutils.h>
diff --git a/tests/test_selfhosting_sqlinjection.cc b/tests/test_selfhosting_sqlinjection.cc
index f683ed0..4cd8cc2 100644
--- a/tests/test_selfhosting_sqlinjection.cc
+++ b/tests/test_selfhosting_sqlinjection.cc
@@ -20,7 +20,7 @@
 
 #include "tests/test_selfhosting_utils.h"
 #include <libglom/init.h>
-#include <libglom/utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/db_utils.h>
 #include <libglom/connectionpool.h>
 #include <glib.h> //For g_assert()
diff --git a/tests/test_selfhosting_utils.cc b/tests/test_selfhosting_utils.cc
index 07efa10..bc48b50 100644
--- a/tests/test_selfhosting_utils.cc
+++ b/tests/test_selfhosting_utils.cc
@@ -27,6 +27,7 @@
 #include <libglom/privs.h>
 #include <libglom/db_utils.h>
 #include <libglom/file_utils.h>
+#include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <giomm/file.h>
 #include <glibmm/convert.h>


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