#include <sqlpp/table.hpp>
#include <sqlpp/field.hpp>
#include <sqlpp/database.hpp>
namespace sqlpp{
table::table(
database_shared_ptr database_,
string_const_reference name_,
string_const_reference field_prefix_
)
:
properties::database_property(database_),
properties::name_property(name_),
m_field_prefix(field_prefix_)
{};
field_shared_ptr table::get_field( string_const_reference name_) const
{
try
{
return field_container::get_field( name_);
}
catch( exceptions::sqlpp_exception e)
{
}
return field_container::get_field( m_field_prefix + name_ );
}
primary_key_constraint_shared_ptr table::set_primary_key(
field_container_const_reference fields_,
string_const_reference name_)
{
m_primary_key = primary_key_constraint_shared_ptr(
new primary_key_constraint(
shared_from_this(),
name_,
fields_)
);
if (!m_primary_key)
throw exceptions::sqlpp_exception("table::set_primary_key: memory could not be allocated");
return m_primary_key;
};
ref_constraint_shared_ptr table::add_ref(
field_container_const_reference fields_,
table_shared_ptr reference_table_,
string_const_reference name_,
ref_constraint::EventAction on_delete_,
ref_constraint::EventAction on_update_,
ref_constraint::Match match_
)
{
ref_constraint_shared_ptr rc(
new ref_constraint(
shared_from_this(),
name_,
fields_,
reference_table_,
on_delete_,
on_update_,
match_
)
);
if (!rc)
throw exceptions::sqlpp_exception("table::add_ref: memory could not be allocated");
m_refs.insert_constraint(rc);
// now add join in database graph
get_checked_database()->join_tables( rc );
return rc;
};
unique_constraint_shared_ptr table::add_unique(
field_container_const_reference fields_,
string_const_reference name_ )
{
unique_constraint_shared_ptr uc(
new unique_constraint(
shared_from_this(),
name_,
fields_
)
);
if (!uc)
throw exceptions::sqlpp_exception("table::add_unique: memory could not be allocated");
m_uniques.insert_constraint(uc);
return uc;
};
// adding fields
field_shared_ptr table::add_field(
string_const_reference name_,
string_const_reference type_,
bool not_null_
)
{
string_type real_name = m_field_prefix + name_;
// check if name exists
if ( contains_field( real_name ) )
throw exceptions::sqlpp_exception("table::add_field: duplicate field name");
// creating field
field_shared_ptr f( new
field(
shared_from_this(),
real_name,
type_,
not_null_
)
);
if (!f)
throw exceptions::sqlpp_exception("table::add_field: memory allocation error");
insert_field(f);
return f;
};
ref_constraint_shared_ptr table::add_foreign_key(
table_shared_ptr reference_table_,
string_const_reference name_,
bool not_null_,
ref_constraint::EventAction on_delete_,
ref_constraint::EventAction on_update_,
ref_constraint::Match match_
)
{
// check if name exists
if ( !reference_table_)
throw exceptions::sqlpp_exception("table::set_foreign_key: reference table null");
// getting primary keys
primary_key_constraint_shared_ptr pks = reference_table_->get_primary_key();
if ( !pks || pks->empty() )
throw exceptions::sqlpp_exception("table::add_foreign_key: trying to create foreign key, could not find primary key in reference table");
field_map::const_field_iterator it,it_end;
field_container fc;
field_shared_ptr pk;
string_type real_name;
for (
boost::tie(it, it_end) = pks->get_fields() ;
it != it_end;
++it
)
{
// get referenced field
pk=*it;
if (!pk)
throw exceptions::sqlpp_exception("table::add_foreign_key: primary key field in reference table is null");
// check if name is empty or no ref. field
if ( !name_.empty())
real_name = name_;
else
// no table, get reference_field_ raw name
real_name = pk->get_name();
// check if already exists
if (contains_field(real_name))
throw exceptions::sqlpp_exception("table::add_foreign_key: duplicate field name while creating foreign keys");
// creating fields
field_shared_ptr fk( new
field(
shared_from_this(),
real_name,
pk->get_type()
)
);
if (!fk)
throw exceptions::sqlpp_exception("table::add_foreign_key: field memory allocation error");
insert_field( fk);
fc.insert_field(fk);
};
// create foreing key
ref_constraint_shared_ptr rc(
new ref_constraint(
shared_from_this(),
"",
fc,
reference_table_,
on_delete_,
on_update_,
match_)
);
if (!m_refs.insert_constraint( rc ))
throw exceptions::sqlpp_exception("table::add_foreign_key: ref constraint insertion error");
// now add join in database graph
get_checked_database()->join_tables( rc );
return rc;
};
primary_key_constraint_shared_ptr table::add_primary_key(
string_const_reference name_,
string_const_reference type_
)
{
string_type real_name = m_field_prefix + name_;
// check if name exists
if ( contains_field( real_name ) )
throw exceptions::sqlpp_exception("table::add_primary_key: field to add already there");
// creating field
field_shared_ptr pk( new
field(
shared_from_this(),
real_name,
type_
)
);
if (!pk)
throw exceptions::sqlpp_exception("table::add_primary_key: field memory allocation error");
insert_field(pk);
field_container fc;
fc.insert_field(pk);
m_primary_key=primary_key_constraint_shared_ptr(
new primary_key_constraint(
shared_from_this(),
"",
fc
)
);
if (!m_primary_key)
throw exceptions::sqlpp_exception("table::add_primary_key: primary key constraint memory allocation error");
return m_primary_key;
};
string_type table::get_create_statement() const
{
std::ostringstream out;
string_vector_type v_s;
const_iterator itf,itf_end;
out<<"CREATE TABLE "<<get_name()<<"("<<std::endl;
if ( empty() )
v_s.push_back("<this table has no fields>");
for (
boost::tie( itf, itf_end ) = get_fields();
itf!=itf_end;
++itf)
v_s.push_back(
itf->second->get_create_statement()
);
if (get_checked_database()->get_adaptor()->support_inline_constraints())
{
// primary key constraints
if (m_primary_key)
v_s.push_back( m_primary_key->get_sql() );
if (get_checked_database()->get_adaptor()->support_forward_declaration())
{
// foreign keys
ref_constraint_container_type::const_iterator itfk,itfk_end;
for (
boost::tie(itfk, itfk_end) = m_refs.get_constraints();
itfk != itfk_end;
++itfk)
v_s.push_back( itfk->second->get_sql() );
}
// unique keys
v_s.push_back( get_unique_statement() );
}
out<<vector_to_string( v_s.begin(), v_s.end(),",\n")<<std::endl;
out<<")";
return out.str();
};
string_type table::make_alter_constraint_statement( string_type constraint_) const
{
if (constraint_.empty())
return string_type();
std::ostringstream out;
out<<"ALTER TABLE "<<get_name()<<std::endl
<<"ADD "<<constraint_<<std::endl;
return out.str();
}
string_type table::get_unique_statement() const
{
if (m_uniques.empty())
return string_type();
std::ostringstream out;
string_vector_type v_s;
unique_constraint_container_type::const_iterator itfk,itfk_end;
for (
boost::tie(itfk, itfk_end) = m_uniques.get_constraints();
itfk != itfk_end;
++itfk)
v_s.push_back( itfk->second->get_sql() );
out<<vector_to_string( v_s.begin(), v_s.end(), ",")<<std::endl;
return out.str();
};
string_type table::get_alter_create_statement() const
{
std::ostringstream out;
out<<get_alter_primary_key()<<std::endl
<<get_alter_foreign_keys()<<std::endl
<<get_alter_unique_fields();
return out.str();
}
string_type table::get_alter_primary_key() const
{
if (!m_primary_key)
return string_type();
else
return make_alter_constraint_statement(
m_primary_key->get_sql()
);
};
string_type table::get_alter_foreign_keys() const
{
if (m_refs.empty())
return string_type();
string_vector_type v_s;
// foreign keys
ref_constraint_container_type::const_iterator itfk,itfk_end;
for (
boost::tie(itfk, itfk_end) = m_refs.get_constraints();
itfk != itfk_end;
++itfk)
v_s.push_back(
make_alter_constraint_statement(
itfk->second->get_sql()
)
);
return vector_to_string( v_s.begin(), v_s.end(),"");
};
string_type table::get_alter_unique_fields() const
{
return make_alter_constraint_statement(get_unique_statement());
};
};