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

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

import java.util.ArrayList;

import com.scudata.array.IArray;
import com.scudata.cellset.INormalCell;
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.DataStruct;
import com.scudata.dm.IResource;
import com.scudata.dm.Param;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.Current;
import com.scudata.dm.op.Channel;
import com.scudata.dm.op.GroupxResult;
import com.scudata.dm.op.IDResult;
import com.scudata.dm.op.IGroupsResult;
import com.scudata.dm.op.Operable;
import com.scudata.dm.op.Operation;
import com.scudata.dw.ColPhyTable;
import com.scudata.dw.JoinCursor;
import com.scudata.expression.Expression;
import com.scudata.expression.Function;
import com.scudata.resources.EngineMessage;
import com.scudata.util.CursorUtil;
import com.scudata.util.Variant;

/**
 * ?α???࣬??????Ҫʵ??get??skipOver????
 * @author WangXiaoJun
 *
 */
abstract public class ICursor extends Operable implements IResource {
	public static final int MAXSIZE = Integer.MAX_VALUE - 1; // ???fetch???????ڴ?ֵ??ʾȡ????
	public static final long MAXSKIPSIZE = Long.MAX_VALUE; // ???skip?IJ??????ڴ?ֵ??ʾ????????
	
	public static int INITSIZE = 99999; // ȡ????????ʱ?????????л?????ij?ʼ??С
	public static int FETCHCOUNT = 9999; // ???????ÿ?δ??α??ȡ???ݵ?????
	public static final int FETCHCOUNT_M = 999; // ??·?α겢?м???ʱÿһ·??ȡ???ݵ?????

	protected Sequence cache; // ?и??Ӳ??????ߵ?????peek????˳?Ա??Ž?????Ҫ????ȡ?IJ???????
	protected ArrayList opList; // ???Ӳ????б?
	protected Context ctx; // ?ö??߳??α?ȡ??ʱ??Ҫ?????????IJ????½???????ʽ
	
	protected DataStruct dataStruct; // ????????ݽṹ
	private boolean isDecrease = false; // ???ӵ??????Ƿ??ʹ???ݱ??٣?????select
	private boolean isFinished = false; // ?Ƿ??????finish
	
	/**
	 * ȡ?α??Ĭ??ȡ????С
	 * @return
	 */
	public static int getFetchCount() {
		return FETCHCOUNT;
	}

	/**
	 * ?????α??Ĭ??ȡ????С
	 * @param count
	 */
	public static void setFetchCount(int count) {
		FETCHCOUNT = count;
	}

	
	public static int getInitSize() {
		return INITSIZE;
	}

	public static void setInitSize(int size) {
		INITSIZE = size;
	}

	/**
	 * ???м???ʱ??Ҫ?ı???????
	 * ????????õ??˱???ʽ????Ҫ?????????????½???????ʽ
	 * ???????ش˷???ʱ??Ҫ????һ?¸???ķ???
	 * @param ctx
	 */
	public void resetContext(Context ctx) {
		if (this.ctx != ctx) {
			this.ctx = ctx;
			opList = duplicateOperations(ctx);
		}
	}
	
	/**
	 * ȡ??????????
	 * @return
	 */
	public Context getContext() {
		return ctx;
	}
	
	private ArrayList duplicateOperations(Context ctx) {
		ArrayList opList = this.opList;
		if (opList == null) return null;
				
		ArrayList newList = new ArrayList(opList.size());
		for (Operation op : opList) {
			newList.add(op.duplicate(ctx));
		}
		
		return newList;
	}
	
	/**
	 * ?????α????????
	 * ??·?α???߳?????ʱ??Ҫ??????????
	 * @param ctx
	 */
	public void setContext(Context ctx) {
		this.ctx = ctx;
	}

	/**
	 * Ϊ?α긽??????
	 * @param op ????
	 * @param ctx ??????????
	 */
	public Operable addOperation(Operation op, Context ctx) {
		if (opList == null) {
			opList = new ArrayList();
		}
		
		opList.add(op);
		if (op.isDecrease()) {
			isDecrease = true;
		}
		
		if (this.ctx == null) {
			this.ctx = ctx;
		}
		
		// ?ֶβ????α?ʱ???ڶ????α??ʱ????ܻ???????????ݻ?????
		if (cache != null) {
			cache = op.process(cache, ctx);
		}
		
		return this;
	}
	
	/**
	 * ?????????кϲ???һ?????У????ݽṹ?Ƿ???????????Ƿ????????????
	 * ???ںϲ??α???ȡ???õ??Ľ??
	 * @param dest ????
	 * @param src ????
	 * @return Sequence
	 */
	public static Sequence append(Sequence dest, Sequence src) {
		if (src != null) {
			return dest.append(src);
		} else {
			return dest;
		}
	}
	
	protected Sequence doOperation(Sequence result, ArrayList opList, Context ctx) {
		for (Operation op : opList) {
			if (result == null || result.length() == 0) {
				return null;
			}
			
			try {
				result = op.process(result, ctx);
			} catch (RQException e) {
				INormalCell cell = op.getCurrentCell();
				if (cell != null) {
					MessageManager mm = EngineMessage.get();
					e.setMessage(mm.getMessage("error.cell", cell.getCellId()) + e.getMessage());
				}
				
				throw e;
			} catch (RuntimeException e) {
				INormalCell cell = op.getCurrentCell();
				if (cell != null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("error.cell", cell.getCellId()) + e.getMessage(), e);
				} else {
					throw e;
				}
			}
		}
		
		return result;
	}
	
	protected Sequence finish(ArrayList opList, Context ctx) {
		isFinished = true;
		Sequence result = null;
		for (Operation op : opList) {
			if (result == null || result.length() == 0) {
				result = op.finish(ctx);
			} else {
				result = op.process(result, ctx);
				Sequence tmp = op.finish(ctx);
				if (tmp != null) {
					if (result != null) {
						result = append(result, tmp);
					} else {
						result = tmp;
					}
				}
			}
		}
		
		return result;
	}
	
	public synchronized Sequence peek(int n) {
		ArrayList opList = this.opList;
		if (opList == null) {
			if (cache == null) {
				cache = get(n);
			} else if (cache.length() < n) {
				cache = append(cache, get(n - cache.length()));
			} else if (cache.length() > n) {
				return cache.get(1, n + 1);
			}
			
			return cache;
		}
		
		int size;
		if (n > FETCHCOUNT && n < MAXSIZE) {
			size = n;
		} else {
			size = FETCHCOUNT;
		}
		
		while (cache == null || cache.length() < n) {
			Sequence cur = get(size);
			if (cur == null || cur.length() == 0) {
				Sequence tmp = finish(opList, ctx);
				if (tmp != null) {
					if (cache == null) {
						cache = tmp;
					} else {
						cache = append(cache, tmp);
					}
				}

				return cache;
			} else {
				cur = doOperation(cur, opList, ctx);
				if (cache == null) {
					cache = cur;
				} else if (cur != null) {
					cache = append(cache, cur);
				}
			}
		}
		
		if (cache.length() == n) {
			return cache;
		} else {
			if (cache instanceof Table) {
				Table table = new Table(cache.dataStruct(), n);
				table.getMems().addAll(cache.getMems(), n);
				return table;
			} else {
				Sequence seq = new Sequence(n);
				seq.getMems().addAll(cache.getMems(), n);
				return seq;
			}
		}
	}

	/**
	 * ???ȡָ???????ļ?¼??ȡ?ļ?¼?????ܲ?????n
	 * @param n ????
	 * @return Sequence
	 */
	public Sequence fuzzyFetch(int n) {
		if (cache == null) {
			Sequence result = null;
			ArrayList opList = this.opList;
			
			do {
				Sequence cur = fuzzyGet(n);
				if (cur != null) {
					if (opList != null) {
						cur = doOperation(cur, opList, ctx);
						if (result == null) {
							result = cur;
						} else if (cur != null) {
							result = append(result, cur);
						}
					} else {
						if (result == null) {
							result = cur;
						} else {
							result = append(result, cur);
						}
					}
				} else {
					if (opList != null) {
						Sequence tmp = finish(opList, ctx);
						if (tmp != null) {
							if (result == null) {
								result = tmp;
							} else {
								result = append(result, tmp);
							}
						}
					}

					close();
					return result;
				}
			} while (result == null || result.length() < n);
			
			return result;
		} else {
			Sequence result = cache;
			cache = null;
			return result;
		}
	}
	
	/**
	 * ????ʣ??ļ?¼???ر??α?
	 * @return Sequence
	 */
	public Sequence fetch() {
		return fetch(MAXSIZE);
	}

	/**
	 * ȡָ???????ļ?¼
	 * @param n Ҫȡ?ļ?¼??
	 * @return Sequence
	 */
	public synchronized Sequence fetch(int n) {
		if (n < 1) {
			return null;
		}
		
		ArrayList opList = this.opList;
		Sequence result = cache;
		if (opList == null) {
			if (result == null) {
				result = get(n);
				if (result == null || result.length() < n) {
					close();
				}
				
				return result;
			} else if (result.length() > n) {
				return result.split(1, n);
			} else if (result.length() == n) {
				cache = null;
				return result;
			} else {
				cache = null;
				result = append(result, get(n - result.length()));
				if (result == null || result.length() < n) {
					close();
				}
				
				return result;
			}
		}
		
		// ??????????˵???¼?ֲ???ȡ????????ʵ????ȡ
		int size;
		if ((n > FETCHCOUNT || !isDecrease) && n < MAXSIZE) {
			size = n;
		} else {
			size = FETCHCOUNT;
		}
		
		while (result == null || result.length() < n) {
			Sequence cur = get(size);
			if (cur == null) {
				Sequence tmp = finish(opList, ctx);
				if (tmp != null) {
					if (result == null) {
						result = tmp;
					} else {
						result = append(result, tmp);
					}
				}
				
				close();
				return result;
			} else {
				int len = cur.length();
				cur = doOperation(cur, opList, ctx);
				if (result == null) {
					result = cur;
				} else if (cur != null) {
					result = append(result, cur);
				}
				
				if (len < size) {
					Sequence tmp = finish(opList, ctx);
					if (tmp != null) {
						if (result == null) {
							result = tmp;
						} else {
							result = append(result, tmp);
						}
					}
					
					if (result == null || result.length() < n) {
						close();
						return result;
					}
				}
			}
		}
		
		if (result.length() == n) {
			cache = null;
			return result;
		} else {
			cache = result.split(n + 1);
			return result;
		}
	}
	
	/**
	 * ??ָ??????ʽȡn??????
	 * @param exps ????ʽ????
	 * @param n ????
	 * @param ctx ??????????
	 * @return Sequence
	 */
	public synchronized Sequence fetchGroup(Expression[] exps, int n, Context ctx) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		Sequence newTable = null;
		int keyCount = exps.length; 
		Object []keys = new Object[keyCount];

		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(data);
		stack.push(current);
		current.setCurrent(1);
		int index = 2;
		int count = 0;

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

			End:
			while (true) {
				for (int len = data.length(); index <= len; ++index) {
					current.setCurrent(index);
					for (int k = 0; k < keyCount; ++k) {
						if (!Variant.isEquals(keys[k], exps[k].calculate(ctx))) {
							if (count + index >= n) {
								break End;
							} else {
								for (int j = 0; j < keyCount; ++j) {
									keys[j] = exps[j].calculate(ctx);
								}
							}
						}
					}
				}

				if (newTable == null) {
					newTable = data;
				} else {
					newTable.getMems().addAll(data.getMems());
				}
				count = newTable.length();
				
				data = fuzzyFetch(FETCHCOUNT);
				if (data == null) break;

				index = 1;
				stack.pop();
				current = new Current(data);
				stack.push(current);
			}
		} finally {
			stack.pop();
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(data.getMems());
			}
		}

		return newTable;
	}

	/**
	 * ??ָ??????ʽȡһ??????
	 * @param exps ????ʽ????
	 * @param ctx ??????????
	 * @return Sequence
	 */
	public synchronized Sequence fetchGroup(Expression[] exps, Context ctx) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		Sequence newTable = null;
		int keyCount = exps.length; 
		Object []keys = new Object[keyCount];

		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(data);
		stack.push(current);
		current.setCurrent(1);
		int index = 2;

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

			End:
			while (true) {
				for (int len = data.length(); index <= len; ++index) {
					current.setCurrent(index);
					for (int k = 0; k < keyCount; ++k) {
						if (!Variant.isEquals(keys[k], exps[k].calculate(ctx))) {
							break End;
						}
					}
				}

				if (newTable == null) {
					newTable = data;
				} else {
					newTable.getMems().addAll(data.getMems());
				}

				data = fuzzyFetch(FETCHCOUNT);
				if (data == null) break;

				index = 1;
				stack.pop();
				current = new Current(data);
				stack.push(current);
			}
		} finally {
			stack.pop();
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(data.getMems());
			}
		}

		return newTable;
	}

	/**
	 * ??ָ??????ʽȡһ??????
	 * @param exp ????ʽ
	 * @param ctx ??????????
	 * @return Sequence
	 */
	public synchronized Sequence fetchGroup(Expression exp, Context ctx) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		Sequence newTable = null;
		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(data);
		stack.push(current);
		current.setCurrent(1);
		int index = 2;

		try {
			Object key = exp.calculate(ctx);
			if (key instanceof Boolean) {
				End:
				while (true) {
					for (int len = data.length(); index <= len; ++index) {
						current.setCurrent(index);
						if (Variant.isTrue(exp.calculate(ctx))) {
							break End;
						}
					}

					if (newTable == null) {
						newTable = data;
					} else {
						newTable.getMems().addAll(data.getMems());
					}

					data = fuzzyFetch(FETCHCOUNT);
					if (data == null) break;

					index = 1;
					stack.pop();
					current = new Current(data);
					stack.push(current);
				}
			} else {
				End:
				while (true) {
					for (int len = data.length(); index <= len; ++index) {
						current.setCurrent(index);
						if (!Variant.isEquals(key, exp.calculate(ctx))) {
							break End;
						}
					}

					if (newTable == null) {
						newTable = data;
					} else {
						newTable.getMems().addAll(data.getMems());
					}

					data = fuzzyFetch(FETCHCOUNT);
					if (data == null) break;

					index = 1;
					stack.pop();
					current = new Current(data);
					stack.push(current);
				}
			}
		} finally {
			stack.pop();
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(data.getMems());
			}
		}
		
		return newTable;
	}

	/**
	 * ??ָ???ֶκ?ȡһ?????ݣ???????̵߳???
	 * @param field ?ֶ????
	 * @return Sequence
	 */
	public Sequence fetchGroup(int field) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		IArray mems = data.getMems();
		BaseRecord r = (BaseRecord)mems.get(1);
		Sequence newTable = null;
		Object key = r.getNormalFieldValue(field);
		int index = 2;

		End:
		while (true) {
			for (int len = data.length(); index <= len; ++index) {
				r = (BaseRecord)mems.get(index);;
				if (!Variant.isEquals(key, r.getNormalFieldValue(field))) {
					break End;
				}
			}

			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
			
			data = fuzzyFetch(FETCHCOUNT);
			if (data == null) break;
			
			mems = data.getMems();
			index = 1;
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
		}

		return newTable;
	}

	/**
	 * ??ָ???ֶκ?ȡһ?????ݣ???????̵߳???
	 * @param fields ?ֶ????????
	 * @return Sequence
	 */
	public Sequence fetchGroup(int []fields) {
		int keyCount = fields.length;
		if (keyCount == 1) {
			return fetchGroup(fields[0]);
		}
		
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		Sequence newTable = null;
		IArray mems = data.getMems();
		BaseRecord r = (BaseRecord)mems.get(1);
		int index = 2;
		
		Object []keys = new Object[keyCount];
		for (int i = 0; i < keyCount; ++i) {
			keys[i] = r.getNormalFieldValue(fields[i]);
		}

		End:
		while (true) {
			for (int len = data.length(); index <= len; ++index) {
				r = (BaseRecord)mems.get(index);
				for (int i = 0; i < keyCount; ++i) {
					if (!Variant.isEquals(keys[i], r.getNormalFieldValue(fields[i]))) {
						break End;
					}
				}
			}

			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
			
			data = fuzzyFetch(FETCHCOUNT);
			if (data == null) break;
			
			mems = data.getMems();
			index = 1;
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
		}

		return newTable;
	}

	/**
	 * ??ָ???ֶκ?ȡһ?????ݣ?????????limit??ȡ????һ??Ҳ?᷵?أ???????̵߳???
	 * @param fields ?ֶ????????
	 * @param limit ????¼??
	 * @return Sequence
	 */
	public Sequence fetchGroup(int []fields, int limit) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return null;
		}

		int keyCount = fields.length;
		Sequence newTable = null;
		IArray mems = data.getMems();
		BaseRecord r = (BaseRecord)mems.get(1);
		int index = 2;
		int count = 0;
		
		Object []keys = new Object[keyCount];
		for (int i = 0; i < keyCount; ++i) {
			keys[i] = r.getNormalFieldValue(fields[i]);
		}

		End:
		while (true) {
			for (int len = data.length(); index <= len; ++index) {
				r = (BaseRecord)mems.get(index);
				for (int i = 0; i < keyCount; ++i) {
					if (!Variant.isEquals(keys[i], r.getNormalFieldValue(fields[i]))) {
						break End;
					}
				}
				if (count + index >= limit + 1) {
					break End;
				}
			}

			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
			count = newTable.length();
			
			data = fuzzyFetch(FETCHCOUNT);
			if (data == null) break;
			
			mems = data.getMems();
			index = 1;
		}

		if (data != null && data.length() >= index) {
			cache = data.split(index);
			if (newTable == null) {
				newTable = data;
			} else {
				newTable.getMems().addAll(mems);
			}
		}

		return newTable;
	}
	
	/**
	 * ????һ??????
	 * @param exps
	 * @param ctx
	 * @return
	 */
	public synchronized int skipGroup(Expression[] exps, Context ctx) {
		Sequence data = fuzzyFetch(FETCHCOUNT);
		if (data == null) {
			return 0;
		}

		int keyCount = exps.length;
		Object []keys = new Object[keyCount];

		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(data);
		stack.push(current);
		current.setCurrent(1);

		int count = 1;
		int index = 2;

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

			End:
			while (true) {
				for (int len = data.length(); index <= len; ++index, ++count) {
					current.setCurrent(index);
					for (int k = 0; k < keyCount; ++k) {
						if (!Variant.isEquals(keys[k], exps[k].calculate(ctx))) {
							break End;
						}
					}
				}

				data = fuzzyFetch(FETCHCOUNT);
				if (data == null) break;

				index = 1;
				stack.pop();
				current = new Current(data);
				stack.push(current);
			}
		} finally {
			stack.pop();
		}

		if (data != null && data.length() > index) {
			cache = data.split(index);
		}

		return count;
	}

	/**
	 * ???????м?¼
	 * @return ʵ???????ļ?¼??
	 */
	public long skip() {
		return skip(MAXSKIPSIZE);
	}
	
	/**
	 * ????ָ????¼??
	 * @param n ??¼??
	 * @return long ʵ???????ļ?¼??
	 */
	public synchronized long skip(long n) {
		if (opList == null) {
			if (cache == null) {
				long count = skipOver(n);
				if (count < n) {
					close();
				}
				
				return count;
			} else {
				int len = cache.length();
				if (len == n) {
					cache = null;
					return n;
				} else if (len > n) {
					cache.split(1, (int)n);
					return n;
				} else {
					cache = null;
					long count = n + skipOver(n - len);
					if (count < n) {
						close();
					}
					
					return count;
				}
			}
		} else {
			long total = 0;
			while (n > 0) {
				Sequence seq;
				if (n > FETCHCOUNT) {
					seq = fetch(FETCHCOUNT);
				} else {
					seq = fetch((int)n);
				}
				
				if (seq == null || seq.length() == 0) {
					close();
					break;
				}
				
				total += seq.length();
				n -= seq.length();
			}
			
			return total;
		}
	}

	/**
	 * ?ر??α?
	 */
	public void close() {
		cache = null;
		
		if (isFinished) {
			// ??????reset
			isFinished = false;
		} else if (opList != null) {
			finish(opList, ctx);
		}
	}
	
	/**
	 * ȡ??¼????????Ҫʵ?ִ˷???
	 * @param n Ҫȡ?ļ?¼??
	 * @return Sequence
	 */
	protected abstract Sequence get(int n);

	/**
	 * ģ??ȡ??¼?????صļ?¼?????Բ??????????????ͬ
	 * @param n Ҫȡ?ļ?¼??
	 * @return Sequence
	 */
	protected Sequence fuzzyGet(int n) {
		return get(n);
	}

	/**
	 * ????ָ????¼??????????Ҫʵ?ִ˷???
	 * @param n ??¼??
	 * @return long
	 */
	protected abstract long skipOver(long n);
	
	/**
	 * ?????α?
	 * @return ?????Ƿ?ɹ???true???α???Դ?ͷ????ȡ????false???????Դ?ͷ????ȡ??
	 */
	public boolean reset() {
		return false;
	}
	
	/**
	 * ???ؽ???????ݽṹ
	 * @return DataStruct
	 */
	public DataStruct getDataStruct() {
		return dataStruct;
	}
	
	/**
	 * ???ý???????ݽṹ
	 * @param ds ???ݽṹ
	 */
	public void setDataStruct(DataStruct ds) {
		dataStruct = ds;
	}
	
	// ?????α???????ֶΣ?????????򷵻?null
	public String[] getSortFields() {
		return null;
	}
	
	/**
	 * ȡ??????????
	 * @param exps ?????ֶα???ʽ????
	 * @param names ?????ֶ???????
	 * @param calcExps ?????ֶα???ʽ????
	 * @param calcNames ?????ֶ???????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @return IGroupsResult
	 */
	public IGroupsResult getGroupsResult(Expression[] exps, String[] names, Expression[] calcExps, 
			String[] calcNames, String opt, Context ctx) {
		DataStruct ds = getDataStruct();
		return IGroupsResult.instance(exps, names, calcExps, calcNames, ds, opt, ctx);
	}
	
	/**
	 * ???α???з??????
	 * @param exps ?????ֶα???ʽ????
	 * @param names ?????ֶ???????
	 * @param calcExps ?????ֶα???ʽ????
	 * @param calcNames ?????ֶ???????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @return ??????
	 */
	public Table groups(Expression[] exps, String[] names, Expression[] calcExps, String[] calcNames, 
			String opt, Context ctx) {
		DataStruct ds = getDataStruct();
		IGroupsResult groups = IGroupsResult.instance(exps, names, calcExps, calcNames, ds, opt, ctx);
		groups.push(this);
		return groups.getResultTable();
	}
	
	/**
	 * ???α???з??????
	 * @param exps ?????ֶα???ʽ????
	 * @param names ?????ֶ???????
	 * @param calcExps ?????ֶα???ʽ????
	 * @param calcNames ?????ֶ???????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @param groupCount ?????????
	 * @return ??????
	 */
	public Table groups(Expression[] exps, String[] names, Expression[] calcExps, String[] calcNames, 
			String opt, Context ctx, int groupCount) {
		if (groupCount < 1 || exps == null || exps.length == 0) {
			return groups(exps, names, calcExps, calcNames, opt, ctx);
		} else if (opt != null && opt.indexOf('n') != -1) {
			DataStruct ds = getDataStruct();
			IGroupsResult groups = IGroupsResult.instance(exps, names, calcExps, calcNames, ds, opt, ctx);
			groups.setGroupCount(groupCount);
			groups.push(this);
			return groups.getResultTable();
		} else {
			return CursorUtil.fuzzyGroups(this, exps, names, calcExps, calcNames, opt, ctx, groupCount);
		}
	}

	/**
	 * ???α?????????????
	 * @param exps ???????ʽ????
	 * @param names	?????ֶ???????
	 * @param calcExps ???ܱ???ʽ	????
	 * @param calcNames	?????ֶ???????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @param capacity	?ڴ??б??????????????
	 * @return ICursor ???????α?
	 */
	public ICursor groupx(Expression[] exps, String []names, 
			Expression[] calcExps, String []calcNames, String opt, Context ctx, int capacity) {
		if (opt != null && opt.indexOf('n') != -1) {
			return CursorUtil.groupx_n(this, exps, names, calcExps, calcNames, ctx, capacity);
		}
		
		GroupxResult groupx = new GroupxResult(exps, names, calcExps, calcNames, opt, ctx, capacity);
		while (true) {
			Sequence src = fetch(INITSIZE);
			if (src == null || src.length() == 0) break;
			
			groupx.push(src, ctx);
		}
		
		return groupx.getResultCursor();
	}

	/**
	 * ??ÿ??????ʽ???й?ϣȥ?أ?????count????ֵͬ
	 * @param exps ????ʽ????
	 * @param count ????
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @return Sequence ???????е????У????countΪ1????????
	 */
	public Sequence id(Expression []exps, int count, String opt, Context ctx) {
		IDResult id = new IDResult(exps, count, opt, ctx);
		id.push(this);
		return id.getResultSequence();
	}

	/**
	 * ?????????α?
	 * @param exp ????????ʽ
	 * @param initVal ??ʼֵ
	 * @param c ????????ʽ??Ϊtrue??ֹͣ
	 * @param ctx ??????????
	 * @return ???????
	 */
	public Object iterator(Expression exp, Object initVal, Expression c, Context ctx) {
		ComputeStack stack = ctx.getComputeStack();
		Param param = ctx.getIterateParam();
		Object oldVal = param.getValue();
		param.setValue(initVal);
		
		try {
			while (true) {
				// ???α???ȡ??һ?????ݡ?
				Sequence src = fuzzyFetch(FETCHCOUNT);
				if (src == null || src.length() == 0) break;
				
				Current current = new Current(src);
				stack.push(current);
				try {
					if (c == null) {
						for (int i = 1, size = src.length(); i <= size; ++i) {
							current.setCurrent(i);
							initVal = exp.calculate(ctx);
							param.setValue(initVal);
						}
					} else {
						for (int i = 1, size = src.length(); i <= size; ++i) {
							current.setCurrent(i);
							Object obj = c.calculate(ctx);
							
							// ???????Ϊ???򷵻?
							if (obj instanceof Boolean && ((Boolean)obj).booleanValue()) {
								return initVal;
							}
							
							initVal = exp.calculate(ctx);
							param.setValue(initVal);
						}
					}
				} finally {
					stack.pop();
				}
			}
		} finally {
			param.setValue(oldVal);
		}
		
		return initVal;
	}

	/**
	 * ???α???????????
	 * @param cursor ?α?
	 * @param exps ?????ֶα???ʽ????
	 * @param ctx ??????????
	 * @param capacity ?ڴ????ܹ?????ļ?¼???????û?????????Զ?????һ??
	 * @param opt ѡ?? 0??null?????
	 * @return ?ź?????α?
	 */
	public ICursor sortx(Expression[] exps, Context ctx, int capacity, String opt) {
		return CursorUtil.sortx(this, exps, ctx, capacity, opt);
	}

	/**
	 * ????????????ֶ?ֵ??ͬ?ļ?¼??ֵ??ͬ??ͬ??
	 * ??ֵ??ͬ?ļ?¼???浽һ????ʱ?ļ???Ȼ??ÿ????ʱ?ļ?????????
	 * @param exps ???????ʽ
	 * @param gexp ?????ʽ
	 * @param ctx ??????????
	 * @param opt ѡ??
	 * @return ?ź?????α?
	 */
	public ICursor sortx(Expression[] exps, Expression gexp, Context ctx, String opt) {
		return CursorUtil.sortx(this, exps, gexp, ctx, opt);
	}

	/**
	 * ???α???л???
	 * @param calcExps ???ܱ???ʽ????
	 * @param ctx ??????????
	 * @return ???ֻ??һ?????ܱ???ʽ???ػ??ܽ???????򷵻ػ??ܽ?????ɵ?????
	 */
	public Object total(Expression[] calcExps, Context ctx) {
		//TotalResult total = new TotalResult(calcExps, ctx);
		//total.push(this);
		//return total.result();
		Table table = groups(null, null, calcExps, null, null, ctx);
		
		if (table == null || table.length() == 0) {
			return null;
		} else {
			BaseRecord r = table.getRecord(1);
			int count = calcExps.length;
			if (count == 1) {
				return r.getNormalFieldValue(0);
			} else {
				Sequence seq = new Sequence(count);
				for (int i = 0; i < count; ++i) {
					seq.add(r.getNormalFieldValue(i));
				}
				
				return seq;
			}
		}
	}
	
	/**
	 * ???α???????鲢????
	 * @param function ??Ӧ?ĺ???
	 * @param exps ??ǰ???????ֶα???ʽ????
	 * @param cursors ά???α?????
	 * @param codeExps ά???????ֶα???ʽ????
	 * @param newExps
	 * @param newNames
	 * @param opt ѡ??
	 * @param ctx ??????????
	 * @return Operable
	 */
	public Operable mergeJoinx(Function function, Expression[][] exps, 
			ICursor []cursors, Expression[][] codeExps, 
			Expression[][] newExps, String[][] newNames, String opt, Context ctx) {
		//TODO ?Ժ?Ҫ?޸?ΪOperable
		//return CSJoinxCursor3.MergeJoinx(this, exps, cursors, codeExps, newExps, newNames, null, ctx, FETCHCOUNT, opt);
		return new MergeJoinxCursor(this, exps, cursors, codeExps, newExps, newNames, opt, ctx);
	}
	
	/**
	 * ?õ?????news??????α? T.news(this)
	 * @param table ????
	 * @param exps ȡ??????ʽ
	 * @param fields ȡ???ֶ?????
	 * @param csNames ????K??ָ??A/cs???????ӵ??ֶ?
	 * @param type	???????ͣ?0:derive; 1:new; 2:news; 0x1X ??ʾ????;
	 * @param option ѡ??	
	 * @param filter ??table?Ĺ???????
	 * @param fkNames ??table??Switch????????
	 * @param codes
	 * @param ctx
	 */
	public ICursor attachNews(ColPhyTable table, String[] csNames, 
			Expression filter, Expression []exps, String[] names, String []fkNames, 
			Sequence []codes, String[] opts, String option, int type, Context ctx) {
		return new JoinCursor(table, exps, names, this, csNames, type, option, filter, fkNames, codes, opts, ctx); 
	}
	
	/**
	 * ȡ?ֶ??α????ʼֵ??????зֶ??ֶ??򷵻طֶ??ֶε?ֵ??û???򷵻?ά?ֶε?ֵ
	 * @return ?ֶ??α???????¼?ķֶ??ֶε?ֵ???????ǰ????Ϊ0?򷵻?null
	 */
	public Object[] getSegmentStartValues(String option) {
		throw new RQException();
	}
	
	/**
	 * ????һ???뵱ǰ?α???ƥ??Ĺܵ?
	 * @param ctx ??????????
	 * @param doPush ?Ƿ???α?????push????
	 * @return Channel
	 */
	public Channel newChannel(Context ctx, boolean doPush) {
		if (doPush) {
			return new Channel(ctx, this);
		} else {
			return new Channel(ctx);
		}
	}
	
	/**
	 * ?α??Ƿ????????
	 * @return
	 */
	public boolean canSkipBlock() {
		return false;
	}
	
	/**
	 * ?õ??α??????ڿ?ķ?Χ
	 * @param key
	 * @return
	 */
	public IArray[] getSkipBlockInfo(String key) {
		return null;
	}
	
	/**
	 * ???α?????Ϊ????key?ֶ????? ??pjoinʱʹ?ã?
	 * ???ú??α?ᰴ??values???ֵ???????顣
	 * @param key ά?ֶ???
	 * @param values [minValue, maxValue] 
	 */
	public void setSkipBlockInfo(String key, IArray[] values) {
	}

	/**
	 * ??????????Ϣ
	 * @param srcKeyExps ???ӱ???ʽ????
	 * @param cursors ?????α?????
	 * @param options ????ѡ??
	 * @param keyExps ???ӱ???ʽ????
	 * @param newExps
	 * @param opt
	 */
	public void setSkipBlock(Expression []srcKeyExps, ICursor []cursors, String []options, Expression [][]keyExps, Expression [][]newExps, String option) {
		int tableCount = cursors.length;
		String key = srcKeyExps[0].getFieldName();
		if (option == null || option.indexOf('f') == -1) {
			if ((option == null || option.indexOf('r') == -1) && canSkipBlock()) {
				// ?????α?????????α????????
				IArray []values = null;
				boolean isGet = false;
				
				for (int t = 0; t < tableCount; ++t) {
					if (cursors[t] == null) {
						continue;
					}
					
					String opt = options[t];
					if (opt == null || !opt.equals("null") || newExps[t] != null) {
						if (!isGet) {
							isGet = true;
							values = getSkipBlockInfo(key);
							if (values == null) {
								break;
							}
						}
						
						cursors[t].setSkipBlockInfo(keyExps[t][0].getFieldName(), values);
					}
				}
			} else {
				// ?????α?????????α????????
				IArray []values = null;
				for (int t = 0; t < tableCount; ++t) {
					if (cursors[t] == null || !cursors[t].canSkipBlock()) {
						continue;
					}
					
					String opt = options[t];
					if (opt == null || !opt.equals("null")) {
						values = cursors[t].getSkipBlockInfo(keyExps[t][0].getFieldName());
						if (values != null) {
							setSkipBlockInfo(key, values);
							break;
						}
					}
				}
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy