| 148 | } |
| 149 | |
| 150 | @Override |
| 151 | public Iter iter(final QueryContext qc) { |
| 152 | return new Iter() { |
| 153 | private final int el = exprs.length; |
| 154 | private final Iter[] iters = new Iter[el]; |
| 155 | private long[] offsets; |
| 156 | private long size; |
| 157 | private int e; |
| 158 | |
| 159 | @Override |
| 160 | public Item next() throws QueryException { |
| 161 | while(e < el) { |
| 162 | final Item item = qc.next(iter(e)); |
| 163 | if(item != null) return item; |
| 164 | e++; |
| 165 | } |
| 166 | return null; |
| 167 | } |
| 168 | |
| 169 | @Override |
| 170 | public Item get(final long i) throws QueryException { |
| 171 | int o = 0; |
| 172 | while(o < el - 1 && offsets[o + 1] <= i) o++; |
| 173 | return iter(o).get(i - offsets[o]); |
| 174 | } |
| 175 | |
| 176 | @Override |
| 177 | public long size() throws QueryException { |
| 178 | if(offsets == null) { |
| 179 | // first call: sum up sizes |
| 180 | offsets = new long[el]; |
| 181 | for(int o = 0; o < el && size != -1; o++) { |
| 182 | // cache offsets for direct access |
| 183 | offsets[o] = size; |
| 184 | final long s = iter(o).size(); |
| 185 | size = s == -1 || size + s < 0 ? -1 : size + s; |
| 186 | } |
| 187 | } |
| 188 | return size; |
| 189 | } |
| 190 | |
| 191 | private Iter iter(final int i) throws QueryException { |
| 192 | Iter iter = iters[i]; |
| 193 | if(iter == null) { |
| 194 | iter = exprs[i].iter(qc); |
| 195 | iters[i] = iter; |
| 196 | } |
| 197 | return iter; |
| 198 | } |
| 199 | }; |
| 200 | } |
| 201 | |
| 202 | @Override |
| 203 | public Value value(final QueryContext qc) throws QueryException { |