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 module hunt.database.base.impl.RowSetImpl; 18 19 import hunt.database.base.impl.RowInternal; 20 import hunt.database.base.impl.SqlResultBase; 21 22 import hunt.database.base.RowIterator; 23 import hunt.database.base.RowSet; 24 import hunt.database.base.Row; 25 26 import hunt.Exceptions; 27 import hunt.Functions; 28 29 import std.array; 30 import std.ascii : newline; 31 import std.variant; 32 33 /** 34 * 35 */ 36 class RowSetImpl : SqlResultBase!(RowSet, RowSetImpl), RowSet { 37 38 static void accumulator(RowSetImpl set, Row row) { 39 if (set.head is null) { 40 set.head = set.tail = cast(RowInternal) row; 41 } else { 42 set.tail.setNext(cast(RowInternal) row); 43 set.tail = set.tail.getNext(); 44 } 45 } 46 47 static Function!(RowSet, RowSetImpl) FACTORY() { 48 return (rs) { return cast(RowSetImpl) rs; } ; 49 } 50 51 private RowInternal head; 52 private RowInternal tail; 53 54 override 55 RowSet value() { 56 return this; 57 } 58 59 override 60 string[] columnsNames() { 61 return _columnNames; 62 } 63 64 override 65 int rowCount() { 66 return _updated; 67 } 68 69 void rowCount(int v) { 70 this._updated = v; 71 } 72 73 override int size() { 74 return _size; 75 } 76 77 78 Row firstRow() { 79 return head; 80 } 81 82 Row lastRow() { 83 return tail; 84 } 85 86 Variant property(string key) { 87 if(key.empty) { 88 throw new IllegalArgumentException("Property can not be null"); 89 } 90 91 if(properties is null) 92 return Variant(null); 93 94 return properties.get(key, Variant(null)); 95 } 96 97 override 98 RowSetImpl next() { 99 return _next; 100 } 101 102 alias next = SqlResultBase!(RowSet, RowSetImpl).next; 103 104 void append(Row row) { 105 if (this.head is null) { 106 this.head = this.tail = cast(RowInternal) row; 107 } else { 108 this.tail.setNext(cast(RowInternal) row); 109 this.tail = this.tail.getNext(); 110 } 111 } 112 113 // override int size() { 114 // return super.size(); 115 // } 116 117 // override int rowCount() { 118 // return super.rowCount(); 119 // } 120 121 // override string[] columnsNames() { 122 // return super.columnsNames(); 123 // } 124 125 override string toString() { 126 Appender!string sb; 127 128 sb.put("|"); 129 foreach(string name; _columnNames) { 130 sb.put(" "); 131 sb.put(name); 132 sb.put(" |"); 133 } 134 sb.put(newline); 135 sb.put("-------------------------------------------------------"); 136 sb.put(newline); 137 138 foreach(Row row; this) { 139 sb.put("|"); 140 for(int i=0; i<row.size(); i++) { 141 sb.put(" "); 142 sb.put(row[i].toString()); 143 sb.put(" |"); 144 } 145 sb.put(newline); 146 } 147 148 return sb.data; 149 } 150 151 int opApply(scope int delegate(ref Row) dg) { 152 153 int result = 0; 154 RowInternal cur = head; 155 while(cur !is null) { 156 Row r = cur; 157 result = dg(r); 158 cur = cur.getNext(); 159 } 160 return result; 161 } 162 163 override 164 RowIterator iterator() { 165 return new IteratorImpl(); 166 } 167 168 private class IteratorImpl : RowIterator { 169 RowInternal current; 170 171 this() { 172 current = head; 173 } 174 175 bool empty() { 176 return current is null; 177 } 178 179 Row front() { 180 if (current is null) { 181 throw new NoSuchElementException("No such element!"); 182 } 183 184 return current; 185 } 186 187 void popFront() { 188 if (current is null) { 189 throw new NoSuchElementException(); 190 } 191 current = current.getNext(); 192 } 193 194 Row moveFront() { 195 throw new NotImplementedException(); 196 } 197 198 int opApply(scope int delegate(Row) dg) { 199 int result = 0; 200 RowInternal cur = head; 201 while(cur !is null) { 202 result = dg(cur); 203 cur = cur.getNext(); 204 } 205 return result; 206 } 207 208 /// Ditto 209 int opApply(scope int delegate(size_t, Row) dg) { 210 int result = 0; 211 size_t index = 0; 212 RowInternal cur = head; 213 while(cur !is null) { 214 result = dg(index++, cur); 215 cur = cur.getNext(); 216 } 217 return result; 218 } 219 220 } 221 }