[glom] utils: Move some functions into sql_utils.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] utils: Move some functions into sql_utils.
- Date: Thu, 17 Mar 2016 12:34:54 +0000 (UTC)
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]