1 package com.quadcap.sql; 2 3 40 41 import java.io.ByteArrayOutputStream ; 42 import java.io.Externalizable ; 43 import java.io.IOException ; 44 import java.io.ObjectInput ; 45 import java.io.ObjectOutput ; 46 47 import java.util.Vector ; 48 49 import java.sql.ResultSet ; 50 import java.sql.SQLException ; 51 52 import com.quadcap.sql.file.ByteUtil; 53 54 import com.quadcap.sql.index.Btree; 55 import com.quadcap.sql.index.Comparator; 56 57 import com.quadcap.sql.file.BlockFile; 58 59 import com.quadcap.util.Debug; 60 import com.quadcap.util.Util; 61 62 67 abstract public class IndexConstraint extends Constraint 68 implements Externalizable { 69 Btree index = null; 70 long indexRoot = -1; 71 protected boolean useComparator = true; 72 73 76 public IndexConstraint() {} 77 78 81 public IndexConstraint(String name) { 82 super(name); 83 } 84 85 public IndexConstraint(String name, Vector names) { 86 super(name, names); 87 } 88 89 95 abstract public byte[] makeKey(Session session, Row row, long rowId) 96 throws SQLException 97 ; 98 99 103 abstract public String constraintType(); 104 105 108 public void add(Session session) throws SQLException , IOException { 109 index = null; 110 indexRoot = -1; 111 resetColumns(); 112 getIndex(session.getDatabase()); 113 114 getColumns(); 115 IndexCursor c = table.getCursor(session, this); 116 if (c != null) { 117 try { 118 while (c.next()) { 119 Row row = c.getRow(); 120 long rowId = c.getRowId(); 121 byte[] key = makeKey(session, row, rowId); 122 if (index.get(key) != null) { 123 throw new SQLException (constraintType() + 124 " constraint violated"); 125 } 126 if (session.getConnection().inRecovery()) { 127 rowId = session.getLog().getRowMap(rowId); 128 } 129 index.set(key, key.length, session.getBuf8(rowId), 0, 8); 130 } 131 } finally { 132 c.close(); 133 } 134 } 135 136 } 137 138 141 public void delete(Session session) throws IOException { 142 if (indexRoot > 0) { 143 Database db = session.getDatabase(); 144 getIndex(db); 145 if (index != null) { 146 index.free(); 147 } 148 } 149 } 150 151 154 public void readExternal(ObjectInput in) 155 throws IOException , ClassNotFoundException 156 { 157 super.readExternal(in); 158 indexRoot = in.readLong(); 159 useComparator = in.read() == 1; 160 } 161 162 165 public void writeExternal(ObjectOutput out) throws IOException { 166 super.writeExternal(out); 167 out.writeLong(indexRoot); 168 out.write(useComparator ? 1 : 0); 169 } 170 171 174 177 public void checkInsert(Session session, Row row) 178 throws SQLException , IOException 179 { 180 } 181 182 public void checkUpdate(Session session, byte[] oldKey, Row row, 183 Row oldRow, long rowId, Constraint activeIndex) 184 throws SQLException , IOException 185 { 186 } 187 188 public void checkDelete(Session session, Row row, long rowId) 189 throws SQLException , IOException 190 { 191 } 192 193 196 199 public void applyInsert(Session session, Row row, long rowId, 200 Constraint activeIndex) 201 throws SQLException , IOException 202 { 203 204 Database db = session.getDatabase(); 205 byte[] key = makeKey(session, row, rowId); 206 AddIndexEntry add = new AddIndexEntry(session, this, key, rowId); 207 if (activeIndex == this) { 208 session.addPendingAction(add); 209 } else { 210 session.doStep(add); 211 } 212 } 213 214 public void applyUpdate(Session session, byte[] oldKey, Row row, 217 Row oldRow, long rowId, Constraint activeIndex) 218 throws SQLException , IOException 219 { 220 byte[] key = makeKey(session, row, rowId); 221 if (activeIndex != this) { 222 oldKey = makeKey(session, oldRow, rowId); 223 } 224 if (Util.compareBytes(key, oldKey) != 0) { 225 UpdateIndex ui = 226 (UpdateIndex)session.getContext(this, isDeferred()); 227 if (ui == null) { 228 ui = new UpdateIndex(session, this); 229 session.putContext(this, isDeferred(), ui); 230 } 231 ui.addEntry(key, oldKey, rowId); 232 } else { 233 } 234 } 235 236 public void applyDelete(Session session, Row row, long rowId, 237 Constraint activeIndex) 238 throws SQLException , IOException 239 { 240 Database db = session.getDatabase(); 241 byte[] key = makeKey(session, row, rowId); 242 243 if (index == null) getIndex(db); 244 DeleteIndexEntry del = new DeleteIndexEntry(session, this, key); 245 if (activeIndex == this) { 246 session.addPendingAction(del); 247 } else { 248 session.doStep(del); 249 } 250 } 251 252 256 public boolean isUnique() { return true; } 257 258 261 public int getIndexColumnCount() { 262 return getColumnCount(); 263 } 264 265 268 public Btree getIndex(Database db) throws IOException { 269 if (index == null) { 270 BlockFile file = db.getFile(); 271 boolean create = false; 272 if (indexRoot == -1) { 273 indexRoot = file.newPage(); 274 db.updateRelation(table); 275 create = true; 276 } 277 if (useComparator) { 278 Comparator compare = new Key(getIndexColumnCount()); 279 index = new Btree(file, compare, indexRoot, create); 280 } else { 281 index = new Btree(file, indexRoot, create); 282 } 283 } 284 return index; 285 } 286 287 290 public String toString() { 291 StringBuffer sb = new StringBuffer (); 292 sb.append(getName()); 293 if (table != null) { 294 sb.append("("); 295 try { 296 Vector v = getColumnNames(); 297 for (int i = 0; i < v.size(); i++) { 298 if (i > 0) sb.append(','); 299 sb.append(v.elementAt(i).toString()); 300 } 301 sb.append(")"); 302 } catch (SQLException e) { 303 sb.append("Exception: " + e.toString()); 304 } 305 } 306 return sb.toString(); 307 } 308 } 309 | Popular Tags |