/*
 * 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 Library 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 <libgnomedbmm.h>
#include <libgdamm.h>

#include <iostream>

#ifdef GLIBMM_EXCEPTIONS_ENABLED
void do_example()
#else
void do_example(std::auto_ptr<Glib::Error>& error)
#endif // GLIBMM_EXCEPTIONS_ENABLED
{
  Glib::RefPtr<Gnome::Gda::Dict> dict = Gnome::Gda::Dict::create();
  Glib::RefPtr<Gnome::Gda::Client> client = Gnome::Gda::Client::create();
  Glib::ustring connection_string = "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db";

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite", connection_string, "" /* username */, "" /* password */);
  dict->set_connection(cnc);
  dict->update_dbms_meta_data();
#else
  Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite", connection_string, "", "", Gnome::Gda::ConnectionOptions(0), error);
  if(error.get() != NULL) return;

  dict->set_connection(cnc);
  dict->update_dbms_meta_data(error);
  if(error.get() != NULL) return;
#endif

  Glib::RefPtr<Gnome::Gda::Query> query = Gnome::Gda::Query::create(dict);

  // This defines two targets for the SELECT query
  Glib::RefPtr<Gnome::Gda::QueryTarget> customers = Gnome::Gda::QueryTarget::create(query, "customers");
  Glib::RefPtr<Gnome::Gda::QueryTarget> orders = Gnome::Gda::QueryTarget::create(query, "orders");

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  query->add_target(customers);
  query->add_target(orders);
#else
  query->add_target(customers, error);
  query->add_target(orders, error);
  if(error.get() != NULL) return;
#endif // GLIBMM_EXCEPTIONS_ENABLED

  // This specifies a field from the products table we are going to use
  // later for the condition and ORDER BY field.
  Glib::RefPtr<Gnome::Gda::QueryFieldField> cust_id = Gnome::Gda::QueryFieldField::create(query, "id", customers);
  // Another field from the order table.
  Glib::RefPtr<Gnome::Gda::QueryFieldField> ord_customer = Gnome::Gda::QueryFieldField::create(query, "customer", orders);

  // This SELECTs the creation_date field from the orders table
  query->add_field(Gnome::Gda::QueryFieldField::create(query, "creation_date", orders));

  // This shortcut function also works in this case, but be sure to mention
  // the table from which you want to SELECT a field.
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  Glib::RefPtr<Gnome::Gda::QueryField> cust_name = query->add_field_from_sql("customers.name");
#else
  Glib::RefPtr<Gnome::Gda::QueryField> cust_name = query->add_field_from_sql("customers.name", error);
  if(error.get() != NULL) return;
#endif // GLIBMM_EXCEPTIONS_ENABLED

  // Create a new leaf condition that tests something for equality.
  Glib::RefPtr<Gnome::Gda::QueryCondition> condition = Gnome::Gda::QueryCondition::create(query, Gnome::Gda::QUERY_CONDITION_LEAF_EQUAL);
  // This sets the left and right operator for the condition. It now checks
  // the "id" field is the customer table and the "customer" field in the
  // orders table for equality.
  condition->leaf_set_operator(Gnome::Gda::QUERY_CONDITION_OP_LEFT, cust_id);
  condition->leaf_set_operator(Gnome::Gda::QUERY_CONDITION_OP_RIGHT, ord_customer);

  // TODO: We should perhaps add a Gnome::Gda::QueryCondition::create(query, type, cond_left, cond_right) convenience function.

  query->set_condition(condition);

  // Orders the result by the customer's name (ascending)
  query->set_order_by_field(cust_name);

 // Prints "SELECT t2.creation_date, t1.name FROM customers AS t1, orders AS t2 WHERE t1.id=t2.customer ORDER BY t1.name"
  std::cout << query->get_sql_text() << std::endl;
}


int main(int argc, char* argv[])
{
  Gnome::Db::init("Queries example", "1.0", argc, argv);

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  try
  {
    do_example();
  }
  catch(const Glib::Error& err)
  {
    std::cerr << "Exception caught: " << err.what() << std::endl;
    return 1;
  }
#else
  std::auto_ptr<Glib::Error> error;
  do_example(error);
  if(error.get() != NULL)
  {
    std::cerr << "Exception caught: " << error->what() << std::endl;
    return 1;
  }
#endif // GLIBMM_EXCEPTIONS_ENABLED

  return 0;
}

