#include "stdafx.h"

#include "mysql_sql_inserts_loader.h"
#include "mysql_sql_parser_utils.h"
#include <boost/foreach.hpp>


using namespace grt;


#define NULL_STATE_KEEPER Null_state_keeper _nsk(this);


Mysql_sql_inserts_loader::Mysql_sql_inserts_loader(grt::GRT *grt)
:
Sql_parser_base(grt),
Mysql_sql_parser_base(grt)
{
  NULL_STATE_KEEPER
}


void Mysql_sql_inserts_loader::load(const std::string &sql, const std::string &schema_name)
{
  NULL_STATE_KEEPER

  _schema_name= schema_name;
  _process_sql_statement= sigc::mem_fun(this, &Mysql_sql_inserts_loader::process_sql_statement);

  Mysql_sql_parser_fe sql_parser_fe(_grtm->get_grt());
  sql_parser_fe.ignore_dml= false;
  Mysql_sql_parser_base::parse_sql_script(sql_parser_fe, sql.c_str());
}


int Mysql_sql_inserts_loader::process_sql_statement(const MyxSQLTreeItem *tree)
{
  if (tree)
  {
    if (const MyxSQLTreeItem *item= tree->subitem(sql::_statement, sql::_insert))
      process_insert_statement(item);
  }

  return 0; // error count
}


Mysql_sql_inserts_loader::Parse_result
Mysql_sql_inserts_loader::process_insert_statement(const MyxSQLTreeItem *tree)
{
  std::string schema_name= _schema_name;
  std::string table_name;
  Strings fields_names;
  Strings fields_values;

  const MyxSQLTreeItem *insert_field_spec= tree->subitem(sql::_insert_field_spec);
  if (insert_field_spec)
  {
    // schema & table name
    {
      const MyxSQLTreeItem *table_ident= tree->subitem(sql::_insert2, sql::_insert_table, sql::_table_ident);
      process_obj_full_name_item(table_ident, schema_name, table_name);
    }

    // fields names
    {
      const MyxSQLTreeItem *fields= insert_field_spec->subitem(sql::_fields);
      if (fields)
      {
        BOOST_FOREACH (const MyxSQLTreeItem *item, *fields->subitems())
          if (item->name_equals(sql::_insert_ident))
            fields_names.push_back(item->restore_sql_text(_sql_statement));
      }
    }

    // fields values
    {
      fields_values.reserve(fields_names.size());

      const MyxSQLTreeItem *insert_values= insert_field_spec->subitem(sql::_insert_values, sql::_values_list);
      BOOST_FOREACH (const MyxSQLTreeItem *item, *insert_values->subitems())
      {
        if (item->name_equals(sql::_no_braces))
        {
          const MyxSQLTreeItem *values= item->subitem(sql::_opt_values, sql::_values);
          BOOST_FOREACH (const MyxSQLTreeItem *item, *values->subitems())
          {
            if (item->name_equals(sql::_expr_or_default))
            {
              std::string value= item->restore_sql_text(_sql_statement);
              if (1 < value.size())
              {
                switch (value[0])
                {
                case '\'':
                case '"':
                  value= value.substr(1, value.size()-2);
                  break;
                }
              }
              fields_values.push_back(value);
            }
          }
        }
      }
    }

    _process_insert(sql_statement(), schema_name, table_name, fields_names, fields_values);
  }

  return pr_processed;
}
