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.file.ByteUtil;
00053
00054
import com.quadcap.sql.index.Btree;
00055
import com.quadcap.sql.index.Comparator;
00056
00057
import com.quadcap.sql.file.BlockFile;
00058
00059
import com.quadcap.util.Debug;
00060
import com.quadcap.util.Util;
00061
00062
00063
00064
00065
00066
00067 abstract public class IndexConstraint extends Constraint
00068 implements
Externalizable {
00069 Btree
index = null;
00070 long indexRoot = -1;
00071 protected boolean useComparator =
true;
00072
00073
00074
00075
00076 public IndexConstraint() {}
00077
00078
00079
00080
00081 public IndexConstraint(String name) {
00082 super(name);
00083 }
00084
00085 public IndexConstraint(String name, Vector names) {
00086 super(name, names);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
abstract public byte[] makeKey(
Session session,
Row row,
long rowId)
00096
throws SQLException
00097 ;
00098
00099
00100
00101
00102
00103
abstract public String
constraintType();
00104
00105
00106
00107
00108 public void add(
Session session)
throws SQLException, IOException {
00109
index = null;
00110
indexRoot = -1;
00111
resetColumns();
00112
getIndex(session.getDatabase());
00113
00114
getColumns();
00115
IndexCursor c = table.
getCursor(session,
this);
00116
if (c != null) {
00117
try {
00118
while (c.
next()) {
00119
Row row = c.
getRow();
00120
long rowId = c.
getRowId();
00121 byte[] key = makeKey(session, row, rowId);
00122
if (
index.get(key) != null) {
00123
throw new SQLException(
constraintType() +
00124
" constraint violated");
00125 }
00126
if (session.getConnection().inRecovery()) {
00127 rowId = session.getLog().getRowMap(rowId);
00128 }
00129
index.set(key, key.length, session.getBuf8(rowId), 0, 8);
00130 }
00131 } finally {
00132 c.
close();
00133 }
00134 }
00135
00136 }
00137
00138
00139
00140
00141 public void delete(
Session session)
throws IOException {
00142
if (
indexRoot > 0) {
00143
Database db = session.getDatabase();
00144
getIndex(db);
00145
if (
index != null) {
00146
index.free();
00147 }
00148 }
00149 }
00150
00151
00152
00153
00154 public void readExternal(ObjectInput in)
00155
throws IOException, ClassNotFoundException
00156 {
00157 super.readExternal(in);
00158
indexRoot = in.readLong();
00159
useComparator = in.read() == 1;
00160 }
00161
00162
00163
00164
00165 public void writeExternal(ObjectOutput out)
throws IOException {
00166 super.writeExternal(out);
00167 out.writeLong(
indexRoot);
00168 out.write(
useComparator ? 1 : 0);
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 public void checkInsert(
Session session,
Row row)
00178
throws SQLException, IOException
00179 {
00180 }
00181
00182 public void checkUpdate(
Session session, byte[] oldKey,
Row row,
00183
Row oldRow,
long rowId,
Constraint activeIndex)
00184
throws SQLException, IOException
00185 {
00186 }
00187
00188 public void checkDelete(
Session session,
Row row,
long rowId)
00189
throws SQLException, IOException
00190 {
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 public void applyInsert(
Session session,
Row row,
long rowId,
00200
Constraint activeIndex)
00201
throws SQLException, IOException
00202 {
00203
00204
Database db = session.getDatabase();
00205 byte[] key = makeKey(session, row, rowId);
00206
AddIndexEntry add =
new AddIndexEntry(session,
this, key, rowId);
00207
if (activeIndex ==
this) {
00208 session.addPendingAction(add);
00209 }
else {
00210 session.doStep(add);
00211 }
00212 }
00213
00214
00215
00216 public void applyUpdate(
Session session, byte[] oldKey,
Row row,
00217
Row oldRow,
long rowId,
Constraint activeIndex)
00218
throws SQLException, IOException
00219 {
00220 byte[] key = makeKey(session, row, rowId);
00221
if (activeIndex !=
this) {
00222 oldKey = makeKey(session, oldRow, rowId);
00223 }
00224
if (
Util.compareBytes(key, oldKey) != 0) {
00225
UpdateIndex ui =
00226 (
UpdateIndex)session.getContext(
this,
isDeferred());
00227
if (ui == null) {
00228 ui =
new UpdateIndex(session,
this);
00229 session.putContext(
this,
isDeferred(), ui);
00230 }
00231 ui.
addEntry(key, oldKey, rowId);
00232 }
else {
00233 }
00234 }
00235
00236 public void applyDelete(
Session session,
Row row,
long rowId,
00237
Constraint activeIndex)
00238
throws SQLException, IOException
00239 {
00240
Database db = session.getDatabase();
00241 byte[] key = makeKey(session, row, rowId);
00242
00243
if (
index == null)
getIndex(db);
00244
DeleteIndexEntry del =
new DeleteIndexEntry(session,
this, key);
00245
if (activeIndex ==
this) {
00246 session.addPendingAction(del);
00247 }
else {
00248 session.doStep(del);
00249 }
00250 }
00251
00252
00253
00254
00255
00256 public boolean isUnique() {
return true; }
00257
00258
00259
00260
00261 public int getIndexColumnCount() {
00262
return getColumnCount();
00263 }
00264
00265
00266
00267
00268 public Btree
getIndex(
Database db)
throws IOException {
00269
if (
index == null) {
00270
BlockFile file = db.getFile();
00271
boolean create =
false;
00272
if (
indexRoot == -1) {
00273
indexRoot = file.
newPage();
00274 db.updateRelation(table);
00275 create =
true;
00276 }
00277
if (
useComparator) {
00278
Comparator compare =
new Key(
getIndexColumnCount());
00279
index =
new Btree(file, compare,
indexRoot, create);
00280 }
else {
00281
index =
new Btree(file,
indexRoot, create);
00282 }
00283 }
00284
return index;
00285 }
00286
00287
00288
00289
00290 public String
toString() {
00291 StringBuffer sb =
new StringBuffer();
00292 sb.append(
getName());
00293
if (table != null) {
00294 sb.append(
"(");
00295
try {
00296 Vector v =
getColumnNames();
00297
for (
int i = 0; i < v.size(); i++) {
00298
if (i > 0) sb.append(
',');
00299 sb.append(v.elementAt(i).toString());
00300 }
00301 sb.append(
")");
00302 }
catch (SQLException e) {
00303 sb.append(
"Exception: " + e.toString());
00304 }
00305 }
00306
return sb.toString();
00307 }
00308 }