1 module pgator.sql_transaction; 2 3 import pgator.rpc_table; 4 import pgator.app; 5 import vibe.db.postgresql; 6 7 struct TransactionQueryParams 8 { 9 QueryParams[] queryParams; 10 AuthorizationCredentials auth; 11 } 12 13 struct SQLTransaction 14 { 15 private LockedConnection!__Conn conn; 16 private bool opened = false; 17 18 @disable this(this){} 19 20 this(PostgresClient client) 21 { 22 conn = client.lockConnection(); 23 } 24 25 void begin(bool isReadOnly) 26 { 27 execBuiltIn(isReadOnly ? BuiltInPrep.BEGIN_RO : BuiltInPrep.BEGIN); 28 opened = true; 29 } 30 31 void resetStart() 32 { 33 import vibe.core.log; 34 35 logDebugV(__FUNCTION__); 36 37 opened = false; 38 conn.resetStart(); 39 } 40 41 void commit() 42 { 43 execBuiltIn(BuiltInPrep.COMMIT); 44 opened = false; 45 } 46 47 ~this() 48 { 49 if(opened) 50 execBuiltIn(BuiltInPrep.ROLLBACK); 51 52 delete conn; 53 } 54 55 immutable(Answer)[] execMethod(in Method method, TransactionQueryParams qp) 56 { 57 assert(opened); 58 59 if(method.needAuthVariablesFlag) 60 { 61 QueryParams q; 62 q.preparedStatementName = BuiltInPrep.SET_AUTH_VARS; 63 q.args = [qp.auth.username.toValue, qp.auth.password.toValue]; 64 65 conn.execPreparedStatement(q); 66 } 67 68 immutable(Answer)[] ret; 69 70 foreach(i, s; method.statements) 71 { 72 ret ~= conn.execPreparedStatement(qp.queryParams[i]); 73 } 74 75 return ret; 76 } 77 78 private void execBuiltIn(BuiltInPrep prepared) 79 { 80 QueryParams q; 81 q.preparedStatementName = prepared; 82 83 conn.execPreparedStatement(q); 84 } 85 } 86 87 enum BuiltInPrep : string 88 { 89 BEGIN = "#b#", 90 BEGIN_RO = "#r#", 91 COMMIT = "#C#", 92 ROLLBACK = "#R#", 93 SET_AUTH_VARS = "#a#" 94 }