// Range Transaction over a DBConnection: Insertion into a DBView 

const TIMESTAMP_STRUCT chrysalis = {2002, 4, 3, 0, 0, 0, 0};
const TIMESTAMP_STRUCT mikero = {2001, 11, 2, 0, 0, 0, 0};
const TIMESTAMP_STRUCT victory = {2001, 3, 10, 0, 0, 0, 0};

// this example shows range insert transactions in action
void RangeInsertExample()
{
	DBConnection conn;
        conn.Connect("UID=example;PWD=example;DSN=example;");

	typedef DBView DBV;

	DBV view("DB_EXAMPLE", DefaultBCA(), 
	   "", DefaultBPA >(), DefaultSelValidate(),
	   DefaultInsValidate(), conn);

	cout << "Examples in view before attempted range insert:" << endl;

	copy(view.begin(), view.end(), ostream_iterator(cout, "\n"));

	vector read_from_DB_before;

	copy(view.begin(), view.end(), back_inserter(read_from_DB_before));

	// examples that we want to insert into the DB ...
	// we want an all or nothing on these guys!
	vector all_or_nothing_examples;

	// third element will fail to be inserted, should force rollback
	all_or_nothing_examples.push_back(Example(79, "FUBAR", 2.2, 99, mikero));
	all_or_nothing_examples.push_back(Example(81, "All Messed Up", 21.09, 75, chrysalis));
	all_or_nothing_examples.push_back(Example(85, "Bad Boy", -21.22, 11, victory));
	all_or_nothing_examples.push_back(Example(99, "Good One", 77.99, 41, victory));
	
	// must write all the elements to succeed in the transaction
	// else we rollback
	try { 
      
	  DBV::insert_iterator write_it = view;

	  write_it.set_io_handler(AlwaysThrowsHandler());

	  for (vector::iterator ins_it = all_or_nothing_examples.begin(); 
	      ins_it != all_or_nothing_examples.end(); ins_it++, write_it++)
		  {	  
			 *write_it = *ins_it;
		  }

          conn.CommitAll(); // we assume commit and rollback must always succeed to avoid two-phase commit type logic
	}
        catch(RootException &ex) 
	{ 
	  cout << ex << endl;
          conn.RollbackAll(); 
	}

	cout << "Examples in view after attempted range insert:" << endl;

	copy(view.begin(), view.end(), ostream_iterator(cout, "\n"));

	vector read_from_DB_after;

	copy(view.begin(), view.end(), back_inserter(read_from_DB_after));

	cout << "Changes resulting from attempted range insert:" << endl;
   
        TableDiff(cout, read_from_DB_before, read_from_DB_after);
}