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

COVERAGE SUMMARY FOR SOURCE FILE [Update.java]

nameclass, %method, %block, %line, %
Update.java100% (1/1)100% (12/12)99%  (420/425)99%  (98/99)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Update100% (1/1)100% (12/12)99%  (420/425)99%  (98/99)
setAssignment (Column, Expression): void 100% (1/1)84%  (26/31)88%  (7/8)
Update (Session): void 100% (1/1)100% (10/10)100% (4/4)
getPlanSQL (): String 100% (1/1)100% (65/65)100% (10/10)
getType (): int 100% (1/1)100% (2/2)100% (1/1)
isCacheable (): boolean 100% (1/1)100% (2/2)100% (1/1)
isTransactional (): boolean 100% (1/1)100% (2/2)100% (1/1)
prepare (): void 100% (1/1)100% (75/75)100% (13/13)
queryMeta (): ResultInterface 100% (1/1)100% (2/2)100% (1/1)
setCondition (Expression): void 100% (1/1)100% (4/4)100% (2/2)
setLimit (Expression): void 100% (1/1)100% (4/4)100% (2/2)
setTableFilter (TableFilter): void 100% (1/1)100% (4/4)100% (2/2)
update (): int 100% (1/1)100% (224/224)100% (54/54)

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.command.dml;
7 
8import java.util.ArrayList;
9import java.util.HashMap;
10 
11import org.h2.api.ErrorCode;
12import org.h2.api.Trigger;
13import org.h2.command.CommandInterface;
14import org.h2.command.Prepared;
15import org.h2.engine.Right;
16import org.h2.engine.Session;
17import org.h2.expression.Expression;
18import org.h2.expression.Parameter;
19import org.h2.expression.ValueExpression;
20import org.h2.message.DbException;
21import org.h2.result.ResultInterface;
22import org.h2.result.Row;
23import org.h2.result.RowList;
24import org.h2.table.Column;
25import org.h2.table.PlanItem;
26import org.h2.table.Table;
27import org.h2.table.TableFilter;
28import org.h2.util.New;
29import org.h2.util.StatementBuilder;
30import org.h2.util.StringUtils;
31import org.h2.value.Value;
32import org.h2.value.ValueNull;
33 
34/**
35 * This class represents the statement
36 * UPDATE
37 */
38public class Update extends Prepared {
39 
40    private Expression condition;
41    private TableFilter tableFilter;
42 
43    /** The limit expression as specified in the LIMIT clause. */
44    private Expression limitExpr;
45 
46    private final ArrayList<Column> columns = New.arrayList();
47    private final HashMap<Column, Expression> expressionMap  = New.hashMap();
48 
49    public Update(Session session) {
50        super(session);
51    }
52 
53    public void setTableFilter(TableFilter tableFilter) {
54        this.tableFilter = tableFilter;
55    }
56 
57    public void setCondition(Expression condition) {
58        this.condition = condition;
59    }
60 
61    /**
62     * Add an assignment of the form column = expression.
63     *
64     * @param column the column
65     * @param expression the expression
66     */
67    public void setAssignment(Column column, Expression expression) {
68        if (expressionMap.containsKey(column)) {
69            throw DbException.get(ErrorCode.DUPLICATE_COLUMN_NAME_1, column
70                    .getName());
71        }
72        columns.add(column);
73        expressionMap.put(column, expression);
74        if (expression instanceof Parameter) {
75            Parameter p = (Parameter) expression;
76            p.setColumn(column);
77        }
78    }
79 
80    @Override
81    public int update() {
82        tableFilter.startQuery(session);
83        tableFilter.reset();
84        RowList rows = new RowList(session);
85        try {
86            Table table = tableFilter.getTable();
87            session.getUser().checkRight(table, Right.UPDATE);
88            table.fire(session, Trigger.UPDATE, true);
89            table.lock(session, true, false);
90            int columnCount = table.getColumns().length;
91            // get the old rows, compute the new rows
92            setCurrentRowNumber(0);
93            int count = 0;
94            Column[] columns = table.getColumns();
95            int limitRows = -1;
96            if (limitExpr != null) {
97                Value v = limitExpr.getValue(session);
98                if (v != ValueNull.INSTANCE) {
99                    limitRows = v.getInt();
100                }
101            }
102            while (tableFilter.next()) {
103                setCurrentRowNumber(count+1);
104                if (limitRows >= 0 && count >= limitRows) {
105                    break;
106                }
107                if (condition == null ||
108                        Boolean.TRUE.equals(condition.getBooleanValue(session))) {
109                    Row oldRow = tableFilter.get();
110                    Row newRow = table.getTemplateRow();
111                    for (int i = 0; i < columnCount; i++) {
112                        Expression newExpr = expressionMap.get(columns[i]);
113                        Value newValue;
114                        if (newExpr == null) {
115                            newValue = oldRow.getValue(i);
116                        } else if (newExpr == ValueExpression.getDefault()) {
117                            Column column = table.getColumn(i);
118                            newValue = table.getDefaultValue(session, column);
119                        } else {
120                            Column column = table.getColumn(i);
121                            newValue = column.convert(newExpr.getValue(session));
122                        }
123                        newRow.setValue(i, newValue);
124                    }
125                    table.validateConvertUpdateSequence(session, newRow);
126                    boolean done = false;
127                    if (table.fireRow()) {
128                        done = table.fireBeforeRow(session, oldRow, newRow);
129                    }
130                    if (!done) {
131                        rows.add(oldRow);
132                        rows.add(newRow);
133                    }
134                    count++;
135                }
136            }
137            // TODO self referencing referential integrity constraints
138            // don't work if update is multi-row and 'inversed' the condition!
139            // probably need multi-row triggers with 'deleted' and 'inserted'
140            // at the same time. anyway good for sql compatibility
141            // TODO update in-place (but if the key changes,
142            // we need to update all indexes) before row triggers
143 
144            // the cached row is already updated - we need the old values
145            table.updateRows(this, session, rows);
146            if (table.fireRow()) {
147                rows.invalidateCache();
148                for (rows.reset(); rows.hasNext();) {
149                    Row o = rows.next();
150                    Row n = rows.next();
151                    table.fireAfterRow(session, o, n, false);
152                }
153            }
154            table.fire(session, Trigger.UPDATE, false);
155            return count;
156        } finally {
157            rows.close();
158        }
159    }
160 
161    @Override
162    public String getPlanSQL() {
163        StatementBuilder buff = new StatementBuilder("UPDATE ");
164        buff.append(tableFilter.getPlanSQL(false)).append("\nSET\n    ");
165        for (int i = 0, size = columns.size(); i < size; i++) {
166            Column c = columns.get(i);
167            Expression e = expressionMap.get(c);
168            buff.appendExceptFirst(",\n    ");
169            buff.append(c.getName()).append(" = ").append(e.getSQL());
170        }
171        if (condition != null) {
172            buff.append("\nWHERE ").append(StringUtils.unEnclose(condition.getSQL()));
173        }
174        return buff.toString();
175    }
176 
177    @Override
178    public void prepare() {
179        if (condition != null) {
180            condition.mapColumns(tableFilter, 0);
181            condition = condition.optimize(session);
182            condition.createIndexConditions(session, tableFilter);
183        }
184        for (int i = 0, size = columns.size(); i < size; i++) {
185            Column c = columns.get(i);
186            Expression e = expressionMap.get(c);
187            e.mapColumns(tableFilter, 0);
188            expressionMap.put(c, e.optimize(session));
189        }
190        PlanItem item = tableFilter.getBestPlanItem(session, 1);
191        tableFilter.setPlanItem(item);
192        tableFilter.prepare();
193    }
194 
195    @Override
196    public boolean isTransactional() {
197        return true;
198    }
199 
200    @Override
201    public ResultInterface queryMeta() {
202        return null;
203    }
204 
205    @Override
206    public int getType() {
207        return CommandInterface.UPDATE;
208    }
209 
210    public void setLimit(Expression limit) {
211        this.limitExpr = limit;
212    }
213 
214    @Override
215    public boolean isCacheable() {
216        return true;
217    }
218 
219}

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