| 1 package com.quadcap.sql; 2 3 40 41 import java.io.BufferedOutputStream ; 42 import java.io.ByteArrayOutputStream ; 43 import java.io.Externalizable ; 44 import java.io.InputStream ; 45 import java.io.IOException ; 46 import java.io.ObjectInput ; 47 import java.io.ObjectOutput ; 48 import java.io.OutputStream ; 49 50 import java.util.Vector ; 51 52 import java.sql.SQLException ; 53 54 import com.quadcap.sql.io.Arrays; 55 import com.quadcap.sql.io.ObjectInputStream; 56 import com.quadcap.sql.io.ObjectOutputStream; 57 import com.quadcap.sql.io.Extern; 58 59 import com.quadcap.sql.file.BlockFile; 60 import com.quadcap.sql.file.Datafile; 61 import com.quadcap.sql.file.Log; 62 import com.quadcap.sql.file.PageManager; 63 import com.quadcap.sql.file.SubPageManager; 64 65 import com.quadcap.sql.index.Btree; 66 67 import com.quadcap.sql.types.Value; 68 import com.quadcap.sql.types.ValueBlob; 69 70 import com.quadcap.util.Debug; 71 import com.quadcap.util.Util; 72 73 78 public class UpdateRow extends LogStep implements Externalizable { 79 transient Table table = null; 80 81 String tableName = null; 82 Row memRow; 83 Row oldRow; 84 byte[] rowBytes = null; 85 byte[] oldRowBytes = null; 86 long rowId = -1; 87 88 91 public UpdateRow() {} 92 93 96 public UpdateRow(Session session, Table table, long rowId, Row row) 97 throws IOException , SQLException  98 { 99 super(session); 100 init(session, table, rowId, row); 101 } 102 103 106 public UpdateRow(Session session, long rowId, Row orow, 107 Row nrow) 108 throws IOException , SQLException  109 { 110 super(session); 111 init(session, null, rowId, nrow); 112 oldRow = orow; 113 } 114 115 118 public UpdateRow(Session session, Table table, long rowId, 119 byte[] oldRowBytes, byte[] rowBytes) 120 throws IOException , SQLException  121 { 122 super(session); 123 if (session.getDatabase().inMemory()) { 124 throw new SQLException ("in Memory Database: internal error"); 125 } 126 initx(table, rowId, oldRowBytes, rowBytes); 127 } 128 129 132 public void initx(Table table, long rowId, byte[] oldRowBytes, 133 byte[] rowBytes) { 134 this.table = table; 135 this.tableName = table.getName(); 136 this.rowBytes = copy(rowBytes); 137 this.oldRowBytes = copy(oldRowBytes); 138 this.rowId = rowId; 139 } 140 141 final byte[] copy(byte[] b) { 142 byte[] r = new byte[b.length]; 143 System.arraycopy(b, 0, r, 0, b.length); 144 return r; 145 } 146 147 150 public void init(Session session, Table table, long rowId, Row row) 151 throws IOException , SQLException  152 { 153 this.table = table; 154 this.tableName = table == null ? null : table.getName(); 155 if (session.getDatabase().inMemory()) { 156 this.memRow = row; 157 } else { 158 this.rowBytes = LazyRow.writeRow(session, table, row); 159 } 160 this.rowId = rowId; 161 } 162 163 166 Table getTable(Database db) throws IOException { 167 if (table == null && tableName != null) { 168 table = (Table)db.getRelation(tableName); 169 } 170 return table; 171 } 172 173 176 final LazyRow getRow(Datafile db) throws IOException , SQLException { 177 LazyRow r = new LazyRow(table.getColumnCount()); 178 r.reset(rowBytes, db); 179 return r; 180 } 181 182 186 public void redo(Session session) throws IOException , SQLException { 187 Database db = session.getDatabase(); 188 BlockFile file = db.getFile(); 189 190 if (session.getConnection().inRecovery()) { 191 Log log = session.getLog(); 192 getTable(db); 193 194 if (table.hasBlobs()) { 196 boolean anyChanged = false; 197 Row row = getRow(db); 198 for (int i = 1; i <= row.size(); i++) { 199 Value v = row.item(i); 200 if (v instanceof ValueBlob) { 201 ValueBlob vb = (ValueBlob)v; 202 long blk = vb.getPermBlock(); 203 long blk2 = log.getRowMap(blk); 204 if (blk != blk2) { 205 vb.setPermBlock(blk2); 206 anyChanged = true; 207 } 208 } 209 } 210 if (anyChanged) { 211 row.set(1, row.item(1)); 212 if (!db.inMemory()) { 213 this.rowBytes = LazyRow.writeRow(session, table, row); 214 } 215 } 216 } 217 rowId = log.getRowMap(rowId); 218 } 219 if (db.inMemory()) { 220 db.putRow(session, getTable(db), rowId, memRow); 221 } else { 222 file.updateBytes(rowId, rowBytes); 223 } 224 session.incrUpdateCount(); 225 } 226 227 231 public void undo(Session session) throws IOException , SQLException { 232 Database db = session.getDatabase(); 233 BlockFile file = db.getFile(); 234 Log log = session.getLog(); 235 236 long actualRowId = log.getRowMap(rowId); 237 if (db.inMemory()) { 238 db.putRow(session, getTable(db), rowId, oldRow); 239 } else { 240 file.updateBytes(actualRowId, oldRowBytes); 241 } 242 session.decrUpdateCount(); 243 } 244 245 248 public void prepare(Session session) throws SQLException , IOException { 249 if (session.getDatabase().inMemory()) { 250 if (oldRow == null) { 251 oldRow = table.getRow(session.getDatabase(), rowId); 252 } 253 } else { 254 if (oldRowBytes == null) { 255 oldRowBytes = session.getFile().getBytes(rowId); 256 } 257 } 258 } 259 260 263 public void readExternal(ObjectInput in) 264 throws IOException , ClassNotFoundException  265 { 266 super.readExternal(in); 267 tableName = (String )in.readObject(); 268 rowId = in.readLong(); 269 270 rowBytes = Arrays.readBytes(in); 271 oldRowBytes = Arrays.readBytes(in); 272 273 } 274 275 278 public void writeExternal(ObjectOutput out) throws IOException { 279 super.writeExternal(out); 280 out.writeObject(tableName); 281 out.writeLong(rowId); 282 283 Arrays.writeBytes(out, rowBytes); 284 Arrays.writeBytes(out, oldRowBytes); 285 286 } 287 288 292 public String toString() { 293 StringBuffer sb = new StringBuffer (super.toString()); 294 sb.append(" UpdateRow("); 295 sb.append(SubPageManager.toString(rowId)); 296 if (true) { 297 sb.append(",["); 298 sb.append(Util.hexBytes(oldRowBytes)); 299 sb.append("] -> ["); 300 sb.append(Util.hexBytes(rowBytes)); 301 sb.append("]"); 302 } 303 sb.append(')'); 304 return sb.toString(); 305 } 306 308 311 static Extern extern; 312 public void setExtern(Extern extern) { UpdateRow.extern = extern; } 313 public Extern getExtern() { return extern; } 314 } 315 | Popular Tags |