00001
package com.quadcap.sql;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.ByteArrayOutputStream;
00042
import java.io.Externalizable;
00043
import java.io.IOException;
00044
import java.io.ObjectInput;
00045
import java.io.ObjectOutput;
00046
00047
import java.util.Vector;
00048
00049
import java.sql.ResultSet;
00050
import java.sql.SQLException;
00051
00052
import com.quadcap.sql.index.Btree;
00053
import com.quadcap.sql.index.BCursor;
00054
00055
import com.quadcap.util.Debug;
00056
import com.quadcap.util.Util;
00057
00058
00059
00060
00061
00062
00063
00064 public class ExportedKeyConstraint extends ForeignKeyConstraint
00065 implements
Externalizable
00066 {
00067 transient ImportedKeyConstraint iConstraint;
00068 transient String
iConstraintName;
00069
00070 String
uConstraintName;
00071
00072
00073
00074
00075
00076 public ExportedKeyConstraint() {}
00077
00078
00079
00080
00081 public ExportedKeyConstraint(String name, Vector colNames,
00082 String fTableName, Vector fColNames,
00083
ImportedKeyConstraint iConstraint,
00084
UniqueConstraint uConstraint)
00085
throws SQLException
00086 {
00087 super(name, colNames, fTableName, fColNames);
00088
this.iConstraint =
iConstraint;
00089
this.iConstraintName =
iConstraint.
getName();
00090
this.uConstraintName = uConstraint.getName();
00091 uConstraint.addExportConstraint(
this);
00092
if (
this.colNames == null) {
00093
this.colNames = uConstraint.getColumnNames();
00094 }
00095 }
00096
00097 public void delete(
Session session)
throws SQLException, IOException {
00098
UniqueConstraint uc =
00099 (
UniqueConstraint)table.
getConstraint(
uConstraintName);
00100
if (uc != null) {
00101 uc.
removeExportConstraint(name);
00102 }
00103 }
00104
00105 void setForeignKeyCols(
int[] fCols) {
00106
this.fCols = fCols;
00107 }
00108
00109 public void checkUpdate(
Session session, byte[] oldKey,
Row row,
00110
Row oldRow,
long rowId,
Constraint activeIndex)
00111
throws SQLException, IOException
00112 {
00113
getComparator();
00114
Database db = session.getDatabase();
00115 byte[] newKey = makeKey(session, row);
00116
if (activeIndex !=
this) oldKey = makeKey(session, oldRow);
00117
if (compare.
compare(newKey, oldKey) != 0) {
00118
ExportedKeys ek =
getExportedKeys(session);
00119
if (isSelfReferencing(db)) {
00120 byte[] oldfKey = makeFKey(session, oldRow);
00121 byte[] newfKey = makeFKey(session, row);
00122 ek.
addSelfRefEntry(oldKey, newKey, oldfKey, newfKey);
00123 }
else {
00124 ek.
addEntry(oldKey, newKey);
00125 }
00126 }
00127 }
00128
00129 public void checkDelete(
Session session,
Row row,
long rowId)
00130
throws SQLException, IOException
00131 {
00132 byte[] fkey =
getImportedKeyConstraint(session.getDatabase()).
makeFKey(session, row);
00133
if (isSelfReferencing(session.getDatabase())) {
00134
ExportedKeys ek =
getExportedKeys(session);
00135 byte[] key = makeKey(session, row);
00136 ek.
addDeleteSelfRef(key, fkey);
00137 }
else {
00138
checkKeyRemoval(session, fkey);
00139 }
00140 }
00141
00142 public void checkKeyRemoval(
Session session, byte[] oldkey)
00143
throws SQLException, IOException
00144 {
00145
getComparator();
00146
Database db = session.getDatabase();
00147
Btree fTree =
getForeignIndex(db);
00148
int count = 0;
00149
boolean match =
false;
00150
BCursor cursor = fTree.
getCursor(
false);
00151
try {
00152
boolean kvalid = cursor.
seek(oldkey);
00153
while (!match && (kvalid || cursor.
next())) {
00154 byte[] key = cursor.
getKey();
00155
int cmp = compare.
compare(key, oldkey);
00156 match = cmp == 0;
00157 kvalid =
false;
00158 }
00159 } finally {
00160 cursor.
release();
00161 }
00162
if (match) {
00163
int refSpec =
iConstraint.
getRefAction(DELETE);
00164
switch (refSpec) {
00165
case NOACTION:
00166
throw new SQLException(
00167
"Foreign key constraint violation: children exist",
00168
"23000");
00169
00170
case CASCADE:
00171
ExportedKeys ek =
getExportedKeys(session);
00172 ek.
removeKey(refSpec, oldkey);
00173
break;
00174
case SETNULL:
00175
case SETDEFAULT:
00176
00177
throw new SQLException(
00178
"Foreign key constraint violation and SET " +
00179
"{NULL|DEFAULT} not implemented",
"23000");
00180 }
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189 ExportedKeys getExportedKeys(
Session session)
throws IOException {
00190
ExportedKeys ek =
00191 (
ExportedKeys)session.getContext(
this,
isDeferred());
00192
if (ek == null) {
00193 ek =
new ExportedKeys(session,
this);
00194 session.putContext(
this,
isDeferred(), ek);
00195 }
00196
return ek;
00197 }
00198
00199 ImportedKeyConstraint getImportedKeyConstraint(
Database db)
00200
throws SQLException, IOException
00201 {
00202
if (
iConstraint == null) {
00203 getFTable(db);
00204
iConstraint =
00205 (
ImportedKeyConstraint)fTable.
getConstraint(
iConstraintName);
00206 }
00207
return iConstraint;
00208 }
00209
00210 Btree getForeignIndex(
Database db)
throws SQLException, IOException {
00211
return getImportedKeyConstraint(db).
getIndex(db);
00212 }
00213
00214 public void readExternal(ObjectInput in)
00215
throws IOException, ClassNotFoundException
00216 {
00217 super.readExternal(in);
00218
iConstraintName = (String)in.readObject();
00219
uConstraintName = (String)in.readObject();
00220 }
00221
00222 public void writeExternal(ObjectOutput out)
throws IOException {
00223 super.writeExternal(out);
00224 out.writeObject(
iConstraintName);
00225 out.writeObject(
uConstraintName);
00226 }
00227 }