ForeignKeyIndex.java [plain text]
package com.sleepycat.bdb;
import com.sleepycat.bdb.bind.KeyExtractor;
import com.sleepycat.db.Db;
import com.sleepycat.db.Dbc;
import com.sleepycat.db.DbTxn;
import com.sleepycat.db.DbException;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ForeignKeyIndex extends DataIndex {
public static final int ON_DELETE_ABORT = 0;
public static final int ON_DELETE_CASCADE = 1;
public static final int ON_DELETE_CLEAR = 2;
DataStore foreignStore;
int deleteAction;
public ForeignKeyIndex(DataStore store, Db db, KeyExtractor keyExtractor,
DataStore foreignStore, int deleteAction) {
super(store, db, foreignStore.keyFormat, keyExtractor);
this.foreignStore = foreignStore;
this.deleteAction = deleteAction;
foreignStore.addInverseIndex(this);
if (deleteAction == ON_DELETE_CLEAR &&
keyExtractor.getPrimaryKeyFormat() != null) {
throw new IllegalArgumentException(
"ON_DELETE_CLEAR cannot be used with key extractor that " +
"requires primary key");
}
}
public final DataStore getForeignStore() {
return foreignStore;
}
public final int getDeleteAction() {
return deleteAction;
}
final void applyIndexInsert(DataThang keyThang, DataThang newIndexKey)
throws DbException, IOException {
int err = foreignStore.db.get(newIndexKey,
DataThang.getDiscardDataThang(), 0);
if (err != 0) {
throw new IllegalArgumentException(
"Integrity error inserting in " +
db + ", index key not found in " +
foreignStore.db);
}
super.applyIndexInsert(keyThang, newIndexKey);
}
final void applyForeignDelete(DataThang foreignPrimaryKeyThang)
throws DbException, IOException {
DataEnvironment env = store.db.env;
DataThang primaryKeyThang = new DataThang();
int err = db.get(foreignPrimaryKeyThang, primaryKeyThang, 0);
if (err == 0) {
switch (deleteAction) {
case ON_DELETE_ABORT: {
throw new IntegrityConstraintException(
"ON_DELETE_ABORT: deletion not allowed");
}
case ON_DELETE_CASCADE: {
DataThang tempThang = new DataThang();
Dbc cursor = store.db.openCursor(true);
try {
err = cursor.get(primaryKeyThang, tempThang,
Db.DB_SET | env.getWriteLockFlag());
if (err == 0) {
cursor.delete(0);
store.applyChange(primaryKeyThang, tempThang,
null);
} else {
throw new IntegrityConstraintException(
"ON_DELETE_CASCADE: index entry not found");
}
} finally {
store.db.closeCursor(cursor);
}
break;
}
case ON_DELETE_CLEAR: {
DataThang valueThang = new DataThang();
Dbc cursor = store.db.openCursor(true);
try {
err = cursor.get(primaryKeyThang, valueThang,
Db.DB_SET | env.getWriteLockFlag());
if (err == 0) {
keyExtractor.clearIndexKey(
(keyExtractor.getValueFormat() != null)
? valueThang : null);
cursor.put(primaryKeyThang, valueThang,
Db.DB_CURRENT);
} else {
throw new IntegrityConstraintException(
"ON_DELETE_CLEAR: index entry not found");
}
} finally {
store.db.closeCursor(cursor);
}
break;
}
default: {
throw new IllegalArgumentException(
"unknown delete action " + deleteAction);
}
}
}
}
}