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

com.scudata.dw.JoinCursor2 Maven / Gradle / Ivy

Go to download

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

There is a newer version: 20241126
Show newest version
package com.scudata.dw;

import java.util.ArrayList;

import com.scudata.array.IArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MultipathCursors;
import com.scudata.dm.op.Switch;
import com.scudata.expression.Expression;
import com.scudata.expression.FieldRef;
import com.scudata.expression.Function;
import com.scudata.expression.IParam;
import com.scudata.expression.Moves;
import com.scudata.expression.Node;
import com.scudata.expression.ParamInfo2;
import com.scudata.expression.UnknownSymbol;
import com.scudata.expression.mfn.sequence.Avg;
import com.scudata.expression.mfn.sequence.Count;
import com.scudata.expression.mfn.sequence.Max;
import com.scudata.expression.mfn.sequence.Min;
import com.scudata.expression.mfn.sequence.New;
import com.scudata.expression.mfn.sequence.Sum;
import com.scudata.parallel.ClusterPhyTable;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;

/**
 * ????T.new T.derive T.news?Ľ?????α? (T???д桢?в?????????ʱ)
 * @author runqian
 *
 */
public class JoinCursor2 extends ICursor {
	private boolean isClosed;
	private boolean isNew;
	private boolean isNews;
	private DataStruct ds;
	
	private ICursor cursor1;//T???α?
	private Sequence cache1;
	private ICursor cursor2;//A/cs
	//private String[] csNames;//A/cs:K??K??????ָ??A/cs???????ӵ??ֶ?
	private Sequence cache2;

	private int cur1 = -1;
	private int cur2 = -1;
	
	private int keyCount;
	private int csFieldsCount;//A/cs???ֶθ???
	private int []keyIndex2;//A/cs???????±?
	private int []fieldIndex2;//A/csȡ???ֶε??±?
	
	private int []fieldIndex1;//Tȡ???ֶε??±?
	
	private boolean hasExps;//
	private Node nodes[];
	
	private boolean hasR;
	
	/**
	 * 
	 * @param table
	 * @param exps
	 * @param fields
	 * @param cursor2
	 * @param opt	0:derive; 1:new; 2:news
	 * @param ctx
	 */
	public JoinCursor2(Object table, Expression []exps, String []fields, ICursor cursor2, String[] csNames, Expression filter,
			String []fkNames, Sequence []codes, String[] opts, int opt, String option, Context ctx) {
		this.isNew = opt == 1;
		this.isNews = opt == 2;
		this.ctx = ctx;
		
		if (ctx != null) {
			ctx.addResource(this);
		}
		
		hasR = option != null && option.indexOf("r") != -1;
		
		String []keyNames;
		if (table instanceof IPhyTable) {
			keyNames = ((IPhyTable) table).getAllSortedColNames();
		} else {
			keyNames = ((ClusterPhyTable) table).getAllSortedColNames();
		}
		
		this.cursor2 = cursor2;
		//this.csNames = csNames;
		Sequence seq = cursor2.peek(1);
		if (seq == null) {
			isClosed = true;
			return;
		}
		DataStruct ds2 = ((Record) seq.get(1)).dataStruct();
		
		String []joinNames = keyNames;//join?ֶΣ?Ĭ??ȡT??????
		if (isNew) {
			//newʱ????T??????
			if (joinNames == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			keyCount = joinNames.length;
			keyIndex2 = new int[keyCount];
			if (csNames == null) {
				for (int i = 0; i < keyCount; i++) {
					keyIndex2[i] = i;
				}
			} else {
				if (csNames.length > keyCount) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				for (int i = 0; i < keyCount; i++) {
					keyIndex2[i] = ds2.getFieldIndex(csNames[i]);
				}
			}
		} else {
			//newsʱȡcs??????
			
			//1.?õ?cs???????±?
			if (csNames == null) {
				keyIndex2 = ds2.getPKIndex();
			} else {
				int csNamesLen = csNames.length;
				keyIndex2 = new int[csNamesLen];
				for (int i = 0; i < csNamesLen; i++) {
					keyIndex2[i] = ds2.getFieldIndex(csNames[i]);
				}
			}
			if (keyIndex2 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			keyCount = keyIndex2.length;
			
			//2.ȡTǰ????ֶ?
			joinNames = new String[keyCount];//??ʱ????T??????
			String[] allNames;
			if (table instanceof IPhyTable) {
				allNames = ((IPhyTable) table).getAllColNames();
			} else {
				allNames = ((ClusterPhyTable) table).getAllColNames();
			}
			for (int i = 0; i < keyCount; i++) {
				joinNames[i] = allNames[i];
			}
		}
		
		ArrayList keyList = new ArrayList();//??ʱʹ??
		for (int i = 0; i < keyCount; i++) {
			keyList.add(keyNames[i]);
		}
		
		//????????ʽ??exps???????{????}
		ArrayList fetchExps = new ArrayList();
		for (int i = 0, len = exps.length; i < len; i++) {
			Expression exp = exps[i];
			if (exp == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("Expression.missingParam"));
			}
			
			if (fields[i] == null) {
				fields[i] = exps[i].getFieldName();
			}
			
			Node home = exp.getHome();
			if (home instanceof UnknownSymbol) {
				String f = exp.getFieldName();
				if (!keyList.contains(f) && ds2.getFieldIndex(f) < 0)
						fetchExps.add(exp);
			} else {
				hasExps = true;
				if (home instanceof Moves) {
					IParam fieldParam = ((Moves) exp.getHome()).getParam();
					ParamInfo2 pi = ParamInfo2.parse(fieldParam, "cursor", false, false);
					String []subFields = pi.getExpressionStrs1();
					for (String f : subFields) {
						if (!keyList.contains(f))
								fetchExps.add(new Expression(f));
					}
				} else if (home instanceof com.scudata.expression.fn.gather.Top) {
					IParam fieldParam = ((com.scudata.expression.fn.gather.Top) exp.getHome()).getParam();
					if (fieldParam != null) {
						if (!fieldParam.isLeaf()) {
							IParam sub1 = fieldParam.getSub(1);
							if (!keyList.contains(sub1.getLeafExpression().getFieldName()))
								fetchExps.add(sub1.getLeafExpression());
						}
					}
				} else {
					String field = ((Function)home).getParamString();
					if (!keyList.contains(field) && ds2.getFieldIndex(field) < 0)
						fetchExps.add(new Expression(field));
				}
			}
		}
		
		Expression []allExps;
		allExps = new Expression[keyCount + fetchExps.size()];
		int i = 0;
		for (; i < keyCount; i++) {
			allExps[i] = new Expression(keyNames[i]);
		}
		for (Expression exp : fetchExps) {
			allExps[i++] = exp;
		}
		
		if (hasExps) {
			int len = exps.length;
			nodes = new Node[len];
			for (i = 0; i < len; i++) {
				nodes[i] = parseNode(exps[i], ctx);
			}
		}
		
		if (table instanceof IPhyTable) {
			this.cursor1 = ((IPhyTable) table).cursor(allExps, null, filter, null, null, null, null, ctx);
		}
		
		if (isNew || isNews) {
			ds = new DataStruct(fields);
		} else {
			csFieldsCount = ds2.getFieldCount();
			String[] fieldNames = new String[csFieldsCount + fields.length];
			System.arraycopy(ds2.getFieldNames(), 0, fieldNames, 0, csFieldsCount);
			System.arraycopy(fields, 0, fieldNames, csFieldsCount, fields.length);
			ds = new DataStruct(fieldNames);
		}
		
		int len = exps.length;
		fieldIndex1 = new int[len];
		fieldIndex2 = new int[len];
		DataStruct ds1 = cursor1.getDataStruct();
		for (i = 0; i < len; i++) {
			fieldIndex1[i] = ds1.getFieldIndex(exps[i].getIdentifierName());
			fieldIndex2[i] = ds2.getFieldIndex(exps[i].getIdentifierName());
		}
		
		init();
		
		if (fkNames != null) {
			int fkCount = fkNames.length;
			for (int j = 0; j < fkCount; j++) {
				String[] fkn = new String[] {fkNames[j]};
				Sequence[] code = new Sequence[] {codes[j]};
				String _opt = null;
				Expression _exps[] = null;
				if (opts[j] != null && opts[j].indexOf("#") != -1) {
					_exps = new Expression[] {new Expression("#")};
				} else if (opts[j] != null && opts[j].indexOf("null") != -1) {
					_opt = "d";
				} else {
					_opt = "i";
				}
				Switch op = new Switch(fkn, code, _exps, _opt);
				addOperation(op, ctx);
			}
		}
	}
	
	public JoinCursor2(ICursor cursor1, ICursor cursor2, Context ctx) {
		this.cursor1 = cursor1;
		this.cursor2 = cursor2;
		this.ctx = ctx;
	}
	
	void init() {
		cache1 = cursor1.fetch(FETCHCOUNT);
		if (cache1 == null || cache1.length() == 0) {
			isClosed = true;
			return;
		}
		cur1 = 1;
	}
	
	public static MultipathCursors makeMultiJoinCursor(Object table, Expression []exps, String []fields, MultipathCursors cursor2, 
			String[] csNames, Expression filter, String []fkNames, Sequence []codes, String[] opts, int opt, String option, Context ctx) {
		boolean isNew = opt == 1;
		boolean isNews = opt == 2;
		boolean hasExps = false;
		int csFieldsCount = 0;
		DataStruct ds;
		int []fieldIndex1 = null;
		
		String []keyNames;
		if (table instanceof IPhyTable) {
			keyNames = ((IPhyTable) table).getAllSortedColNames();
		} else {
			keyNames = ((ClusterPhyTable) table).getAllSortedColNames();
		}
		
		DataStruct ds2 = (cursor2.getCursors()[0]).getDataStruct();
		int []keyIndex2;
		int keyCount;
		String []joinNames = keyNames;//join?ֶΣ?Ĭ??ȡT??????
		if (isNew) {
			//newʱ????T??????
			if (joinNames == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			keyCount = joinNames.length;
			keyIndex2 = new int[keyCount];
			if (csNames == null) {
				for (int i = 0; i < keyCount; i++) {
					keyIndex2[i] = i;
				}
			} else {
				if (csNames.length > keyCount) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				for (int i = 0; i < keyCount; i++) {
					keyIndex2[i] = ds2.getFieldIndex(csNames[i]);
				}
			}
		} else {
			//newsʱȡcs??????
			
			//1.?õ?cs???????±?
			if (csNames == null) {
				keyIndex2 = ds2.getPKIndex();
			} else {
				int csNamesLen = csNames.length;
				keyIndex2 = new int[csNamesLen];
				for (int i = 0; i < csNamesLen; i++) {
					keyIndex2[i] = ds2.getFieldIndex(csNames[i]);
				}
			}
			if (keyIndex2 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			keyCount = keyIndex2.length;
			
			//2.ȡTǰ????ֶ?
			joinNames = new String[keyCount];//??ʱ????T??????
			String[] allNames;
			if (table instanceof IPhyTable) {
				allNames = ((IPhyTable) table).getAllColNames();
			} else {
				allNames = ((ClusterPhyTable) table).getAllColNames();
			}
			for (int i = 0; i < keyCount; i++) {
				joinNames[i] = allNames[i];
			}
		}
		
		ArrayList keyList = new ArrayList();//??ʱʹ??
		for (int i = 0; i < keyCount; i++) {
			keyList.add(keyNames[i]);
		}
		
		//????????ʽ??exps???????{????}
		ArrayList fetchExps = new ArrayList();
		for (int i = 0, len = exps.length; i < len; i++) {
			Expression exp = exps[i];
			if (exp == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("Expression.missingParam"));
			}
			
			if (fields[i] == null) {
				fields[i] = exps[i].getFieldName();
			}
			
			Node home = exp.getHome();
			if (home instanceof UnknownSymbol) {
				if (!keyList.contains(exp.getFieldName()))
						fetchExps.add(exp);
			} else {
				hasExps = true;
				isNews = false;//?б???ʽʱ??????news
				if (home instanceof Moves) {
					IParam fieldParam = ((Moves) exp.getHome()).getParam();
					ParamInfo2 pi = ParamInfo2.parse(fieldParam, "cursor", false, false);
					String []subFields = pi.getExpressionStrs1();

					for (String f : subFields) {
						if (!keyList.contains(f))
								fetchExps.add(new Expression(f));
					}
				} else if (home instanceof com.scudata.expression.fn.gather.Top) {
					IParam fieldParam = ((com.scudata.expression.fn.gather.Top) exp.getHome()).getParam();
					if (fieldParam != null) {
						if (!fieldParam.isLeaf()) {
							IParam sub1 = fieldParam.getSub(1);
							if (!keyList.contains(sub1.getLeafExpression().getFieldName()))
								fetchExps.add(sub1.getLeafExpression());
						}
					}
				} else {
					String field = ((Function)home).getParamString();
					if (!keyList.contains(field))
						fetchExps.add(new Expression(field));
				}
			}
		}
		
		Expression []allExps;
		allExps = new Expression[keyCount + fetchExps.size()];
		int i = 0;
		for (; i < keyCount; i++) {
			allExps[i] = new Expression(keyNames[i]);
		}
		for (Expression exp : fetchExps) {
			allExps[i++] = exp;
		}
		
		Node nodes[] = null; 
		if (hasExps) {
			int len = exps.length;
			nodes = new Node[len];
			for (i = 0; i < len; i++) {
				nodes[i] = parseNode(exps[i], ctx);
			}
		}
		
		String[] allExpNames = new String[allExps.length];
		for (i = 0; i < allExpNames.length; i++) {
			allExpNames[i] = allExps[i].toString();
		}
		
		ICursor cursor1 = null;
		if (table instanceof IPhyTable) {
			Expression w = null;
			if (filter != null) {
				w = filter.newExpression(ctx); // ?ֶβ??ж?ȡʱ??Ҫ???Ʊ???ʽ??ͬһ??????ʽ??֧?ֲ???????
			}
			cursor1 = ((IPhyTable) table).cursor(null, allExpNames, w, null, null, null, cursor2, null, ctx);
		}

		if (isNew || isNews) {
			ds = new DataStruct(fields);
		} else {
			csFieldsCount = ds2.getFieldCount();
			String[] fieldNames = new String[csFieldsCount + fields.length];
			System.arraycopy(ds2.getFieldNames(), 0, fieldNames, 0, csFieldsCount);
			System.arraycopy(fields, 0, fieldNames, csFieldsCount, fields.length);
			ds = new DataStruct(fieldNames);
		}
		
		if (!hasExps) {
			int len = exps.length;
			fieldIndex1 = new int[len];
			for (i = 0; i < len; i++) {
				fieldIndex1[i] = cursor1.getDataStruct().getFieldIndex(fields[i]);
			}
		}
		
		int len = cursor2.getPathCount();
		ICursor cursors1[] = ((MultipathCursors) cursor1).getParallelCursors();
		ICursor cursors2[] = cursor2.getParallelCursors();
		ICursor cursors[] = new ICursor[len];
		boolean hasR = option != null && option.indexOf("r") != -1;
		for (i = 0; i < len; i++) {
			JoinCursor2 cs = new JoinCursor2(cursors1[i], cursors2[i], ctx);
			cs.ds = ds;
			cs.isNew = opt == 1;
			cs.isNews = opt == 2;
			cs.hasExps = hasExps;
			cs.csFieldsCount = csFieldsCount;
			cs.fieldIndex1 = fieldIndex1;
			cs.keyIndex2 = keyIndex2;
			cs.keyCount = keyCount;
			cs.nodes = nodes;
			cs.hasR = hasR;
			cs.init();
			if (fkNames != null) {
				int fkCount = fkNames.length;
				for (int j = 0; j < fkCount; j++) {
					String[] fkn = new String[] {fkNames[j]};
					Sequence[] code = new Sequence[] {codes[j]};
					String _opt = null;
					Expression _exps[] = null;
					if (opts[j] != null && opts[j].indexOf("#") != -1) {
						_exps = new Expression[] {new Expression("#")};
					} else if (opts[j] != null && opts[j].indexOf("null") != -1) {
						_opt = "d";
					} else {
						_opt = "i";
					}
					Switch op = new Switch(fkn, code, _exps, _opt);
					cs.addOperation(op, ctx);
				}
				
			}
			cursors[i] = cs;
		}
		return new MultipathCursors(cursors, ctx);
	}
	
	protected Sequence get(int n) {
		if (isClosed || n < 1) {
			return null;
		}

		if (isNews) {
			return getDataForNews(n);
		}
		
		if (hasExps) {
			return getDataForNew(n);
		}
		
		int keyCount = this.keyCount;
		int csFieldsCount = this.csFieldsCount;
		int len = isNew ? ds.getFieldCount() : ds.getFieldCount() - csFieldsCount;
		
		if (cache2 == null || cache2.length() == 0) {
			cache2 = cursor2.fetch(n);
			cur2 = 1;
		}
		
		int cur1 = this.cur1;
		int cur2 = this.cur2;
		Sequence cache1 = this.cache1;
		Sequence cache2 = this.cache2;
		IArray mems1 = cache1.getMems();
		IArray mems2 = cache2.getMems();
		int len1 = cache1.length();
		int len2 = cache2.length();
		int []fieldIndex1 = this.fieldIndex1;
		int []fieldIndex2 = this.fieldIndex2;
		int []keyIndex2 = this.keyIndex2;
		boolean isNew = this.isNew;
		boolean isNews = this.isNews;
		ICursor cursor1 = this.cursor1;
		ICursor cursor2 = this.cursor2;
		
		Table newTable;
		if (n > INITSIZE) {
			newTable = new Table(ds, INITSIZE);
		} else {
			newTable = new Table(ds, n);
		}
		
		Object []keys2 = new Object[keyCount];
		while (true) {
			Record record1 = (Record) mems1.get(cur1);
			Record record2 = (Record) mems2.get(cur2);
			
			for (int i = 0; i < keyCount; i++) {
				keys2[i] = record2.getFieldValue(keyIndex2[i]);
			}
			Object []keys1 = record1.getFieldValues();
			
			int cmp = Variant.compareArrays(keys2, keys1);
			if (cmp == 0) {
				cur1++;
				if (!isNews) {
					cur2++;
				}
				BaseRecord record = newTable.newLast();
				Object [] objs2 = record2.getFieldValues();
				if (isNew || isNews) {
					for (int i = 0; i < len; i++) {
						int idx = fieldIndex1[i];
						if (idx >= 0) {
							record.setNormalFieldValue(i, keys1[idx]);
						}
						else {
							idx = fieldIndex2[i];
							record.setNormalFieldValue(i, objs2[idx]);
						}
					}
				} else {
					Object []vals = record2.getFieldValues();
					System.arraycopy(vals, 0, record.getFieldValues(), 0, csFieldsCount);
					for (int i = 0; i < len; i++) {
						record.setNormalFieldValue(i + csFieldsCount, keys1[fieldIndex1[i]]);
					}
				}
			} else if (cmp > 0) {
				cur1++;
			} else if (cmp < 0) {
				cur2++;
			}
			
			if (cur1 > len1) {
				cur1 = 1;
				cache1 = cursor1.fetch(FETCHCOUNT);
				if (cache1 == null || cache1.length() == 0) {
					isClosed = true;
					break;
				}
				mems1 = cache1.getMems();
				len1 = cache1.length();
			}
			if (cur2 > len2) {
				cur2 = 1;
				cache2 = cursor2.fetch(n - newTable.length());
				if (cache2 == null || cache2.length() == 0) {
					isClosed = true;
					break;
				}
				mems2 = cache2.getMems();
				len2 = cache2.length();
			}
			
			if (newTable.length() == n) {
				break;
			}
		}
		
		this.cache1 = cache1;
		this.cache2 = cache2;
		this.cur1 = cur1;
		this.cur2 = cur2;
		
		if (newTable.length() > 0) {
			return newTable;
		} else {
			return null;
		}
	}

	protected long skipOver(long n) {
		Sequence data;
		long rest = n;
		long count = 0;
		while (rest != 0) {
			if (rest > FETCHCOUNT) {
				data = get(FETCHCOUNT);
			} else {
				data = get((int)rest);
			}
			if (data == null) {
				break;
			} else {
				count += data.length();
			}
			rest -= data.length();
		}
		return count;
	}
	
	
	public void close() {
		super.close();
		isClosed = true;
		cache1 = null;
		cache2 = null;
		cursor1.close();
		cursor2.close();
	}
	
	public boolean reset() {
		close();
		if (!cursor1.reset() || !cursor2.reset()) {
			return false;
		} else {
			isClosed = false;
			cur1 = -1;
			cur2 = -1;
			return true;
		}
	}
	
	/**
	 * ?б???ʽʱȡ????
	 * @param n
	 * @return
	 */
	protected Sequence getData(int n) {
		if (isClosed || n < 1) {
			return null;
		}

		Node nodes[] = this.nodes;
		int keyCount = this.keyCount;
		int csFieldsCount = this.csFieldsCount;
		int len = isNew ? ds.getFieldCount() : ds.getFieldCount() - csFieldsCount;
		
		if (cache2 == null || cache2.length() == 0) {
			cache2 = cursor2.fetch(n);
			cur2 = 1;
		}

		int cur2 = this.cur2;
		Sequence cache2 = this.cache2;
		
		Table newTable;
		if (n > INITSIZE) {
			newTable = new Table(ds, INITSIZE);
		} else {
			newTable = new Table(ds, n);
		}
		
		int keysIndex[] = new int[keyCount];
		for (int i = 0; i < keyCount; i++) {
			keysIndex[i] = i;
		}
		
		while (true) {
			Sequence seq1 = cursor1.fetchGroup(keysIndex);
			if (seq1 == null || seq1.length() == 0) {
				isClosed = true;
				break;
			}
			
			Record record1 = (Record) seq1.get(1);
			Record record2 = (Record) cache2.get(cur2);
			Object []keys2 = new Object[keyCount];
			for (int i = 0; i < keyCount; i++) {
				keys2[i] = record2.getFieldValue(keyIndex2[i]);
			}
			Object []keys1 = record1.getFieldValues();
			
			int cmp = Variant.compareArrays(keys2, keys1);
			if (cmp == 0) {
				cur2++;
				BaseRecord record = newTable.newLast();
				if (isNew) {
					for (int i = 0; i < len; i++) {
						//record.setNormalFieldValue(i, keys1[i + keyCount]);
						Node node = nodes[i];
						if (node instanceof FieldRef) {
							node.setDotLeftObject(seq1.get(1));
						} else {
							node.setDotLeftObject(seq1);
						}
						record.setNormalFieldValue(i, node.calculate(ctx));
					}
				} else {
					Object []vals = record2.getFieldValues();
					System.arraycopy(vals, 0, record.getFieldValues(), 0, csFieldsCount);
					for (int i = 0; i < len; i++) {
						Node node = nodes[i];
						if (node instanceof FieldRef) {
							node.setDotLeftObject(seq1.get(1));
						} else {
							node.setDotLeftObject(seq1);
						}
						record.setNormalFieldValue(i + csFieldsCount, node.calculate(ctx));
					}
				}
			} else if (cmp > 0) {
			} else if (cmp < 0) {
				cur2++;
			}
			
			if (cur2 > cache2.length()) {
				cur2 = 1;
				cache2 = cursor2.fetch(n - newTable.length());
				if (cache2 == null || cache2.length() == 0) {
					isClosed = true;
					break;
				}
			}
			
			if (newTable.length() == n) {
				break;
			}
		}
		
		this.cache2 = cache2;
		this.cur2 = cur2;
		
		if (newTable.length() > 0) {
			return newTable;
		} else {
			return null;
		}
	}
	
	//?б???ʽ
	private Sequence getDataForNew(int n) {
		if (isClosed || n < 1) {
			return null;
		}

		int keyCount = this.keyCount;
		int len = ds.getFieldCount();
		
		Object []keys2 = new Object[keyCount];
		
		//ȡ????һ??cs??????
		if (cache2 == null || cache2.length() == 0) {
			cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
			cur2 = 1;
			BaseRecord record2 = (BaseRecord) cache2.get(1);
			for (int i = 0; i < keyCount; i++) {
				keys2[i] = record2.getFieldValue(keyIndex2[i]);
			}
		}
		
		int cur1 = this.cur1;
		Sequence cache1 = this.cache1;
		int len1 = this.cache1.length();
		IArray mems1 = cache1.getMems();
		
		int cur2 = this.cur2;
		Sequence cache2 = this.cache2;
		IArray mems2 = cache2.getMems();
		int len2 = cache2.length();
		int []keyIndex2 = this.keyIndex2;
		ICursor cursor2 = this.cursor2;
		
		Table newTable;
		if (n > INITSIZE) {
			newTable = new Table(ds, INITSIZE);
		} else {
			newTable = new Table(ds, n);
		}

		Table tempTable = new Table(cache2.dataStruct());//???ڻ???
		
		while (true) {
			BaseRecord record1 = (BaseRecord) mems1.get(cur1);
			BaseRecord record2 = (BaseRecord) mems2.get(cur2);
			for (int i = 0; i < keyCount; i++) {
				keys2[i] = record2.getFieldValue(keyIndex2[i]);
			}
			Object []keys1 = record1.getFieldValues();
			
			int cmp = Variant.compareArrays(keys2, keys1);
			if (cmp == 0) {
				//????һ????????ʱ????table
				tempTable.add(record2);
				
				cur2++;
				if (cur2 > len2) {
					cur2 = 1;
					cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
					if (cache2 == null || cache2.length() == 0) {
						isClosed = true;
						break;
					}
					mems2 = cache2.getMems();
					len2 = cache2.length();
				}
				record2 = (BaseRecord) mems2.get(cur2);
				for (int i = 0; i < keyCount; i++) {
					keys2[i] = record2.getFieldValue(keyIndex2[i]);
				}
				
				if (0 != Variant.compareArrays(keys2, keys1)) {
					//???????ȣ???ʾ??һ??ȡ???ˣ???????ʱ????????
					BaseRecord record = newTable.newLast();
					calcExpsForNew(record, tempTable, record1, len);
					
					//ȡ????һ????????????
					cur1++;
					if (cur1 > len1) {
						cur1 = 1;
						cache1 = cursor1.fetch(FETCHCOUNT);
						if (cache1 == null || cache1.length() == 0) {
							isClosed = true;
							break;
						}
						mems1 = cache1.getMems();
						len1 = cache1.length();
					}
				}
			} else if (cmp > 0) {
				//ȡ????һ????????????
				cur1++;
				if (cur1 > len1) {
					cur1 = 1;
					cache1 = cursor1.fetch(FETCHCOUNT);
					if (cache1 == null || cache1.length() == 0) {
						isClosed = true;
						break;
					}
					mems1 = cache1.getMems();
					len1 = cache1.length();
				}
			} else if (cmp < 0) {
				cur2++;
				if (cur2 > len2) {
					cur2 = 1;
					cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
					if (cache2 == null || cache2.length() == 0) {
						isClosed = true;
						break;
					}
					mems2 = cache2.getMems();
					len2 = cache2.length();
				}
				record2 = (BaseRecord) mems2.get(cur2);
				for (int i = 0; i < keyCount; i++) {
					keys2[i] = record2.getFieldValue(keyIndex2[i]);
				}
			}
			
			if (newTable.length() == n) {
				break;
			}
		}
		
		BaseRecord record1 = (BaseRecord) mems1.get(cur1);
		if (isClosed && tempTable != null && tempTable.length() != 0) {
			//???????ȣ???ʾ??һ??ȡ???ˣ???????ʱ????????
			BaseRecord record = newTable.newLast();
			calcExpsForNew(record, tempTable, record1, len);
		}
		
		this.cache1 = cache1;
		this.cache2 = cache2;
		this.cur1 = cur1;
		this.cur2 = cur2;
		
		if (newTable.length() > 0) {
			return newTable;
		} else {
			return null;
		}
	}

	/**
	 * T.news??ȡ??
	 * @param n
	 * @return
	 */
	private Sequence getDataForNews(int n) {
		if (isClosed || n < 1) {
			return null;
		}

		int keyCount = this.keyCount;
		int len = ds.getFieldCount();
		
		
		Object []keys2 = new Object[keyCount];
		//Object []keys1 = this.keys1;
		
		if (cache2 == null || cache2.length() == 0) {
			cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
			cur2 = 1;
			BaseRecord record2 = (BaseRecord) cache2.get(1);
			for (int i = 0; i < keyCount; i++) {
				keys2[i] = record2.getFieldValue(keyIndex2[i]);
			}
		}
		
		int cur1 = this.cur1;
		Sequence cache1 = this.cache1;
		int len1 = this.cache1.length();
		IArray mems1 = cache1.getMems();
		
		int cur2 = this.cur2;
		Sequence cache2 = this.cache2;
		IArray mems2 = cache2.getMems();
		int len2 = cache2.length();
		int []fieldIndex1 = this.fieldIndex1;
		int []fieldIndex2 = this.fieldIndex2;
		int []keyIndex2 = this.keyIndex2;
		boolean hasR = this.hasR;
		boolean hasExps = this.hasExps;
		ICursor cursor2 = this.cursor2;
		
		Table newTable;
		if (n > INITSIZE) {
			newTable = new Table(ds, INITSIZE);
		} else {
			newTable = new Table(ds, n);
		}
		Table tempTable = new Table(cache1.dataStruct());//???ڻ???
		BaseRecord record1 = (BaseRecord) mems1.get(cur1);
		BaseRecord record2 = (BaseRecord) mems2.get(cur2);
		for (int i = 0; i < keyCount; i++) {
			keys2[i] = record2.getFieldValue(keyIndex2[i]);
		}
		Object []keys1 = record1.getFieldValues();
		
		while (true) {
			int cmp = Variant.compareArrays(keys2, keys1);
			if (cmp == 0) {
				BaseRecord record = newTable.newLast();
				if (hasExps) {
					tempTable.newLast(keys1);//???ӵ???ʱ????
				} else {
					for (int i = 0; i < len; i++) {
						int idx = fieldIndex1[i];
						if (idx < 0)
							record.setNormalFieldValue(i, record2.getFieldValue(fieldIndex2[i]));
						else 
							record.setNormalFieldValue(i, keys1[idx]);
					}
				}
				
				cur1++;
				if (cur1 > len1) {
					cur1 = 1;
					cache1 = cursor1.fetch(FETCHCOUNT);
					if (cache1 == null || cache1.length() == 0) {
						isClosed = true;
						break;
					}
					mems1 = cache1.getMems();
					len1 = cache1.length();
				}
				record1 = (BaseRecord) mems1.get(cur1);
				keys1 = record1.getFieldValues();
				
				if (hasR) {
					if (hasExps) {
						//????һ??ȡ??
						while(Variant.compareArrays(keys2, keys1) == 0) {
							record1 = (BaseRecord) mems1.get(cur1);
							keys1 = record1.getFieldValues();
							tempTable.newLast(keys1);//???ӵ???ʱ????
							cur1++;
							if (cur1 > len1) {
								cur1 = 1;
								cache1 = cursor1.fetch(FETCHCOUNT);
								if (cache1 == null || cache1.length() == 0) {
									isClosed = true;
									break;
								}
								mems1 = cache1.getMems();
								len1 = cache1.length();
							}
							record1 = (BaseRecord) mems1.get(cur1);
							keys1 = record1.getFieldValues();
						}
						
						calcExpsForNews(record, tempTable, record2, len);
					}
					
					//????cs????
					cur2++;
					if (cur2 > len2) {
						cur2 = 1;
						cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
						if (cache2 == null || cache2.length() == 0) {
							isClosed = true;
							break;
						}
						mems2 = cache2.getMems();
						len2 = cache2.length();
					}
					record2 = (BaseRecord) mems2.get(cur2);
					for (int i = 0; i < keyCount; i++) {
						keys2[i] = record2.getFieldValue(keyIndex2[i]);
					}
				}
			} else if (cmp > 0) {
				cur1++;
				if (cur1 > len1) {
					cur1 = 1;
					cache1 = cursor1.fetch(FETCHCOUNT);
					if (cache1 == null || cache1.length() == 0) {
						isClosed = true;
						break;
					}
					mems1 = cache1.getMems();
					len1 = cache1.length();
				}
				record1 = (BaseRecord) mems1.get(cur1);
				keys1 = record1.getFieldValues();
			} else if (cmp < 0) {
				cur2++;
				if (cur2 > len2) {
					cur2 = 1;
					cache2 = cursor2.fetch(ICursor.FETCHCOUNT);
					if (cache2 == null || cache2.length() == 0) {
						isClosed = true;
						break;
					}
					mems2 = cache2.getMems();
					len2 = cache2.length();
				}
				record2 = (BaseRecord) mems2.get(cur2);
				for (int i = 0; i < keyCount; i++) {
					keys2[i] = record2.getFieldValue(keyIndex2[i]);
				}
			}
			
			if (newTable.length() >= n) {
				break;
			}
		}
		
		this.cache1 = cache1;
		this.cache2 = cache2;
		this.cur1 = cur1;
		this.cur2 = cur2;
		
		if (newTable.length() > 0) {
			return newTable;
		} else {
			return null;
		}
	}
	
	/**
	 * ??????????¼???Լ?ͬ?????ݣ????????ʽ
	 * @param record
	 * @param tempTable ??????ͬ??һ??????
	 * @param r
	 * @param len
	 */
	private void calcExpsForNew(BaseRecord record, Table tempTable, BaseRecord r, int len) {
		Node nodes[] = this.nodes;
		int fieldIndex2[] = this.fieldIndex2;
		for (int i = 0; i < len; i++) {
			Node node = nodes[i];
			if (node instanceof FieldRef) {
				if (fieldIndex2[i] < 0) {
					node.setDotLeftObject(r);
				} else {
					node.setDotLeftObject(tempTable.get(1));
				}
			} else {
				node.setDotLeftObject(tempTable);
			}
			record.setNormalFieldValue(i, node.calculate(ctx));
		}
	
		tempTable.clear();
	}
	
	private void calcExpsForNews(BaseRecord record, Table tempTable, BaseRecord r, int len) {
		Node nodes[] = this.nodes;
		for (int i = 0; i < len; i++) {
			Node node = nodes[i];
			if (node instanceof FieldRef) {
				node.setDotLeftObject(r);
			} else {
				node.setDotLeftObject(tempTable);
			}
			record.setNormalFieldValue(i, node.calculate(ctx));
		}
	
		tempTable.clear();
	}
	
	private static Node parseNode(Expression exp, Context ctx) {
		Node home = exp.getHome();
		Node node = null;
		
		if (home instanceof Moves) {
			node = new New();
			((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
		} else if (home instanceof UnknownSymbol) {
			node = new FieldRef(exp.getFieldName());
		} else if (home instanceof Function) {
			String fname = ((Function)home).getFunctionName();
			if (fname.equals("sum")) {
				node = new Sum();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			} else if (fname.equals("count")) {
				node = new Count();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			} else if (fname.equals("min")) {
				node = new Min();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			} else if (fname.equals("max")) {
				node = new Max();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			} else if (fname.equals("avg")) {
				node = new Avg();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			} else if (fname.equals("top")) {
				node = new com.scudata.expression.mfn.sequence.Top();
				((Function) node).setParameter(null, ctx, ((Function)exp.getHome()).getParamString());
			}
		}
		return node;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy