All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.dm.op.JoinRemote Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20240823
Show newest version
package com.scudata.dm.op;

import java.util.ArrayList;

import com.scudata.array.IArray;
import com.scudata.array.ObjectArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
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.IndexTable;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.expression.CurrentElement;
import com.scudata.expression.CurrentSeq;
import com.scudata.expression.Expression;
import com.scudata.expression.Function;
import com.scudata.parallel.ClusterMemoryTable;
import com.scudata.resources.EngineMessage;

/**
 * ???α??ܵ?????join???㣬???ӵı??а???Զ?̱?
 * @author WangXiaoJun
 *
 */
public class JoinRemote extends Operation {
	private String fname; // @oѡ????ʹ?ã?ԭ??¼??????Ϊ?¼?¼???ֶ?
	private Expression [][]exps; // ?????ֶα???ʽ????
	private Object[] datas; // ?????????
	private Expression [][]dataExps; // ?????????????ʽ????
	private Expression [][]newExps; // ȡ???Ĵ???????ֶα???ʽ????
	private String [][]newExpStrs; // ȡ???Ĵ???????ֶα???ʽ?ַ???
	private String [][]newNames; // ȡ???Ĵ???????ֶ???????
	private String opt; // ѡ??
	
	private DataStruct oldDs; // Դ?????ݽṹ
	private DataStruct newDs; // ????????ݽṹ
	private IndexTable []indexTables; // ???????hashֵ????
	private Sequence []codes; // ???ش???????飬???ij???Ǽ?Ⱥ?????????Ӧλ??Ϊ??
	private ClusterMemoryTable []cts; // ??Ⱥ????????飬???ij???DZ??ش????????Ӧλ??Ϊ??
	
	private boolean isIsect; // ?????ӣ?Ĭ??Ϊ??????
	private boolean isOrg;
	private boolean containNull; // ?Ƿ??еĴ????Ϊ??
	
	public JoinRemote(String fname, Expression[][] exps, 
			Object[] datas, Expression[][] dataExps, 
			Expression[][] newExps, String[][] newNames, String opt) {
		this(null, fname, exps, datas, dataExps, newExps, newNames, opt);
	}
	
	public JoinRemote(Function function, String fname, Expression[][] exps, 
			Object[] datas, Expression[][] dataExps, 
			Expression[][] newExps, String[][] newNames, String opt) {
		super(function);
		this.fname = fname;
		this.exps = exps;
		this.datas = datas;
		this.dataExps = dataExps;
		this.newExps = newExps;
		this.opt = opt;
		
		if (opt != null) {
			if (opt.indexOf('i') != -1) isIsect = true;
			if (opt.indexOf('o') != -1) isOrg = true;
		}
		
		ArrayList srcFieldsList = new ArrayList();
		ArrayList refFieldList = new ArrayList();

		int count = datas.length;		
		newExpStrs = new String[count][];
		if (newNames == null) newNames = new String[count][];
		
		for (int i = 0; i < count; ++i) {
			Expression []curExps = newExps[i];
			int curLen = curExps.length;

			newExpStrs[i] = new String[curLen];
			if (newNames[i] == null) newNames[i] = new String[curLen];
			String []curNames = newNames[i];

			for (int j = 0; j < curLen; ++j) {
				newExpStrs[i][j] = curExps[j].toString();
				if (curNames[j] == null || curNames[j].length() == 0) {
					curNames[j] = curExps[j].getFieldName();
				}
			}
			
			// x??~ʱ???ڽ??????м?¼F??C:????Ӧ??ϵ????ʶ??Ԥ???????
			if (curLen == 1 && curExps[0].getHome() instanceof CurrentElement) {
				Expression []srcExps = exps[i];
				int srcCount = srcExps.length;
				String []srcFields = new String[srcCount];
				for (int f = 0; f < srcCount; ++f) {
					srcFields[f] = srcExps[f].getFieldName();
				}
				
				srcFieldsList.add(srcFields);
				refFieldList.add(curNames[0]);
			}
		}
		
		this.newNames = newNames;
	}
	
	/**
	 * ȡ?????Ƿ?????Ԫ????????????˺???????ټ?¼
	 * ?˺????????α?ľ?ȷȡ??????????ӵIJ???????ʹ??¼????????ֻ?谴?????????ȡ??????
	 * @return true???ᣬfalse??????
	 */
	public boolean isDecrease() {
		return isIsect;
	}
	
	/**
	 * ???????????ڶ??̼߳??㣬??Ϊ????ʽ???ܶ??̼߳???
	 * @param ctx ??????????
	 * @return Operation
	 */
	public Operation duplicate(Context ctx) {
		Expression [][]exps1 = dupExpressions(exps, ctx);
		Expression [][]dataExps1 = dupExpressions(dataExps, ctx);
		Expression [][]newExps1 = dupExpressions(newExps, ctx);
				
		return new JoinRemote(function, fname, exps1, codes, dataExps1, newExps1, newNames, opt);
	}

	private void init(Sequence data, Context ctx) {
		if (newDs != null) {
			return;
		}
		
		Sequence seq = new Sequence();
		String []oldKey = null;
		if (isOrg) {
			seq.add(fname);
		} else {
			oldDs = data.dataStruct();
			if (oldDs == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("engine.needPurePmt"));
			}
			
			oldKey = oldDs.getPrimary();
			seq.addAll(oldDs.getFieldNames());
		}

		for (int i = 0; i < newNames.length; ++i) {
			seq.addAll(newNames[i]);
		}

		String []names = new String[seq.length()];
		seq.toArray(names);
		newDs = new DataStruct(names);
		if (oldKey != null) {
			newDs.setPrimary(oldKey);
		}

		int count = datas.length;
		codes = new Sequence[count];
		cts = new ClusterMemoryTable[count];
		indexTables = new IndexTable[count];
		
		for (int i = 0; i < count; ++i) {
			if (datas[i] instanceof Sequence) {
				codes[i] = (Sequence)datas[i];
				if (codes[i] == null || codes[i].length() == 0) {
					codes[i] = null;
					containNull = true;
				}
				
				Expression []curExps = dataExps[i];
				IndexTable indexTable;
				if (curExps == null) {
					indexTable = codes[i].getIndexTable();
					if (indexTable == null) {
						Object obj = codes[i].getMem(1);
						if (!(obj instanceof BaseRecord)) {
							MessageManager mm = EngineMessage.get();
							throw new RQException("join: " + mm.getMessage("engine.needPmt"));
						}

						DataStruct ds = ((BaseRecord)obj).dataStruct();
						String[] pks = ds.getPrimary();
						if (pks == null) {
							MessageManager mm = EngineMessage.get();
							throw new RQException(mm.getMessage("ds.lessKey"));
						}
						
						int pkCount = pks.length;
						if (ds.getTimeKeyCount() == 0 && exps[i].length != pkCount) {
							MessageManager mm = EngineMessage.get();
							throw new RQException("join" + mm.getMessage("function.invalidParam"));
						}

						if (pkCount > 1) {
							curExps = new Expression[pkCount];
							dataExps[i] = curExps;
							for (int k = 0; k < pkCount; ++k) {
								curExps[k] = new Expression(ctx, pks[k]);
							}
						}

						indexTable = codes[i].newIndexTable(curExps, ctx);
					}
				} else {
					int fcount = exps[i].length;
					if (fcount != curExps.length) {
						MessageManager mm = EngineMessage.get();
						throw new RQException("join" + mm.getMessage("function.invalidParam"));
					}

					// ?????????#????????????????
					if (fcount != 1 || !(curExps[0].getHome() instanceof CurrentSeq)) {
						indexTable = codes[i].getIndexTable(curExps, ctx);
						if (indexTable == null) {
							indexTable = codes[i].newIndexTable(curExps, ctx);
						}
					} else {
						indexTable = null;
					}
				}

				indexTables[i] = indexTable;
			} else if (datas[i] instanceof ClusterMemoryTable) {
				cts[i] = (ClusterMemoryTable)datas[i];
			} else {
				containNull = true;
				//MessageManager mm = EngineMessage.get();
				//throw new RQException("join" + mm.getMessage("function.paramTypeError"));
			}
		}
	}
	
	/**
	 * ?????α??ܵ???ǰ???͵?????
	 * @param seq ????
	 * @param ctx ??????????
	 * @return
	 */
	public Sequence process(Sequence seq, Context ctx) {
		init(seq, ctx);
		if (isIsect) {
			return join_i(seq, ctx);
		} else {
			return join(seq, ctx);
		}
	}
	
	private Sequence calc(Sequence src, Expression []exps, Context ctx) {
		if (exps == null || exps.length == 0) {
			return src;
		} else if (exps.length == 1) {
			return src.calc(exps[0], ctx);
		} else {
			int keyCount = exps.length;
			int size = src.length();
			Sequence result = new Sequence(size);

			ComputeStack stack = ctx.getComputeStack();
			Current current = new Current(src);
			stack.push(current);

			try {
				for (int i = 1; i <= size; ++i) {
					current.setCurrent(i);
					Object []keys = new Object[keyCount];
					result.add(keys);

					for (int k = 0; k < keyCount; ++k) {
						keys[k] = exps[k].calculate(ctx);
					}
				}
			} finally {
				stack.pop();
			}

			return result;
		}
	}

	private Sequence join(Sequence data, Context ctx) {
		int len = data.length();
		Table result = new Table(newDs, len);
		
		int findex;
		if (isOrg) {
			findex = 1;
			for (int i = 1; i <= len; ++i) {
				BaseRecord old = (BaseRecord)data.getMem(i);
				result.newLast().setNormalFieldValue(0, old);
			}

			for (int fk = 0, fkCount = exps.length; fk < fkCount; ++fk) {
				Sequence newSeq ;
				if (cts[fk] != null) {
					Sequence keyValues = calc(data, exps[fk], ctx);
					newSeq = cts[fk].getRows(keyValues, newExpStrs[fk], newNames[fk], ctx);
				} else if (indexTables[fk] != null) {
					newSeq = fetch(data, exps[fk], indexTables[fk], newExps[fk], newNames[fk], ctx);
				} else if (codes[fk] != null) {
					newSeq = fetch(data, exps[fk], codes[fk], newExps[fk], newNames[fk], ctx);
				} else {
					continue;
				}
				
				IArray newMems = newSeq.getMems();
				for (int i = 1; i <= len; ++i) {
					BaseRecord nr = (BaseRecord)newMems.get(i);
					if (nr != null) {
						BaseRecord r = (BaseRecord)result.getMem(i);
						r.setStart(findex, nr);
					}
				}

				findex += newExps[fk].length;
			}
		} else {
			findex = oldDs.getFieldCount();
			for (int i = 1; i <= len; ++i) {
				BaseRecord old = (BaseRecord)data.getMem(i);
				result.newLast(old.getFieldValues());
			}

			for (int fk = 0, fkCount = exps.length; fk < fkCount; ++fk) {
				Sequence newSeq ;
				if (cts[fk] != null) {
					Sequence keyValues = calc(result, exps[fk], ctx);
					newSeq = cts[fk].getRows(keyValues, newExpStrs[fk], newNames[fk], ctx);
				} else if (indexTables[fk] != null) {
					newSeq = fetch(result, exps[fk], indexTables[fk], newExps[fk], newNames[fk], ctx);
				} else if (codes[fk] != null) {
					newSeq = fetch(result, exps[fk], codes[fk], newExps[fk], newNames[fk], ctx);
				} else {
					continue;
				}
				
				IArray newMems = newSeq.getMems();
				for (int i = 1; i <= len; ++i) {
					BaseRecord nr = (BaseRecord)newMems.get(i);
					if (nr != null) {
						BaseRecord r = (BaseRecord)result.getMem(i);
						r.setStart(findex, nr);
					}
				}

				findex += newExps[fk].length;
			}
		}

		return result;
	}

	private Sequence fetch(Sequence src, Expression[] exps, IndexTable it, 
			Expression[] newExps, String[] newNames, Context ctx) {
		int pkCount = exps.length;
		int newCount = newExps.length;
		Object []pkValues = new Object[pkCount];
		DataStruct ds = new DataStruct(newNames);
		int len = src.length();
		Sequence result = new Sequence(len);
		
		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(src);
		stack.push(current);
		try {
			for (int i = 1; i <= len; ++i) {
				current.setCurrent(i);
				for (int f = 0; f < pkCount; ++f) {
					pkValues[f] = exps[f].calculate(ctx);
				}
	
				BaseRecord r = (BaseRecord)it.find(pkValues);
				if (r != null) {
					stack.push(r);
					Record nr = new Record(ds);
					result.add(nr);
					try {
						for (int f = 0; f < newCount; ++f) {
							nr.setNormalFieldValue(f, newExps[f].calculate(ctx));
						}
					} finally {
						stack.pop();
					}
				} else {
					result.add(null);
				}
			}
		} finally {
			stack.pop();
		}
		
		return result;
	}
	
	private Sequence fetch(Sequence src, Expression[] exps, Sequence code, 
			Expression[] newExps, String[] newNames, Context ctx) {
		int newCount = newExps.length;
		DataStruct ds = new DataStruct(newNames);
		int len = src.length();
		Sequence result = new Sequence(len);
		
		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(src);
		stack.push(current);
		Current codeCurrent = new Current(code);
		stack.push(codeCurrent);
		
		try {
			Expression exp = exps[0];
			IArray codeMems = code.getMems();
			int codeLen = codeMems.size();
			for (int i = 1; i <= len; ++i) {
				current.setCurrent(i);
				Object val = exp.calculate(ctx);
				if (val instanceof Number) {
					int seq = ((Number)val).intValue();
					if (seq > 0 && seq <= codeLen) {
						codeCurrent.setCurrent(seq);
						Record nr = new Record(ds);
						result.add(nr);
						for (int f = 0; f < newCount; ++f) {
							nr.setNormalFieldValue(f, newExps[f].calculate(ctx));
						}
					} else {
						result.add(null);
					}
				} else {
					result.add(null);
				}
			}				
		} finally {
			stack.pop();
			stack.pop();
		}
		
		return result;
	}

	private Table join_i(Sequence data, Context ctx) {
		if (containNull) return null;
		
		Sequence newSeq;
		if (cts[0] != null) {
			Sequence keyValues = calc(data, exps[0], ctx);
			newSeq = cts[0].getRows(keyValues, newExpStrs[0], newNames[0], ctx);
		} else if (indexTables[0] != null) {
			newSeq = fetch(data, exps[0], indexTables[0], newExps[0], newNames[0], ctx);
		} else {
			newSeq = fetch(data, exps[0], codes[0], newExps[0], newNames[0], ctx);
		}
		
		IArray newMems = newSeq.getMems();
		int findex = oldDs.getFieldCount();
		int len = data.length();
		Table result = new Table(newDs, len);
		
		for (int i = 1; i <= len; ++i) {
			BaseRecord nr = (BaseRecord)newMems.get(i);
			if (nr != null) {
				BaseRecord old = (BaseRecord)data.getMem(i);
				BaseRecord r = result.newLast(old.getFieldValues());
				r.setStart(findex, nr);
			}
		}
		
		findex += newExps[0].length;
		for (int fk = 1, fkCount = exps.length; fk < fkCount; ++fk) {
			len = result.length();
			if (len == 0) break;

			ObjectArray tmpMems = new ObjectArray(len);
			if (cts[fk] != null) {
				Sequence keyValues = calc(result, exps[fk], ctx);
				newSeq = cts[fk].getRows(keyValues, newExpStrs[fk], newNames[fk], ctx);
			} else if (indexTables[fk] != null) {
				newSeq = fetch(result, exps[fk], indexTables[fk], newExps[fk], newNames[fk], ctx);
			} else {
				newSeq = fetch(result, exps[fk], codes[fk], newExps[fk], newNames[fk], ctx);
			}

			newMems = newSeq.getMems();
			for (int i = 1; i <= len; ++i) {
				BaseRecord nr = (BaseRecord)newMems.get(i);
				if (nr != null) {
					BaseRecord r = (BaseRecord)result.getMem(i);
					r.setStart(findex, nr);
					tmpMems.add(r);
				}
			}

			result.setMems(tmpMems);
			findex += newExps[fk].length;
		}

		if (result.length() != 0) {
			return result;
		} else {
			return null;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy