1 5 package org.h2.command.dml; 6 7 import java.sql.SQLException ; 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 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 { 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 buff = new StringBuffer ("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 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 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 { 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 getPlan() { 178 StringBuffer buff = new StringBuffer (); 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 { 228 if (columns == null) { 229 if(list.size() > 0 && ((Expression[])list.get(0)).length == 0) { 230 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 |