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.Enumeration;
00048
import java.util.Hashtable;
00049
00050
import java.util.Vector;
00051
00052
import java.sql.SQLException;
00053
00054
import com.quadcap.sql.io.ObjectInputStream;
00055
import com.quadcap.sql.io.ObjectOutputStream;
00056
00057
import com.quadcap.sql.file.ByteUtil;
00058
00059
import com.quadcap.util.Debug;
00060
import com.quadcap.util.Util;
00061
00062
00063
00064
00065
00066
00067
00068 public class DistinctCursor extends BC_Cursor {
00069 Cursor sourceCursor;
00070 Vector
orderBy = null;
00071 TempTable tempTable;
00072 boolean distinct =
true;
00073
00074
00075
00076
00077 public DistinctCursor(
Session session,
Cursor cursor)
throws SQLException {
00078 super(session, null, null);
00079
this.sourceCursor = cursor;
00080 addColumns(session, cursor);
00081 }
00082
00083 public final void checkCursor() throws SQLException, IOException {
00084
if (bc == null) {
00085
try {
00086
makeTempTable();
00087 } finally {
00088
try {
00089
sourceCursor.
close();
00090 }
catch (Throwable t) {
00091 } finally {
00092
sourceCursor = null;
00093 }
00094 }
00095 }
00096 }
00097
00098
00099 private void makeTempTable() throws IOException, SQLException {
00100
int size =
getColumnCount();
00101
if (
orderBy == null) {
00102
if (
distinct) {
00103
tempTable =
new TempTable(session,
new Key(size), null);
00104 }
else {
00105
tempTable =
new TempTable(session,
new Key(1),
new int[0]);
00106 }
00107 }
else {
00108
tempTable =
makeObTemp();
00109 }
00110
tempTable.
addRows(
sourceCursor);
00111 row =
new LazyRow(size);
00112 bc =
tempTable.
getCursor();
00113 }
00114
00115 TempTable makeObTemp() throws SQLException, IOException {
00116
int[] map =
new int[
getColumnCount()];
00117
boolean[] rmap =
new boolean[map.length+1];
00118
boolean[] asc =
new boolean[map.length];
00119
for (
int i = 0; i <
orderBy.size(); i++) {
00120
OrderElement elem = (
OrderElement)
orderBy.elementAt(i);
00121
int num = elem.
getColumn();
00122
if (num < 0) {
00123 String name = elem.
getColName();
00124
Column col = getColumn(name);
00125
if (col == null) {
00126
throw new SQLException(
"Bad column name: " + name);
00127 }
00128 num = col.
getColumn();
00129 elem.
setColumn(num);
00130 }
00131 map[i] = num;
00132 rmap[num] =
true;
00133 asc[i] = elem.
isAscending();
00134 }
00135
int cnt =
orderBy.size();
00136
for (
int i = 1; i < rmap.length; i++) {
00137
if (!rmap[i]) {
00138 map[cnt] = i;
00139 asc[cnt] =
true;
00140 cnt++;
00141 }
00142 }
00143
Key compare =
new Key(asc);
00144
return new TempTable(session, compare, map);
00145 }
00146
00147 public void setOrder(Vector v) {
00148
this.orderBy = v;
00149 }
00150
00151 public void setDistinct(
boolean b) {
00152
this.distinct = b;
00153 }
00154
00155 public long getCurrentRowId() throws SQLException {
00156
return ByteUtil.getLong(bc.
getValBuf(), 1);
00157 }
00158
00159 public void fetchCurrentRow() throws SQLException, IOException {
00160
tempTable.
getRow(bc.
getValBuf(), row);
00161 rowValid =
true;
00162 }
00163
00164
00165
00166
00167 public void close() throws SQLException {
00168
try {
00169 super.close();
00170 } finally {
00171
try {
00172
if (
sourceCursor != null)
sourceCursor.
close();
00173 } finally {
00174
sourceCursor = null;
00175
try {
00176
if (
tempTable != null)
tempTable.
release();
00177 }
catch (IOException ex) {
00178
throw DbException.wrapThrowable(ex);
00179 } finally {
00180
tempTable = null;
00181 }
00182 }
00183 }
00184 }
00185
00186
00187 public String
toString() {
00188
return super.toString() +
"\n\t[source cursor = " +
sourceCursor +
"]\n";
00189 }
00190
00191 }