com.scudata.dm.HashPrimaryJoin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esproc Show documentation
Show all versions of esproc Show documentation
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.dm;
import java.util.ArrayList;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.expression.Expression;
import com.scudata.expression.Gather;
import com.scudata.resources.EngineMessage;
import com.scudata.util.HashUtil;
import com.scudata.util.Variant;
class HashPrimaryJoin {
private static class PrimaryJoinNode {
private Object []keyValues;
private Object [][]newValues; // ÿ??????ѡ???ֶ?
private PrimaryJoinNode next;
private boolean isMatch = false; // ?Ƿ??????ƥ?????ˣ?????full join
public PrimaryJoinNode(Object []keyValues, Object []curNewValues, int tableCount, int tableSeq, PrimaryJoinNode next) {
this.keyValues = keyValues;
this.newValues = new Object[tableCount][];
this.newValues[tableSeq] = curNewValues;
this.next = next;
}
}
private Sequence srcSequence;
private Expression []srcKeyExps;
private Expression []srcNewExps;
private String []srcNewNames;
private Sequence []sequences;
private String []options;
private Expression [][]keyExps;
private Expression [][]newExps;
private String [][]newNames;
private String opt;
private Context ctx;
private HashUtil hashUtil;
private PrimaryJoinNode []hashTable;
private int tableCount;
private int srcRefCount; // ??????????????????ֶ???
private DataStruct resultDs; // ????????ݽṹ
private int []newSeqs; // new?ֶ??ڽ???????ݽṹ?е????
private int []keySeqs; // ?????ֶ??ڽ???????ݽṹ?е????
public HashPrimaryJoin(Sequence srcSequence, Expression []srcKeyExps, Expression []srcNewExps, String []srcNewNames,
Sequence []sequences, String []options, Expression [][]keyExps,
Expression [][]newExps, String [][]newNames, String opt, Context ctx) {
this.srcSequence = srcSequence;
this.srcKeyExps = srcKeyExps;
this.srcNewExps = srcNewExps;
this.srcNewNames = srcNewNames;
this.sequences = sequences;
this.options = options;
this.keyExps = keyExps;
this.newExps = newExps;
this.newNames = newNames;
this.opt = opt;
this.ctx = ctx;
this.tableCount = sequences.length;
}
private void init() {
int keyCount = srcKeyExps.length;
keySeqs = new int[keyCount];
ArrayList fieldList = new ArrayList();
DataStruct srcDs = null;
if (srcNewExps == null || srcNewExps.length == 0) {
srcDs = srcSequence.dataStruct();
if (srcDs == null) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("engine.needPurePmt"));
}
String []names = srcDs.getFieldNames();
srcRefCount = names.length;
for (String name : names) {
fieldList.add(name);
}
for (int k = 0; k < keyCount; ++k) {
keySeqs[k] = srcKeyExps[k].getFieldIndex(srcDs);
}
} else {
int fcount = srcRefCount = srcNewExps.length;
String []oldFieldNames = new String[fcount];
for (int i = 0; i < fcount; ++i) {
oldFieldNames[i] = srcNewExps[i].getFieldName();
}
for (int k = 0; k < keyCount; ++k) {
keySeqs[k] = -1;
String keyName = srcKeyExps[k].getFieldName();
for (int i = 0; i < fcount; ++i) {
if (keyName.equals(oldFieldNames[i])) {
keySeqs[k] = i;
break;
}
}
}
for (int i = 0; i < fcount; ++i) {
if (srcNewNames != null && srcNewNames[i] != null) {
fieldList.add(srcNewNames[i]);
} else {
fieldList.add(oldFieldNames[i]);
}
}
}
newSeqs = new int[tableCount];
for (int t = 0; t < tableCount; ++t) {
//keyValues[t] = new Object[keyCount];
Expression []curNewExps = newExps[t];
newSeqs[t] = fieldList.size();
if (curNewExps != null) {
String []curNewNames = newNames[t];
int count = curNewExps.length;
for (int i = 0; i < count; ++i) {
if (curNewNames != null && curNewNames[i] != null) {
fieldList.add(curNewNames[i]);
} else {
fieldList.add(curNewExps[i].getFieldName());
}
}
}
}
int fcount = fieldList.size();
if (srcDs == null || srcDs.getFieldCount() != fcount) {
String []fnames = new String[fcount];
fieldList.toArray(fnames);
resultDs = new DataStruct(fnames);
} else {
resultDs = srcDs;
}
int capacity = srcSequence.length();
for (Sequence sequence : sequences) {
if (sequence != null && sequence.length() > capacity) {
capacity = sequence.length();
}
}
hashUtil = new HashUtil(capacity);
hashTable = new PrimaryJoinNode[hashUtil.getCapacity()];
for (int t = 0; t < tableCount; ++t) {
addTable(sequences[t], keyExps[t], newExps[t], t, ctx);
}
}
private void addTable(Sequence sequence, Expression []keyExps, Expression []newExps, int tableSeq, Context ctx) {
if (sequence == null || sequence.length() == 0) {
return;
}
HashUtil hashUtil = this.hashUtil;
PrimaryJoinNode []hashTable = this.hashTable;
int tableCount = this.tableCount;
int keyCount = keyExps.length;
if (newExps != null && newExps.length > 0) {
int newCount = newExps.length;
for (Expression exp : newExps) {
if (exp.getHome() instanceof Gather) {
// ????ǻ???????α긽???Ϸ??????????
sequence = sequence.groups(keyExps, null, newExps, null, null, ctx);
int q = 1;
keyExps = new Expression[keyCount];
for (int i = 0; i < keyCount; ++i, ++q) {
keyExps[i] = new Expression("#" + q);
}
newExps = new Expression[newCount];
for (int i = 0; i < newCount; ++i, ++q) {
newExps[i] = new Expression("#" + q);
}
break;
}
}
}
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(sequence);
stack.push(current);
try {
if (newExps == null || newExps.length == 0) {
int len = sequence.length();
Object []newValues = new Object[0];
Next:
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
Object []keys = new Object[keyCount];
for (int c = 0; c < keyCount; ++c) {
keys[c] = keyExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
if (entry.newValues[tableSeq] != null) {
MessageManager mm = EngineMessage.get();
String str = "[";
for (int k = 0; k < keyCount; ++k) {
if (k != 0) {
str += ",";
}
str += Variant.toString(keys[k]);
}
str += "]";
throw new RQException(str + mm.getMessage("engine.dupKeys"));
}
entry.newValues[tableSeq] = newValues;
continue Next;
}
}
hashTable[hash] = new PrimaryJoinNode(keys, newValues, tableCount, tableSeq, hashTable[hash]);
}
} else {
int newCount = newExps.length;
int len = sequence.length();
Next:
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
Object []keys = new Object[keyCount];
for (int c = 0; c < keyCount; ++c) {
keys[c] = keyExps[c].calculate(ctx);
}
Object []newValues = new Object[newCount];
for (int c = 0; c < newCount; ++c) {
newValues[c] = newExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
if (entry.newValues[tableSeq] != null) {
MessageManager mm = EngineMessage.get();
String str = "[";
for (int k = 0; k < keyCount; ++k) {
if (k != 0) {
str += ",";
}
str += Variant.toString(keys[k]);
}
str += "]";
throw new RQException(str + mm.getMessage("engine.dupKeys"));
}
entry.newValues[tableSeq] = newValues;
continue Next;
}
}
hashTable[hash] = new PrimaryJoinNode(keys, newValues, tableCount, tableSeq, hashTable[hash]);
}
}
} finally {
stack.pop();
}
}
public Sequence result() {
init();
if (opt != null && opt.indexOf('f') != -1) {
return fullJoin();
} else {
return join();
}
}
private Sequence join() {
Sequence srcSequence = this.srcSequence;
Expression []srcKeyExps = this.srcKeyExps;
Expression []srcNewExps = this.srcNewExps;
String []options = this.options;
Context ctx = this.ctx;
HashUtil hashUtil = this.hashUtil;
PrimaryJoinNode []hashTable = this.hashTable;
int []newSeqs = this.newSeqs;
int tableCount = this.tableCount;
int srcRefCount = this.srcRefCount;
DataStruct resultDs = this.resultDs;
// ???????ͣ?0:??????, 1:??????, 2???????㣬????ƥ?䲻?ϵ?
int []joinTypes = new int[tableCount];
for (int t = 0; t < tableCount; ++t) {
String option = options[t];
if (option == null) {
joinTypes[t] = 0;
} else if (option.equals("null")) {
if (newExps[t] != null && newExps[t].length > 0) {
joinTypes[t] = 1;
} else {
joinTypes[t] = 2;
}
} else {
joinTypes[t] = 0;
}
}
int len = srcSequence.length();
int keyCount = srcKeyExps.length;
Object []keys = new Object[keyCount];
Table result = new Table(resultDs, len + 1024);
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(srcSequence);
stack.push(current);
try {
if (srcNewExps == null || srcNewExps.length == 0) {
Next:
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = srcKeyExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
for (int t = 0; t < tableCount; ++t) {
if (entry.newValues[t] == null) {
if (joinTypes[t] == 0) {
continue Next;
}
} else {
if (joinTypes[t] == 2) {
continue Next;
}
}
}
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
BaseRecord sr = (BaseRecord)srcSequence.getMem(i);
System.arraycopy(sr.getFieldValues(), 0, values, 0, srcRefCount);
for (int t = 0; t < tableCount; ++t) {
Object []vals = entry.newValues[t];
if (vals != null) {
System.arraycopy(vals, 0, values, newSeqs[t], vals.length);
}
}
continue Next;
}
}
for (int t : joinTypes) {
if (t == 0) {
continue Next;
}
}
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
BaseRecord sr = (BaseRecord)srcSequence.getMem(i);
System.arraycopy(sr.getFieldValues(), 0, values, 0, srcRefCount);
}
} else {
int newCount = srcNewExps.length;
Next:
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
for (int c = 0; c < keyCount; ++c) {
keys[c] = srcKeyExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
for (int t = 0; t < tableCount; ++t) {
if (entry.newValues[t] == null) {
if (joinTypes[t] == 0) {
continue Next;
}
} else {
if (joinTypes[t] == 2) {
continue Next;
}
}
}
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
for (int f = 0; f < newCount; ++f) {
values[f] = srcNewExps[f].calculate(ctx);
}
for (int t = 0; t < tableCount; ++t) {
Object []vals = entry.newValues[t];
if (vals != null) {
System.arraycopy(vals, 0, values, newSeqs[t], vals.length);
}
}
continue Next;
}
}
for (int t : joinTypes) {
if (t == 0) {
continue Next;
}
}
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
for (int f = 0; f < newCount; ++f) {
values[f] = srcNewExps[f].calculate(ctx);
}
}
}
} finally {
stack.pop();
}
return result;
}
private Sequence fullJoin() {
Sequence srcSequence = this.srcSequence;
Expression []srcKeyExps = this.srcKeyExps;
Expression []srcNewExps = this.srcNewExps;
Context ctx = this.ctx;
HashUtil hashUtil = this.hashUtil;
PrimaryJoinNode []hashTable = this.hashTable;
int []keySeqs = this.keySeqs;
int []newSeqs = this.newSeqs;
int tableCount = this.tableCount;
int srcRefCount = this.srcRefCount;
DataStruct resultDs = this.resultDs;
int len = srcSequence.length();
int keyCount = srcKeyExps.length;
Object []keys = new Object[keyCount];
Table result = new Table(resultDs, len + 1024);
ComputeStack stack = ctx.getComputeStack();
Current current = new Current(srcSequence);
stack.push(current);
try {
if (srcNewExps == null || srcNewExps.length == 0) {
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
BaseRecord sr = (BaseRecord)srcSequence.getMem(i);
System.arraycopy(sr.getFieldValues(), 0, values, 0, srcRefCount);
for (int c = 0; c < keyCount; ++c) {
keys[c] = srcKeyExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
for (int t = 0; t < tableCount; ++t) {
Object []vals = entry.newValues[t];
if (vals != null) {
System.arraycopy(vals, 0, values, newSeqs[t], vals.length);
}
}
entry.isMatch = true;
break;
}
}
}
} else {
int newCount = srcNewExps.length;
for (int i = 1; i <= len; ++i) {
current.setCurrent(i);
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
for (int f = 0; f < newCount; ++f) {
values[f] = srcNewExps[f].calculate(ctx);
}
for (int c = 0; c < keyCount; ++c) {
keys[c] = srcKeyExps[c].calculate(ctx);
}
int hash = hashUtil.hashCode(keys, keyCount);
for (PrimaryJoinNode entry = hashTable[hash]; entry != null; entry = entry.next) {
if (Variant.compareArrays(entry.keyValues, keys, keyCount) == 0) {
for (int t = 0; t < tableCount; ++t) {
Object []vals = entry.newValues[t];
if (vals != null) {
System.arraycopy(vals, 0, values, newSeqs[t], vals.length);
}
}
entry.isMatch = true;
break;
}
}
}
}
} finally {
stack.pop();
}
for (PrimaryJoinNode entry : hashTable) {
for (; entry != null; entry = entry.next) {
if (!entry.isMatch) {
Record r = (Record)result.newLast();
Object []values = r.getFieldValues();
for (int t = 0; t < tableCount; ++t) {
Object []vals = entry.newValues[t];
if (vals != null) {
System.arraycopy(vals, 0, values, newSeqs[t], vals.length);
}
}
for (int f = 0; f < keyCount; ++f) {
if (keySeqs[f] != -1) {
values[keySeqs[f]] = entry.keyValues[f];
}
}
}
}
}
return result;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy