EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.index]

COVERAGE SUMMARY FOR SOURCE FILE [ScanIndex.java]

nameclass, %method, %block, %line, %
ScanIndex.java100% (1/1)0%   (0/23)0%   (0/453)0%   (0/106)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ScanIndex100% (1/1)0%   (0/23)0%   (0/453)0%   (0/106)
ScanIndex (RegularTable, int, IndexColumn [], IndexType): void 0%   (0/1)0%   (0/38)0%   (0/9)
add (Session, Row): void 0%   (0/1)0%   (0/80)0%   (0/20)
canGetFirstOrLast (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
checkRename (): void 0%   (0/1)0%   (0/3)0%   (0/1)
close (Session): void 0%   (0/1)0%   (0/1)0%   (0/1)
commit (int, Row): void 0%   (0/1)0%   (0/23)0%   (0/5)
find (Session, SearchRow, SearchRow): Cursor 0%   (0/1)0%   (0/9)0%   (0/1)
findFirstOrLast (Session, boolean): Cursor 0%   (0/1)0%   (0/3)0%   (0/1)
getColumnIndex (Column): int 0%   (0/1)0%   (0/2)0%   (0/1)
getCost (Session, int [], TableFilter, SortOrder): double 0%   (0/1)0%   (0/7)0%   (0/1)
getCreateSQL (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getDelta (): Iterator 0%   (0/1)0%   (0/12)0%   (0/4)
getDiskSpaceUsed (): long 0%   (0/1)0%   (0/2)0%   (0/1)
getNextRow (Row): Row 0%   (0/1)0%   (0/33)0%   (0/9)
getPlanSQL (): String 0%   (0/1)0%   (0/11)0%   (0/1)
getRow (Session, long): Row 0%   (0/1)0%   (0/7)0%   (0/1)
getRowCount (Session): long 0%   (0/1)0%   (0/36)0%   (0/7)
getRowCountApproximation (): long 0%   (0/1)0%   (0/3)0%   (0/1)
incrementRowCount (int, int): void 0%   (0/1)0%   (0/36)0%   (0/7)
needRebuild (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
remove (Session): void 0%   (0/1)0%   (0/4)0%   (0/2)
remove (Session, Row): void 0%   (0/1)0%   (0/98)0%   (0/20)
truncate (Session): void 0%   (0/1)0%   (0/39)0%   (0/10)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.index;
7 
8import java.util.ArrayList;
9import java.util.Collections;
10import java.util.HashMap;
11import java.util.HashSet;
12import java.util.Iterator;
13import java.util.List;
14 
15import org.h2.api.ErrorCode;
16import org.h2.engine.Constants;
17import org.h2.engine.Session;
18import org.h2.engine.UndoLogRecord;
19import org.h2.message.DbException;
20import org.h2.result.Row;
21import org.h2.result.SearchRow;
22import org.h2.result.SortOrder;
23import org.h2.table.Column;
24import org.h2.table.IndexColumn;
25import org.h2.table.RegularTable;
26import org.h2.table.TableFilter;
27import org.h2.util.New;
28 
29/**
30 * The scan index is not really an 'index' in the strict sense, because it can
31 * not be used for direct lookup. It can only be used to iterate over all rows
32 * of a table. Each regular table has one such object, even if no primary key or
33 * indexes are defined.
34 */
35public class ScanIndex extends BaseIndex {
36    private long firstFree = -1;
37    private ArrayList<Row> rows = New.arrayList();
38    private final RegularTable tableData;
39    private int rowCountDiff;
40    private final HashMap<Integer, Integer> sessionRowCount;
41    private HashSet<Row> delta;
42    private long rowCount;
43 
44    public ScanIndex(RegularTable table, int id, IndexColumn[] columns,
45            IndexType indexType) {
46        initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType);
47        if (database.isMultiVersion()) {
48            sessionRowCount = New.hashMap();
49        } else {
50            sessionRowCount = null;
51        }
52        tableData = table;
53    }
54 
55    @Override
56    public void remove(Session session) {
57        truncate(session);
58    }
59 
60    @Override
61    public void truncate(Session session) {
62        rows = New.arrayList();
63        firstFree = -1;
64        if (tableData.getContainsLargeObject() && tableData.isPersistData()) {
65            database.getLobStorage().removeAllForTable(table.getId());
66        }
67        tableData.setRowCount(0);
68        rowCount = 0;
69        rowCountDiff = 0;
70        if (database.isMultiVersion()) {
71            sessionRowCount.clear();
72        }
73    }
74 
75    @Override
76    public String getCreateSQL() {
77        return null;
78    }
79 
80    @Override
81    public void close(Session session) {
82        // nothing to do
83    }
84 
85    @Override
86    public Row getRow(Session session, long key) {
87        return rows.get((int) key);
88    }
89 
90    @Override
91    public void add(Session session, Row row) {
92        // in-memory
93        if (firstFree == -1) {
94            int key = rows.size();
95            row.setKey(key);
96            rows.add(row);
97        } else {
98            long key = firstFree;
99            Row free = rows.get((int) key);
100            firstFree = free.getKey();
101            row.setKey(key);
102            rows.set((int) key, row);
103        }
104        row.setDeleted(false);
105        if (database.isMultiVersion()) {
106            if (delta == null) {
107                delta = New.hashSet();
108            }
109            boolean wasDeleted = delta.remove(row);
110            if (!wasDeleted) {
111                delta.add(row);
112            }
113            incrementRowCount(session.getId(), 1);
114        }
115        rowCount++;
116    }
117 
118    @Override
119    public void commit(int operation, Row row) {
120        if (database.isMultiVersion()) {
121            if (delta != null) {
122                delta.remove(row);
123            }
124            incrementRowCount(row.getSessionId(),
125                    operation == UndoLogRecord.DELETE ? 1 : -1);
126        }
127    }
128 
129    private void incrementRowCount(int sessionId, int count) {
130        if (database.isMultiVersion()) {
131            Integer id = sessionId;
132            Integer c = sessionRowCount.get(id);
133            int current = c == null ? 0 : c.intValue();
134            sessionRowCount.put(id, current + count);
135            rowCountDiff += count;
136        }
137    }
138 
139    @Override
140    public void remove(Session session, Row row) {
141        // in-memory
142        if (!database.isMultiVersion() && rowCount == 1) {
143            rows = New.arrayList();
144            firstFree = -1;
145        } else {
146            Row free = new Row(null, 1);
147            free.setKey(firstFree);
148            long key = row.getKey();
149            if (rows.size() <= key) {
150                throw DbException.get(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1,
151                        rows.size() + ": " + key);
152            }
153            rows.set((int) key, free);
154            firstFree = key;
155        }
156        if (database.isMultiVersion()) {
157            // if storage is null, the delete flag is not yet set
158            row.setDeleted(true);
159            if (delta == null) {
160                delta = New.hashSet();
161            }
162            boolean wasAdded = delta.remove(row);
163            if (!wasAdded) {
164                delta.add(row);
165            }
166            incrementRowCount(session.getId(), -1);
167        }
168        rowCount--;
169    }
170 
171    @Override
172    public Cursor find(Session session, SearchRow first, SearchRow last) {
173        return new ScanCursor(session, this, database.isMultiVersion());
174    }
175 
176    @Override
177    public double getCost(Session session, int[] masks, TableFilter filter,
178            SortOrder sortOrder) {
179        return tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET;
180    }
181 
182    @Override
183    public long getRowCount(Session session) {
184        if (database.isMultiVersion()) {
185            Integer i = sessionRowCount.get(session.getId());
186            long count = i == null ? 0 : i.intValue();
187            count += rowCount;
188            count -= rowCountDiff;
189            return count;
190        }
191        return rowCount;
192    }
193 
194    /**
195     * Get the next row that is stored after this row.
196     *
197     * @param row the current row or null to start the scan
198     * @return the next row or null if there are no more rows
199     */
200    Row getNextRow(Row row) {
201        long key;
202        if (row == null) {
203            key = -1;
204        } else {
205            key = row.getKey();
206        }
207        while (true) {
208            key++;
209            if (key >= rows.size()) {
210                return null;
211            }
212            row = rows.get((int) key);
213            if (!row.isEmpty()) {
214                return row;
215            }
216        }
217    }
218 
219    @Override
220    public int getColumnIndex(Column col) {
221        // the scan index cannot use any columns
222        return -1;
223    }
224 
225    @Override
226    public void checkRename() {
227        throw DbException.getUnsupportedException("SCAN");
228    }
229 
230    @Override
231    public boolean needRebuild() {
232        return false;
233    }
234 
235    @Override
236    public boolean canGetFirstOrLast() {
237        return false;
238    }
239 
240    @Override
241    public Cursor findFirstOrLast(Session session, boolean first) {
242        throw DbException.getUnsupportedException("SCAN");
243    }
244 
245    Iterator<Row> getDelta() {
246        if (delta == null) {
247            List<Row> e = Collections.emptyList();
248            return e.iterator();
249        }
250        return delta.iterator();
251    }
252 
253    @Override
254    public long getRowCountApproximation() {
255        return rowCount;
256    }
257 
258    @Override
259    public long getDiskSpaceUsed() {
260        return 0;
261    }
262 
263    @Override
264    public String getPlanSQL() {
265        return table.getSQL() + ".tableScan";
266    }
267 
268}

[all classes][org.h2.index]
EMMA 2.0.5312 (C) Vladimir Roubtsov