001: package com.quadcap.sql;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.BufferedOutputStream;
042: import java.io.Externalizable;
043: import java.io.IOException;
044: import java.io.ObjectInput;
045: import java.io.ObjectOutput;
046: import java.io.OutputStream;
047:
048: import java.sql.SQLException;
049:
050: import com.quadcap.sql.io.ObjectInputStream;
051: import com.quadcap.sql.io.ObjectOutputStream;
052: import com.quadcap.sql.io.Extern;
053:
054: import com.quadcap.sql.file.BlockAccess;
055: import com.quadcap.sql.file.BlockFile;
056: import com.quadcap.sql.file.ByteArrayRandomAccess;
057: import com.quadcap.sql.file.Datafile;
058: import com.quadcap.sql.file.Log;
059: import com.quadcap.sql.file.PageManager;
060: import com.quadcap.sql.file.SubPageManager;
061:
062: import com.quadcap.sql.types.Value;
063: import com.quadcap.sql.types.ValueBlob;
064:
065: import com.quadcap.util.Debug;
066: import com.quadcap.util.Util;
067:
068: /**
069: * Log step to insert a row into a table.
070: *
071: * @author Stan Bailes
072: */
073: public class InsertRow extends LogStep implements Externalizable {
074:
075: transient Table table;
076: transient Row row = null;
077:
078: byte[] rowBytes;
079: String tableName = null;
080: long rowId = 0;
081:
082: public InsertRow() {
083: }
084:
085: public InsertRow(Session session, Table table, Row row) {
086: super (session);
087: this .table = table;
088: this .row = row;
089: this .tableName = table.getName();
090: }
091:
092: public long getRowId() {
093: return rowId;
094: }
095:
096: Table getTable(Database db) throws IOException {
097: if (table == null) {
098: table = (Table) db.getRelation(tableName);
099: if (table == null) {
100: throw new IOException("Table not found: " + tableName);
101: }
102: }
103: return table;
104: }
105:
106: /**
107: * Instantiate the row from the serialized byte array (if necessary)
108: */
109: final void getRow(Datafile db) throws IOException, SQLException {
110: if (row == null) {
111: LazyRow lrow = new LazyRow(table.getColumnCount());
112: lrow.reset(rowBytes, db);
113: row = lrow;
114: }
115: }
116:
117: public void redo(Session session) throws IOException, SQLException {
118: Database db = session.getDatabase();
119: BlockFile file = db.getFile();
120: if (session.getConnection().inRecovery()) {
121: Log log = session.getLog();
122: getTable(db);
123:
124: // The row may contain blobs which have been mapped.
125: if (table.hasBlobs()) {
126: boolean anyChanged = false;
127: getRow(db);
128: for (int i = 1; i <= row.size(); i++) {
129: Value v = row.item(i);
130: if (v instanceof ValueBlob) {
131: ValueBlob vb = (ValueBlob) v;
132: long blk = vb.getPermBlock();
133: long blk2 = log.getRowMap(blk);
134: if (blk != blk2) {
135: vb.setPermBlock(blk2);
136: anyChanged = true;
137: }
138: }
139: }
140: if (anyChanged) {
141: row.set(1, row.item(1));
142: this .rowBytes = LazyRow.writeRow(session, table,
143: row);
144: }
145: }
146: long oldRowId = rowId;
147: rowId = file.putBytes(rowBytes);
148: if (oldRowId != 0)
149: log.putRowMap(oldRowId, rowId);
150: }
151: session.incrUpdateCount();
152: }
153:
154: public void undo(Session session) throws IOException, SQLException {
155: Database db = session.getDatabase();
156: Log log = session.getLog();
157: BlockFile file = db.getFile();
158: getTable(db);
159:
160: long actualRowId = log.getRowMap(rowId);
161: log.removeRowMap(rowId);
162: if (actualRowId != 0)
163: db.removeRow(actualRowId);
164:
165: session.decrUpdateCount();
166: }
167:
168: /**
169: * Serialize the row to a byte array and allocate a page for it.
170: */
171: public void prepare(Session session) throws IOException,
172: SQLException {
173: Database db = session.getDatabase();
174: if (db.inMemory()) {
175: this .rowId = db.putRow(session, db.getFile(), getTable(db),
176: row);
177: } else {
178: BlockFile file = db.getFile();
179: this .rowBytes = LazyRow.writeRow(session, table, row);
180: this .rowId = file.putBytes(rowBytes);
181: }
182: }
183:
184: public void readExternal(ObjectInput in) throws IOException,
185: ClassNotFoundException {
186: super .readExternal(in);
187: rowId = in.readLong();
188: tableName = (String) in.readObject();
189: int size = in.readInt();
190: this .rowBytes = new byte[size];
191: in.read(rowBytes);
192: }
193:
194: public void writeExternal(ObjectOutput out) throws IOException {
195: super .writeExternal(out);
196: out.writeLong(rowId);
197: out.writeObject(tableName);
198: out.writeInt(rowBytes.length);
199: out.write(rowBytes);
200: }
201:
202: //#ifdef DEBUG
203: public String toString() {
204: StringBuffer sb = new StringBuffer(super .toString());
205: sb.append(" InsertRow(");
206: sb.append(tableName);
207: sb.append(',');
208: sb.append(SubPageManager.toString(rowId));
209: if (!Trace.bit(3)) {
210: sb.append(',');
211: sb.append(Util.hexBytes(rowBytes));
212: }
213: sb.append(')');
214: return sb.toString();
215: }
216:
217: //#endif
218:
219: static Extern extern;
220:
221: public void setExtern(Extern extern) {
222: InsertRow.extern = extern;
223: }
224:
225: public Extern getExtern() {
226: return extern;
227: }
228: }
|