Click here to Skip to main content
15,886,362 members
Articles / Database Development / SQL Server

A scripted SQL query generation framework with IDE: SQLpp (v1.4)

Rate me:
Please Sign up or sign in to vote.
4.98/5 (47 votes)
12 Sep 200311 min read 411.1K   5.4K   133  
A helper framework for generation of SQL queries in C++ and Lua
#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());
	};
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Engineer
United States United States
Jonathan de Halleux is Civil Engineer in Applied Mathematics. He finished his PhD in 2004 in the rainy country of Belgium. After 2 years in the Common Language Runtime (i.e. .net), he is now working at Microsoft Research on Pex (http://research.microsoft.com/pex).

Comments and Discussions