11package me .zort .sqllib .transaction ;
22
33import lombok .*;
4+ import me .zort .sqllib .SQLDatabaseConnection ;
5+ import me .zort .sqllib .api .Query ;
46import me .zort .sqllib .api .data .QueryResult ;
7+ import me .zort .sqllib .api .data .QueryRowsResult ;
58import me .zort .sqllib .internal .query .QueryNode ;
6- import me .zort .sqllib .transaction .step .FlowStepImpl ;
79import me .zort .sqllib .util .Arrays ;
810import org .jetbrains .annotations .NotNull ;
911
1315public class TransactionFlow {
1416
1517 private final Transaction transaction ;
16- private final FlowStep [] steps ;
18+ private final Step [] steps ;
1719 private final Options options ;
1820 private boolean executed = false ;
1921 private int index = -1 ;
2022
21- public FlowResult execute () {
23+ public Result execute () {
2224 return executeNext (steps .length );
2325 }
2426
2527 @ SneakyThrows (SQLException .class )
26- public FlowResult executeNext (int count ) {
28+ public Result executeNext (int count ) {
2729 if (executed ) throw new IllegalStateException ("TransactionFlow already fully executed!" );
2830
2931 QueryResult [] results = new QueryResult [steps .length ];
3032 int maxIndex = index + count ;
3133 int lastIndex = index ;
3234 for (int i = 0 ; i <= maxIndex ; i ++) {
33- FlowStep .Status status = steps [i ].execute (transaction .getDatabaseConnection ());
34- if (status .equals (FlowStep .Status .BREAK )) {
35+ Step .Status status = steps [i ].execute (transaction .getDatabaseConnection ());
36+ if (status .equals (Step .Status .BREAK )) {
3537 if (options .rollbackOnFailure ) {
3638 transaction .rollback ();
3739 index = -1 ;
3840 }
3941 break ;
4042 }
41- results [i ] = status .equals (FlowStep .Status .SUCCESS ) ? steps [i ].getResult () : null ;
43+ results [i ] = status .equals (Step .Status .SUCCESS ) ? steps [i ].getResult () : null ;
4244 lastIndex = i ;
4345 }
4446 boolean success = true ;
@@ -48,9 +50,9 @@ public FlowResult executeNext(int count) {
4850 results [++lastIndex ] = null ;
4951 }
5052
51- FlowResult result = success
52- ? new FlowResult (true )
53- : new FlowResult (false ,
53+ Result result = success
54+ ? new Result (true )
55+ : new Result (false ,
5456 String .format ("Transaction failed at step %d!" , lastIndexFinal + 1 ));
5557
5658 result .addAll (java .util .Arrays .asList (results ));
@@ -76,7 +78,7 @@ private void close() {
7678 public static final class Builder {
7779 private final Transaction transaction ;
7880 private final Options options ;
79- private FlowStep [] steps = new FlowStep [0 ];
81+ private Step [] steps = new Step [0 ];
8082
8183 public Builder (Transaction transaction ) {
8284 this .transaction = transaction ;
@@ -88,10 +90,10 @@ public Builder(Transaction transaction) {
8890 }
8991
9092 public @ NotNull Builder step (final @ NotNull QueryNode <?> node , boolean optional ) {
91- return step (new FlowStepImpl (node , optional ));
93+ return step (new StepImpl (node , optional ));
9294 }
9395
94- public @ NotNull Builder step (final @ NotNull FlowStep step ) {
96+ public @ NotNull Builder step (final @ NotNull TransactionFlow . Step step ) {
9597 steps = Arrays .add (steps , step );
9698 return this ;
9799 }
@@ -124,4 +126,55 @@ public static final class Options {
124126 private boolean autoClose = true ;
125127 }
126128
129+ public static final class Result extends QueryRowsResult <QueryResult > {
130+ @ Setter (AccessLevel .PROTECTED )
131+ @ Getter
132+ private int brokenIndex = -1 ;
133+
134+ public Result (final boolean successful ) {
135+ super (successful );
136+ }
137+
138+ public Result (final boolean successful , String rejectMessage ) {
139+ super (successful , rejectMessage );
140+ }
141+
142+ }
143+
144+ @ RequiredArgsConstructor
145+ private static class StepImpl implements Step {
146+ private final Query query ;
147+ @ Getter
148+ private final boolean optional ;
149+ @ Getter
150+ private QueryResult result = null ;
151+
152+ @ Override
153+ public Status execute (SQLDatabaseConnection connection ) {
154+ if (!(query instanceof QueryNode )) throw new IllegalStateException ("FlowStepImpl accepts only QueryNode!" );
155+
156+ QueryNode <?> node = (QueryNode <?>) query ;
157+ node = node .getAncestor ();
158+ QueryResult localResult = node .generatesResultSet ()
159+ ? connection .query (node )
160+ : connection .exec (node );
161+
162+ if (localResult .isSuccessful ()) result = localResult ;
163+ return localResult .isSuccessful () ? Status .SUCCESS : (optional ? Status .CONTINUE : Status .BREAK );
164+ }
165+ }
166+
167+ public interface Step {
168+
169+ Status execute (SQLDatabaseConnection connection );
170+
171+ QueryResult getResult (); // Result if the #execute returned SUCCESS, otherwise null
172+
173+ boolean isOptional ();
174+
175+ enum Status {
176+ SUCCESS , BREAK , CONTINUE
177+ }
178+
179+ }
127180}
0 commit comments