package com.orientechnologies.orient.core.sql.executor;

import com.orientechnologies.orient.core.command.OCommandContext;

import java.text.DecimalFormat;
import java.util.Optional;

/**
 * @author Luigi Dell'Aquila (l.dellaquila-(at)-orientdb.com)
 */
public abstract class AbstractExecutionStep implements OExecutionStepInternal {

  protected final OCommandContext ctx;
  protected Optional<OExecutionStepInternal> prev     = Optional.empty();
  protected Optional<OExecutionStepInternal> next     = Optional.empty();
  protected boolean                          timedOut = false;

  protected boolean profilingEnabled = false;

  public AbstractExecutionStep(OCommandContext ctx, boolean profilingEnabled) {
    this.ctx = ctx;
    this.profilingEnabled = profilingEnabled;
  }

  @Override
  public void setPrevious(OExecutionStepInternal step) {
    this.prev = Optional.ofNullable(step);
  }

  @Override
  public void setNext(OExecutionStepInternal step) {
    this.next = Optional.ofNullable(step);
  }

  public OCommandContext getContext() {
    return ctx;
  }

  public Optional<OExecutionStepInternal> getPrev() {
    return prev;
  }

  public Optional<OExecutionStepInternal> getNext() {
    return next;
  }

  @Override
  public void sendTimeout() {
    this.timedOut = true;
    prev.ifPresent(p -> p.sendTimeout());
  }

  @Override
  public void close() {
    prev.ifPresent(p -> p.close());
  }

  public boolean isProfilingEnabled() {
    return profilingEnabled;
  }

  public void setProfilingEnabled(boolean profilingEnabled) {
    this.profilingEnabled = profilingEnabled;
  }

  protected String getCostFormatted() {
    return new DecimalFormat().format(getCost() / 1000) + "μs";
  }

}

@@ -362,16 +362,33 @@
 Context 
+                 
 ctx;%0A  p
@@ -388,32 +388,38 @@
 tx;%0A  protected 
+      
 Optional%3COExecut
@@ -476,16 +476,22 @@
 otected 
+      
 Optional
@@ -548,32 +548,38 @@
 ();%0A  protected 
+      
 boolean         
@@ -1376,41 +1376,154 @@
 %0A%0A  
-@Override%0A  public void close() %7B
+private boolean alreadyClosed = false;%0A%0A  @Override%0A  public void close() %7B%0A    if (alreadyClosed) %7B%0A      return;%0A    %7D%0A    alreadyClosed = true;
 %0A   

make sure that SQL steps are closed only once