/* 
 * © 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef _DB_OBJECT_HELPERS_H_
#define _DB_OBJECT_HELPERS_H_

#include <grtpp.h>
#include <grts/structs.db.h>
#include <grts/structs.db.mgmt.h>
#include <grts/structs.db.mysql.h>

#include "wbpublic_public_interface.h"

#include "charset_utils.h"

// misc helper functions for db objects


// replaces old DbUtils.lua
// the functions here are also exposed as a GRT module in 
// modules/db/dbutils.cpp

db_mgmt_RdbmsRef WBPUBLICBACKEND_PUBLIC_FUNC get_rdbms_for_db_object(const ::grt::ValueRef &object);


namespace bec {

  // these constants for comparing db_SimpleDatatypeRef members. Cannot use -1 because for characterOctetLength it means pow(10, -1)
  const int EMPTY_TYPE_MAXIMUM_LENGTH = 0;
  const int EMPTY_TYPE_OCTET_LENGTH = EMPTY_TYPE_MAXIMUM_LENGTH;
  const int EMPTY_TYPE_PRECISION = EMPTY_TYPE_MAXIMUM_LENGTH;
  const int EMPTY_TYPE_SCALE = EMPTY_TYPE_MAXIMUM_LENGTH;
  // these constants for comparing db_SimpleDatatypeRef members. Cannot use 0 because char(0) and char are different types
  const int EMPTY_COLUMN_LENGTH=    -1;
  const int EMPTY_COLUMN_PRECISION= EMPTY_COLUMN_LENGTH;
  const int EMPTY_COLUMN_SCALE=     EMPTY_COLUMN_LENGTH;
  
  struct WBPUBLICBACKEND_PUBLIC_FUNC CatalogHelper 
  {
    static void apply_defaults(db_mysql_CatalogRef catalog);
    static void apply_defaults(db_mysql_ColumnRef column);
    static db_SimpleDatatypeRef get_datatype(grt::ListRef<db_SimpleDatatype> types, const std::string &name);

    static std::string dbobject_list_to_dragdata(const std::list<db_DatabaseObjectRef> &object);
    static std::list<db_DatabaseObjectRef> dragdata_to_dbobject_list(const db_CatalogRef &catalog, const std::string &object);

    static std::string dbobject_to_dragdata(const db_DatabaseObjectRef &object);
    static db_DatabaseObjectRef dragdata_to_dbobject(const db_CatalogRef &catalog, const std::string &object);
  };

  struct WBPUBLICBACKEND_PUBLIC_FUNC SchemaHelper 
  {
    static std::string get_unique_foreign_key_name(const db_SchemaRef &schema, const std::string &prefix,
                                                   int maxlength);
  };

  struct WBPUBLICBACKEND_PUBLIC_FUNC TableHelper 
  {
    static db_ForeignKeyRef create_foreign_key_to_table(const db_TableRef &table, 
                                                        const db_TableRef &ref_table,
                                                        bool mandatory, bool ref_mandatory,
                                                        bool many, bool identifying,
                                                        const db_mgmt_RdbmsRef &rdbms,
                                                        const grt::DictRef &global_options,
                                                        const grt::DictRef &options);

    static db_ForeignKeyRef create_foreign_key_to_table(const db_TableRef &table, const std::vector<db_ColumnRef> &columns,
                                                        const db_TableRef &ref_table, const std::vector<db_ColumnRef> &refcolumns,
                                                        bool mandatory, 
                                                        bool many, 
                                                        const db_mgmt_RdbmsRef &rdbms,
                                                        const grt::DictRef &global_options,
                                                        const grt::DictRef &options);

    static std::string generate_foreign_key_name();
    static db_ForeignKeyRef create_empty_foreign_key(grt::GRT *grt, const db_TableRef &table, const std::string &name);
    static void update_foreign_key_index(grt::GRT *grt, const db_ForeignKeyRef &fk);

    static bool rename_foreign_key(const db_TableRef &table, db_ForeignKeyRef &fk, const std::string &new_name);
    static bool rename_index(const db_TableRef &table, db_IndexRef &index, const std::string &new_name);
    
    static void update_foreign_keys_from_column_notnull(const db_TableRef &table, const db_ColumnRef &column);

    static bool is_identifying_foreign_key(const db_TableRef &table, const db_ForeignKeyRef &fk);

    static db_TableRef create_associative_table(const db_SchemaRef &schema, const db_TableRef &table1, const db_TableRef &table2, 
                                                bool mandatory1, bool mandatory2, 
                                                const db_mgmt_RdbmsRef &rdbms,
                                                const grt::DictRef &global_options, const grt::DictRef &options);

    static db_TableRef clone_table(const db_TableRef &table);
    static db_mysql_StorageEngineRef get_engine_by_name(grt::GRT *grt, const std::string &name);
  };

  enum ColumnTypeCompareResult { COLUMNS_TYPES_EQUAL          = 0, 
         COLUMNS_TYPES_DIFFER         = 1, 
         COLUMNS_CHARSETS_DIFFER      = 2, 
         COLUMNS_COLLATIONS_DIFFER    = 3,
         COLUMNS_FLAGS_DIFFER         = 4
  };

  struct WBPUBLICBACKEND_PUBLIC_FUNC ColumnHelper 
  {
    //static std::string quote_default_if_needed(const db_ColumnRef &column, const std::string &value);

    static void copy_column(const db_ColumnRef &from, db_ColumnRef &to);
    static ColumnTypeCompareResult compare_column_types(const db_ColumnRef &from, const db_ColumnRef &to);

    static void set_default_value(db_ColumnRef column, const std::string &value);
  };

};

#endif /* _DB_OBJECT_HELPERS_H_ */
