1 /*
2  * Copyright (C) 2019, HuntLabs
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 
18 module hunt.database.driver.postgresql.impl.codec.RowResultDecoder;
19 
20 import hunt.database.driver.postgresql.impl.codec.DataFormat;
21 import hunt.database.driver.postgresql.impl.codec.DataType;
22 import hunt.database.driver.postgresql.impl.codec.DataTypeCodec;
23 import hunt.database.driver.postgresql.impl.codec.PgRowDesc;
24 import hunt.database.driver.postgresql.impl.codec.PgColumnDesc;
25 import hunt.database.driver.postgresql.impl.PostgreSQLRowImpl;
26 
27 import hunt.database.base.Row;
28 import hunt.database.base.impl.RowDecoder;
29 import hunt.database.base.impl.RowSetImpl;
30 
31 import hunt.Exceptions;
32 import hunt.Functions;
33 import hunt.logging;
34 import hunt.net.buffer.ByteBuf;
35 
36 import std.variant;
37 
38 /**
39  * 
40  */
41 class RowResultDecoder(R) : RowDecoder {
42 
43     private int _size;
44     private RowSetImpl container;
45     private Row row;
46     private bool singleton;
47     PgRowDesc desc;
48 
49     this(bool singleton, PgRowDesc desc) {
50         this.singleton = singleton;
51         this.desc = desc;
52     }
53 
54     int size() {
55         return _size;
56     }
57 
58     // override
59     void decodeRow(int len, ByteBuf buffer) {
60         if (container is null) {
61             container = new RowSetImpl(); 
62         }
63 
64         if (singleton) {
65             if (row is null) {
66                 row = new PgRowImpl(desc);
67             } else {
68                 row.clear();
69             }
70         } else {
71             row = new PgRowImpl(desc);
72         }
73 
74         version(HUNT_DB_DEBUG_MORE) infof("row: %d, size: %d", _size+1, len);
75         
76         Row row = new PgRowImpl(desc);
77         for (int c = 0; c < len; ++c) {
78             int length = buffer.readInt();
79             Variant decoded = null;
80             if (length != -1) {
81                 PgColumnDesc columnDesc = desc.columns[c];
82 
83                 version(HUNT_DB_DEBUG_MORE) {
84                     tracef("    column[%d]: name=%s, %s, dataFormat=%s", 
85                        c, columnDesc.name, columnDesc.dataType, columnDesc.dataFormat);
86                 }
87 
88                 if (columnDesc.dataFormat == DataFormat.BINARY) {
89                     decoded = DataTypeCodec.decodeBinary(cast(DataType)columnDesc.dataType.id, 
90                         buffer.readerIndex(), length, buffer);
91                 } else {
92                     decoded = DataTypeCodec.decodeText(cast(DataType)columnDesc.dataType.id, 
93                         buffer.readerIndex(), length, buffer);
94                 }
95 
96                 version(HUNT_DB_DEBUG_MORE) {
97                     tracef("    colum[%d]: value=%s", c,  decoded.toString());
98                 }
99 
100                 buffer.skipBytes(length);
101             }
102             row.addValue(decoded);
103         }
104         container.append(row);
105         _size++;
106     }
107 
108     R complete() {
109         if (container is null) {
110             container = new RowSetImpl(); 
111         }
112         return container;
113     }
114 
115     void reset() {
116         container = null;
117         _size = 0;
118     }
119 }