1 // Written in D programming language
2 /**
3 *    Part of asynchronous pool realization.
4 *    
5 *    Copyright: © 2014 DSoftOut
6 *    License: Subject to the terms of the MIT license, as written in the included LICENSE file.
7 *    Authors: NCrashed <ncrashed@gmail.com>
8 */
9 module pgator.db.async.transaction;
10 
11 import std.conv;
12 import std.exception;
13 
14 import pgator.db.pool;
15 
16 private T min(T)(T a, T b) { return a < b ? a : b; }
17 
18 /**
19 *   Handles all data that is need to perform SQL transaction: queries, parameters,
20 *   info where to put parameters and local enviroment variables.
21 */
22 class Transaction : IConnectionPool.ITransaction
23 {
24     this(string[] commands, string[] params, uint[] argnums, string[string] vars, bool[] oneRowConstraints) immutable
25     {
26         this.commands = commands.idup;
27         this.params = params.idup;
28         this.argnums = argnums.idup;
29         string[string] temp = vars.dup;
30         this.vars = assumeUnique(temp);
31         this.oneRowConstraints = oneRowConstraints.idup;
32     }
33     
34     override bool opEquals(Object o) nothrow 
35     {
36         auto b = cast(Transaction)o;
37         if(b is null) return false;
38         
39         return commands == b.commands && params == b.params && argnums == b.argnums && vars == b.vars && oneRowConstraints == b.oneRowConstraints;
40     }
41     
42     override hash_t toHash() nothrow @trusted
43     {
44         hash_t toHashArr(T)(immutable T[] arr) nothrow
45         {
46             hash_t h;
47             auto hashFunc = &(typeid(T).getHash);
48             foreach(elem; arr) h += hashFunc(&elem);
49             return h;
50         }
51         
52         hash_t toHashAss(T)(immutable T[T] arr) nothrow
53         {
54             hash_t h;
55             scope(failure) return 0;
56             auto hashFunc = &(typeid(T).getHash);
57             foreach(key, val; arr) h += hashFunc(&key) + hashFunc(&val);
58             return h;
59         }
60         
61         return toHashArr(commands) + toHashArr(params) + toHashArr(argnums) + toHashAss(vars) + toHashArr(oneRowConstraints);
62     }
63     
64     void toString(scope void delegate(const(char)[]) sink) const
65     {
66         if(commands.length == 1)
67         {
68             sink("Command: ");
69             sink(commands[0]);
70             if(params.length != 0)
71             {
72                 sink("\n");
73                 sink(text("With params: ", params));
74             }
75             sink("\n");
76             sink(text("One row: ",oneRowConstraints[0]));
77             if(vars.length != 0) sink("\n");
78         } 
79         else
80         {
81             sink("Commands: \n");
82             size_t j = 0;
83             foreach(immutable i, command; commands)
84             {
85                 sink(text(i, ": ", command));
86                 sink("\n");
87                 if(i >= argnums.length) continue;
88                 
89                 if(params.length != 0)
90                 {
91                     size_t k = min(j+argnums[i], params.length);
92                     sink(text("With params: ", params[j .. k]));
93                 }
94                 sink("\n");
95                 sink(text("One row: ",oneRowConstraints[i]));
96                 if(i != commands.length-1) sink("\n");
97                 j += argnums[i];
98             }
99             if(vars.length != 0) sink("\n");
100         }
101         
102         if(vars.length != 0)
103         {
104             sink("Variables: \n");
105             size_t i = 0;
106             foreach(key, value; vars)
107             {
108                 sink(text(key, " : ", value));
109                 if(i++ != vars.length - 1) sink("\n");
110             }
111         }
112     }
113     
114     immutable string[] commands;
115     immutable string[] params;
116     immutable uint[]   argnums;
117     immutable string[string] vars;
118     immutable bool[] oneRowConstraints;
119 }