Quadcap Embeddable Database

com/quadcap/sql/TableOps.java

Go to the documentation of this file.
00001 package com.quadcap.sql; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.IOException; 00042 00043 import java.util.ArrayList; 00044 import java.util.Enumeration; 00045 00046 import java.sql.SQLException; 00047 import java.sql.Types; 00048 00049 import com.quadcap.sql.file.BlockFile; 00050 import com.quadcap.sql.file.Datafile; 00051 import com.quadcap.sql.file.PageManager; 00052 00053 import com.quadcap.sql.types.Value; 00054 import com.quadcap.sql.types.ValueBlob; 00055 import com.quadcap.sql.types.Type; 00056 00057 import com.quadcap.util.Debug; 00058 import com.quadcap.util.Util; 00059 00060 /** 00061 * 00062 * 00063 * @author Stan Bailes 00064 */ 00065 public class TableOps { 00066 /** 00067 * Called to insert a new row on behalf of a session. 00068 */ 00069 public static void insertRow(Session session, Table table, Row row) 00070 throws SQLException, IOException 00071 { 00072 session.getTableWriteLock(table.getName()); 00073 int num = table.getNumConstraints(); 00074 00075 for (int i = 0; i < num; i++) { 00076 table.getConstraint(i).checkInsert(session, row); 00077 } 00078 00079 if (table.hasBlobs()) { 00080 holdBlobsInRow(session, table, row); 00081 } 00082 00083 InsertRow ins = new InsertRow(session, table, row); 00084 session.doStep(ins); 00085 long rowId = ins.getRowId(); 00086 00087 for (int i = 0; i < num; i++) { 00088 table.getConstraint(i).applyInsert(session, row, rowId, null); 00089 } 00090 00091 //#ifdef DEBUG 00092 if (Trace.bit(14)) { 00093 Debug.println("insertRow(" + table.getName() + "): " + 00094 row + " -> " + rowId); 00095 } 00096 //#endif 00097 } 00098 00099 /** 00100 * Update an existing table row with integrity checking 00101 */ 00102 public static void updateRow(Session session, Table table, 00103 byte[] key, long rowId, Row row, 00104 Constraint constraint) 00105 throws SQLException, IOException 00106 { 00107 session.getTableWriteLock(table.getName()); 00108 //#ifdef DEBUG 00109 if (Trace.bit(14)) { 00110 Debug.println("updateRow(" + table.getName() + "): " + 00111 row + " -> " + rowId); 00112 } 00113 //#endif 00114 00115 Database db = session.getDatabase(); 00116 BlockFile file = db.getFile(); 00117 Row oldRow = table.getRow(db, rowId); 00118 int num = table.getNumConstraints(); 00119 00120 for (int i = 0; i < num; i++) { 00121 Constraint c = table.getConstraint(i); 00122 c.checkUpdate(session, key, row, oldRow, rowId, constraint); 00123 } 00124 00125 if (table.hasBlobs()) { 00126 holdBlobsInRow(session, table, row); 00127 freeBlobsInRow(session, table, oldRow); 00128 } 00129 00130 if (db.inMemory()) { 00131 // because we "know" that UpdateRow *doesn't* make a copy! 00132 row = new Row(row, table); 00133 } 00134 UpdateRow update = new UpdateRow(session, table, rowId, row); 00135 session.doStep(update) ; 00136 00137 for (int i = 0; i < num; i++) { 00138 Constraint c = table.getConstraint(i); 00139 //Debug.println(c.getClass().getName() + ".applyUpdate"); 00140 c.applyUpdate(session, key, row, oldRow, rowId, constraint); 00141 } 00142 } 00143 00144 00145 /** 00146 * Delete a row with integrity checking under control of a given 00147 * constraint. 00148 */ 00149 public static void deleteRow(Session session, Table table, 00150 long rowId, Row row, 00151 Constraint constraint) 00152 throws SQLException, IOException 00153 { 00154 session.getTableWriteLock(table.getName()); 00155 int num = table.getNumConstraints(); 00156 00157 for (int i = 0; i < num; i++) { 00158 Constraint c = table.getConstraint(i); 00159 c.checkDelete(session, row, rowId); 00160 } 00161 00162 for (int i = 0; i < num; i++) { 00163 Constraint c = table.getConstraint(i); 00164 c.applyDelete(session, row, rowId, constraint); 00165 } 00166 00167 DeletedRows d = 00168 (DeletedRows)session.getContext("DeleteRow:" + table.getName(), 00169 false); 00170 if (d == null) { 00171 d = new DeletedRows(session, table); 00172 session.putContext("DeleteRow:" + table.getName(), false, d); 00173 } 00174 d.addEntry(rowId); 00175 00176 //#ifdef DEBUG 00177 if (Trace.bit(14)) { 00178 Debug.println("deleteRow(" + table.getName() + "): " + 00179 row + " -> " + rowId); 00180 } 00181 //#endif 00182 } 00183 00184 public static Cursor getCursor(Session session, Relation t, 00185 SelectExpression select) 00186 throws SQLException 00187 { 00188 Cursor c = null; 00189 if (select != null) { 00190 c = select.getCursor(session, null);//ZZZ hot 00191 } else { 00192 c = t.getCursor(session, null, null, null); 00193 } 00194 return c; 00195 } 00196 00197 /** 00198 * Hold references to any blobs in the row. 00199 */ 00200 static final void holdBlobsInRow(Session session, 00201 Table tuple, Row row) 00202 throws SQLException, IOException 00203 { 00204 if (tuple.hasBlobs()) { 00205 final long transId = session.getTransactionId(); 00206 final Database db = session.getDatabase(); 00207 for (int i = 1; i <= row.size(); i++) { 00208 Value v = row.item(i); 00209 Column col = tuple.getColumn(i); 00210 Type t = col.getType(); 00211 if (isLargeObject(t)) { 00212 00213 ValueBlob vb = null; 00214 if (!(v instanceof ValueBlob)) { 00215 v = t.convert(v); 00216 row.set(i, v); 00217 } 00218 if (v instanceof ValueBlob) { 00219 vb = (ValueBlob)v; 00220 } 00221 if (vb != null) { 00222 if (vb.getBytesVal() != null) { 00223 byte[] ff = vb.getBytesVal(); 00224 session.doStep(new InsertBlob(session, vb)); 00225 } 00226 session.doStep( 00227 new RefcountBlob(session, vb.getPermBlock(), 1)); 00228 } 00229 } 00230 } 00231 } 00232 } 00233 00234 /** 00235 * Release any BLOB references held by this row. 00236 */ 00237 static final void freeBlobsInRow(Session session, Table tuple, Row row) 00238 throws SQLException, IOException 00239 { 00240 if (row.getBlobCount() > 0) { 00241 for (int i = 1; i <= row.size(); i++) { 00242 Value v = row.item(i); 00243 Type t = v.getType(); 00244 if (isLargeObject(t)) { 00245 long transId = session.getTransactionId(); 00246 ValueBlob vb = (ValueBlob)v; 00247 session.doStep( 00248 new RefcountBlob(session, vb.getPermBlock(), -1)); 00249 } 00250 } 00251 } 00252 } 00253 00254 /** 00255 * Helper function to check for BLOB or CLOB types 00256 */ 00257 static private final boolean isLargeObject(Type t) { 00258 final int type = t.getJDBCType(); 00259 return type == Types.BLOB || type == Types.CLOB; 00260 } 00261 00262 }