with GNATCOLL.SQL.Exec;
with GNATCOLL.SQL.Sqlite;

procedure Great_Expectations
is
   Description : GNATCOLL.SQL.Exec.Database_Description;
   Connection : GNATCOLL.SQL.Exec.Database_Connection;
   Is_In_Transaction : Boolean;
   Transaction_Started : Boolean;

   procedure Raise_On_Database_Error
      (Connection : not null GNATCOLL.SQL.Exec.Database_Connection;
      Context : String)
   is
   begin
      if not GNATCOLL.SQL.Exec.Success (Connection => Connection) then
         raise Program_Error with Context & " : " & GNATCOLL.SQL.Exec.Error (Connection => Connection);
      end if;
   end Raise_On_Database_Error;

begin

   Description := GNATCOLL.SQL.Sqlite.Setup (Database => ":memory:");
   Connection := Description.Build_Connection;
   GNATCOLL.SQL.Exec.Automatic_Transactions (Connection => Connection, Active => False);
   Raise_On_Database_Error (Connection => Connection, Context => "Build");

   Is_In_Transaction := GNATCOLL.SQL.Exec.In_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if Is_In_Transaction then
      raise Program_Error with "(1) not expecting to be in a transaction before Start_Transaction";
   end if;



   --  test with rollback

   Transaction_Started := GNATCOLL.SQL.Exec.Start_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if not Transaction_Started then
      raise Program_Error with "(2) expecting transaction to be opened.";
   end if;

   Is_In_Transaction := GNATCOLL.SQL.Exec.In_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if not Is_In_Transaction then
      raise Program_Error with "(3) expecting transaction to be open after Start_Transaction.";
   end if;

   GNATCOLL.SQL.Exec.Rollback (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "Rollback");

   Is_In_Transaction := GNATCOLL.SQL.Exec.In_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if Is_In_Transaction then
      raise Program_Error with "(4) not expecting to be in a transaction after rollback";
   end if;



   --  test with Commit

   Transaction_Started := GNATCOLL.SQL.Exec.Start_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "Start_Transaction");
   if not Transaction_Started then
      raise Program_Error with "(5) expecting transaction to be opened.";
   end if;

   Is_In_Transaction := GNATCOLL.SQL.Exec.In_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if not Is_In_Transaction then
      raise Program_Error with "(6) expecting transaction to be open after Start_Transaction.";
   end if;

   GNATCOLL.SQL.Exec.Commit (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "Commit");

   Is_In_Transaction := GNATCOLL.SQL.Exec.In_Transaction (Connection => Connection);
   Raise_On_Database_Error (Connection => Connection, Context => "In_Transaction");
   if Is_In_Transaction then
      raise Program_Error with "(7) not expecting to be in a transaction after commit";
   end if;

end Great_Expectations;
