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.IOException;
042:
043: import java.util.ArrayList;
044: import java.util.Enumeration;
045:
046: import java.sql.SQLException;
047: import java.sql.Types;
048:
049: import com.quadcap.sql.file.BlockFile;
050: import com.quadcap.sql.file.Datafile;
051: import com.quadcap.sql.file.PageManager;
052:
053: import com.quadcap.sql.types.Value;
054: import com.quadcap.sql.types.ValueBlob;
055: import com.quadcap.sql.types.Type;
056:
057: import com.quadcap.util.Debug;
058: import com.quadcap.util.Util;
059:
060: /**
061: *
062: *
063: * @author Stan Bailes
064: */
065: public class TableOps {
066: /**
067: * Called to insert a new row on behalf of a session.
068: */
069: public static void insertRow(Session session, Table table, Row row)
070: throws SQLException, IOException {
071: session.getTableWriteLock(table.getName());
072: int num = table.getNumConstraints();
073:
074: for (int i = 0; i < num; i++) {
075: table.getConstraint(i).checkInsert(session, row);
076: }
077:
078: if (table.hasBlobs()) {
079: holdBlobsInRow(session, table, row);
080: }
081:
082: InsertRow ins = new InsertRow(session, table, row);
083: session.doStep(ins);
084: long rowId = ins.getRowId();
085:
086: for (int i = 0; i < num; i++) {
087: table.getConstraint(i).applyInsert(session, row, rowId,
088: null);
089: }
090:
091: //#ifdef DEBUG
092: if (Trace.bit(14)) {
093: Debug.println("insertRow(" + table.getName() + "): " + row
094: + " -> " + rowId);
095: }
096: //#endif
097: }
098:
099: /**
100: * Update an existing table row with integrity checking
101: */
102: public static void updateRow(Session session, Table table,
103: byte[] key, long rowId, Row row, Constraint constraint)
104: throws SQLException, IOException {
105: session.getTableWriteLock(table.getName());
106: //#ifdef DEBUG
107: if (Trace.bit(14)) {
108: Debug.println("updateRow(" + table.getName() + "): " + row
109: + " -> " + rowId);
110: }
111: //#endif
112:
113: Database db = session.getDatabase();
114: BlockFile file = db.getFile();
115: Row oldRow = table.getRow(db, rowId);
116: int num = table.getNumConstraints();
117:
118: for (int i = 0; i < num; i++) {
119: Constraint c = table.getConstraint(i);
120: c.checkUpdate(session, key, row, oldRow, rowId, constraint);
121: }
122:
123: if (table.hasBlobs()) {
124: holdBlobsInRow(session, table, row);
125: freeBlobsInRow(session, table, oldRow);
126: }
127:
128: if (db.inMemory()) {
129: // because we "know" that UpdateRow *doesn't* make a copy!
130: row = new Row(row, table);
131: }
132: UpdateRow update = new UpdateRow(session, table, rowId, row);
133: session.doStep(update);
134:
135: for (int i = 0; i < num; i++) {
136: Constraint c = table.getConstraint(i);
137: //Debug.println(c.getClass().getName() + ".applyUpdate");
138: c.applyUpdate(session, key, row, oldRow, rowId, constraint);
139: }
140: }
141:
142: /**
143: * Delete a row with integrity checking under control of a given
144: * constraint.
145: */
146: public static void deleteRow(Session session, Table table,
147: long rowId, Row row, Constraint constraint)
148: throws SQLException, IOException {
149: session.getTableWriteLock(table.getName());
150: int num = table.getNumConstraints();
151:
152: for (int i = 0; i < num; i++) {
153: Constraint c = table.getConstraint(i);
154: c.checkDelete(session, row, rowId);
155: }
156:
157: for (int i = 0; i < num; i++) {
158: Constraint c = table.getConstraint(i);
159: c.applyDelete(session, row, rowId, constraint);
160: }
161:
162: DeletedRows d = (DeletedRows) session.getContext("DeleteRow:"
163: + table.getName(), false);
164: if (d == null) {
165: d = new DeletedRows(session, table);
166: session
167: .putContext("DeleteRow:" + table.getName(), false,
168: d);
169: }
170: d.addEntry(rowId);
171:
172: //#ifdef DEBUG
173: if (Trace.bit(14)) {
174: Debug.println("deleteRow(" + table.getName() + "): " + row
175: + " -> " + rowId);
176: }
177: //#endif
178: }
179:
180: public static Cursor getCursor(Session session, Relation t,
181: SelectExpression select) throws SQLException {
182: Cursor c = null;
183: if (select != null) {
184: c = select.getCursor(session, null);//ZZZ hot
185: } else {
186: c = t.getCursor(session, null, null, null);
187: }
188: return c;
189: }
190:
191: /**
192: * Hold references to any blobs in the row.
193: */
194: static final void holdBlobsInRow(Session session, Table tuple,
195: Row row) throws SQLException, IOException {
196: if (tuple.hasBlobs()) {
197: final long transId = session.getTransactionId();
198: final Database db = session.getDatabase();
199: for (int i = 1; i <= row.size(); i++) {
200: Value v = row.item(i);
201: Column col = tuple.getColumn(i);
202: Type t = col.getType();
203: if (isLargeObject(t)) {
204:
205: ValueBlob vb = null;
206: if (!(v instanceof ValueBlob)) {
207: v = t.convert(v);
208: row.set(i, v);
209: }
210: if (v instanceof ValueBlob) {
211: vb = (ValueBlob) v;
212: }
213: if (vb != null) {
214: if (vb.getBytesVal() != null) {
215: byte[] ff = vb.getBytesVal();
216: session.doStep(new InsertBlob(session, vb));
217: }
218: session.doStep(new RefcountBlob(session, vb
219: .getPermBlock(), 1));
220: }
221: }
222: }
223: }
224: }
225:
226: /**
227: * Release any BLOB references held by this row.
228: */
229: static final void freeBlobsInRow(Session session, Table tuple,
230: Row row) throws SQLException, IOException {
231: if (row.getBlobCount() > 0) {
232: for (int i = 1; i <= row.size(); i++) {
233: Value v = row.item(i);
234: Type t = v.getType();
235: if (isLargeObject(t)) {
236: long transId = session.getTransactionId();
237: ValueBlob vb = (ValueBlob) v;
238: session.doStep(new RefcountBlob(session, vb
239: .getPermBlock(), -1));
240: }
241: }
242: }
243: }
244:
245: /**
246: * Helper function to check for BLOB or CLOB types
247: */
248: static private final boolean isLargeObject(Type t) {
249: final int type = t.getJDBCType();
250: return type == Types.BLOB || type == Types.CLOB;
251: }
252:
253: }
|