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.SQLException;
00050
00051
import com.quadcap.sql.io.ObjectInputStream;
00052
import com.quadcap.sql.io.ObjectOutputStream;
00053
00054
import com.quadcap.sql.file.BlockFile;
00055
00056
import com.quadcap.sql.types.Op;
00057
import com.quadcap.sql.types.Type;
00058
import com.quadcap.sql.types.Value;
00059
00060
import com.quadcap.util.Debug;
00061
import com.quadcap.util.Util;
00062
00063
00064
00065
00066
00067
00068
00069 public class MergeExpression extends TableExpression
00070 implements
Externalizable
00071 {
00072 int op;
00073 boolean all;
00074 boolean corr;
00075 TableExpression a;
00076 TableExpression b;
00077 Vector
columns;
00078 TempTableMerge tempTable;
00079 MergeCursor mcursor = null;
00080 int[]
amap = null;
00081 int[]
bmap = null;
00082 Type[]
typeMap = null;
00083
00084 public MergeExpression() {}
00085
00086 public MergeExpression(
int op,
boolean all,
TableExpression a,
00087
TableExpression b, Vector columns,
00088
boolean corr) {
00089
this.op = op;
00090
this.all = all;
00091
this.a = a;
00092
this.b = b;
00093
this.columns = columns;
00094
this.corr = corr;
00095 }
00096
00097 public int rank() {
return 2; }
00098
00099 public boolean isUpdatable() {
return false; }
00100
00101 public void getBaseTables(Vector v) {
00102
a.
getBaseTables(v);
00103
b.
getBaseTables(v);
00104 }
00105
00106 public void setWhere(
Expression where) {
00107
this.where = where;
00108
a.
setWhere(where);
00109
b.
setWhere(where);
00110 }
00111
00112 public Cursor getCursor(
Session session,
Cursor c)
throws SQLException {
00113
try {
00114
Cursor ca =
a.
getCursor(session, c);
00115
Cursor cb =
b.
getCursor(session, c);
00116
00117
try {
00118
checkCorresponding(ca, cb);
00119
00120
Key compare =
new Key(
amap.length);
00121
00122
tempTable =
new TempTableMerge(session, compare);
00123
tempTable.
addRows(session, ca, 0,
amap);
00124
tempTable.
addRows(session, cb, 1,
bmap);
00125
00126
mcursor =
new MergeCursor(session,
op,
all,
tempTable);
00127
00128
if (!
corr) {
00129
for (
int i = 1; i <= ca.
getColumnCount(); i++) {
00130
Column col = ca.
getColumn(i);
00131
mcursor.
addColumn(
new Column(col.
getName(), col));
00132 }
00133 }
else {
00134
for (
int i = 0; i <
amap.length; i++) {
00135
Column col = ca.
getColumn(
amap[i]);
00136
mcursor.
addColumn(
new Column(col.
getName(), col));
00137 }
00138 }
00139
mcursor.
resolveColumns();
00140 } finally {
00141 ca.
close();
00142 cb.
close();
00143 }
00144 }
catch (IOException e) {
00145
throw DbException.wrapThrowable(e);
00146 }
00147
return mcursor;
00148 }
00149
00150 void checkCorresponding(
Cursor ca,
Cursor cb)
throws SQLException {
00151
if (!
corr) {
00152
if (ca.getColumnCount() != cb.getColumnCount()) {
00153
throw new SQLException(
Op.toString(
op) +
" merge " +
00154
"operation, tables must have the " +
00155
"same number of columns",
"42000");
00156 }
00157
amap =
new int[ca.getColumnCount()];
00158
bmap =
new int[
amap.length];
00159
for (
int i = 0; i <
amap.length; i++) {
00160
amap[i] =
bmap[i] = i+1;
00161 }
00162 }
else if (
columns == null) {
00163
00164
int cnt = 0;
00165
for (
int i = 1; i <= ca.getColumnCount(); i++) {
00166
Column cola = ca.getColumn(i);
00167
Column colb = cb.getColumn(cola.
getShortName());
00168
if (colb != null) {
00169 cnt++;
00170 }
00171 }
00172
if (cnt == 0) {
00173
throw new SQLException(
Op.toString(
op) +
" CORRESPONDING, " +
00174
"no common columns found",
"42000");
00175 }
00176
amap =
new int[cnt];
00177
bmap =
new int[cnt];
00178
int p = 0;
00179
for (
int i = 1; i <= ca.getColumnCount(); i++) {
00180
Column cola = ca.getColumn(i);
00181
Column colb = cb.getColumn(cola.
getShortName());
00182
if (colb != null) {
00183
amap[p] = cola.
getColumn();
00184
bmap[p] = colb.
getColumn();
00185 p++;
00186 }
00187 }
00188 }
else {
00189
amap =
new int[
columns.size()];
00190
bmap =
new int[
amap.length];
00191
00192
for (
int i = 0; i <
columns.size(); i++) {
00193 String
name = (String)
columns.elementAt(i);
00194
Column cola = ca.getColumn(name);
00195
if (cola == null) {
00196
throw new SQLException(
"Not found: " + name,
"42000");
00197 }
00198
amap[i] = cola.
getColumn();
00199
00200
Column colb = cb.getColumn(name);
00201
if (colb == null) {
00202
throw new SQLException(
"Not found: " + name,
"42000");
00203 }
00204
bmap[i] = colb.
getColumn();
00205 }
00206 }
00207 }
00208
00209 public void invert() {
00210
throw new RuntimeException(
00211
"invert not implemented for MergeExpression");
00212 }
00213
00214 public void readExternal(ObjectInput in)
00215
throws IOException, ClassNotFoundException
00216 {
00217
this.op = in.read();
00218
this.all = in.read() == 1;
00219
this.a = (
TableExpression)in.readObject();
00220
this.b = (
TableExpression)in.readObject();
00221
this.columns = (Vector)in.readObject();
00222
this.corr = in.read() == 1;
00223 }
00224
00225 public void writeExternal(ObjectOutput out)
throws IOException {
00226 out.write(
op);
00227 out.write(
all ? 1 : 0);
00228 out.writeObject(
a);
00229 out.writeObject(
b);
00230 out.writeObject(
columns);
00231 out.write(
corr ? 1 : 0);
00232 }
00233
00234 public void visitSubExpressions(
ExpressionVisitor ev) {
00235 ev.
visit(
a);
00236 ev.
visit(
b);
00237 }
00238
00239 public String
toString() {
00240 StringBuffer sb =
new StringBuffer(
a.
toString());
00241 sb.append(
' ');
00242 sb.append(
Op.toString(
op));
00243
if (
all) sb.append(
" ALL");
00244
if (
corr) {
00245 sb.append(
" CORRESPONDING");
00246
if (
columns != null) {
00247 sb.append(
" BY (");
00248
for (
int i = 0; i <
columns.size(); i++) {
00249
if (i > 0) sb.append(
',');
00250 sb.append(
columns.get(i).toString());
00251 }
00252 sb.append(
")");
00253 }
00254 }
00255 sb.append(
' ');
00256 sb.append(
b.
toString());
00257
return sb.toString();
00258 }
00259
00260
00261 public String
name() {
00262 StringBuffer sb =
new StringBuffer(
'(');
00263 sb.append(
a.
name());
00264 sb.append(
' ');
00265 sb.append(
Op.toString(
op));
00266 sb.append(
' ');
00267 sb.append(
b.
name());
00268 sb.append(
')');
00269
return sb.toString();
00270 }
00271
00272 }