package com.novarto.sanedbc.core.interpreter;

import com.novarto.sanedbc.core.ops.DbOps;
import fj.control.db.DB;
import fj.function.Try0;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * A set of utilities to aid in implementing {@link DB} interpreters.
 */
public final class InterpreterUtils
{
    private InterpreterUtils()
    {
        throw new UnsupportedOperationException();
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(DbOps.class);

    /**
     * Returns an operation that will try to rollback the given operation upon failure.
     *
     * - Upon any instance of {@link Throwable} caught, a connection rollback will be issued
     * - The original throwable instance will be preserved without being mutated
     * - If the connection auto-commit was mutated as part of this transformation, connection setAutoCommit
     *  will be finally issued to the connection.
     */
    public static <A> DB<A> transactional(DB<A> op)
    {

        return new DB<A>()
        {
            @Override public A run(Connection c) throws SQLException
            {
                boolean wasAutocommit = c.getAutoCommit();
                if (wasAutocommit)
                {
                    c.setAutoCommit(false);
                }
                try
                {
                    A result = op.run(c);
                    c.commit();
                    return result;
                }
                catch (RuntimeException | SQLException e)
                {
                    c.rollback();
                    throw e;

                }
                catch (Error e)
                {
                    try
                    {
                        c.rollback();
                    }
                    catch (SQLException sqlE)
                    {
                        LOGGER.error("Could not roll back transaction which failed with java.lang.Error", sqlE);
                    }
                    throw e;
                }
                catch (Throwable t)
                {
                    c.rollback();
                    throw t;
                }
                finally
                {
                    if (wasAutocommit)
                    {
                        c.setAutoCommit(true);
                    }
                }

            }
        };
    }

    /**
     * Lifts a DataSource to Try0<Connection, SQLException> (i.e. converts it to Try0<Connection, SQLException>)
     */
    public static Try0<Connection, SQLException> lift(DataSource ds)
    {
        return ds::getConnection;
    }
}

@@ -839,21 +839,21 @@
 t being 
-mutat
+wrapp
 ed%0A     
@@ -1208,16 +1208,22 @@
         
+final 
 boolean 
@@ -1249,32 +1249,69 @@
 etAutoCommit();%0A
+                Throwable th = null;%0A
                 
@@ -1401,32 +1401,33 @@
               %7D%0A
+%0A
                 
@@ -1602,60 +1602,66 @@
 ch (
-RuntimeException %7C SQLException e)%0A                %7B
+Throwable e)%0A                %7B%0A                    th = e;
 %0A   
@@ -1759,23 +1759,15 @@
     
-catch (Error e)
+finally
 %0A   
@@ -1847,37 +1847,42 @@
             
-c.rollback();
+if (wasAutocommit)
 %0A           
@@ -1882,34 +1882,40 @@
                 
-%7D%0A
+    %7B%0A  
                 
@@ -1922,33 +1922,36 @@
     
-catch (SQLException sqlE)
+      c.setAutoCommit(true);
 %0A   
@@ -1959,33 +1959,37 @@
                 
-%7B
+    %7D
 %0A               
@@ -1997,122 +1997,52 @@
     
-    LOGGER.error(%22Could not roll back transaction which failed with java.lang.Error%22, sqlE);%0A                    %7D
+%7D%0A                    catch (SQLException e)
 %0A   
@@ -2058,25 +2058,26 @@
         
-throw e;%0A
+%7B%0A        
         
@@ -2088,46 +2088,32 @@
     
-%7D%0A                catch (Throwable t)%0A
+if (th != null)%0A        
     
@@ -2142,35 +2142,50 @@
             
-c.rollback(
+        th.addSuppressed(e
 );%0A         
@@ -2199,20 +2199,14 @@
     
-throw t;%0A
+ 
    
+%7D%0A
     
@@ -2206,34 +2206,32 @@
  %7D%0A             
-%7D%0A
                 
@@ -2221,37 +2221,37 @@
             
-     finally%0A
+else%0A        
             
@@ -2273,34 +2273,8 @@
     
-       if (wasAutocommit)%0A
     
@@ -2276,38 +2276,40 @@
                 
-     %7B
+throw e;
 %0A               
@@ -2317,38 +2317,17 @@
         
-c.setAutoCommit(true);
+%7D
 %0A       

simplify transactional