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

com.scudata.dm.cursor.JoinxCursor_u 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.cursor;

import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.Current;
import com.scudata.dm.DataStruct;
import com.scudata.dm.ListBase1;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.op.Operation;
import com.scudata.expression.Expression;
import com.scudata.util.CursorUtil;
import com.scudata.util.HashUtil;

/**
 * ?????α????????ڴ???????????
 * joinx@u(csi:Fi,xj,..;P:Fi,xj,..;??)
 * @author RunQian
 *
 */
public class JoinxCursor_u extends ICursor {
	private ICursor cursor; // ?α?
	private Expression[] exps; // ????????ʽ
	private DataStruct ds; // ????????ݽṹ
	private int type = 0; // 0:JOIN, 1:LEFTJOIN, 2:FULLJOIN
	private boolean isEnd = false; // ?Ƿ?ȡ??????

	private HashUtil hashUtil = new HashUtil(); // ??ϣ?????ߣ????ڼ????ϣֵ
	private ListBase1 [][]hashGroups; // ?ڴ????а??????ֶ????Ĺ?ϣ????
	
	private Table result; // ????????
	
	/**
	 * ?????????α?
	 * @param objs ????Դ???飬?׸?Ϊ?α꣬??????Ϊ????
	 * @param exps ????????ʽ????
	 * @param names ??????ֶ???????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 */
	public JoinxCursor_u(Object []objs, Expression[][] exps, String []names, String opt, Context ctx) {
		this.cursor = (ICursor)objs[0];
		this.exps = exps[0];
		this.ctx = ctx;

		int srcCount = objs.length;
		if (names == null) {
			names = new String[srcCount];
		}

		ds = new DataStruct(names);
		setDataStruct(ds);
		
		if (opt != null) {
			if (opt.indexOf('1') != -1) {
				type = 1;
			} else if (opt.indexOf('f') != -1) {
				type = 2;
			}
		}
		
		hashGroups = new ListBase1[hashUtil.getCapacity()][];
		result = new Table(ds, INITSIZE);
		int keyCount = exps[0] == null ? 1 : exps[0].length;
		int count = keyCount + 1;
		ComputeStack stack = ctx.getComputeStack();
		final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
		HashUtil hashUtil = this.hashUtil;
		ListBase1 [][]hashGroups = this.hashGroups;
		
		for (int s = 1; s < srcCount; ++s) {
			Sequence src = (Sequence)objs[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();
			}
		}
	}
	
	// ???м???ʱ??Ҫ?ı???????
	// ?̳???????õ??˱???ʽ????Ҫ?????????????½???????ʽ
	public void resetContext(Context ctx) {
		if (this.ctx != ctx) {
			cursor.resetContext(ctx);
			exps = Operation.dupExpressions(exps, ctx);
			super.resetContext(ctx);
		}
	}

	/**
	 * ??ȡָ???????????ݷ???
	 * @param n ????
	 * @return Sequence
	 */
	protected Sequence get(int n) {
		if (isEnd || n < 1) return null;
		
		Table result = this.result;
		ICursor cursor = this.cursor;
		
		final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
		HashUtil hashUtil = this.hashUtil;
		ListBase1 [][]hashGroups = this.hashGroups;
		Expression[] exps = this.exps;
		Context ctx = this.ctx;
		int keyCount = exps == null ? 1 : exps.length;
		int count = keyCount + 1;
		int srcCount = ds.getFieldCount();
		ComputeStack stack = ctx.getComputeStack();
		
		while (result.length() < n) {
			Sequence src = cursor.fetch(INITSIZE);
			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) {
					Object []keys = new Object[count];
					keys[keyCount] = src.getMem(i);
					current.setCurrent(i);
					if (exps == null) {
						keys[0] = keys[keyCount];
					} else {
						for (int k = 0; k < keyCount; ++k) {
							keys[k] = exps[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[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();
			}
			
			for (int i = 0, len = hashGroups.length; i < len; ++i) {
				if (hashGroups[i] != null) {
					CursorUtil.join_m(hashGroups[i], keyCount, type, result);
					if (hashGroups[i][0] != null && hashGroups[i][0].size() > 0) {
						hashGroups[i][0].clear();;
					}
				}
			}
		}
		
		int len = result.length();
		if (len > n) {
			return result.split(1, n);
		} else if (len == n) {
			this.result = new Table(ds, INITSIZE);
			return result;
		} else {
			if (len > 0) {
				return result;
			} else {
				return null;
			}
		}
	}

	/**
	 * ????ָ????????????
	 * @param n ????
	 * @return long ʵ????????????
	 */
	protected long skipOver(long n) {
		if (isEnd || n < 1) return 0;
		
		long skipCount = result.length();
		Table result = this.result;
		if (skipCount > n) {
			result.split(1, (int)n);
			return n;
		} else if (skipCount == n) {
			result.clear();
			return n;
		} else if (skipCount > 0) {
			result.clear();
		}
		
		ICursor cursor = this.cursor;
		final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
		HashUtil hashUtil = this.hashUtil;
		ListBase1 [][]hashGroups = this.hashGroups;
		Expression[] exps = this.exps;
		Context ctx = this.ctx;
		int keyCount = exps == null ? 1 : exps.length;
		int count = keyCount + 1;
		int srcCount = ds.getFieldCount();
		ComputeStack stack = ctx.getComputeStack();
		
		while (true) {
			Sequence src = cursor.fetch(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) {
					Object []keys = new Object[count];
					keys[keyCount] = src.getMem(i);
					current.setCurrent(i);
					if (exps == null) {
						keys[0] = keys[keyCount];
					} else {
						for (int k = 0; k < keyCount; ++k) {
							keys[k] = exps[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[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();
			}
			
			for (int i = 0, len = hashGroups.length; i < len; ++i) {
				if (hashGroups[i] != null) {
					CursorUtil.join_m(hashGroups[i], keyCount, type, result);
					hashGroups[i][0] = null;
				}
			}
			
			int len = result.length();
			long dif = n - skipCount;
			if (len > dif) {
				result.split(1, (int)dif);
				return n;
			} else if (len == dif) {
				result.clear();
				return n;
			} else if (len > 0) {
				skipCount += len;
				result.clear();
			}
		}
		
		return skipCount;
	}

	/**
	 * ?ر??α?
	 */
	public synchronized void close() {
		super.close();
		cursor.close();
		result = null;
		isEnd = true;
	}
	
	/**
	 * ?????α?
	 * @return ?????Ƿ?ɹ???true???α???Դ?ͷ????ȡ????false???????Դ?ͷ????ȡ??
	 */
	public boolean reset() {
		close();
		
		if (!cursor.reset()) {
			return false;
		}
		
		result = new Table(ds, INITSIZE);
		isEnd = false;
		return true;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy