Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.scudata.util.CursorUtil Maven / Gradle / Ivy
Go to download
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeMap;
import com.scudata.array.IArray;
import com.scudata.common.IntArrayList;
import com.scudata.common.Logger;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BFileReader;
import com.scudata.dm.BFileWriter;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.Current;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;
import com.scudata.dm.HashArraySet;
import com.scudata.dm.IndexTable;
import com.scudata.dm.ListBase1;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.comparator.*;
import com.scudata.dm.cursor.*;
import com.scudata.dm.op.DiffJoin;
import com.scudata.dm.op.FilterJoin;
import com.scudata.dm.op.IGroupsResult;
import com.scudata.dm.op.Join;
import com.scudata.dm.op.Operation;
import com.scudata.dw.ColPhyTable;
import com.scudata.dw.IDWCursor;
import com.scudata.dw.PhyTable;
import com.scudata.expression.CurrentSeq;
import com.scudata.expression.Expression;
import com.scudata.expression.Node;
import com.scudata.expression.fn.gather.ICount.ICountBitSet;
import com.scudata.expression.fn.gather.ICount.ICountPositionSet;
import com.scudata.parallel.ClusterCursor;
import com.scudata.resources.EngineMessage;
import com.scudata.thread.GroupsJob;
import com.scudata.thread.GroupsJob2;
import com.scudata.thread.GroupxJob;
import com.scudata.thread.MultithreadUtil;
import com.scudata.thread.ThreadPool;
public final class CursorUtil {
/**
* ȡ?α?????ݽṹ
* @param cs
* @return
*/
public static DataStruct getDataStruct(ICursor cs) {
DataStruct ds = cs.getDataStruct();
if (ds == null) {
Sequence seq = cs.peek(ICursor.FETCHCOUNT_M);
ds = cs.getDataStruct();
if (ds == null && seq != null) {
ds = seq.dataStruct();
}
}
return ds;
}
/**
* ?????н??в??з???
* @param src ????
* @param exps ?????ֶα???ʽ????
* @param names ?????ֶ???????
* @param calcExps ?????ֶα???ʽ????
* @param calcNames ?????ֶ???????
* @param opt ѡ??
* @param ctx ??????????
* @returns
*/
public static Table groups_m(Sequence src, Expression[] exps, String[] names,
Expression[] calcExps, String[] calcNames, String opt, Context ctx) {
int len = src.length();
int parallelNum = Env.getParallelNum();
if (len <= MultithreadUtil.SINGLE_PROSS_COUNT || parallelNum < 2) {
return src.groups(exps, names, calcExps, calcNames, opt, ctx);
}
int threadCount = (len - 1) / MultithreadUtil.SINGLE_PROSS_COUNT + 1;
if (threadCount > parallelNum) {
threadCount = parallelNum;
}
int singleCount = len / threadCount;
int keyCount = exps == null ? 0 : exps.length;
// ???ɷ????????ύ???̳߳?
ThreadPool pool = ThreadPool.instance();
GroupsJob []jobs = new GroupsJob[threadCount];
int start = 1;
int end; // ??????
for (int i = 0; i < threadCount; ++i) {
if (i + 1 == threadCount) {
end = len + 1;
} else {
end = start + singleCount;
}
Context tmpCtx = ctx.newComputeContext();
Expression []tmpExps = Operation.dupExpressions(exps, tmpCtx);
Expression []tmpCalcExps = Operation.dupExpressions(calcExps, tmpCtx);
Sequence seq = src.get(start, end);
jobs[i] = new GroupsJob(seq, tmpExps, names, tmpCalcExps, calcNames, opt, tmpCtx);
pool.submit(jobs[i]);
start = end;
}
// ?ȴ?????????ִ????ϣ????ѽ?????ӵ?һ?????
Table result = null;
IGroupsResult groupsResult = null;
for (int i = 0; i < threadCount; ++i) {
jobs[i].join();
groupsResult = jobs[i].getGroupsResult();
if (result == null) {
result = groupsResult.getTempResult();
} else {
result.addAll(groupsResult.getTempResult());
}
}
if (result == null || result.length() == 0) {
return result;
}
// ???ɶ??η?????????ʽ
Expression []keyExps = null;
if (keyCount > 0) {
keyExps = new Expression[keyCount];
for (int i = 0, q = 1; i < keyCount; ++i, ++q) {
keyExps[i] = new Expression(ctx, "#" + q);
}
}
// ???ɶ??η?????ܱ???ʽ??avg???ܱ??ֳ?sum??count???н??м???
Expression []valExps = groupsResult.getRegatherExpressions();
DataStruct tempDs = groupsResult.getRegatherDataStruct();
int tempFieldCount = tempDs.getFieldCount();
if (keyCount > 0) {
if (names == null) {
names = new String[keyCount];
}
for (int i = 0; i < keyCount; ++i) {
names[i] = tempDs.getFieldName(i);
}
}
if (tempFieldCount > keyCount) {
int gatherCount = tempFieldCount - keyCount;
calcNames = new String[gatherCount];
for (int i = 0; i < gatherCount; ++i) {
calcNames[i] = tempDs.getFieldName(keyCount + i);
}
}
// ???ж??η???
result = result.groups(keyExps, names, valExps, calcNames, opt, ctx);
Expression []newExps = groupsResult.getResultExpressions();
if (newExps != null) {
return result.newTable(groupsResult.getResultDataStruct(), newExps, null, ctx);
} else {
return result;
}
}
/**
* ?????н??в??з???
* @param src ????
* @param exps ?????ֶα???ʽ????
* @param names ?????ֶ???????
* @param calcExps ?????ֶα???ʽ????
* @param calcNames ?????ֶ???????
* @param opt ѡ??
* @param ctx ??????????
* @param hashCapacity ??ϣ??????
* @returns
*/
public static Table groups_z(Sequence src, Expression[] exps, String[] names, Expression[] calcExps,
String[] calcNames, String opt, Context ctx, int hashCapacity) {
int capacity = hashCapacity > 0 ? hashCapacity :Env.getDefaultHashCapacity();
HashUtil hashUtil = new HashUtil(capacity);
capacity = hashUtil.getCapacity();
// ???ɷ????????ύ???̳߳?
int parallelNum = Env.getParallelNum();
ThreadPool pool = ThreadPool.newInstance(parallelNum);
GroupsJob2 []jobs = new GroupsJob2[parallelNum];
Table groupsResult = null;
try {
for (int i = 0; i < parallelNum; ++i) {
Context tmpCtx = ctx.newComputeContext();
Expression []tmpExps = Operation.dupExpressions(exps, tmpCtx);
Expression []tmpCalcExps = Operation.dupExpressions(calcExps, tmpCtx);
GroupsJob2 job = new GroupsJob2(src, hashUtil, null, tmpExps, names, tmpCalcExps, calcNames, opt, tmpCtx, capacity);
job.setHashStart(i);
job.setHashEnd(parallelNum);
jobs[i] = job;
pool.submit(jobs[i]);
}
// ?ȴ?????????ִ????ϣ????ѽ?????ӵ?һ?????
for (int i = 0; i < parallelNum; ++i) {
jobs[i].join();
if (i == 0) {
groupsResult = jobs[i].getGroupsResult().getResultTable();
} else {
Table t = jobs[i].getGroupsResult().getResultTable();
groupsResult.addAll(t);
}
}
} finally {
pool.shutdown();
}
if (opt == null || opt.indexOf('u') == -1) {
int keyCount = exps.length;
int []fields = new int[keyCount];
for (int i = 0; i < keyCount; ++i) {
fields[i] = i;
}
groupsResult.sortFields(fields);
}
return groupsResult;
}
/**
* ?趨???????????????????ﵽ???ֵ??ֹͣ????
* @param cursor ?α?
* @param exps ?????ֶα???ʽ????
* @param names ?????ֶ???????
* @param calcExps ?????ֶα???ʽ????
* @param calcNames ?????ֶ???????
* @param maxGroupCount
* @param opt ѡ??
* @param ctx ??????????
* @return ??????
*/
public static Table fuzzyGroups(ICursor cursor, Expression[] exps, String[] names,
Expression[] calcExps, String[] calcNames, String opt, Context ctx, int maxGroupCount) {
DataStruct ds = cursor.getDataStruct();
int count = exps.length;
if (names == null) names = new String[count];
for (int i = 0; i < count; ++i) {
if (names[i] == null || names[i].length() == 0) {
names[i] = exps[i].getFieldName(ds);
}
}
if (calcExps != null) {
count = calcExps.length;
if (calcNames == null) calcNames = new String[count];
for (int i = 0; i < count; ++i) {
if (calcNames[i] == null || calcNames[i].length() == 0) {
calcNames[i] = calcExps[i].getFieldName(ds);
}
}
}
int keyCount = exps.length;
int valCount = calcExps == null ? 0 : calcExps.length;
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil(maxGroupCount);
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
Object []keys = new Object[keyCount];
String[] colNames = new String[keyCount + valCount];
System.arraycopy(names, 0, colNames, 0, keyCount);
if (calcNames != null) {
System.arraycopy(calcNames, 0, colNames, keyCount, valCount);
}
Table table = new Table(colNames, hashUtil.getCapacity());
table.setPrimary(names);
Node []gathers = Sequence.prepareGatherMethods(calcExps, ctx);
ComputeStack stack = ctx.getComputeStack();
while (true) {
Sequence src = cursor.fetch(ICursor.FETCHCOUNT);
if (src == null || src.length() == 0) break;
Current current = new Current(src);
stack.push(current);
try {
for (int i = 1, len = src.length(); i <= len; ++i) {
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = exps[k].calculate(ctx);
}
BaseRecord r;
int hash = hashUtil.hashCode(keys);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
r = table.newLast(keys);
groups[hash].add(r);
for (int v = 0, f = keyCount; v < valCount; ++v, ++f) {
Object val = gathers[v].gather(ctx);
r.setNormalFieldValue(f, val);
}
} else {
int index = HashUtil.bsearch_r(groups[hash], keys);
if (index < 1) {
r = table.newLast(keys);
groups[hash].add(-index, r);
for (int v = 0, f = keyCount; v < valCount; ++v, ++f) {
Object val = gathers[v].gather(ctx);
r.setNormalFieldValue(f, val);
}
} else {
r = (BaseRecord)groups[hash].get(index);
for (int v = 0, f = keyCount; v < valCount; ++v, ++f) {
Object val = gathers[v].gather(r.getNormalFieldValue(f), ctx);
r.setNormalFieldValue(f, val);
}
}
}
}
} finally {
stack.pop();
}
if (table.length() >= maxGroupCount) {
break;
}
}
if (opt == null || opt.indexOf('u') == -1) {
int []fields = new int[keyCount];
for (int i = 0; i < keyCount; ++i) {
fields[i] = i;
}
table.sortFields(fields);
}
table.finishGather(gathers);
return table;
}
/**
* ?????н??й?ϣ????
* @param src ????
* @param exps ???????ʽ????
* @param opt ѡ??
* @param ctx ??????????
* @return ??????
*/
public static Sequence hashGroup(Sequence src, Expression[] exps, String opt, Context ctx) {
if (src == null || src.length() == 0) {
return new Sequence(0);
}
int srcLen = src.length();
boolean isAll = true, isSort = true, isPos = false, isConj = false;
if (opt != null) {
if (opt.indexOf('1') != -1) isAll = false;
if (opt.indexOf('u') != -1) isSort = false;
if (opt.indexOf('p') != -1) isPos = true;
if (opt.indexOf('s') != -1) isConj = true;
}
int keyCount = exps.length;
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil(srcLen / 2);
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
Sequence result = new Sequence(hashUtil.getCapacity());
boolean isSingleField = keyCount == 1 && !isAll;
ListBase1 keyList = null;
if (isSort) {
keyList = new ListBase1(hashUtil.getCapacity());
}
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(src);
stack.push(current);
try {
if (isSingleField) {
Expression exp = exps[0];
for (int i = 1; i <= srcLen; ++i) {
current.setCurrent(i);
Object key = exp.calculate(ctx);
int hash = hashUtil.hashCode(key);
if (groups[hash] == null) {
result.add(isPos ? new Integer(i):current.getCurrent());
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(key);
if (isSort) {
keyList.add(key);
}
} else {
int index = groups[hash].binarySearch(key);
if (index < 1) {
result.add(isPos ? new Integer(i):current.getCurrent());
groups[hash].add(-index, key);
if (isSort) {
keyList.add(key);
}
}
}
}
} else {
int count = isAll ? keyCount + 1 : keyCount;
for (int i = 1; i <= srcLen; ++i) {
current.setCurrent(i);
Object []keys = new Object[count];
for (int k = 0; k < keyCount; ++k) {
keys[k] = exps[k].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
if (isAll) {
Sequence group = new Sequence(INIT_GROUPSIZE);
group.add(isPos ? new Integer(i):current.getCurrent());
keys[keyCount] = group;
result.add(group);
} else {
result.add(isPos ? new Integer(i):current.getCurrent());
}
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(keys);
if (isSort) {
keyList.add(keys);
}
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
if (isAll) {
Sequence group = new Sequence(INIT_GROUPSIZE);
group.add(isPos ? new Integer(i):current.getCurrent());
keys[keyCount] = group;
result.add(group);
} else {
result.add(isPos ? new Integer(i):current.getCurrent());
}
groups[hash].add(-index, keys);
if (isSort) {
keyList.add(keys);
}
} else {
if (isAll) {
Object []tmps = (Object[])groups[hash].get(index);
((Sequence)tmps[keyCount]).add(isPos ? new Integer(i):current.getCurrent());
}
}
}
}
}
} finally {
stack.pop();
}
if (isSort) {
int len = result.length();
PSortItem []infos = new PSortItem[len + 1];
for (int i = 1; i <= len; ++i) {
infos[i] = new PSortItem(i, keyList.get(i));
}
Comparator comparator;
if (isSingleField) {
comparator = new BaseComparator();
} else {
comparator = new ArrayComparator(keyCount);
}
comparator = new PSortComparator(comparator);
MultithreadUtil.sort(infos, 1, infos.length, comparator);
Sequence retSeries = new Sequence(len);
for (int i = 1; i <= len; ++i) {
retSeries.add(result.getMem(infos[i].index));
}
if (isAll && isConj) {
return retSeries.conj(null);
} else {
return retSeries;
}
} else {
if (isAll && isConj) {
return result.conj(null);
} else {
return result;
}
}
}
/**
* ?????н??й?ϣ????
* @param src ????
* @param opt ѡ??
* @param ctx ??????????
* @return ??????
*/
public static Sequence hashGroup(Sequence src, String opt) {
if (src == null || src.length() == 0) return new Sequence(0);
boolean isAll = true, isSort = true, isPos = false, isConj = false;
if (opt != null) {
if (opt.indexOf('1') != -1) isAll = false;
if (opt.indexOf('u') != -1) isSort = false;
if (opt.indexOf('p') != -1) isPos = true;
if (opt.indexOf('s') != -1) isConj = true;
}
if (!isAll) {
return hashId(src, opt);
} else if (isPos) {
Context ctx = new Context();
Expression exp = new Expression("~");
return hashGroup(src, new Expression[] {exp}, opt, ctx);
}
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil(src.length() / 2);
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
Sequence result = new Sequence(hashUtil.getCapacity());
for (int i = 1, len = src.length(); i <= len; ++i) {
Object mem = src.getMem(i);
int hash = hashUtil.hashCode(mem);
if (groups[hash] == null) {
Sequence group = new Sequence(INIT_GROUPSIZE);
group.add(mem);
result.add(group);
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(group);
} else {
int index = HashUtil.bsearch_g(groups[hash], mem);
if (index < 1) {
Sequence group = new Sequence(INIT_GROUPSIZE);
group.add(mem);
result.add(group);
groups[hash].add(-index, group);
} else {
Sequence group = (Sequence)groups[hash].get(index);
group.add(mem);
}
}
}
if (isSort) {
Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
return Variant.compare(((Sequence)o1).getMem(1), ((Sequence)o2).getMem(1), true);
}
};
result.getMems().sort(comparator);
}
if (isConj) {
return result.conj(null);
} else {
return result;
}
}
/**
* ?????н??й?ϣȥ??
* @param src ????
* @param opt ѡ??
* @param ctx ??????????
* @return ??????
*/
public static Sequence hashId(Sequence src, String opt) {
int len = src.length();
if (len == 0) {
return new Sequence();
}
if (opt != null && opt.indexOf('m') != -1) {
return MultithreadUtil.hashId(src, opt);
}
HashUtil hashUtil = new HashUtil(len / 2);
Sequence out = new Sequence(len);
if (opt != null && opt.indexOf('n') != -1) {
ICountPositionSet set = new ICountPositionSet();
for (int i = 1; i <= len; ++i) {
Object item = src.getMem(i);
if (item instanceof Number && set.add(((Number)item).intValue())) {
out.add(item);
}
}
} else if (opt != null && opt.indexOf('b') != -1) {
ICountBitSet set = new ICountBitSet();
for (int i = 1; i <= len; ++i) {
Object item = src.getMem(i);
if (item instanceof Number && set.add(((Number)item).intValue())) {
out.add(item);
}
}
} else {
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
for (int i = 1; i <= len; ++i) {
Object item = src.getMem(i);
int hash = hashUtil.hashCode(item);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(item);
out.add(item);
} else {
int index = groups[hash].binarySearch(item);
if (index < 1) {
groups[hash].add(-index, item);
out.add(item);
}
}
}
}
if (opt == null || opt.indexOf('u') == -1) {
Comparator comparator = new BaseComparator();
out.getMems().sort(comparator);
}
return out;
}
/**
* ???????б????????鲢????
* @param groups ?б?????
* @param keyCount ?????ֶ???
* @param type ???????ͣ?0??join??1??left join??2??full join
* @param out
*/
public static void join_m(ListBase1 []groups, int fcount, int type, Table out) {
int srcCount = groups.length;
int []ranks = new int[srcCount]; // ??ǰԪ?ص???????0??1??-1
int []curIndex = new int[srcCount];
for (int i = 0; i < srcCount; ++i) {
curIndex[i] = 1;
}
Next:
while (true) {
boolean has = false; // ?Ƿ??еı???û??????
boolean equals = true; // ?Ƿ????ܹ????ϵļ?¼
for (int i = 0; i < srcCount; ++i) {
ListBase1 group = groups[i];
if (group != null && group.size() >= curIndex[i]) {
has = true;
ranks[i] = 0;
Object []curValues = (Object[])group.get(curIndex[i]);
// ??ǰ????????ֶε?ֵ??С?ı????бȽϣ?
for (int j = 0; j < i; ++j) {
if (ranks[j] == 0) {
Object [] prevValues = (Object[])groups[j].get(curIndex[j]);
int cmp = Variant.compareArrays(curValues, prevValues, fcount);
// ??????淢?ָ?С??ֵ????????
if (cmp < 0) {
equals = false;
ranks[j] = 1;
for (++j; j < i; ++j) {
if (ranks[j] == 0) {
ranks[j] = 1;
}
}
} else if (cmp > 0) {
equals = false;
ranks[i] = 1;
}
break;
}
}
} else {
// ??ǰ???????Ѿ???????
if (type == 0 || (type == 1 && i == 0)) { // join
break Next;
}
equals = false;
ranks[i] = -1;
}
}
if (!has) {
break;
} else if ((!equals && type == 0) || (ranks[0] != 0 && type == 1)) {
// ??????ڹ??????ϵı??????????????ӻ??????????Ӷ???һ??????ֵ?ֲ?????С????????????Ϊ0?ļ?¼
for (int i = 0; i < srcCount; ++i) {
if (ranks[i] == 0) {
ListBase1 group = groups[i];
int len = group.size();
int cur = curIndex[i];
Object []curValues = (Object[])group.get(cur);
for (++cur; cur <= len; ++cur) {
if (Variant.compareArrays(curValues, (Object[])group.get(cur), fcount) != 0) {
break;
}
}
curIndex[i] = cur;
}
}
} else {
// ???ɹ?????¼
int start = -1;
for (int i = 0; i < srcCount; ++i) {
if (ranks[i] == 0) {
ListBase1 group = groups[i];
int len = group.size();
int cur = curIndex[i];
Object []curValues = (Object[])group.get(cur);
if (start == -1) {
BaseRecord r = out.newLast();
r.setNormalFieldValue(i, curValues[fcount]);
start = out.length();
for (++cur; cur <= len; ++cur) {
Object []tmp = (Object[])group.get(cur);
if (Variant.compareArrays(curValues, tmp, fcount) == 0) {
r = out.newLast();
r.setNormalFieldValue(i, tmp[fcount]);
} else {
break;
}
}
curIndex[i] = cur;
} else {
int end = out.length();
for (int p = start; p <= end; ++p) {
BaseRecord pr = (BaseRecord)out.getMem(p);
pr.setNormalFieldValue(i, curValues[fcount]);
}
for (++cur; cur <= len; ++cur) {
Object []tmp = (Object[])group.get(cur);
if (Variant.compareArrays(curValues, tmp, fcount) == 0) {
for (int p = start; p <= end; ++p) {
BaseRecord pr = (BaseRecord)out.getMem(p);
BaseRecord r = out.newLast(pr.getFieldValues());
r.setNormalFieldValue(i, tmp[fcount]);
}
} else {
break;
}
}
curIndex[i] = cur;
}
}
}
}
}
}
/**
* Դ???ݰ??????ֶ????????鲢????
* @param srcs ????????
* @param exps ?????ֶα???ʽ????
* @param names ??????ֶ???????
* @param type ???????ͣ?0??join??1??left join??2??full join
* @param ctx Context ??????????
* @return Table ???????
*/
public static Table mergeJoin(Sequence[] srcs, Expression[][] exps,
String[] names, int type, Context ctx) {
int srcCount = srcs.length;
ListBase1 []groups = new ListBase1[srcCount];
int keyCount = exps[0] == null ? 1 : exps[0].length;
int count = keyCount + 1;
ComputeStack stack = ctx.getComputeStack();
for (int s = 0; s < srcCount; ++s) {
Sequence src = srcs[s];
int len = src.length();
ListBase1 group = new ListBase1(len);
groups[s] = group;
Expression []srcExps = exps[s];
Current current = new Current(src);
stack.push(current);
try {
// ????????ֶ?ֵ??Դ??¼????????????λ??
for (int i = 1; i <= len; ++i) {
Object []keys = new Object[count];
keys[keyCount] = src.getMem(i);
current.setCurrent(i);
if (srcExps == null) {
keys[0] = keys[keyCount];
} else {
for (int k = 0; k < keyCount; ++k) {
keys[k] = srcExps[k].calculate(ctx);
}
}
groups[s].add(keys);
}
} finally {
stack.pop();
}
}
Table out = new Table(names);
join_m(groups, keyCount, type, out);
return out;
}
/**
* ?????ϣֵ?????ù?ϣֵ????join
* @param srcs ????????
* @param exps ?????ֶα???ʽ????
* @param names ??????ֶ???????
* @param type ???????ͣ?0??join??1??left join??2??full join
* @param ctx Context ??????????
* @return Table ???????
*/
public static Table hashJoin(Sequence[] srcs, Expression[][] exps,
String[] names, int type, Context ctx) {
int srcCount = srcs.length;
int keyCount = exps[0] == null ? 1 : exps[0].length;
int count = keyCount + 1;
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil();
ListBase1 [][]hashGroups = new ListBase1[hashUtil.getCapacity()][];
ComputeStack stack = ctx.getComputeStack();
// ??ÿ?????а??չ????ֶν??й?ϣ????
for (int s = 0; s < srcCount; ++s) {
Sequence src = srcs[s];
Expression []srcExps = exps[s];
Current current = new Current(src);
stack.push(current);
try {
for (int i = 1, len = src.length(); i <= len; ++i) {
Object []keys = new Object[count];
keys[keyCount] = src.getMem(i);
current.setCurrent(i);
if (srcExps == null) {
keys[0] = keys[keyCount];
} else {
for (int k = 0; k < keyCount; ++k) {
keys[k] = srcExps[k].calculate(ctx);
}
}
int hash = hashUtil.hashCode(keys, keyCount);
ListBase1 []groups = hashGroups[hash];
if (groups == null) {
groups = new ListBase1[srcCount];
hashGroups[hash] = groups;
}
if (groups[s] == null) {
groups[s] = new ListBase1(INIT_GROUPSIZE);
groups[s].add(keys);
} else {
// ??ϣֵ??ͬ??Ԫ?ذ??չ????ֶ?????
int index = HashUtil.bsearch_a(groups[s], keys, keyCount);
if (index < 1) {
groups[s].add(-index, keys);
} else {
groups[s].add(index + 1, keys);
}
}
}
} finally {
stack.pop();
}
}
Table out = new Table(names);
for (int i = 0, len = hashGroups.length; i < len; ++i) {
// ??ÿ????ϣ????????鲢????
if (hashGroups[i] != null) {
join_m(hashGroups[i], keyCount, type, out);
hashGroups[i] = null;
}
}
return out;
}
/**
* ?????ֶ???????ͬ??????
* @param srcs ????????
* @param exps ?????ֶα???ʽ????
* @param names ??????ֶ???????
* @param type ???????ͣ?0??join??1??left join??2??full join
* @param ctx Context ??????????
* @return Table ???????
*/
public static Table mixJoin(Sequence[] srcs, Expression[][] exps,
String[] names, int type, Context ctx) {
int tcount = srcs.length;
int expCount = exps[0].length;
Expression []prevExps = exps[1];
int prevLen = prevExps.length;
IntArrayList seqList = new IntArrayList(expCount);
for (int i = 0; i < prevLen; ++i) {
if (prevExps[i] != null) {
seqList.addInt(i);
}
}
// ?ҳ?ǰ??????ֶ?????ͬ?ı?
int next = 2;
for (; next < tcount; ++next) {
Expression []tmp = exps[next];
if (tmp.length != prevLen) {
break;
}
for (int i = 0; i < tmp.length; ++i) {
if ((tmp[i] == null && prevExps[i] != null) || (tmp[i] != null && prevExps[i] == null)) {
break;
}
}
}
Sequence []tmpSeqs = new Sequence[next];
Expression[][] tmpExps = new Expression[next][];
String[] tmpNames = new String[next];
for (int i = 0; i < next; ++i) {
Expression []curExps = new Expression[prevLen];
tmpSeqs[i] = srcs[i];
tmpExps[i] = curExps;
tmpNames[i] = names[i];
Expression []srcExps = exps[i];
for (int j = 0; j < prevLen; ++j) {
curExps[j] = srcExps[seqList.getInt(j)];
}
}
// ?Թ????ֶ???ͬ?ı?????ϣ????
Table prevResult = hashJoin(tmpSeqs, tmpExps, tmpNames, type, ctx);
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil();
ComputeStack stack = ctx.getComputeStack();
for (; next < tcount; ++next) {
// ?ҳ???ǰ?????һ?????Ĺ????ֶ?
prevExps = exps[next];
prevLen = prevExps.length;
seqList.clear();;
for (int i = 0; i < prevLen; ++i) {
if (prevExps[i] != null) {
seqList.addInt(i);
}
}
int keyCount = seqList.size();
Expression []exps1 = new Expression[keyCount];
Expression []exps2 = new Expression[keyCount];
for (int j = 0; j < prevLen; ++j) {
exps1[j] = exps[0][seqList.getInt(j)];
exps2[j] = exps[next][seqList.getInt(j)];
}
int count = keyCount + 1;
ListBase1 [][]hashGroups = new ListBase1[hashUtil.getCapacity()][];
Sequence value = prevResult.fieldValues(0);
Current current = new Current(value);
stack.push(current);
try {
// ?Ե?һ????????ϣ????
for (int i = 1, len = value.length(); i <= len; ++i) {
Object []keys = new Object[count];
keys[keyCount] = prevResult.getMem(i);
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = exps1[k].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
ListBase1 []groups = hashGroups[hash];
if (groups == null) {
groups = new ListBase1[2];
hashGroups[hash] = groups;
}
if (groups[0] == null) {
groups[0] = new ListBase1(INIT_GROUPSIZE);
groups[0].add(keys);
} else {
int index = HashUtil.bsearch_a(groups[0], keys, keyCount);
if (index < 1) {
groups[0].add(-index, keys);
} else {
groups[0].add(index + 1, keys);
}
}
}
} finally {
stack.pop();
}
value = srcs[next];
current = new Current(value);
stack.push(current);
try {
// ?Ե?ǰ??????ϣ????
for (int i = 1, len = value.length(); i <= len; ++i) {
Object []keys = new Object[count];
keys[keyCount] = value.getMem(i);
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = exps2[k].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
ListBase1 []groups = hashGroups[hash];
if (groups == null) {
groups = new ListBase1[2];
hashGroups[hash] = groups;
}
if (groups[1] == null) {
groups[1] = new ListBase1(INIT_GROUPSIZE);
groups[1].add(keys);
} else {
int index = HashUtil.bsearch_a(groups[1], keys, keyCount);
if (index < 1) {
groups[1].add(-index, keys);
} else {
groups[1].add(index + 1, keys);
}
}
}
} finally {
stack.pop();
}
// ??ÿ????ϣ????????鲢????
Table out = new Table(new String[2]);
for (int i = 0, len = hashGroups.length; i < len; ++i) {
if (hashGroups[i] != null) {
join_m(hashGroups[i], keyCount, type, out);
hashGroups[i] = null;
}
}
// չ?????????
String []curNames = new String[next + 1];
System.arraycopy(names, 0, curNames, 0, next + 1);
int len = out.length();
prevResult = new Table(curNames, len);
for (int i = 1; i <= len; ++i) {
BaseRecord r = (BaseRecord)out.getMem(i);
BaseRecord nr = prevResult.newLast();
nr.set((BaseRecord)r.getNormalFieldValue(0));
nr.setNormalFieldValue(next, r.getNormalFieldValue(1));
}
}
return prevResult;
}
/**
* ???Ե?һ???????????ӹ???
* @param srcs ????????
* @param exps ????????ʽ????
* @param opt ѡ?m???????ù鲢???????ӣ?i????????????1???ܹ????ϵļ?¼??d????????????1?й??????ϵļ?¼
* @param ctx ??????????
* @return Sequence ????1???˺?ļ?¼??ɵ?????
*/
public static Sequence filterJoin(Sequence[] srcs, Expression[][] exps, String opt, Context ctx) {
if (opt.indexOf('m') != -1) {
int count = srcs.length;
ICursor []cursors = new ICursor[count];
for (int i = 0; i < count; ++i) {
cursors[i] = new MemoryCursor(srcs[i]);
}
MergeFilterCursor cs = new MergeFilterCursor(cursors, exps, opt, ctx);
return cs.fetch();
}
ComputeStack stack = ctx.getComputeStack();
Expression []exps0 = exps[0];
Sequence seq = srcs[0];
for (int s = 1; s < srcs.length; ++s) {
if (seq == null || seq.length() == 0) {
return new Sequence();
}
// ?ҳ?????????ʽ??????null
ArrayList expList0 = new ArrayList();
ArrayList expList = new ArrayList();
Expression []curExps = exps[s];
for (int i = 0; i < curExps.length; ++i) {
if (curExps[i] != null) {
expList0.add(exps0[i]);
expList.add(curExps[i]);
}
}
int keyCount = expList0.size();
Expression []curExps0 = new Expression[keyCount];
curExps = new Expression[keyCount];
expList0.toArray(curExps0);
expList.toArray(curExps);
Sequence result = new Sequence(seq.length());
// ???ݵ?ǰѭ???ı????????ʽ??ֵ?????ɹ?ϣ????
Sequence curSeq = srcs[s];
Current current = new Current(curSeq);
stack.push(current);
int len = curSeq.length();
HashArraySet set = new HashArraySet(len);
try {
for (int i = 1; i <= len; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = curExps[k].calculate(ctx);
}
set.put(keys);
}
} finally {
stack.pop();
}
// ѭ????һ?????е?ǰ??Ĺ?ϣ??????ƥ??
len = seq.length();
Object []keys = new Object[keyCount];
current = new Current(seq);
stack.push(current);
try {
if (opt.indexOf('i') != -1) {
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = curExps0[k].calculate(ctx);
}
if (set.contains(keys)) {
result.add(seq.getMem(i));
}
}
} else {
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
for (int k = 0; k < keyCount; ++k) {
keys[k] = curExps0[k].calculate(ctx);
}
if (!set.contains(keys)) {
result.add(seq.getMem(i));
}
}
}
} finally {
stack.pop();
}
seq = result;
}
return seq;
}
/**
* ?α?Թ????ֶ???????????鲢????
* @param cursors ?α?????
* @param names ??????ֶ???????
* @param exps ?????ֶα???ʽ????
* @param opt ѡ??
* @param ctx Context ??????????
* @return ICursor ??????α?
*/
public static ICursor joinx(ICursor []cursors, String []names, Expression [][]exps, String opt, Context ctx) {
boolean isPJoin = false, isIsect = false, isDiff = false;
if (opt != null) {
if (opt.indexOf('p') != -1) {
isPJoin = true;
} else if (opt.indexOf('i') != -1) {
isIsect = true;
} else if (opt.indexOf('d') != -1) {
isDiff = true;
}
}
int count = cursors.length;
boolean isCluster = true; // ?Ƿ??м?Ⱥ?α?
boolean isMultipath = false; // ?Ƿ??Ƕ?·?α?????
int pathCount = 1;
for (int i = 0; i < count; ++i) {
if (cursors[i] instanceof IMultipath) {
if (i == 0) {
isMultipath = true;
pathCount = ((IMultipath)cursors[i]).getPathCount();
} else if (pathCount != ((IMultipath)cursors[i]).getPathCount()) {
isMultipath = false;
}
} else {
isMultipath = false;
}
if (!(cursors[i] instanceof ClusterCursor)) {
isCluster = false;
}
}
if (isCluster) {
ClusterCursor []tmp = new ClusterCursor[count];
System.arraycopy(cursors, 0, tmp, 0, count);
return ClusterCursor.joinx(tmp, exps, names, opt, ctx);
} else if (isMultipath && pathCount > 1) {
// ??·?α????ͬ???ֶΣ?ֻҪÿ????????Ӧ·?????Ӽ???
ICursor []result = new ICursor[pathCount];
ICursor [][]multiCursors = new ICursor[count][];
for (int i = 0; i < count; ++i) {
IMultipath multipath = (IMultipath)cursors[i];
multiCursors[i] = multipath.getParallelCursors();
}
for (int i = 0; i < pathCount; ++i) {
if (isPJoin) {
ICursor []curs = new ICursor[count];
for (int c = 0; c < count; ++c) {
curs[c] = multiCursors[c][i];
}
result[i] = new PJoinCursor(curs, names);
} else if (isIsect || isDiff) {
ICursor []curs = new ICursor[count];
for (int c = 0; c < count; ++c) {
curs[c] = multiCursors[c][i];
}
Context tmpCtx = ctx.newComputeContext();
Expression [][]tmpExps = Operation.dupExpressions(exps, tmpCtx);
result[i] = new MergeFilterCursor(curs, tmpExps, opt, tmpCtx);
} else {
if (count == 2 && exps[0].length == 1) {
Context tmpCtx = ctx.newComputeContext();
Expression exp1 = Operation.dupExpression(exps[0][0], tmpCtx);
Expression exp2 = Operation.dupExpression(exps[1][0], tmpCtx);
result[i] = new JoinxCursor2(multiCursors[0][i], exp1, multiCursors[1][i], exp2, names, opt, tmpCtx);
} else {
ICursor []curs = new ICursor[count];
for (int c = 0; c < count; ++c) {
curs[c] = multiCursors[c][i];
}
Context tmpCtx = ctx.newComputeContext();
Expression [][]tmpExps = Operation.dupExpressions(exps, tmpCtx);
result[i] = new JoinxCursor(curs, tmpExps, names, opt, tmpCtx);
}
}
}
// ÿһ·?Ĺ??????????ɶ?·?α?
return new MultipathCursors(result, ctx);
} else if (isPJoin) {
return new PJoinCursor(cursors, names);
} else if (isIsect || isDiff) {
return new MergeFilterCursor(cursors, exps, opt, ctx);
} else {
if (count == 2 && exps[0].length == 1) {
// ?Թ????ֶθ???Ϊ1?????????????Ż?
return new JoinxCursor2(cursors[0], exps[0][0], cursors[1], exps[1][0], names, opt, ctx);
} else {
return new JoinxCursor(cursors, exps, names, opt, ctx);
}
}
}
public static Sequence joinx(Sequence seq, Expression [][]fields, Object []fileTable,
Expression[][] keys, Expression[][] exps, String[][] expNames, String fname, Context ctx, String option) {
if (seq.length() == 0) {
return null;
}
boolean hasC = option != null && option.indexOf('c') != -1;
boolean hasNewExps = false;
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(seq);
//????????ÿ??f/T
int len = seq.length();
int fileCount = fileTable.length;
Sequence []seqs = new Sequence[fileCount];
for (int i = 0; i < fileCount; i++) {
if (exps[i] != null && exps[i].length > 0) {
hasNewExps = true;
}
Expression []curExps = fields[i];
if (fileTable[i] != null) {
int pkCount = curExps.length;
Object fileOrTable = fileTable[i];
ColPhyTable table = null;
BFileReader reader = null;
Sequence pkSeq = new Sequence();
String [] refFields = null;
if (fileOrTable instanceof ColPhyTable) {
table = (ColPhyTable) fileOrTable;
int fcount = keys[i].length;
ArrayList fieldList = new ArrayList(fcount);
for (int j = 0; j < fcount; j++) {
fieldList.add(keys[i][j].toString());
}
for (Expression exp : exps[i]) {
exp.getUsedFields(ctx, fieldList);
}
refFields = new String[fieldList.size()];
fieldList.toArray(refFields);
} else if (fileOrTable instanceof FileObject) {
reader = new BFileReader((FileObject) fileOrTable);
}
//???Ҫ???ӵı???ʽֵ
stack.push(current);
try {
for (int j = 1; j <= len; ++j) {
current.setCurrent(j);
Sequence temp = new Sequence();
if (pkCount > 1) {
for (int f = 0; f < pkCount; ++f) {
temp.add(curExps[f].calculate(ctx));
}
} else {
temp.add(curExps[0].calculate(ctx));
}
pkSeq.add(temp);
}
} finally {
stack.pop();
}
//??f/T???ö?Ӧֵ
Sequence valueSeq = null;
if (hasC && i == 0) {}
else pkSeq.sort("o");
try {
if (table != null) {
valueSeq = table.finds(pkSeq, refFields);
} else if (fileOrTable instanceof FileObject) {
refFields = new String[pkCount];
for (int j = 0; j < pkCount; j++) {
refFields[j] = keys[i][j].toString();
}
reader.open();
valueSeq = reader.iselectFields(refFields, pkSeq, null, ctx).fetch();
reader.close();
}
} catch (IOException e) {
throw new RQException(e);
}
seqs[i] = valueSeq;
}
}
boolean isIsect = false, isDiff = false;
if (!hasNewExps && option != null) {
if (option.indexOf('i') != -1) {
isIsect = true;
} else if (option.indexOf('d') != -1) {
isDiff = true;
}
}
Operation op;
if (isIsect) {
op = new FilterJoin(null, fields, seqs, keys, option);
} else if (isDiff) {
op = new DiffJoin(null, fields, seqs, keys, option);
} else {
op = new Join(null, fname, fields, seqs, keys, exps, expNames, option);
}
return op.process(seq, ctx);
}
/**
* ??????????ϣ????
* @param data ???
* @param fkName ????ֶ???
* @param code ά??
* @param exp ά??????????ʽ
* @param opt ѡ??
* @param ctx ??????????
*/
public static void hashSwitch(Sequence data, String fkName, Sequence code,
Expression exp, String opt, Context ctx) {
if (data.length() == 0) {
return;
}
boolean isIsect = false, isDiff = false, isLeft = false;
if (opt != null) {
if (opt.indexOf('i') != -1) {
// ??????
isIsect = true;
} else if (opt.indexOf('d') != -1) {
// ????
isDiff = true;
} else if (opt.indexOf('1') != -1) {
// ?????ӣ??Ҳ???F??Ӧֵʱ???????????ݽṹ???ɿ?ֵ?????????⣩??¼??Ӧ
isLeft = true;
}
}
int col = -1; // ?ֶ?????һ????¼??????
BaseRecord prevRecord = null; // ??һ????¼
if (exp == null || !(exp.getHome() instanceof CurrentSeq)) { // #
IndexTable indexTable = code.getIndexTable(exp, ctx);
if (indexTable == null) {
indexTable = code.newIndexTable(exp, ctx);
}
if (isDiff) {
for (int i = 1, len = data.length(); i <= len; ++i) {
Object obj = data.getMem(i);
if (obj instanceof BaseRecord) {
BaseRecord cur = (BaseRecord)obj;
if (prevRecord == null || !prevRecord.isSameDataStruct(cur)) {
col = cur.getFieldIndex(fkName);
if (col < 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(fkName + mm.getMessage("ds.fieldNotExist"));
}
prevRecord = cur;
}
// ?Ҳ???ʱ????Դֵ
Object key = cur.getNormalFieldValue(col);
if (indexTable.find(key) != null) {
cur.setNormalFieldValue(col, null);
}
} else if (obj != null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPmt"));
}
}
} else if (isLeft) {
DataStruct codeDs = code.dataStruct();
if (codeDs == null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPurePmt"));
}
int keySeq = -1;
if (exp != null) {
keySeq = codeDs.getFieldIndex(exp.getIdentifierName());
}
if (keySeq == -1) {
int []pks = codeDs.getPKIndex();
if (pks != null && pks.length == 1) {
keySeq = pks[0];
}
}
if (keySeq == -1) {
keySeq = 0;
}
for (int i = 1, len = data.length(); i <= len; ++i) {
Object obj = data.getMem(i);
if (obj instanceof BaseRecord) {
BaseRecord cur = (BaseRecord)obj;
if (prevRecord == null || !prevRecord.isSameDataStruct(cur)) {
col = cur.getFieldIndex(fkName);
if (col < 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(fkName + mm.getMessage("ds.fieldNotExist"));
}
prevRecord = cur;
}
Object key = cur.getNormalFieldValue(col);
Object p = indexTable.find(key);
if (p != null) {
cur.setNormalFieldValue(col, p);
} else {
Record record = new Record(codeDs);
record.setNormalFieldValue(keySeq, key);
cur.setNormalFieldValue(col, record);
}
} else if (obj != null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPmt"));
}
}
} else {
for (int i = 1, len = data.length(); i <= len; ++i) {
Object obj = data.getMem(i);
if (obj instanceof BaseRecord) {
BaseRecord cur = (BaseRecord)obj;
if (prevRecord == null || !prevRecord.isSameDataStruct(cur)) {
col = cur.getFieldIndex(fkName);
if (col < 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(fkName + mm.getMessage("ds.fieldNotExist"));
}
prevRecord = cur;
}
Object key = cur.getNormalFieldValue(col);
Object p = indexTable.find(key);
cur.setNormalFieldValue(col, p);
} else if (obj != null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPmt"));
}
}
}
} else {
// ???ά????????????ʽ??#????ô?????ֵʵ???϶?Ӧά????¼????ţ?ֱ???????ȡ??ά???ļ?¼
int codeLen = code.length();
for (int i = 1, len = data.length(); i <= len; ++i) {
Object obj = data.getMem(i);
if (obj instanceof BaseRecord) {
BaseRecord cur = (BaseRecord)obj;
if (prevRecord == null || !prevRecord.isSameDataStruct(cur)) {
col = cur.getFieldIndex(fkName);
if (col < 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(fkName + mm.getMessage("ds.fieldNotExist"));
}
prevRecord = cur;
}
Object val = cur.getNormalFieldValue(col);
if (val instanceof Number) {
int seq = ((Number)val).intValue();
if (isDiff) {
// ?Ҳ???ʱ????Դֵ
if (seq > 0 && seq <= codeLen) {
cur.setNormalFieldValue(col, null);
}
} else {
if (seq > 0 && seq <= codeLen) {
cur.setNormalFieldValue(col, code.getMem(seq));
} else {
cur.setNormalFieldValue(col, null);
}
}
}
} else if (obj != null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPmt"));
}
}
}
if (isIsect || isDiff) {
data.deleteNullFieldRecord(fkName);
}
}
/**
* ???ڴ?????????????ܴ??ȡ???????????????ʱȷ??ÿ??ȡ???ټ?¼
* @param cursor ?α?
* @return ????
*/
public static Sequence tryFetch(ICursor cursor) {
Runtime rt = Runtime.getRuntime();
EnvUtil.runGC(rt);
long usedMemory = rt.totalMemory() - rt.freeMemory();
final int baseCount = ICursor.INITSIZE;
Sequence seq = cursor.fetch(baseCount);
if (seq == null || seq.length() == 0) {
return null;
}
usedMemory = rt.totalMemory() - rt.freeMemory() - usedMemory;
int fcount = 1;
Object obj = seq.get(1);
if (obj instanceof BaseRecord) {
fcount = ((BaseRecord)obj).getFieldCount();
}
obj = null;
long size = seq.length() * fcount * 48; // ???㵱ǰ????ռ?õ??ڴ??С
if (size < usedMemory) {
size = usedMemory;
}
while (EnvUtil.memoryTest(rt, seq, size)) {
Sequence seq2 = cursor.fetch(baseCount);
if (seq2 == null || seq2.length() == 0) {
break;
} else {
seq.getMems().addAll(seq2.getMems());
}
}
return seq;
}
/**
* ???α???????????
* @param cursor ?α?
* @param exps ?????ֶα???ʽ????
* @param ctx ??????????
* @param capacity ?ڴ????ܹ?????ļ?¼???????û?????????Զ?????һ??
* @param opt ѡ?? 0??null?????
* @return ?ź?????α?
*/
public static ICursor sortx(ICursor cursor, Expression[] exps, Context ctx, int capacity, String opt) {
int fcount = exps.length;
ArrayList cursorList = new ArrayList();
Sequence table;
if (capacity <= 1) {
// ?????ܵĶ?ȡ???ݣ????????Լ?????ʱ?ļ???????
// ֮??ÿ??ȡ?????????????????
table = tryFetch(cursor);
if (table != null) {
capacity = table.length();
}
} else {
table = cursor.fetch(capacity);
}
MessageManager mm = EngineMessage.get();
String msg = mm.getMessage("engine.createTmpFile");
Expression[] tempExps = exps.clone();
while (table != null && table.length() > 0) {
// ?ֶα???ʽ??????ʱΪ???????Ż??ᱣ????¼??ָ??
// Ϊ?????´?ȡ??ǰ?ܹ??ͷ?ǰһ?ε????ݣ??ȸ????±???ʽ???ź???????ͷű???ʽ
for (int i = 0, len = tempExps.length; i < len; i++) {
tempExps[i] = exps[i].newExpression(ctx);
}
Sequence sequence;
if (fcount == 1) {
sequence = table.sort(tempExps[0], null, opt, ctx);
} else {
sequence = table.sort(tempExps, null, opt, ctx);
}
// ?Ƿ?Դ???ͱ???ʽ
table = null;
for (int i = 0, len = tempExps.length; i < len; i++) {
tempExps[i] = null;
}
// ??????ʱ?ļ?
FileObject fo = FileObject.createTempFileObject();
Logger.info(msg + fo.getFileName());
// ???ź????????д????ʱ???ļ?
fo.exportSeries(sequence, "b", null);
sequence = null;
BFileCursor bfc = new BFileCursor(fo, null, "x", ctx);
cursorList.add(bfc);
// ????ȡ????
table = cursor.fetch(capacity);
}
int size = cursorList.size();
if (size == 0) {
//return null;
return new MemoryCursor(null);
} else if (size == 1) {
return (ICursor)cursorList.get(0);
} else {
// ????ʱ?ļ????鲢
int bufSize = Env.getMergeFileBufSize(size);
for (int i = 0; i < size; ++i) {
BFileCursor bfc = (BFileCursor)cursorList.get(i);
bfc.setFileBufferSize(bufSize);
}
ICursor []cursors = new ICursor[size];
cursorList.toArray(cursors);
return merge(cursors, exps, opt, ctx);
/*if (opt == null || opt.indexOf('0') == -1) {
return new MergesCursor(cursors, exps, ctx);
} else {
return new MergesCursor(cursors, exps, "0", ctx);
}*/
}
}
/**
* ????????????ֶ?ֵ??ͬ?ļ?¼??ֵ??ͬ??ͬ??
* ??ֵ??ͬ?ļ?¼???浽һ????ʱ?ļ???Ȼ??ÿ????ʱ?ļ?????????
* @param cursor ?α?
* @param exps ???????ʽ
* @param gexp ?????ʽ
* @param ctx ??????????
* @param opt ѡ??
* @return
*/
public static ICursor sortx(ICursor cursor, Expression[] exps, Expression gexp, Context ctx, String opt) {
final int fetchCount = ICursor.getInitSize();
Sequence seq = cursor.fetch(fetchCount);
if (seq == null || seq.length() == 0) {
return null;
}
DataStruct ds = seq.dataStruct();
if (ds == null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPurePmt"));
}
// ??ֵ?????ļ?ӳ?????ÿһ????ֵ??Ӧһ?????ļ?
TreeMap map = new TreeMap();
MessageManager mm = EngineMessage.get();
String msg = mm.getMessage("engine.createTmpFile");
try {
while (true) {
// ?????а??????ʽ????
Sequence groups = seq.group(gexp, null, ctx);
int gcount = groups.length();
for (int i = 1; i <= gcount; ++i) {
Sequence group = (Sequence)groups.getMem(i);
Object gval = group.calc(1, gexp, ctx);
// ????ֵ?ҵ???Ӧ?ļ??ļ???д??
BFileWriter writer = map.get(gval);
if (writer == null) {
FileObject fo = FileObject.createTempFileObject();
Logger.info(msg + fo.getFileName());
writer = new BFileWriter(fo, null);
writer.prepareWrite(ds, false);
map.put(gval, writer);
}
writer.write(group);
}
// ?ͷ????ã????????Ա?????????
seq = null;
groups = null;
seq = cursor.fetch(fetchCount);
if (seq == null || seq.length() == 0) {
break;
}
}
} catch (IOException e) {
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
writer.getFile().delete();
}
throw new RQException(e);
}
int size = map.size();
FileObject []files = new FileObject[size];
int index = 0;
Collection writers = map.values();
Iterator itr = writers.iterator();
// д??ɣ??رռ??ļ?
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
files[index++] = writer.getFile();
}
return new SortxCursor(files, exps, ds, ctx);
}
/**
* ?ù?ϣ?????????????еIJ
* @param seq1 ????
* @param seq2 ????
* @return ?????
*/
public static Sequence diff(Sequence seq1, Sequence seq2) {
int len2 = seq2.length();
// ??????2???ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len2 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
for (int i = 1; i <= len2; ++i) {
Object val = seq2.getMem(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(val);
} else {
int index = groups[hash].binarySearch(val);
if (index < 1) {
groups[hash].add(-index, val);
} else {
groups[hash].add(index, val);
}
}
}
int len1 = seq1.length();
Sequence result = new Sequence(len1);
// ????????1??Ԫ?أ?Ȼ????ݹ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len1; ++i) {
Object val = seq1.getMem(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] == null) {
result.add(val);
} else {
int index = groups[hash].binarySearch(val);
if (index < 1) {
result.add(val);
} else {
groups[hash].remove(index);
}
}
}
return result;
}
/**
* ?ù?ϣ?????????????ж?ָ??????ʽ?IJ
* @param seq1 ????
* @param seq2 ????
* @param exps ????ʽ????
* @param ctx ??????????
* @return ?????
*/
public static Sequence diff(Sequence seq1, Sequence seq2, Expression []exps, Context ctx) {
if (exps == null) {
return diff(seq1, seq2);
}
int keyCount = exps.length;
int len2 = seq2.length();
// ??????2??ָ??????ʽ?ļ????????ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len2 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(seq2);
stack.push(current);
try {
for (int i = 1; i <= len2; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(keys);
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
groups[hash].add(-index, keys);
} else {
groups[hash].add(index, keys);
}
}
}
} finally {
stack.pop();
}
int len1 = seq1.length();
Sequence result = new Sequence(len1);
current = new Current(seq1);
stack.push(current);
try {
// ????????1??Ȼ????ݱ???ʽ???????Ĺ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len1; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
result.add(seq1.getMem(i));
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
result.add(seq1.getMem(i));
} else {
groups[hash].remove(index);
}
}
}
} finally {
stack.pop();
}
return result;
}
/**
* ?ù?ϣ?????????????еIJ???
* @param seq1 ????
* @param seq2 ????
* @return ????????
*/
public static Sequence union(Sequence seq1, Sequence seq2) {
IArray mems1 = seq1.getMems();
int len1 = mems1.size();
// ??????2???ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len1 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
for (int i = 1; i <= len1; ++i) {
Object val = mems1.get(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(val);
} else {
int index = groups[hash].binarySearch(val);
if (index < 1) {
groups[hash].add(-index, val);
} else {
groups[hash].add(index, val);
}
}
}
IArray mems2 = seq2.getMems();
int len2 = mems2.size();
Sequence result = new Sequence(len1 + len2);
result.addAll(seq1);
// ????????1??Ԫ?أ?Ȼ????ݹ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len2; ++i) {
Object val = mems2.get(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] == null) {
result.add(val);
} else {
int index = groups[hash].binarySearch(val);
if (index < 1) {
result.add(val);
} else {
groups[hash].remove(index);
}
}
}
return result;
}
/**
* ?ù?ϣ?????????????ж?ָ??????ʽ?IJ???
* @param seq1 ????
* @param seq2 ????
* @param exps ????ʽ????
* @param ctx ??????????
* @return ????????
*/
public static Sequence union(Sequence seq1, Sequence seq2, Expression []exps, Context ctx) {
if (exps == null) {
return union(seq1, seq2);
}
int keyCount = exps.length;
IArray mems1 = seq1.getMems();
int len1 = mems1.size();
// ??????2??ָ??????ʽ?ļ????????ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len1 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(seq1);
stack.push(current);
try {
for (int i = 1; i <= len1; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(keys);
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
groups[hash].add(-index, keys);
} else {
groups[hash].add(index, keys);
}
}
}
} finally {
stack.pop();
}
IArray mems2 = seq2.getMems();
int len2 = mems2.size();
Sequence result = new Sequence(len1 + len2);
result.addAll(seq1);
current = new Current(seq2);
stack.push(current);
try {
// ????????1??Ȼ????ݱ???ʽ???????Ĺ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len2; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
result.add(mems2.get(i));
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
result.add(mems2.get(i));
} else {
groups[hash].remove(index);
}
}
}
} finally {
stack.pop();
}
return result;
}
/**
* ?ù?ϣ?????????????еĽ???
* @param seq1 ????
* @param seq2 ????
* @return ????????
*/
public static Sequence isect(Sequence seq1, Sequence seq2) {
IArray mems1 = seq1.getMems();
int len1 = mems1.size();
IArray mems2 = seq2.getMems();
int len2 = mems2.size();
if (len1 < 12 && len2 < 12) {
Sequence result = new Sequence(len1);
for (int i = 1; i <= len1; ++i) {
Object v1 = mems1.get(i);
for (int j = 1; j <= len2; ++j) {
if (Variant.isEquals(v1, mems2.get(j))) {
result.add(v1);
break;
}
}
}
return result;
}
// ??????2???ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len2 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
for (int i = 1; i <= len2; ++i) {
Object val = mems2.get(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(val);
} else {
int index = groups[hash].binarySearch(val);
if (index < 1) {
groups[hash].add(-index, val);
} else {
groups[hash].add(index, val);
}
}
}
Sequence result = new Sequence(len1);
// ????????1??Ԫ?أ?Ȼ????ݹ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len1; ++i) {
Object val = mems1.get(i);
int hash = hashUtil.hashCode(val);
if (groups[hash] != null) {
int index = groups[hash].binarySearch(val);
if (index > 0) {
result.add(val);
groups[hash].remove(index);
}
}
}
return result;
}
/**
* ?ù?ϣ?????????????ж?ָ??????ʽ?Ľ???
* @param seq1 ????
* @param seq2 ????
* @param exps ????ʽ????
* @param ctx ??????????
* @return ????????
*/
public static Sequence isect(Sequence seq1, Sequence seq2, Expression []exps, Context ctx) {
if (exps == null) {
return isect(seq1, seq2);
}
int keyCount = exps.length;
IArray mems2 = seq2.getMems();
int len2 = mems2.size();
// ??????2??ָ??????ʽ?ļ????????ɹ?ϣ??
final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
HashUtil hashUtil = new HashUtil((int)(len2 * 1.2));
ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(seq2);
stack.push(current);
try {
for (int i = 1; i <= len2; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] == null) {
groups[hash] = new ListBase1(INIT_GROUPSIZE);
groups[hash].add(keys);
} else {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index < 1) {
groups[hash].add(-index, keys);
} else {
groups[hash].add(index, keys);
}
}
}
} finally {
stack.pop();
}
IArray mems1 = seq1.getMems();
int len1 = mems1.size();
Sequence result = new Sequence(len1);
current = new Current(seq1);
stack.push(current);
try {
// ????????1??Ȼ????ݱ???ʽ???????Ĺ?ϣֵ??????2?Ĺ?ϣ???в????Ƿ?????ͬ??Ԫ??
for (int i = 1; i <= len1; ++i) {
Object []keys = new Object[keyCount];
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = exps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
if (groups[hash] != null) {
int index = HashUtil.bsearch_a(groups[hash], keys, keyCount);
if (index > 0) {
result.add(mems1.get(i));
groups[hash].remove(index);
}
}
}
} finally {
stack.pop();
}
return result;
}
/**
* ȡcount??ʹexp????ֵ??С??Ԫ?ص?getExp????ֵ
* @param cursor ?α?
* @param count ????
* @param exp ?Ƚϱ???ʽ
* @param getExp ????ֵ????ʽ
* @param ctx ??????????
* @return Object
*/
public static Object top(ICursor cursor, int count, Expression exp, Expression getExp, Context ctx) {
// ʹ?ö?ȡǰ????
ArrayComparator comparator = new ArrayComparator(1);
MinHeap heap = new MinHeap(count, comparator);
while (true) {
Sequence src = cursor.fuzzyFetch(ICursor.FETCHCOUNT);
if (src == null || src.length() == 0) {
break;
}
src = src.calc(getExp, ctx);
if (src.getMem(1) instanceof Sequence) {
src = src.conj(null);
}
// ?????????ֶ?ֵ???????ӵ?С??????
Sequence v = src.calc(exp, ctx);
for (int i = 1, len = src.length(); i <= len; ++i) {
Object []vals = new Object[2];
vals[0] = v.getMem(i);
vals[1] = src.getMem(i);
heap.insert(vals);
}
}
// ?Խ??????????
Object []objs = heap.toArray();
Arrays.sort(objs, comparator);
int size = objs.length;
Sequence seq = new Sequence(size);
for (int i = 0; i < size; ++i) {
Object []tmp = (Object[])objs[i];
seq.add(tmp[1]);
}
return seq;
}
/**
* ???????????е????ֵ??????ͬ??Ԫ????ɵ?????
* @param seq1 ????
* @param seq2 ????
* @return ???????
*/
public static Sequence xor(Sequence seq1, Sequence seq2) {
Sequence s1 = diff(seq1, seq2);
Sequence s2 = diff(seq2, seq1);
s1.addAll(s2);
return s1;
}
/**
* ?Ȱ?gexp?????ݽ??з??飬ͬ??Ļ???һ??д??һ????ʱ?ļ???????ٶ?ÿ????ʱ?ļ????ж??λ???
* ?????ֶ???ͬ?ļ?¼gexpҲҪ??ͬ??gexp?Ƿ????ֶεĴ????
* @param cursor ?α?
* @param gexp ????????ʽ
* @param exps ???????ʽ????
* @param names ?????ֶ???????
* @param calcExps ???ܱ???ʽ????
* @param calcNames ?????ֶ???????
* @param opt ѡ??
* @param ctx ??????????
* @return ???????α?
*/
public static ICursor groupx_g(ICursor cursor, Expression gexp, Expression[] exps, String []names,
Expression[] calcExps, String []calcNames, String opt, Context ctx) {
if (cursor instanceof MultipathCursors) {
// ??·?α???ö??̷߳???
return groupx_g((MultipathCursors)cursor, gexp, exps, names, calcExps, calcNames, ctx);
}
final int fetchCount = ICursor.INITSIZE;
MessageManager mm = EngineMessage.get();
String msg = mm.getMessage("engine.createTmpFile");
TreeMap map = new TreeMap();
DataStruct ds = cursor.getDataStruct();
try {
// ?????α?????
while (true) {
Sequence seq = cursor.fetch(fetchCount);
if (seq == null || seq.length() == 0) {
break;
}
// ??????????ʽ?????ݽ??з???
Sequence groups = seq.group(gexp, null, ctx);
int gcount = groups.length();
for (int i = 1; i <= gcount; ++i) {
// ??ÿ???????????״λ???
Sequence group = (Sequence)groups.getMem(i);
IGroupsResult gresult = IGroupsResult.instance(exps, names, calcExps, calcNames, ds, null, ctx);
gresult.push(group, ctx);
Table result = gresult.getTempResult();
// ?ҵ???ǰ??????Ӧ????ʱ?ļ??????״λ??ܽ???ӵ???ʱ?ļ???
Object gval = group.calc(1, gexp, ctx);
BFileWriter writer = map.get(gval);
if (writer == null) {
FileObject fo = FileObject.createTempFileObject();
Logger.info(msg + fo.getFileName());
writer = new BFileWriter(fo, null);
writer.prepareWrite(gresult.getResultDataStruct(), false);
map.put(gval, writer);
}
writer.write(result);
}
}
} catch (IOException e) {
// ???쳣????ʱ?رղ?ɾ????ʱ?ļ?
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
writer.getFile().delete();
}
throw new RQException(e);
}
int size = map.size();
if (size == 0) {
return null;
}
// д??ɣ??رռ??ļ?
FileObject []files = new FileObject[size];
int index = 0;
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
files[index++] = writer.getFile();
}
// ????һ????ÿ????ʱ?ļ????з?????α?
return new GroupxnCursor(files, exps, names, calcExps, calcNames, ctx);
}
private static ICursor groupx_g(MultipathCursors mcs, Expression gexp, Expression[] exps, String []names,
Expression[] calcExps, String []calcNames, Context ctx) {
final int fetchCount = ICursor.INITSIZE;
ICursor []cursors = mcs.getParallelCursors();
int cursorCount = cursors.length;
TreeMap map = new TreeMap();
// ???ɷ????????ύ???̳߳?
ThreadPool pool = ThreadPool.newInstance(cursorCount);
Exception exception = null;
try {
GroupxJob []jobs = new GroupxJob[cursorCount];
for (int i = 0; i < cursorCount; ++i) {
Context tmpCtx = ctx.newComputeContext();
Expression tmpGroupExp = Operation.dupExpression(gexp, tmpCtx);
Expression []tmpExps = Operation.dupExpressions(exps, tmpCtx);
Expression []tmpCalcExps = Operation.dupExpressions(calcExps, tmpCtx);
jobs[i] = new GroupxJob(cursors[i], tmpGroupExp, tmpExps, names,
tmpCalcExps, calcNames, tmpCtx, fetchCount, map);
pool.submit(jobs[i]);
}
// ?ȴ?????????ִ?????
for (int i = 0; i < cursorCount; ++i) {
try {
jobs[i].join();
} catch (RuntimeException e) {
exception = e;
}
}
} finally {
pool.shutdown();
}
// ???쳣????ʱ?رղ?ɾ????ʱ?ļ?
if (exception != null) {
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
writer.getFile().delete();
}
if (exception instanceof RQException) {
throw (RQException)exception;
} else {
throw new RQException(exception);
}
}
int size = map.size();
if (size == 0) {
return null;
}
// д??ɣ??رռ??ļ?
FileObject []files = new FileObject[size];
int index = 0;
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
files[index++] = writer.getFile();
}
// ????һ????ÿ????ʱ?ļ????з?????α?
return new GroupxnCursor(files, exps, names, calcExps, calcNames, ctx);
}
/**
* ???еĵ?һ???ֶ?Ϊ????????#1 / capacity + 1?ֳ???????
* @param seq ????
* @param capacity ????
* @return ??????
*/
public static Sequence group_n(Sequence seq, int capacity) {
IArray mems = seq.getMems();
int size = mems.size();
Sequence result = new Sequence(size / 4); // ?????????
IArray resultMems = result.getMems();
int len = 0;
BaseRecord r;
Object value;
for (int i = 1; i <= size; ++i) {
r = (BaseRecord)mems.get(i);
value = r.getNormalFieldValue(0);
if (!(value instanceof Number)) {
MessageManager mm = EngineMessage.get();
throw new RQException("group: " + mm.getMessage("engine.needIntExp"));
}
int index = ((Number)value).intValue() / capacity + 1;
if (index > len) {
resultMems.ensureCapacity(index);
for (int j = len; j < index; ++j) {
resultMems.add(new Sequence(7));
}
len = index;
} else if (index < 1) {
MessageManager mm = EngineMessage.get();
throw new RQException(index + mm.getMessage("engine.indexOutofBound"));
}
Sequence group = (Sequence)resultMems.get(index);
group.add(r);
}
return result;
}
/**
* ?????ֶ?ֵΪ????ţ??ѷ????ֶΰ?capacity???й?ϣ????ϣֵ??ͬ??д??ͬһ????ʱ?ļ???????ٶ?ÿ????ʱ?ļ????ж??λ???
* @param cursor ?α?
* @param exps ???????ʽ????
* @param names ?????ֶ???????
* @param calcExps ???ܱ???ʽ????
* @param calcNames ?????ֶ???????
* @param ctx ??????????
* @param capacity ?ڴ??ܹ???ŵķ???????????
* @return ???????α?
*/
public static ICursor groupx_n(ICursor cursor, Expression[] exps, String []names,
Expression[] calcExps, String []calcNames, Context ctx, int capacity) {
if (cursor instanceof MultipathCursors) {
// ??·?α???ö??̷߳???
return groupx_n((MultipathCursors)cursor, exps, names, calcExps, calcNames, ctx, capacity);
}
final int fetchCount = ICursor.INITSIZE;
MessageManager mm = EngineMessage.get();
String msg = mm.getMessage("engine.createTmpFile");
TreeMap map = new TreeMap();
DataStruct ds = cursor.getDataStruct();
try {
// ?????α?????
while (true) {
Sequence seq = cursor.fetch(fetchCount);
if (seq == null || seq.length() == 0) {
break;
}
// ?Ե?ǰ???ݽ????״λ???
IGroupsResult gresult = IGroupsResult.instance(exps, names, calcExps, calcNames, ds, null, ctx);
gresult.push(seq, ctx);
seq = gresult.getTempResult();
// ???ÿ????ʱ?ļ?Ӧ?ô?ŵķ???
Sequence groups = group_n(seq, capacity);
int gcount = groups.length();
for (int i = 1; i <= gcount; ++i) {
Sequence group = (Sequence)groups.getMem(i);
if (group.length() == 0) {
continue;
}
// ???״η?????д????Ӧ????ʱ?ļ?
Integer gval = new Integer(i);
BFileWriter writer = map.get(gval);
if (writer == null) {
FileObject fo = FileObject.createTempFileObject();
Logger.info(msg + fo.getFileName());
writer = new BFileWriter(fo, null);
writer.prepareWrite(gresult.getResultDataStruct(), false);
map.put(gval, writer);
}
writer.write(group);
}
}
} catch (IOException e) {
// ???쳣????ʱ?رղ?ɾ????ʱ?ļ?
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
writer.getFile().delete();
}
throw new RQException(e);
}
int size = map.size();
if (size == 0) {
return null;
}
// д??ɣ??رռ??ļ?
FileObject []files = new FileObject[size];
int index = 0;
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
files[index++] = writer.getFile();
}
// ????һ????ÿ????ʱ?ļ????з?????α?
return new GroupxnCursor(files, exps, names, calcExps, calcNames, ctx);
}
private static ICursor groupx_n(MultipathCursors mcs, Expression[] exps, String []names,
Expression[] calcExps, String []calcNames, Context ctx, int capacity) {
ICursor []cursors = mcs.getParallelCursors();
int cursorCount = cursors.length;
TreeMap map = new TreeMap();
int fetchCount = capacity / cursorCount;
// ???ɷ????????ύ???̳߳?
ThreadPool pool = ThreadPool.newInstance(cursorCount);
Exception exception = null;
try {
GroupxJob []jobs = new GroupxJob[cursorCount];
for (int i = 0; i < cursorCount; ++i) {
Context tmpCtx = ctx.newComputeContext();
Expression []tmpExps = Operation.dupExpressions(exps, tmpCtx);
Expression []tmpCalcExps = Operation.dupExpressions(calcExps, tmpCtx);
jobs[i] = new GroupxJob(cursors[i], tmpExps, names,
tmpCalcExps, calcNames, tmpCtx, capacity, fetchCount, map);
pool.submit(jobs[i]);
}
// ?ȴ?????????ִ?????
for (int i = 0; i < cursorCount; ++i) {
try {
jobs[i].join();
} catch (RuntimeException e) {
exception = e;
}
}
} finally {
pool.shutdown();
}
// ???쳣????ʱ?رղ?ɾ????ʱ?ļ?
if (exception != null) {
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
writer.getFile().delete();
}
if (exception instanceof RQException) {
throw (RQException)exception;
} else {
throw new RQException(exception);
}
}
int size = map.size();
if (size == 0) {
return null;
}
// д??ɣ??رռ??ļ?
FileObject []files = new FileObject[size];
int index = 0;
Collection writers = map.values();
Iterator itr = writers.iterator();
while (itr.hasNext()) {
BFileWriter writer = itr.next();
writer.close();
files[index++] = writer.getFile();
}
// ????һ????ÿ????ʱ?ļ????з?????α?
return new GroupxnCursor(files, exps, names, calcExps, calcNames, ctx);
}
/**
* ȡ?α??Ӧ??????????ȡ?????ؿ?
* @param cs ?α?
* @return TableMetaData
*/
public static PhyTable getTableMetaData(ICursor cs) {
if (cs instanceof IDWCursor) {
return ((IDWCursor)cs).getTableMetaData();
} else if (cs instanceof MultipathCursors) {
MultipathCursors mcs = (MultipathCursors)cs;
ICursor []cursors = mcs.getCursors();
return getTableMetaData(cursors[0]);
} else if (cs instanceof MergeCursor2) {
MergeCursor2 mc = (MergeCursor2)cs;
return getTableMetaData(mc.getCursor1());
} else {
return null;
}
}
/**
* ???α갴ָ??????ʽ???鲢???????α?
* @param cursors ?α?????
* @param exps ????ʽ????
* @param opt ѡ?
* @param ctx
* @return
*/
public static ICursor merge(ICursor []cursors, Expression []exps, String opt, Context ctx) {
// ????????????㲢?ҹ鲢????ʽ???ֶεĻ??????Ż?
DataStruct ds = null;
if (opt == null || (opt.indexOf('u') == -1 && opt.indexOf('i') == -1 && opt.indexOf('d') == -1 && opt.indexOf('x') == -1)) {
ds = CursorUtil.getDataStruct(cursors[0]);
for (int i = 1, count = cursors.length; ds != null && i < count; ++i) {
if (!ds.isCompatible(CursorUtil.getDataStruct(cursors[i]))) {
ds = null;
break;
}
}
}
int []fields = null;
if (ds != null) {
if (exps == null) {
String []sortFields = cursors[0].getSortFields();
if (sortFields != null) {
int fcount = sortFields.length;
fields = new int[fcount];
for (int f = 0; f < fcount; ++f) {
fields[f] = ds.getFieldIndex(sortFields[f]);
}
} else {
int fcount = ds.getFieldCount();
fields = new int[fcount];
for (int f = 0; f < fcount; ++f) {
fields[f] = f;
}
}
} else {
int fcount = exps.length;
fields = new int[fcount];
for (int f = 0; f < fcount; ++f) {
fields[f] = exps[f].getFieldIndex(ds);
if (fields[f] < 0) {
fields = null;
break;
}
}
}
} else if (exps == null) {
Expression exp = new Expression("~.v()");
exps = new Expression[]{ exp };
}
if (fields != null) {
if (cursors.length == 2) {
return new MergeCursor2(cursors[0], cursors[1], fields, opt, ctx);
} else {
return new MergeCursor(cursors, fields, opt, ctx);
}
} else {
return new MergesCursor(cursors, exps, opt, ctx);
}
}
/**
* ??????ת???α?
* @param data ????
* @param pathCount ?α??·??
* @param opt p???ٶ??Ե?һ?ֶ????ֶ?ʱ???Ὣ??һ?ֶ???ͬ??¼?ֵ?????
* @param ctx
* @return ICursor
*/
public static ICursor cursor(Sequence data, int pathCount, String opt, Context ctx) {
int len = data.length();
boolean psign = opt != null && opt.indexOf('p') != -1;
if (pathCount > 1 && pathCount < len) {
if (ctx == null) {
ctx = new Context();
}
int blockSize = len / pathCount;
ICursor []cursors = new ICursor[pathCount];
int start = 1;
for (int i = 1; i <= pathCount; ++i) {
int end;
if (i == pathCount) {
end = len + 1;
} else {
end = blockSize * i + 1;
}
if (start >= end) {
cursors[i - 1] = data.cursor(start, start);
continue;
}
if (psign) {
// ?ֶ?ʱ???Ὣ??һ?ֶ???ͬ??¼?ֵ?????
BaseRecord record = (BaseRecord)data.get(end - 1);
Object value = record.getNormalFieldValue(0);
int next = end;
end = len + 1;
for (; next <= len; ++next) {
record = (BaseRecord)data.get(next);
if (!Variant.isEquals(record.getNormalFieldValue(0), value)) {
end = next;
break;
}
}
}
cursors[i - 1] = data.cursor(start, end);
start = end;
}
return new MultipathCursors(cursors, ctx);
} else {
return data.cursor();
}
}
/**
* ??????ת?ɶ?·?α꣬ȡ??ָ????·
* @param data ????
* @param path Ҫȡ??·
* @param pathCount ?α??·??
* @param opt p???ٶ??Ե?һ?ֶ????ֶ?ʱ???Ὣ??һ?ֶ???ͬ??¼?ֵ?????
* @param ctx
* @return ICursor
*/
public static ICursor cursor(Sequence data, int path, int pathCount, String opt, Context ctx) {
int len = data.length();
if (opt == null || opt.indexOf('p') == -1) {
int blockSize = len / pathCount;
int start;
int end;
if (path == pathCount) {
start = blockSize * (path - 1) + 1;
end = len + 1;
} else {
start = blockSize * (path - 1) + 1;
end = blockSize * path + 1;
}
return data.cursor(start, end);
}
ICursor cs = null;
if (pathCount > 1 && pathCount < len) {
if (ctx == null) {
ctx = new Context();
}
int blockSize = len / pathCount;
int start = 1;
for (int i = 1; i <= path; ++i) {
int end;
if (i == pathCount) {
end = len + 1;
} else {
end = blockSize * i + 1;
}
if (start >= end) {
cs = data.cursor(start, start);
break;
}
// ?ֶ?ʱ???Ὣ??һ?ֶ???ͬ??¼?ֵ?????
BaseRecord record = (BaseRecord)data.get(end - 1);
Object value = record.getNormalFieldValue(0);
int next = end;
end = len + 1;
for (; next <= len; ++next) {
record = (BaseRecord)data.get(next);
if (!Variant.isEquals(record.getNormalFieldValue(0), value)) {
end = next;
break;
}
}
cs = data.cursor(start, end);
start = end;
}
} else if (path == 1) {
cs = data.cursor();
} else {
cs = data.cursor(len + 1, len + 1);
}
return cs;
}
}