// -*- C++ -*-
//
// This file was generated by ODB, object-relational mapping (ORM)
// compiler for C++.
//

#include <odb/pre.hxx>

#include <bdep/database-views-odb.hxx>

#include <cassert>
#include <cstring>  // std::memcpy


#include <odb/sqlite/traits.hxx>
#include <odb/sqlite/database.hxx>
#include <odb/sqlite/transaction.hxx>
#include <odb/sqlite/connection.hxx>
#include <odb/sqlite/statement.hxx>
#include <odb/sqlite/statement-cache.hxx>
#include <odb/sqlite/view-statements.hxx>
#include <odb/sqlite/container-statements.hxx>
#include <odb/sqlite/exceptions.hxx>
#include <odb/sqlite/view-result.hxx>

namespace odb
{
  // sqlite_master
  //

  bool access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::
  grow (image_type& i,
        bool* t)
  {
    ODB_POTENTIALLY_UNUSED (i);
    ODB_POTENTIALLY_UNUSED (t);

    bool grew (false);

    // type
    //
    if (t[0UL])
    {
      i.type_value.capacity (i.type_size);
      grew = true;
    }

    // name
    //
    if (t[1UL])
    {
      i.name_value.capacity (i.name_size);
      grew = true;
    }

    // sql
    //
    if (t[2UL])
    {
      i.sql_value.capacity (i.sql_size);
      grew = true;
    }

    return grew;
  }

  void access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::
  bind (sqlite::bind* b,
        image_type& i)
  {
    using namespace sqlite;

    sqlite::statement_kind sk (statement_select);
    ODB_POTENTIALLY_UNUSED (sk);

    std::size_t n (0);

    // type
    //
    b[n].type = sqlite::image_traits<
      ::std::string,
      sqlite::id_text>::bind_value;
    b[n].buffer = i.type_value.data ();
    b[n].size = &i.type_size;
    b[n].capacity = i.type_value.capacity ();
    b[n].is_null = &i.type_null;
    n++;

    // name
    //
    b[n].type = sqlite::image_traits<
      ::std::string,
      sqlite::id_text>::bind_value;
    b[n].buffer = i.name_value.data ();
    b[n].size = &i.name_size;
    b[n].capacity = i.name_value.capacity ();
    b[n].is_null = &i.name_null;
    n++;

    // sql
    //
    b[n].type = sqlite::image_traits<
      ::std::string,
      sqlite::id_text>::bind_value;
    b[n].buffer = i.sql_value.data ();
    b[n].size = &i.sql_size;
    b[n].capacity = i.sql_value.capacity ();
    b[n].is_null = &i.sql_null;
    n++;
  }

  void access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::
  init (view_type& o,
        const image_type& i,
        database* db)
  {
    ODB_POTENTIALLY_UNUSED (o);
    ODB_POTENTIALLY_UNUSED (i);
    ODB_POTENTIALLY_UNUSED (db);

    // type
    //
    {
      ::std::string& v =
        o.type;

      sqlite::value_traits<
          ::std::string,
          sqlite::id_text >::set_value (
        v,
        i.type_value,
        i.type_size,
        i.type_null);
    }

    // name
    //
    {
      ::std::string& v =
        o.name;

      sqlite::value_traits<
          ::std::string,
          sqlite::id_text >::set_value (
        v,
        i.name_value,
        i.name_size,
        i.name_null);
    }

    // sql
    //
    {
      ::std::string& v =
        o.sql;

      sqlite::value_traits<
          ::std::string,
          sqlite::id_text >::set_value (
        v,
        i.sql_value,
        i.sql_size,
        i.sql_null);
    }
  }

  access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::query_base_type
  access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::
  query_statement (const query_base_type& q)
  {
    query_base_type r (
      "SELECT "
      "\"type\", "
      "\"type\", "
      "\"sql\" ");

    r += "FROM \"sqlite_master\"";

    if (!q.empty ())
    {
      r += " ";
      r += q.clause_prefix ();
      r += q;
    }

    return r;
  }

  result< access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::view_type >
  access::view_traits_impl< ::bdep::sqlite_master, id_sqlite >::
  query (database& db, const query_base_type& q)
  {
    using namespace sqlite;
    using odb::details::shared;
    using odb::details::shared_ptr;

    sqlite::connection& conn (
      sqlite::transaction::current ().connection (db));
    statements_type& sts (
      conn.statement_cache ().find_view<view_type> ());

    image_type& im (sts.image ());
    binding& imb (sts.image_binding ());

    if (im.version != sts.image_version () || imb.version == 0)
    {
      bind (imb.bind, im);
      sts.image_version (im.version);
      imb.version++;
    }

    const query_base_type& qs (query_statement (q));
    qs.init_parameters ();
    shared_ptr<select_statement> st (
      new (shared) select_statement (
        conn,
        qs.clause (),
        false,
        true,
        qs.parameters_binding (),
        imb));

    st->execute ();

    shared_ptr< odb::view_result_impl<view_type> > r (
      new (shared) sqlite::view_result_impl<view_type> (
        qs, st, sts, 0));

    return result<view_type> (r);
  }
}

#include <odb/post.hxx>
