1 /*
2  * Copyright (C) 2018 Julien Viet
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 module hunt.database.driver.postgresql.impl.codec.CommandCodec;
18 
19 import hunt.database.driver.postgresql.impl.codec.ErrorResponse;
20 import hunt.database.driver.postgresql.impl.codec.NoticeResponse;
21 import hunt.database.driver.postgresql.impl.codec.PgParamDesc;
22 import hunt.database.driver.postgresql.impl.codec.PgEncoder;
23 import hunt.database.driver.postgresql.impl.codec.PgRowDesc;
24 
25 import hunt.database.base.Common;
26 import hunt.database.base.impl.TxStatus;
27 import hunt.database.base.impl.command.CommandResponse;
28 import hunt.database.base.impl.command.CommandBase;
29 
30 import hunt.Exceptions;
31 import hunt.logging;
32 import hunt.net.buffer.ByteBuf;
33 
34 
35 /**
36 */
37 abstract class CommandCodecBase {
38     
39     Throwable _failure;
40     
41     EventHandler!(NoticeResponse) noticeHandler;
42     EventHandler!(ICommandResponse) completionHandler;
43 
44     abstract void encode(PgEncoder encoder);
45 
46     void decodeRow(int len, ByteBuf inBuffer) {
47         throw new NotImplementedException();
48     }
49 
50     void handleBackendKeyData(int processId, int secretKey) {
51         warning(typeid(this).name ~ " should handle message BackendKeyData");
52     }
53 
54     void handleEmptyQueryResponse() {
55         warning(typeid(this).name ~ " should handle message EmptyQueryResponse");
56     }
57 
58     void handleParameterDescription(PgParamDesc paramDesc) {
59         warning(typeid(this).name ~ " should handle message ParameterDescription");
60     }
61 
62     void handleParseComplete() {
63         warning(typeid(this).name ~ " should handle message ParseComplete");
64     }
65 
66     void handleCloseComplete() {
67         warning(typeid(this).name ~ " should handle message CloseComplete");
68     }
69 
70     void handleRowDescription(PgRowDesc rowDescription) {
71         warning(typeid(this).name ~ " should handle message " ~ rowDescription.toString());
72     }
73 
74     void handleNoData() {
75         warning(typeid(this).name ~ " should handle message NoData");
76     }
77 
78     void handleNoticeResponse(NoticeResponse noticeResponse);
79 
80     void handleErrorResponse(ErrorResponse errorResponse) {
81         warning(typeid(this).name ~ " should handle message " ~ errorResponse.toString());
82     }
83 
84     void handlePortalSuspended() {
85         warning(typeid(this).name ~ " should handle message PortalSuspended");
86     }
87 
88     void handleBindComplete() {
89         warning(typeid(this).name ~ " should handle message BindComplete");
90     }
91 
92     void handleCommandComplete(int updated) {
93         warning(typeid(this).name ~ " should handle message CommandComplete");
94     }
95 
96     void handleAuthenticationMD5Password(byte[] salt) {
97         warning(typeid(this).name ~ " should handle message AuthenticationMD5Password");
98     }
99 
100     void handleAuthenticationClearTextPassword() {
101         warning(typeid(this).name ~ " should handle message AuthenticationClearTextPassword");
102     }
103 
104     void handleAuthenticationOk() {
105         warning(typeid(this).name ~ " should handle message AuthenticationOk");
106     }
107 
108     void handleParameterStatus(string key, string value) {
109         warning(typeid(this).name ~ " should handle message ParameterStatus");
110     }
111 
112     void handleReadyForQuery(TxStatus txStatus);
113 
114     ICommand getCommand();
115 }
116 
117 /**
118 */
119 abstract class CommandCodec(R, C) : CommandCodecBase
120         if(is(C : CommandBase!(R))) {
121 
122     R result;
123     C cmd;
124 
125     this(C cmd) {
126         this.cmd = cmd;
127     }
128 
129     /**
130      * <p>
131      * The frontend can issue commands. Every message returned from the backend has transaction status
132      * that would be one of the following
133      * <p>
134      * IDLE : Not in a transaction block
135      * <p>
136      * ACTIVE : In transaction block
137      * <p>
138      * FAILED : Failed transaction block (queries will be rejected until block is ended)
139      */
140     override void handleReadyForQuery(TxStatus txStatus) {
141         CommandResponse!(R) resp;
142         if (_failure !is null) {
143             resp = failedResponse!(R)(_failure, txStatus);
144         } else {
145             resp = succeededResponse(result, txStatus);
146         }
147 
148         if(completionHandler !is null) {
149             // resp.cmd = cmd;
150             completionHandler(resp);
151         }
152     }
153     override void handleNoticeResponse(NoticeResponse noticeResponse) {
154         if(noticeHandler !is null) {
155             noticeHandler(noticeResponse);
156         }
157     }
158 
159     override C getCommand() {
160         return cmd;
161     }
162 }