~ubuntu-branches/ubuntu/quantal/glom/quantal

« back to all changes in this revision

Viewing changes to glom/base_db.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2009-01-11 17:12:01 UTC
  • mfrom: (1.1.39 upstream)
  • Revision ID: james.westby@ubuntu.com-20090111171201-0ov9zh1fxfueshxc
Tags: 1.8.5-0ubuntu1
* New upstream release (LP: #256701), fixes LP bugs: 
  + Clear the text in property dialogs for text items (LP: #309147)
  + Don't crash when showing and then hiding the grid (LP: #303453)
  + Temporarily remember the sort order so it is the same when navigating 
    away and back (LP: #303422)
  + Use the list's sort order for the top-level records in the report 
    (LP: #303425)
  + Users/Groups: Disable drag-and-drop for the treeview, because it is
    useless and confusing (LP: #299573)
  + Import: Sort the fields list alphabetically (LP: #306593)
  + delete primary key make unusuable the database (LP: #299549)
  + Spanish translate incomplete (LP: #299556)
  + import date format error (LP: #299591)
  + can't delete data from table list view (LP: #299853)
  + Field definition: default value not saved (LP: #299896)
  + reports crashing (LP: #300054)
  + Year error with date fields (LP: #300057)
  + list view: 2 records added instead of 1 (LP: #300819)
* debian/control: Refreshed dependencies for libglom-dev.
* debian/control: Updated build-deps to match configure checks. goocavnasmm
  build-dep bumped to version without .la files.
* debian/rules: Don't delete the directory containing the templates.
* debian/control, debian/rules, debian/glom-doc.*: Split out
  arch-independent manual and examples into separate package glom-doc, which
  is now recommended by glom (glom will still work if they're not available)
* debian/copyright: Rewritten to new machine-readable format. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
//#include "reports/dialog_layout_report.h"
39
39
#include <glom/libglom/utils.h>
 
40
#include <glom/libglom/glade_utils.h>
40
41
#include <glom/libglom/data_structure/glomconversions.h>
41
42
#include <glom/libglom/data_structure/layout/report_parts/layoutitem_summary.h>
42
43
#include <glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
58
59
namespace Glom
59
60
{
60
61
 
61
 
FoundSet::FoundSet()
62
 
{
63
 
}
64
 
 
65
 
FoundSet::FoundSet(const FoundSet& src)
66
 
:  m_table_name(src.m_table_name),
67
 
   m_extra_join(src.m_extra_join),
68
 
   m_where_clause(src.m_where_clause),
69
 
   m_extra_group_by(src.m_extra_group_by),
70
 
   m_sort_clause(src.m_sort_clause)
71
 
{
72
 
}
73
 
 
74
 
FoundSet& FoundSet::operator=(const FoundSet& src)
75
 
{
76
 
  m_table_name = src.m_table_name;
77
 
  m_extra_join = src.m_extra_join;
78
 
  m_where_clause = src.m_where_clause;
79
 
  m_extra_group_by = src.m_extra_group_by;
80
 
  m_sort_clause = src.m_sort_clause;
81
 
 
82
 
  return *this;
83
 
}
84
 
 
85
 
bool FoundSet::operator==(const FoundSet& src) const
86
 
{
87
 
  return (m_table_name == src.m_table_name)
88
 
      && (m_extra_join == src.m_extra_join)
89
 
      && (m_where_clause == src.m_where_clause)
90
 
      && (m_extra_group_by == src.m_extra_group_by)
91
 
      && (m_sort_clause == src.m_sort_clause);
92
 
}
93
 
 
94
 
 
95
62
 
96
63
template<class T_Element>
97
64
class predicate_LayoutItemIsEqual
140
107
  return fill_from_database();
141
108
}
142
109
 
143
 
bool Base_DB::refresh_data_from_database()
144
 
{
145
 
  return fill_from_database();
146
 
}
147
 
 
 
110
//TODO: Remove this?
148
111
bool Base_DB::fill_from_database()
149
112
{
150
113
  //m_AddDel.remove_all();
151
114
  return true;
152
115
}
153
116
 
154
 
void Base_DB::fill_end()
155
 
{
156
 
  //Call this from the end of fill_from_database() overrides.
157
 
}
158
 
 
159
117
//static:
160
118
#ifdef GLIBMM_EXCEPTIONS_ENABLED
161
119
sharedptr<SharedConnection> Base_DB::connect_to_server(Gtk::Window* parent_window)
230
188
      try
231
189
      {
232
190
#endif
233
 
        std::cout << "Debug: query_execute():  " << strQuery << std::endl;
 
191
        std::cout << "Debug: Base_DB::query_execute():  " << strQuery << std::endl;
234
192
#ifdef GLIBMM_EXCEPTIONS_ENABLED
235
193
      }
236
194
      catch(const Glib::Exception& ex)
249
207
    if(strQuery.compare(0, 6, "SELECT") == 0)
250
208
    {
251
209
#ifdef GLIBMM_EXCEPTIONS_ENABLED
252
 
      result = gda_connection->execute_select_command(strQuery);
 
210
      try
 
211
      {
 
212
        result = gda_connection->execute_select_command(strQuery);
 
213
      }
 
214
      catch(const Gnome::Gda::ConnectionError& ex)
 
215
      {
 
216
        std::cout << "debug: Base_DB::query_execute(): exception from execute_select_command(): " << ex.what() << std::endl;
 
217
      }
253
218
#else
254
219
      std::auto_ptr<Glib::Error> error;
255
220
      result = gda_connection->execute_select_command(strQuery, error);
256
221
      // Ignore error, empty datamodel is handled below
257
 
#endif
 
222
#endif //GLIBMM_EXCEPTIONS_ENABLED
258
223
    }
259
224
    else
260
225
    {
261
 
      std::auto_ptr<Glib::Error> error;
 
226
 
262
227
#ifdef GLIBMM_EXCEPTIONS_ENABLED
263
 
      if(gda_connection->execute_non_select_command(strQuery) != -1)
 
228
      int execute_result = -1;
 
229
      try
 
230
      {
 
231
        execute_result = gda_connection->execute_non_select_command(strQuery);
 
232
      }
 
233
      catch(const Gnome::Gda::ConnectionError& ex)
 
234
      {
 
235
        std::cout << "debug: Base_DB::query_execute(): exception from execute_non_select_command(): " << ex.what() << std::endl;
 
236
      }
264
237
#else
265
 
      if(gda_connection->execute_non_select_command(strQuery, error) != -1)
266
 
        if(error.get() == NULL)
267
 
#endif
268
 
          result = Gnome::Gda::DataModelArray::create(1);
 
238
      std::auto_ptr<Glib::Error> error;
 
239
      execute_result = gda_connection->execute_non_select_command(strQuery, error);
 
240
#endif //GLIBMM_EXCEPTIONS_ENABLED
 
241
      
 
242
      if(execute_result != -1)
 
243
        result = Gnome::Gda::DataModelArray::create(1);
269
244
    }
270
245
 
271
246
    if(!result)
301
276
 
302
277
  type_vecStrings tables = get_table_names_from_database();
303
278
  type_vecStrings::const_iterator iterFind = std::find(tables.begin(), tables.end(), table_name);
304
 
  bool result = (iterFind != tables.end());
305
 
 
306
 
  return result;
 
279
  return (iterFind != tables.end());
307
280
}
308
281
 
309
282
Base_DB::type_vecStrings Base_DB::get_table_names_from_database(bool ignore_system_tables) const
332
305
    }
333
306
    else if(data_model_tables)
334
307
    {
335
 
      int rows = data_model_tables->get_n_rows();
 
308
      //std::cout << "debug: data_model_tables refcount=" << G_OBJECT(data_model_tables->gobj())->ref_count << std::endl;
 
309
      const int rows = data_model_tables->get_n_rows();
336
310
      for(int i = 0; i < rows; ++i)
337
311
      {
338
312
        Gnome::Gda::Value value = data_model_tables->get_value_at(0, i);
930
904
 
931
905
  SystemPrefs result;
932
906
 
933
 
  //Check that the user is allowd to even view this table:
 
907
  //Check that the user is allowed to even view this table:
934
908
  Privileges table_privs = Privs::get_current_privs(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
935
909
  if(!table_privs.m_view)
936
910
    return result;
949
923
      + Glib::ustring(optional_org_logo ? ", \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\".\"" GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO "\"" : "") +
950
924
      " FROM \"" GLOM_STANDARD_TABLE_PREFS_TABLE_NAME "\"";
951
925
 
952
 
#ifdef GLIBMM_EXCEPTIONS_ENABLED
953
 
  try
954
 
#endif
955
 
  {
956
 
    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute(sql_query);
957
 
    if(datamodel && (datamodel->get_n_rows() != 0))
958
 
    {
959
 
      result.m_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(0, 0));
960
 
      result.m_org_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(1, 0));
961
 
      result.m_org_address_street = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(2, 0));
962
 
      result.m_org_address_street2 = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(3, 0));
963
 
      result.m_org_address_town = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(4, 0));
964
 
      result.m_org_address_county = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(5, 0));
965
 
      result.m_org_address_country = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(6, 0));
966
 
      result.m_org_address_postcode = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(7, 0));
967
 
 
968
 
      //We need to be more clever about these column indexes if we add more new fields:
969
 
      if(optional_org_logo)
970
 
        result.m_org_logo = datamodel->get_value_at(8, 0);
971
 
 
972
 
    }
973
 
  }
974
 
#ifdef GLIBMM_EXCEPTIONS_ENABLED
975
 
  catch(const Glib::Exception& ex)
976
 
  {
977
 
    std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
978
 
  }
979
 
  catch(const std::exception& ex)
980
 
  {
981
 
    std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
982
 
  }
983
 
#endif // GLIBMM_EXCEPTIONS_ENABLED
 
926
  int attempts = 0;
 
927
  while(attempts < 2)
 
928
  {
 
929
    bool succeeded = true;
 
930
    #ifdef GLIBMM_EXCEPTIONS_ENABLED
 
931
    try
 
932
    #endif
 
933
    {
 
934
      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute(sql_query);
 
935
      if(datamodel && (datamodel->get_n_rows() != 0))
 
936
      {
 
937
        result.m_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(0, 0));
 
938
        result.m_org_name = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(1, 0));
 
939
        result.m_org_address_street = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(2, 0));
 
940
        result.m_org_address_street2 = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(3, 0));
 
941
        result.m_org_address_town = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(4, 0));
 
942
        result.m_org_address_county = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(5, 0));
 
943
        result.m_org_address_country = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(6, 0));
 
944
        result.m_org_address_postcode = Conversions::get_text_for_gda_value(Field::TYPE_TEXT, datamodel->get_value_at(7, 0));
 
945
 
 
946
        //We need to be more clever about these column indexes if we add more new fields:
 
947
        if(optional_org_logo)
 
948
          result.m_org_logo = datamodel->get_value_at(8, 0);
 
949
      }
 
950
      else
 
951
        succeeded = false;
 
952
    }
 
953
    #ifdef GLIBMM_EXCEPTIONS_ENABLED
 
954
    catch(const Glib::Exception& ex)
 
955
    {
 
956
      std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
 
957
      succeeded = false;
 
958
    }
 
959
    catch(const std::exception& ex)
 
960
    {
 
961
      std::cerr << "Base_DB::get_database_preferences(): exception: " << ex.what() << std::endl;
 
962
      succeeded = false;
 
963
    }
 
964
    #endif // GLIBMM_EXCEPTIONS_ENABLED
 
965
 
 
966
    //Return the result, or try again:
 
967
    if(succeeded)
 
968
      return result;
 
969
    else
 
970
    {
 
971
      add_standard_tables();
 
972
      ++attempts; //Try again now that we have tried to create the table.
 
973
    }
 
974
  }
984
975
 
985
976
  return result;
986
977
}
1305
1296
#ifdef GLIBMM_EXCEPTIONS_ENABLED
1306
1297
  try
1307
1298
  {
1308
 
    refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "dialog_choose_field");
 
1299
    refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom_developer.glade"), "dialog_choose_field");
1309
1300
  }
1310
1301
  catch(const Gnome::Glade::XmlError& ex)
1311
1302
  {
1314
1305
  }
1315
1306
#else
1316
1307
  std::auto_ptr<Gnome::Glade::XmlError> error;
1317
 
  refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "dialog_choose_field", "", error);
 
1308
  refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom_developer.glade"), "dialog_choose_field", "", error);
1318
1309
  if(error.get())
1319
1310
  {
1320
1311
    std::cerr << error->what() << std::endl;
1338
1329
      //Get the chosen field:
1339
1330
      result = dialog->get_field_chosen();
1340
1331
    }
 
1332
    else if(start_field) //Cancel means use the old one:
 
1333
      result = glom_sharedptr_clone(start_field);
1341
1334
 
1342
1335
    delete dialog;
1343
1336
  }
1352
1345
 
1353
1346
  try
1354
1347
  {
1355
 
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "dialog_layout_field_properties");
 
1348
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom_developer.glade"), "dialog_layout_field_properties");
1356
1349
 
1357
1350
    Dialog_FieldLayout* dialog = 0;
1358
1351
    refXml->get_widget_derived("dialog_layout_field_properties", dialog);
1373
1366
        //Get the chosen field:
1374
1367
        result = dialog->get_field_chosen();
1375
1368
      }
 
1369
      else if(start_field) //Cancel means use the old one:
 
1370
        result = glom_sharedptr_clone(start_field);
1376
1371
 
1377
1372
      remove_view(dialog);
1378
1373
      delete dialog;
1386
1381
  return result;
1387
1382
}
1388
1383
 
1389
 
sharedptr<LayoutItem_Text> Base_DB::offer_textobject(const sharedptr<LayoutItem_Text>& start_textobject, Gtk::Window* transient_for)
 
1384
sharedptr<LayoutItem_Text> Base_DB::offer_textobject(const sharedptr<LayoutItem_Text>& start_textobject, Gtk::Window* transient_for, bool show_title)
1390
1385
{
1391
 
  sharedptr<LayoutItem_Text> result;
 
1386
  sharedptr<LayoutItem_Text> result = start_textobject;
1392
1387
 
1393
1388
  try
1394
1389
  {
1395
 
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "window_textobject");
 
1390
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom_developer.glade"), "window_textobject");
1396
1391
 
1397
1392
    Dialog_TextObject* dialog = 0;
1398
1393
    refXml->get_widget_derived("window_textobject", dialog);
1401
1396
      if(transient_for)
1402
1397
        dialog->set_transient_for(*transient_for);
1403
1398
 
1404
 
      dialog->set_textobject(start_textobject, Glib::ustring());
 
1399
      dialog->set_textobject(start_textobject, Glib::ustring(), show_title);
1405
1400
      int response = Glom::Utils::dialog_run_with_help(dialog, "window_textobject");
1406
1401
      dialog->hide();
1407
1402
      if(response == Gtk::RESPONSE_OK)
1421
1416
  return result;
1422
1417
}
1423
1418
 
1424
 
sharedptr<LayoutItem_Image> Base_DB::offer_imageobject(const sharedptr<LayoutItem_Image>& start_imageobject, Gtk::Window* transient_for)
 
1419
sharedptr<LayoutItem_Image> Base_DB::offer_imageobject(const sharedptr<LayoutItem_Image>& start_imageobject, Gtk::Window* transient_for, bool show_title)
1425
1420
{
1426
 
  sharedptr<LayoutItem_Image> result;
 
1421
  sharedptr<LayoutItem_Image> result = start_imageobject;
1427
1422
 
1428
1423
  try
1429
1424
  {
1430
 
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "window_imageobject");
 
1425
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom_developer.glade"), "window_imageobject");
1431
1426
 
1432
1427
    Dialog_ImageObject* dialog = 0;
1433
1428
    refXml->get_widget_derived("window_imageobject", dialog);
1436
1431
      if(transient_for)
1437
1432
        dialog->set_transient_for(*transient_for);
1438
1433
 
1439
 
      dialog->set_imageobject(start_imageobject, Glib::ustring());
 
1434
      dialog->set_imageobject(start_imageobject, Glib::ustring(), show_title);
1440
1435
      const int response = Glom::Utils::dialog_run_with_help(dialog, "window_imageobject");
1441
1436
      dialog->hide();
1442
1437
      if(response == Gtk::RESPONSE_OK)
1458
1453
 
1459
1454
sharedptr<LayoutItem_Notebook> Base_DB::offer_notebook(const sharedptr<LayoutItem_Notebook>& start_notebook, Gtk::Window* transient_for)
1460
1455
{
1461
 
  sharedptr<LayoutItem_Notebook> result;
 
1456
  sharedptr<LayoutItem_Notebook> result = start_notebook;
1462
1457
 
1463
1458
  try
1464
1459
  {
1465
 
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(GLOM_GLADEDIR "glom.glade", "dialog_notebook");
 
1460
    Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom.glade"), "dialog_notebook");
1466
1461
 
1467
1462
    Dialog_Notebook* dialog = 0;
1468
1463
    refXml->get_widget_derived("dialog_notebook", dialog);
1635
1630
  const Document_Glom* document = get_document();
1636
1631
  if(document)
1637
1632
  {
1638
 
    //TODO_Performance:
 
1633
    //TODO_Performance: Cache this result?
1639
1634
    Document_Glom::type_vecFields fields = document->get_table_fields(table_name);
1640
1635
    for(Document_Glom::type_vecFields::iterator iter = fields.begin(); iter != fields.end(); ++iter)
1641
1636
    {
1653
1648
{
1654
1649
  //g_warning("Box_Data::get_table_fields_to_show_for_sequence_add_group(): table_name=%s, all_db_fields.size()=%d, group->name=%s", table_name.c_str(), all_db_fields.size(), group->get_name().c_str());
1655
1650
 
1656
 
  LayoutGroup::type_map_items items = group->get_items();
1657
 
  for(LayoutGroup::type_map_items::iterator iterItems = items.begin(); iterItems != items.end(); ++iterItems)
 
1651
  LayoutGroup::type_list_items items = group->get_items();
 
1652
  for(LayoutGroup::type_list_items::iterator iterItems = items.begin(); iterItems != items.end(); ++iterItems)
1658
1653
  {
1659
 
    sharedptr<LayoutItem> item = iterItems->second;
 
1654
    sharedptr<LayoutItem> item = *iterItems;
1660
1655
 
1661
1656
    sharedptr<LayoutItem_Field> item_field = sharedptr<LayoutItem_Field>::cast_dynamic(item);
1662
1657
    if(item_field)
1727
1722
  }
1728
1723
}
1729
1724
 
1730
 
Base_DB::type_vecLayoutFields Base_DB::get_table_fields_to_show_for_sequence(const Glib::ustring& table_name, const Document_Glom::type_mapLayoutGroupSequence& mapGroupSequence) const
 
1725
Base_DB::type_vecLayoutFields Base_DB::get_table_fields_to_show_for_sequence(const Glib::ustring& table_name, const Document_Glom::type_list_layout_groups& mapGroupSequence) const
1731
1726
{
1732
1727
  //Get field definitions from the database, with corrections from the document:
1733
1728
  type_vecFields all_fields = get_fields_for_table(table_name);
1789
1784
      type_vecFields vecFieldsInDocument = pDoc->get_table_fields(table_name);
1790
1785
 
1791
1786
      //We will show the fields that the document says we should:
1792
 
      for(Document_Glom::type_mapLayoutGroupSequence::const_iterator iter = mapGroupSequence.begin(); iter != mapGroupSequence.end(); ++iter)
 
1787
      for(Document_Glom::type_list_layout_groups::const_iterator iter = mapGroupSequence.begin(); iter != mapGroupSequence.end(); ++iter)
1793
1788
      {
1794
 
        sharedptr<LayoutGroup> group = iter->second;
 
1789
        sharedptr<LayoutGroup> group = *iter;
1795
1790
 
1796
1791
        if(true) //!group->m_hidden)
1797
1792
        {
2171
2166
  type_vecConstLayoutFields list_fields;
2172
2167
  sharedptr<const LayoutItem_Field> layout_item = field_in_record.m_field;
2173
2168
  list_fields.push_back(layout_item);
2174
 
  const Glib::ustring sql_query = Utils::build_sql_select_with_key(field_in_record.m_table_name,
 
2169
  Glib::ustring sql_query = Utils::build_sql_select_with_key(field_in_record.m_table_name,
2175
2170
      list_fields, field_in_record.m_key, field_in_record.m_key_value);
2176
2171
 
2177
 
  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute(sql_query);
2178
 
  if(data_model)
2179
 
  {
2180
 
    if(data_model->get_n_rows())
2181
 
    {
2182
 
      result = data_model->get_value_at(0, 0);
2183
 
    }
2184
 
  }
2185
 
  else
2186
 
  {
2187
 
    handle_error();
2188
 
  }
2189
 
 
2190
 
  return result;
2191
 
}
 
2172
  if(!sql_query.empty())
 
2173
    sql_query += " LIMIT 1";
 
2174
 
 
2175
  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute(sql_query);
 
2176
  if(data_model)
 
2177
  {
 
2178
    if(data_model->get_n_rows())
 
2179
    {
 
2180
      result = data_model->get_value_at(0, 0);
 
2181
    }
 
2182
  }
 
2183
  else
 
2184
  {
 
2185
    handle_error();
 
2186
  }
 
2187
 
 
2188
  return result;
 
2189
}
 
2190
 
 
2191
Gnome::Gda::Value Base_DB::get_field_value_in_database(const sharedptr<Field>& field, const FoundSet& found_set, Gtk::Window* parent_window)
 
2192
{
 
2193
  Gnome::Gda::Value result;  //TODO: Return suitable empty value for the field when failing?
 
2194
 
 
2195
  //row is invalid, and ignored, for Box_Data_Details.
 
2196
  if(!field)
 
2197
  {
 
2198
    std::cerr << "Base_DB:gset_field_value_in_database(): field is empty." << std::endl;
 
2199
    return result;
 
2200
  }
 
2201
 
 
2202
  if(found_set.m_where_clause.empty())
 
2203
  {
 
2204
    std::cerr << "Base_DB::get_field_value_in_database(): where_clause is empty." << std::endl;
 
2205
    return result;
 
2206
  }
 
2207
 
 
2208
  type_vecConstLayoutFields list_fields;
 
2209
  sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
 
2210
  layout_item->set_full_field_details(field);
 
2211
  list_fields.push_back(layout_item);
 
2212
  Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
 
2213
    list_fields,
 
2214
    found_set.m_where_clause);
 
2215
 
 
2216
  if(!sql_query.empty())
 
2217
    sql_query += " LIMIT 1";
 
2218
 
 
2219
  Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute(sql_query);
 
2220
  if(data_model)
 
2221
  {
 
2222
    if(data_model->get_n_rows())
 
2223
    {
 
2224
      result = data_model->get_value_at(0, 0);
 
2225
    }
 
2226
  }
 
2227
  else
 
2228
  {
 
2229
    handle_error();
 
2230
  }
 
2231
 
 
2232
  return result;
 
2233
}
 
2234
 
2192
2235
 
2193
2236
void Base_DB::do_calculations(const LayoutFieldInRecord& field_changed, bool first_calc_field)
2194
2237
{
2536
2579
 
2537
2580
  const Glib::ustring parent_table_name = portal->get_table_used(Glib::ustring() /* parent table - not relevant */); 
2538
2581
 
2539
 
  LayoutItem_Portal::type_map_const_items items = portal->get_items(); 
2540
 
  for(LayoutItem_Portal::type_map_const_items::const_iterator iter = items.begin(); iter != items.end(); ++iter)
 
2582
  LayoutItem_Portal::type_list_const_items items = portal->get_items(); 
 
2583
  for(LayoutItem_Portal::type_list_const_items::const_iterator iter = items.begin(); iter != items.end(); ++iter)
2541
2584
  {
2542
 
    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->second);
 
2585
    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(*iter);
2543
2586
    if(field)
2544
2587
    {
2545
2588
      if(field->get_has_relationship_name())
2566
2609
 
2567
2610
  const Glib::ustring parent_table_name = portal->get_table_used(Glib::ustring() /* parent table - not relevant */);
2568
2611
 
2569
 
  LayoutItem_Portal::type_map_const_items items = portal->get_items(); 
2570
 
  for(LayoutItem_Portal::type_map_const_items::const_iterator iter = items.begin(); iter != items.end(); ++iter)
 
2612
  LayoutItem_Portal::type_list_const_items items = portal->get_items(); 
 
2613
  for(LayoutItem_Portal::type_list_const_items::const_iterator iter = items.begin(); iter != items.end(); ++iter)
2571
2614
  {
2572
 
    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->second);
 
2615
    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(*iter);
2573
2616
    if(field && !(field->get_has_relationship_name()))
2574
2617
    {
2575
2618
      sharedptr<Relationship> relationship = document->get_field_used_in_relationship_to_one(parent_table_name, field->get_name());
2672
2715
    return false;
2673
2716
}
2674
2717
 
 
2718
int Base_DB::count_rows_returned_by(const Glib::ustring& sql_query)
 
2719
{
 
2720
  int result = 0;
 
2721
 
 
2722
  //TODO: Is this inefficient?
 
2723
  //Note that the alias is just because the SQL syntax requires it - we get an error if we don't use it.
 
2724
  //Be careful not to include ORDER BY clauses in this, because that would make it unnecessarily slow:
 
2725
  const Glib::ustring query_count = "SELECT COUNT (*) FROM (" + sql_query + ") AS glomarbitraryalias";
 
2726
  
 
2727
  const App_Glom* app = App_Glom::get_application();
 
2728
  if(app && app->get_show_sql_debug())
 
2729
  { 
 
2730
    try
 
2731
    {
 
2732
      std::cout << "Debug: count_rows_returned_by():  " << query_count << std::endl;
 
2733
    }
 
2734
    catch(const Glib::Exception& ex)
 
2735
    {
 
2736
      std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
 
2737
    }
 
2738
  }
 
2739
 
 
2740
#ifdef GLIBMM_EXCEPTIONS_ENABLED
 
2741
  sharedptr<SharedConnection> sharedconnection = connect_to_server();
 
2742
#else
 
2743
  std::auto_ptr<ExceptionConnection> error;
 
2744
  sharedptr<SharedConnection> sharedconnection = connect_to_server(0, error);
 
2745
  // TODO: Rethrow?
 
2746
#endif
 
2747
 
 
2748
  if(!sharedconnection)
 
2749
  {
 
2750
    g_warning("Base_DB::count_rows_returned_by(): connection failed.");
 
2751
    return 0;
 
2752
  }
 
2753
 
 
2754
  try
 
2755
  {
 
2756
    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = sharedconnection->get_gda_connection()->execute_select_command(query_count);
 
2757
    if(datamodel && datamodel->get_n_rows() && datamodel->get_n_columns())
 
2758
    {
 
2759
      Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
 
2760
      //This showed me that this contains a gint64: std::cerr << "DEBUG: value type=" << G_VALUE_TYPE_NAME(value.gobj()) << std::endl;
 
2761
      result = (int)value.get_int64();
 
2762
    }
 
2763
  }
 
2764
  catch(const Glib::Exception& ex)
 
2765
  {
 
2766
    std::cerr << "count_rows_returned_by(): exception caught: " << ex.what() << std::endl;
 
2767
  }
 
2768
  catch(const std::exception& ex)
 
2769
  {
 
2770
    std::cerr << "count_rows_returned_by(): exception caught: " << ex.what() << std::endl;
 
2771
  }
 
2772
 
 
2773
  //std::cout << "DEBUG: count_rows_returned_by(): Returning " << result << std::endl;
 
2774
  return result;
 
2775
}
 
2776
 
 
2777
 
 
2778
void Base_DB::set_found_set_where_clause_for_portal(FoundSet& found_set, const sharedptr<LayoutItem_Portal>& portal, const Gnome::Gda::Value& foreign_key_value)
 
2779
{
 
2780
  found_set.m_table_name = Glib::ustring();
 
2781
  found_set.m_where_clause = Glib::ustring();
 
2782
  found_set.m_extra_join = Glib::ustring();
 
2783
  found_set.m_extra_group_by = Glib::ustring();
 
2784
 
 
2785
  if( !portal
 
2786
      || Conversions::value_is_empty(foreign_key_value) )
 
2787
  {
 
2788
    return;
 
2789
  }
 
2790
 
 
2791
 
 
2792
  sharedptr<Relationship> relationship = portal->get_relationship();
 
2793
 
 
2794
  // Notice that, in the case that this is a portal to doubly-related records,
 
2795
  // The WHERE clause mentions the first-related table (though by the alias defined in extra_join)
 
2796
  // and we add an extra JOIN to mention the second-related table.
 
2797
 
 
2798
  Glib::ustring where_clause_to_table_name = relationship->get_to_table();
 
2799
  sharedptr<Field> where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), relationship->get_to_field());
 
2800
 
 
2801
  found_set.m_table_name = portal->get_table_used(Glib::ustring() /* parent table - not relevant */);
 
2802
      
 
2803
  sharedptr<const Relationship> relationship_related = portal->get_related_relationship();
 
2804
  if(relationship_related)
 
2805
  {
 
2806
    //Add the extra JOIN:
 
2807
    sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
 
2808
    uses_rel_temp->set_relationship(relationship);
 
2809
    //found_set.m_extra_join = uses_rel_temp->get_sql_join_alias_definition();
 
2810
    found_set.m_extra_join = "LEFT OUTER JOIN \"" + relationship->get_to_table() + "\" AS \"" + uses_rel_temp->get_sql_join_alias_name() + "\" ON (\"" + uses_rel_temp->get_sql_join_alias_name() + "\".\"" + relationship_related->get_from_field() + "\" = \"" + relationship_related->get_to_table() + "\".\"" + relationship_related->get_to_field() + "\")";
 
2811
 
 
2812
    //Add an extra GROUP BY to ensure that we get no repeated records from the doubly-related table:
 
2813
    sharedptr<Field> to_table_primary_key = get_field_primary_key_for_table( relationship->get_to_table() );
 
2814
    if(to_table_primary_key)
 
2815
      found_set.m_extra_group_by = "GROUP BY \"" + found_set.m_table_name + "\".\"" + to_table_primary_key->get_name() + "\"";
 
2816
 
 
2817
    //Adjust the WHERE clause appropriately for the extra JOIN:
 
2818
    where_clause_to_table_name = uses_rel_temp->get_sql_join_alias_name();
 
2819
 
 
2820
    const Glib::ustring to_field_name = uses_rel_temp->get_to_field_used();
 
2821
    where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), to_field_name);
 
2822
    //std::cout << "extra_join=" << found_set.m_extra_join << std::endl;
 
2823
 
 
2824
    //std::cout << "extra_join where_clause_to_key_field=" << where_clause_to_key_field->get_name() << std::endl;
 
2825
  }
 
2826
 
 
2827
  if(where_clause_to_key_field)
 
2828
    found_set.m_where_clause = "\"" + where_clause_to_table_name + "\".\"" + relationship->get_to_field() + "\" = " + where_clause_to_key_field->sql(foreign_key_value);
 
2829
}
 
2830
 
 
2831
 
2675
2832
} //namespace Glom