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.respond;
10 
11 import pgator.db.connection;
12 import pgator.db.pq.api;
13 import vibe.data.bson;
14 import std.container;
15 import std.range;
16 import derelict.pq.pq;
17 
18 /// Worker returns this as query result
19 struct Respond
20 {
21     /// Constructing from error
22     /**
23     *   The constructor is used when pool detects problem
24     *   at its own level. $(B collect) method handles other
25     *   cases.
26     */
27     this(QueryException e, shared IConnection conn)
28     {
29         scope(exit) conn.clearRaisedMsgs;
30         
31         failed = true;
32         exception = e.msg;
33         msgs = conn.raisedMsgs.array.idup;
34     }
35     
36     /**
37     *   Transforms raw result from data base into BSON format. Also handles
38     *   errors that was raised in the connection.
39     */
40     bool collect(InputRange!(shared IPGresult) results, shared IConnection conn, bool oneRowConstraint, size_t queryId)
41     {
42         scope(exit) conn.clearRaisedMsgs;
43         msgs ~= conn.raisedMsgs.array.idup;
44         
45         bool localSucc = true;
46         foreach(res; results)
47         {
48             if( res.resultStatus != ExecStatusType.PGRES_TUPLES_OK &&
49                 res.resultStatus != ExecStatusType.PGRES_COMMAND_OK)
50             {
51                 failed = true;
52                 exception = res.resultErrorMessage;
53                 localSucc = false;
54             }
55             if(localSucc)
56             {
57                 auto temp = res.asColumnBson(conn);
58                 if(oneRowConstraint && !isOneRow(temp))
59                 {
60                    failed = true;
61                    onRowConstaintFailed = true;
62                    constraintFailQueryId = queryId;
63                    localSucc = false;
64                 } else
65                 {
66                     result ~= temp;
67                 }
68             }
69             res.clear();
70         }
71         return localSucc;
72     }
73     
74     private bool isOneRow(Bson res)
75     {
76         Bson[string] columns;
77         try
78         {
79             columns = res.get!(Bson[string]);
80         } 
81         catch(Exception e)
82         {
83             // something wrong with columns
84             return false;
85         }
86         
87         foreach(col; columns) return col.length == 1;
88         return false;
89     }
90     
91     /// Flag to distinct error case from normal respond
92     bool failed = false;
93     
94     bool onRowConstaintFailed = false;
95     size_t constraintFailQueryId;
96     
97     /// Error stored in string
98     string exception;
99     /// Collected result
100     immutable(Bson)[] result;
101     /// Additional messages
102     immutable(string)[] msgs;
103 }