KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > command > dml > Merge


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.command.dml;
6
7 import java.sql.SQLException JavaDoc;
8
9 import org.h2.command.Command;
10 import org.h2.command.Prepared;
11 import org.h2.engine.Right;
12 import org.h2.engine.Session;
13 import org.h2.expression.Expression;
14 import org.h2.expression.Parameter;
15 import org.h2.index.Index;
16 import org.h2.message.Message;
17 import org.h2.result.LocalResult;
18 import org.h2.result.Row;
19 import org.h2.store.UndoLogRecord;
20 import org.h2.table.Column;
21 import org.h2.table.Table;
22 import org.h2.util.ObjectArray;
23 import org.h2.util.StringUtils;
24 import org.h2.value.Value;
25
26 /**
27  * @author Thomas
28  */

29 public class Merge extends Prepared {
30
31     private Table table;
32     private Column[] columns;
33     private Column[] keys;
34     private ObjectArray list = new ObjectArray();
35     private Query query;
36     private Prepared update;
37
38     public Merge(Session session) {
39         super(session);
40     }
41
42     public void setCommand(Command command) {
43         super.setCommand(command);
44         if(query != null) {
45             query.setCommand(command);
46         }
47     }
48
49     public void setTable(Table table) {
50         this.table = table;
51     }
52
53     public void setColumns(Column[] columns) {
54         this.columns = columns;
55     }
56
57     public void setKeys(Column[] keys) {
58         this.keys = keys;
59     }
60
61     public void setQuery(Query query) {
62         this.query = query;
63     }
64
65     public void addRow(Expression[] expr) {
66         list.add(expr);
67     }
68
69     public int update() throws SQLException JavaDoc {
70         int count;
71         session.getUser().checkRight(table, Right.INSERT);
72         session.getUser().checkRight(table, Right.UPDATE);
73         if(keys == null) {
74             Index idx = table.getPrimaryKey();
75             if(idx == null) {
76                 throw Message.getSQLException(Message.CONSTRAINT_NOT_FOUND_1, "PRIMARY KEY");
77             }
78             keys = idx.getColumns();
79         }
80         StringBuffer JavaDoc buff = new StringBuffer JavaDoc("UPDATE ");
81         buff.append(table.getSQL());
82         buff.append(" SET ");
83         for(int i=0; i<columns.length; i++) {
84             if(i>0) {
85                 buff.append(", ");
86             }
87             buff.append(columns[i].getSQL());
88             buff.append("=?");
89         }
90         buff.append(" WHERE ");
91         for(int i=0; i<keys.length; i++) {
92             if(i>0) {
93                 buff.append(" AND ");
94             }
95             buff.append(keys[i].getSQL());
96             buff.append("=?");
97         }
98         String JavaDoc sql = buff.toString();
99         update = session.prepare(sql);
100         setCurrentRowNumber(0);
101         if(list.size() > 0) {
102             count = 0;
103             for(int x=0; x<list.size(); x++) {
104                 setCurrentRowNumber(x+1);
105                 Expression[] expr = (Expression[])list.get(x);
106                 Row newRow = table.getTemplateRow();
107                 for (int i = 0; i < columns.length; i++) {
108                     Column c = columns[i];
109                     int index = c.getColumnId();
110                     Expression e = expr[i];
111                     if(e != null) {
112                         // e can be null (DEFAULT)
113
Value v = expr[i].getValue(session).convertTo(c.getType());
114                         newRow.setValue(index, v);
115                     }
116                 }
117                 merge(newRow);
118                 count++;
119             }
120         } else {
121             LocalResult rows = query.query(0);
122             count = 0;
123             table.fireBefore(session);
124             table.lock(session, true);
125             while(rows.next()) {
126                 checkCancelled();
127                 count++;
128                 Value[] r = rows.currentRow();
129                 Row newRow = table.getTemplateRow();
130                 setCurrentRowNumber(count);
131                 for (int j = 0; j < columns.length; j++) {
132                     Column c = columns[j];
133                     int index = c.getColumnId();
134                     Value v = r[j].convertTo(c.getType());
135                     newRow.setValue(index, v);
136                 }
137                 merge(newRow);
138             }
139             rows.close();
140             table.fireAfter(session);
141         }
142         return count;
143     }
144
145     private void merge(Row row) throws SQLException JavaDoc {
146         ObjectArray k = update.getParameters();
147         for(int i=0; i<columns.length; i++) {
148             Column col = columns[i];
149             Value v = row.getValue(col.getColumnId());
150             Parameter p = (Parameter) k.get(i);
151             p.setValue(v);
152         }
153         for(int i=0; i<keys.length; i++) {
154             Column col = keys[i];
155             Value v = row.getValue(col.getColumnId());
156             if(v == null) {
157                 throw Message.getSQLException(Message.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL());
158             }
159             Parameter p = (Parameter) k.get(columns.length + i);
160             p.setValue(v);
161         }
162         int count = update.update();
163         if(count == 0) {
164             table.fireBefore(session);
165             table.validateConvertUpdateSequence(session, row);
166             table.fireBeforeRow(session, null, row);
167             table.lock(session, true);
168             table.addRow(session, row);
169             session.log(new UndoLogRecord(table, UndoLogRecord.INSERT, row));
170             table.fireAfter(session);
171             table.fireAfterRow(session, null, row);
172         } else if(count != 1) {
173             throw Message.getSQLException(Message.DUPLICATE_KEY_1, table.getSQL());
174         }
175     }
176
177     public String JavaDoc getPlan() {
178         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
179         buff.append("MERGE INTO ");
180         buff.append(table.getSQL());
181         buff.append('(');
182         for(int i=0; i<columns.length; i++) {
183             if(i>0) {
184                 buff.append(", ");
185             }
186             buff.append(columns[i].getSQL());
187         }
188         buff.append(")");
189         if(keys != null) {
190             buff.append(" KEY(");
191             for(int i=0; i<keys.length; i++) {
192                 if(i>0) {
193                     buff.append(", ");
194                 }
195                 buff.append(keys[i].getSQL());
196             }
197             buff.append(")");
198         }
199         buff.append('\n');
200         if(list.size() > 0) {
201             buff.append("VALUES ");
202             for(int x=0; x<list.size(); x++) {
203                 Expression[] expr = (Expression[])list.get(x);
204                 if(x > 0) {
205                     buff.append(", ");
206                 }
207                 buff.append("(");
208                 for (int i = 0; i < columns.length; i++) {
209                     if(i>0) {
210                         buff.append(", ");
211                     }
212                     Expression e = expr[i];
213                     if(e == null) {
214                         buff.append("DEFAULT");
215                     } else {
216                         buff.append(StringUtils.unEnclose(e.getSQL()));
217                     }
218                 }
219                 buff.append(')');
220             }
221         } else {
222             buff.append(query.getPlan());
223         }
224         return buff.toString();
225     }
226
227     public void prepare() throws SQLException JavaDoc {
228         if (columns == null) {
229             if(list.size() > 0 && ((Expression[])list.get(0)).length == 0) {
230                 // special case where table is used as a sequence
231
columns = new Column[0];
232             } else {
233                 columns = table.getColumns();
234             }
235         }
236         if(list.size() > 0) {
237             for(int x=0; x<list.size(); x++) {
238                 Expression[] expr = (Expression[])list.get(x);
239                 if(expr.length != columns.length) {
240                     throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
241                 }
242                 for(int i=0; i<expr.length; i++) {
243                     Expression e = expr[i];
244                     if(e != null) {
245                         expr[i] = e.optimize(session);
246                     }
247                 }
248             }
249         } else {
250             query.prepare();
251             if(query.getColumnCount() != columns.length) {
252                 throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
253             }
254         }
255     }
256
257     public boolean isTransactional() {
258         return true;
259     }
260
261 }
262
Popular Tags