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

com.scudata.dw.PhyTableGroup 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.io.File;
import java.io.IOException;
import java.util.ArrayList;

import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BFileWriter;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.BFileCursor;
import com.scudata.dm.cursor.ConjxCursor;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MergeCursor;
import com.scudata.dm.cursor.MergeCursor2;
import com.scudata.dm.cursor.MultipathCursors;
import com.scudata.dm.cursor.UpdateMergeCursor;
import com.scudata.dm.op.Operation;
import com.scudata.expression.Expression;
import com.scudata.resources.EngineMessage;

/**
 * ?ļ???
 * @author runqian
 *
 */
public class PhyTableGroup implements IPhyTable {
	private IPhyTable []tables;
	private String fileName;
	private int []partitions;
	private String opt;
	private Context ctx;
	private Expression distribute;
	
	private Sequence memoryTable; // ?ڴ?ֱ?
	
	public PhyTableGroup(String fileName, IPhyTable []tables, int []partitions, String opt, Context ctx) {
		this.fileName = fileName;
		this.tables = tables;
		this.partitions = partitions;
		this.opt = opt;
		this.ctx = ctx;
		distribute = new Expression(ctx, tables[0].getDistribute());
	}
	
	public PhyTableGroup(String fileName, IPhyTable []tables, int []partitions, String opt, Expression distribute, Context ctx) {
		this.fileName = fileName;
		this.tables = tables;
		this.partitions = partitions;
		this.opt = opt;
		this.ctx = ctx;
		this.distribute = distribute;
	}
	
	public void close() {
		for (IPhyTable table : tables) {
			table.close();
		}
	}
	
	/**
	 * ????????Ƿ??ǰ??д洢??
	 * @return true???ǣ?false??????
	 */
	public boolean isColumnStored() {
		return tables[0] instanceof ColPhyTable;
	}
	
	public IPhyTable createAnnexTable(String []colNames, int []serialBytesLen, String tableName) throws IOException {
		int count = tables.length;
		IPhyTable []annexTables = new IPhyTable[count];
		for (int i = 0; i < count; ++i) {
			annexTables[i] = tables[i].createAnnexTable(colNames, serialBytesLen, tableName);
		}
		
		return new PhyTableGroup(fileName, annexTables, partitions, opt, distribute, ctx);
	}
	
	public IPhyTable getAnnexTable(String tableName) {
		int count = tables.length;
		IPhyTable []annexTables = new IPhyTable[count];
		for (int i = 0; i < count; ++i) {
			annexTables[i] = tables[i].getAnnexTable(tableName);
		}
		
		return new PhyTableGroup(fileName, annexTables, partitions, opt, distribute, ctx);
	}
	
	public void append(ICursor cursor) throws IOException {
		append(cursor, null);
	}
	
	/**
	 * ??xѡ??ʱ??????׷?ӣ??α???????ݶ?Ӧ???????
	 * @param cursor
	 * @param opt
	 * @throws IOException
	 */
	private void append_x(ICursor cursor, String opt) throws IOException {
		Expression distribute = this.distribute;
		if (distribute == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("dw.lessDistribute"));
		}
		
		Sequence data = cursor.fetch(ICursor.INITSIZE);
		if (data == null || data.length() == 0) {
			return;
		}
		
		Context ctx = this.ctx;
		DataStruct ds = data.dataStruct();
		if (ds == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("engine.needPurePmt"));
		}
		
		ArrayListtmpFiles = new ArrayList();
		tmpFiles.add(null); // 0λ?ñ?????????1????List??????1??
		int partCount = 0;
		
		try {
			while (data != null && data.length() > 0) {
				Sequence group = data.group(distribute, null, ctx);
				int gcount = group.length();
				for (int g = 1; g <= gcount; ++g) {
					Sequence curGroup = (Sequence)group.getMem(g);
					Object obj = curGroup.calc(1, distribute, ctx);
					if (!(obj instanceof Number)) {
						MessageManager mm = EngineMessage.get();
						throw new RQException(mm.getMessage("dw.distributeError"));
					}
					
					int p = ((Number)obj).intValue();
					if (p < 1) {
						MessageManager mm = EngineMessage.get();
						throw new RQException(mm.getMessage("dw.distributeError"));
					}
					
					if (p > partCount) {
						for (; partCount < p; ++partCount) {
							tmpFiles.add(null);
						}
					}
					
					BFileWriter writer = tmpFiles.get(p);
					if (writer == null) {
						writer = new BFileWriter(FileObject.createTempFileObject(), null);
						writer.prepareWrite(ds, false);
						tmpFiles.set(p, writer);
					}
					
					writer.write(curGroup);
				}
				
				data = cursor.fetch(ICursor.INITSIZE);
			}
			
			for (int p = 1; p <= partCount; ++p) {
				BFileWriter writer = tmpFiles.get(p);
				if (writer == null) {
					continue;
				}
				
				writer.close();
				BFileCursor bcs = new BFileCursor(writer.getFile(), null, null, ctx);
				getPartition(p).append(bcs, opt);
			}
		} finally {
			// ɾ????ʱ?ļ?
			for (int i = 1; i <= partCount; ++i) {
				BFileWriter writer = tmpFiles.get(i);
				if (writer != null) {
					writer.getFile().delete();
				}
			}
		}
	}
	
	public void append(ICursor cursor, String opt) throws IOException {
		if (opt != null) {
			if (opt.indexOf('y') != -1) {
				memoryTable = cursor.fetch();
				return;
			} else if (opt.indexOf('x') != -1) {
				append_x(cursor, opt);
				return;
			}
		}
		
		Expression distribute = this.distribute;
		if (distribute == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("dw.lessDistribute"));
		}
		
		// ÿ????·?α??????????ͬһ??????
		if (cursor instanceof MultipathCursors) {
			ICursor []cursors = ((MultipathCursors)cursor).getCursors();
			for (ICursor cs : cursors) {
				Sequence data = cs.peek(ICursor.FETCHCOUNT);
				if (data == null || data.length() == 0) {
					continue;
				}
				
				Object obj = data.calc(1, distribute, ctx);
				if (!(obj instanceof Number)) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dw.distributeError"));
				}
				
				int p = ((Number)obj).intValue();
				if (p < 1) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dw.distributeError"));
				}
				
				getPartition(p).append(cs, opt);
			}
		} else {
			Sequence data = cursor.peek(ICursor.FETCHCOUNT);
			if (data == null || data.length() == 0) {
				return;
			}
			
			Object obj = data.calc(1, distribute, ctx);
			if (!(obj instanceof Number)) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("dw.distributeError"));
			}
			
			int p = ((Number)obj).intValue();
			if (p < 1) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("dw.distributeError"));
			}
			
			getPartition(p).append(cursor, opt);
		}
	}
	
	private IPhyTable getPartition(int p) {
		int pcount = partitions.length;
		for (int i = 0; i < pcount; ++i) {
			if (partitions[i] == p) {
				return tables[i];
			}
		}
		
		// ?????û?д????˷?????????򴴽?
		File file = Env.getPartitionFile(p, fileName);
		PhyTable tmd = (PhyTable)tables[0];
		ComTable gt = tmd.getGroupTable().dupStruct(file);
		PhyTable result = gt.getBaseTable();
		String tableName = tmd.getTableName();
		if (tableName != null && tableName.length() != 0) {
			result = result.getAnnexTable(tableName);
		}
		
		IPhyTable []tmpTables = new IPhyTable[pcount + 1];
		int []tmpPartitions = new int[pcount + 1];
		System.arraycopy(tables, 0, tmpTables, 0, pcount);
		System.arraycopy(partitions, 0, tmpPartitions, 0, pcount);
		tmpTables[pcount] = result;
		tmpPartitions[pcount] = p;
		
		this.tables = tmpTables;
		this.partitions = tmpPartitions;
		return result;
	}
	
	public Sequence update(Sequence data, String opt) {
		throw new RQException("'update' function is unimplemented in file group!");
	}
	
	public Sequence delete(Sequence data, String opt) {
		throw new RQException("'delete' function is unimplemented in file group!");
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String []opts, MultipathCursors mcs, String opt, Context ctx) {
		ICursor []cursors = mcs.getCursors();
		int pathCount = cursors.length;
		int tableCount = tables.length;
		ArrayList []lists = new ArrayList[pathCount];
		
		if (opt != null && opt.indexOf('w') != -1) {
			MultipathCursors mcs2 = (MultipathCursors)tables[0].cursor(exps, fields, 
					filter, fkNames, codes, opts, mcs, opt, ctx);
			
			int deleteField = getDeleteFieldIndex(exps, fields);
			cursors = mcs2.getCursors();
			DataStruct ds = cursors[0].getDataStruct();
			if (ds == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			
			int []pkIndex = ds.getPKIndex();
			if (pkIndex == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			
			for (int p = 0; p < cursors.length; ++p) {
				lists[p] = new ArrayList(tableCount);
				lists[p].add(cursors[p]);
			}
			
			for (int i = 1; i < tableCount; ++i) {
				mcs2 = (MultipathCursors)tables[i].cursor(exps, fields, 
						filter, fkNames, codes, opts, mcs, opt, ctx);
				cursors = mcs2.getCursors();
				for (int p = 0; p < cursors.length; ++p) {
					lists[p].add(cursors[p]);
				}
			}
			
			if (memoryTable != null) {
				String []sortedFields = getAllSortedColNames();
				mcs2 = memoryTable.cursor(mcs, sortedFields, exps, fields, 
						filter, fkNames, codes, opts, opt, ctx);
				cursors = mcs2.getCursors();
				for (int p = 0; p < cursors.length; ++p) {
					lists[p].add(cursors[p]);
				}
			}
			
			ICursor []resultCursors = new ICursor[pathCount];
			for (int i = 0; i < pathCount; ++i) {
				int size = lists[i].size();
				if (size > 1) {
					cursors = new ICursor[size];
					lists[i].toArray(cursors);
					resultCursors[i] = new UpdateMergeCursor(cursors, pkIndex, deleteField, ctx);
				} else if (size == 1) {
					resultCursors[i] = lists[i].get(0);
				}
			}
			
			return new MultipathCursors(resultCursors, ctx);
		} else {
			MultipathCursors mcs2 = (MultipathCursors)tables[0].cursor(exps, fields, 
					filter, fkNames, codes, opts, mcs, opt, ctx);
			cursors = mcs2.getCursors();
			String []sortFields = cursors[0].getSortFields();
			DataStruct ds = cursors[0].getDataStruct();
			if (ds == null || sortFields == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("grouptable.dataNeedSorted"));
			}
			
			int fcount = sortFields.length;
			int []findex = new int[fcount];
			for (int i = 0; i < fcount; ++i) {
				findex[i] = ds.getFieldIndex(sortFields[i]);
			}
			
			for (int p = 0; p < cursors.length; ++p) {
				lists[p] = new ArrayList(tableCount);
				lists[p].add(cursors[p]);
			}
			
			for (int i = 1; i < tableCount; ++i) {
				mcs2 = (MultipathCursors)tables[i].cursor(exps, fields, 
						filter, fkNames, codes, opts, mcs, opt, ctx);
				cursors = mcs2.getCursors();
				for (int p = 0; p < cursors.length; ++p) {
					lists[p].add(cursors[p]);
				}
			}
			
			if (memoryTable != null) {
				String []sortedFields = getAllSortedColNames();
				mcs2 = memoryTable.cursor(mcs, sortedFields, exps, fields, filter, fkNames, codes, opts, opt, ctx);
				cursors = mcs2.getCursors();
				for (int p = 0; p < cursors.length; ++p) {
					lists[p].add(cursors[p]);
				}
			}
			
			ICursor []resultCursors = new ICursor[pathCount];
			for (int i = 0; i < pathCount; ++i) {
				int size = lists[i].size();
				if (size > 1) {
					cursors = new ICursor[size];
					lists[i].toArray(cursors);
					resultCursors[i] = new MergeCursor(cursors, findex, opt, ctx);
				} else if (size == 1) {
					resultCursors[i] = lists[i].get(0);
				}
			}
			
			return new MultipathCursors(resultCursors, ctx);
		}
	}
	
	public void rename(String[] srcFields, String[] newFields, Context ctx) throws IOException {
		throw new RQException("'rename' function is unimplemented in file group!");
	}
	
	public ICursor cursor() {
		return cursor(null, null, null, null, null, null, null, ctx);
	}
	
	public ICursor cursor(String []fields) {
		return cursor(null, fields, null, null, null, null, null, ctx);
	}
	
	public ICursor cursor(String []fields, Expression filter, Context ctx) {
		return cursor(null, fields, filter, null, null, null, null, ctx);
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String[] opts, String opt, Context ctx) {
		int count = tables.length;
		ICursor []cursors;
		if (memoryTable == null) {
			cursors = new ICursor[count];
		} else {
			cursors = new ICursor[count + 1];
			exps = Operation.dupExpressions(exps, ctx);
			filter = Operation.dupExpression(filter, ctx);
			cursors[count] = memoryTable.cursor(exps, fields, filter, fkNames, codes, opts, ctx);
		}
		
		for (int i = 0; i < count; ++i) {
			exps = Operation.dupExpressions(exps, ctx);
			filter = Operation.dupExpression(filter, ctx);
			cursors[i] = tables[i].cursor(exps, fields, filter, fkNames, codes, opts, opt, ctx);
		}
		
		boolean isUpdate = false, isMerge = true;
		if (opt != null) {
			if (opt.indexOf('w') != -1) {
				isUpdate = true;
			} else if (opt.indexOf('o') != -1) {
				isMerge = false;
			}
		}
		
		if (isUpdate) {
			DataStruct ds = cursors[0].getDataStruct();
			if (ds == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			
			int []pkIndex = ds.getPKIndex();
			if (pkIndex == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("ds.lessKey"));
			}
			
			int deleteField = getDeleteFieldIndex(exps, fields);
			return new UpdateMergeCursor(cursors, pkIndex, deleteField, ctx);
		} else if (isMerge) {
			String []sortFields = cursors[0].getSortFields();
			DataStruct ds = cursors[0].getDataStruct();
			if (ds == null || sortFields == null) {
				return new ConjxCursor(cursors);
			}
			
			int fcount = sortFields.length;
			int []findex = new int[fcount];
			for (int i = 0; i < fcount; ++i) {
				findex[i] = ds.getFieldIndex(sortFields[i]);
			}
			
			return new MergeCursor(cursors, findex, opt, ctx);
		} else {
			return new ConjxCursor(cursors);
		}
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String[] opts, int pathCount, String opt, Context ctx) {
		if (pathCount < 2) {
			return cursor(exps, fields, filter, fkNames, codes, opts, opt, ctx);
		}
		
		int tableCount = tables.length;
		ArrayList []lists = new ArrayList[pathCount];
		ICursor cs = tables[0].cursor(exps, fields, filter, fkNames, codes, opts, pathCount, opt, ctx);
		
		boolean isUpdate = false, isMerge = true;
		if (opt != null) {
			if (opt.indexOf('w') != -1) {
				isUpdate = true;
			} else if (opt.indexOf('o') != -1) {
				isMerge = false;
			}
		}
		
		if (isUpdate) {
			int deleteField = getDeleteFieldIndex(exps, fields);
			if (cs instanceof MultipathCursors) {
				MultipathCursors mcs = (MultipathCursors)cs;
				ICursor []cursors = mcs.getCursors();
				pathCount = cursors.length;
				DataStruct ds = cursors[0].getDataStruct();
				if (ds == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				
				int []pkIndex = ds.getPKIndex();
				if (pkIndex == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				
				for (int p = 0; p < pathCount; ++p) {
					lists[p] = new ArrayList(tableCount);
					lists[p].add(cursors[p]);
				}
				
				for (int i = 1; i < tableCount; ++i) {
					MultipathCursors mcs2 = (MultipathCursors)tables[i].cursor(exps, fields, 
							filter, fkNames, codes, opts, mcs, opt, ctx);
					cursors = mcs2.getCursors();
					for (int p = 0; p < cursors.length; ++p) {
						lists[p].add(cursors[p]);
					}
				}
				
				if (memoryTable != null) {
					String []sortedFields = getAllSortedColNames();
					MultipathCursors mcs2 = memoryTable.cursor(mcs, sortedFields, exps, fields, 
							filter, fkNames, codes, opts, opt, ctx);
					cursors = mcs2.getCursors();
					for (int p = 0; p < cursors.length; ++p) {
						lists[p].add(cursors[p]);
					}
				}
				
				ICursor []resultCursors = new ICursor[pathCount];
				for (int i = 0; i < pathCount; ++i) {
					int size = lists[i].size();
					if (size > 1) {
						cursors = new ICursor[size];
						lists[i].toArray(cursors);
						resultCursors[i] = new UpdateMergeCursor(cursors, pkIndex, deleteField, ctx);
					} else if (size == 1) {
						resultCursors[i] = lists[i].get(0);
					}
				}
				
				return new MultipathCursors(resultCursors, ctx);
			} else {
				DataStruct ds = cs.getDataStruct();
				if (ds == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				
				int []pkIndex = ds.getPKIndex();
				if (pkIndex == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("ds.lessKey"));
				}
				
				ICursor []cursors;
				if (memoryTable == null) {
					cursors = new ICursor[tableCount];
				} else {
					cursors = new ICursor[tableCount + 1];
					exps = Operation.dupExpressions(exps, ctx);
					filter = Operation.dupExpression(filter, ctx);
					cursors[tableCount] = memoryTable.cursor(exps, fields, filter, fkNames, codes, opts, ctx);
				}
				
				cursors[0] = cs;
				for (int i = 1; i < tableCount; ++i) {
					exps = Operation.dupExpressions(exps, ctx);
					filter = Operation.dupExpression(filter, ctx);
					cursors[i] = tables[i].cursor(exps, fields, filter, fkNames, codes, opts, opt, ctx);
				}
								
				return new UpdateMergeCursor(cursors, pkIndex, deleteField, ctx);
			}
		} else if (isMerge) {
			if (cs instanceof MultipathCursors) {
				MultipathCursors mcs = (MultipathCursors)cs;
				ICursor []cursors = mcs.getCursors();
				pathCount = cursors.length;
				String []sortFields = cursors[0].getSortFields();
				DataStruct ds = cursors[0].getDataStruct();
				
				if (ds != null && sortFields != null) {
					int fcount = sortFields.length;
					int []findex = new int[fcount];
					for (int i = 0; i < fcount; ++i) {
						findex[i] = ds.getFieldIndex(sortFields[i]);
					}
					
					for (int p = 0; p < pathCount; ++p) {
						lists[p] = new ArrayList(tableCount);
						lists[p].add(cursors[p]);
					}
					
					for (int i = 1; i < tableCount; ++i) {
						MultipathCursors mcs2 = (MultipathCursors)tables[i].cursor(exps, fields, 
								filter, fkNames, codes, opts, mcs, opt, ctx);
						cursors = mcs2.getCursors();
						for (int p = 0; p < cursors.length; ++p) {
							lists[p].add(cursors[p]);
						}
					}
					
					if (memoryTable != null) {
						String []sortedFields = getAllSortedColNames();
						MultipathCursors mcs2 = memoryTable.cursor(mcs, sortedFields, exps, fields, 
								filter, fkNames, codes, opts, opt, ctx);
						cursors = mcs2.getCursors();
						for (int p = 0; p < cursors.length; ++p) {
							lists[p].add(cursors[p]);
						}
					}
					
					ICursor []resultCursors = new ICursor[pathCount];
					for (int i = 0; i < pathCount; ++i) {
						int size = lists[i].size();
						if (size > 1) {
							cursors = new ICursor[size];
							lists[i].toArray(cursors);
							resultCursors[i] = new MergeCursor(cursors, findex, opt, ctx);
						} else if (size == 1) {
							resultCursors[i] = lists[i].get(0);
						}
					}
					
					return new MultipathCursors(resultCursors, ctx);
				}
			} else {
				ICursor []cursors;
				if (memoryTable == null) {
					cursors = new ICursor[tableCount];
				} else {
					cursors = new ICursor[tableCount + 1];
					exps = Operation.dupExpressions(exps, ctx);
					filter = Operation.dupExpression(filter, ctx);
					cursors[tableCount] = memoryTable.cursor(exps, fields, filter, fkNames, codes, opts, ctx);
				}
				
				cursors[0] = cs;
				for (int i = 1; i < tableCount; ++i) {
					exps = Operation.dupExpressions(exps, ctx);
					filter = Operation.dupExpression(filter, ctx);
					cursors[i] = tables[i].cursor(exps, fields, filter, fkNames, codes, opts, opt, ctx);
				}
				
				String []sortFields = cursors[0].getSortFields();
				DataStruct ds = cursors[0].getDataStruct();
				if (ds == null || sortFields == null) {
					return new ConjxCursor(cursors);
				}
				
				int fcount = sortFields.length;
				int []findex = new int[fcount];
				for (int i = 0; i < fcount; ++i) {
					findex[i] = ds.getFieldIndex(sortFields[i]);
				}
				
				return new MergeCursor(cursors, findex, opt, ctx);
			}
		}
		
		// ??ÿ???ļ??ֳ?pathCount·??Ȼ?????е?i·?ϳ?һ???α꣬???????ɶ?·?α?
		for (int i = 0; i < pathCount; ++i) {
			lists[i] = new ArrayList(tableCount);
		}
		
		if (cs instanceof MultipathCursors) {
			MultipathCursors mcs = (MultipathCursors)cs;
			ICursor []cursors = mcs.getCursors();
			for (int c = 0; c < cursors.length; ++c) {
				lists[c].add(cursors[c]);
			}
		} else {
			lists[0].add(cs);
		}
		
		for (int i = 1; i < tableCount; ++i) {
			cs = tables[i].cursor(exps, fields, filter, fkNames, codes, opts, pathCount, opt, ctx);
			if (cs instanceof MultipathCursors) {
				MultipathCursors mcs = (MultipathCursors)cs;
				ICursor []cursors = mcs.getCursors();
				for (int c = 0; c < cursors.length; ++c) {
					lists[c].add(cursors[c]);
				}
			} else {
				lists[0].add(cs);
			}
		}
		
		if (memoryTable != null) {
			int len = memoryTable.length();
			int blockSize = len / pathCount;
			int start = 1;
			
			for (int i = 1; i <= pathCount; ++i) {
				int end;
				if (i == pathCount) {
					end = len + 1;
				} else {
					end = blockSize * i + 1;
				}

				exps = Operation.dupExpressions(exps, ctx);
				filter = Operation.dupExpression(filter, ctx);
				ICursor cursor = memoryTable.cursor(start, end, exps, fields, filter, fkNames, codes, opts, ctx);
				lists[i].add(cursor);
				start = end;
			}
		}
		
		ArrayList list = new ArrayList(pathCount);
		for (int i = 0; i < pathCount; ++i) {
			int size = lists[i].size();
			if (size > 1) {
				ICursor []cursors = new ICursor[size];
				lists[i].toArray(cursors);
				list.add(new ConjxCursor(cursors));
			} else if (size == 1) {
				list.add(lists[i].get(0));
			}
		}
		
		int size = list.size();
		if (size == 0) {
			return null;
		} else if (size == 1) {
			return list.get(0);
		} else {
			ICursor []cursors = new ICursor[size];
			list.toArray(cursors);
			return new MultipathCursors(cursors, ctx);
		}
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String[] opts, int segSeq, int segCount, String opt, Context ctx) {
		if (segCount < 2) {
			return cursor(exps, fields, filter, fkNames, codes, opts, opt, ctx);
		}
		
		int count = tables.length;
		ArrayList list = new ArrayList(count);
		for (int i = 0; i < count; ++i) {
			exps = Operation.dupExpressions(exps, ctx);
			filter = Operation.dupExpression(filter, ctx);
			ICursor cursor = tables[i].cursor(exps, fields, filter, fkNames, codes, opts, segSeq, segCount, opt, ctx);
			if (cursor != null) {
				list.add(cursor);
			}
		}
		
		if (memoryTable != null) {
			int len = memoryTable.length();
			int blockSize = len / segCount;
			int start;
			int end;
			
			if (segSeq == segCount) {
				start = blockSize * (segSeq - 1) + 1;
				end = len + 1;
			} else {
				start = blockSize * (segSeq - 1) + 1;
				end = blockSize * segSeq + 1;
			}
			
			exps = Operation.dupExpressions(exps, ctx);
			filter = Operation.dupExpression(filter, ctx);
			ICursor cursor = memoryTable.cursor(start, end, exps, fields, filter, fkNames, codes, opts, ctx);
			list.add(cursor);
		}
		
		ICursor []cursors = new ICursor[list.size()];
		list.toArray(cursors);
		
		if (opt == null || opt.indexOf('o') == -1) {
			String []sortFields = cursors[0].getSortFields();
			DataStruct ds = cursors[0].getDataStruct();
			if (ds == null || sortFields == null) {
				return new ConjxCursor(cursors);
			}
			
			int fcount = sortFields.length;
			int []findex = new int[fcount];
			for (int i = 0; i < fcount; ++i) {
				findex[i] = ds.getFieldIndex(sortFields[i]);
			}
			
			return new MergeCursor(cursors, findex, opt, ctx);
		} else {
			return new ConjxCursor(cursors);
		}
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String[] opts, int pathSeq, int pathCount, int pathCount2, String opt, Context ctx) {
		throw new RQException("'mcursor' function is unimplemented in file group!");
	}
	
	public ICursor cursor(Expression []exps, String []fields, Expression filter, 
			String []fkNames, Sequence []codes, String[] opts, ICursor cs, int seg, Object [][]endValues, Context ctx) {
		throw new RQException("'mcursor' function is unimplemented in file group!");
	}
	
	public Table finds(Sequence values) throws IOException {
		Table result = null;
		for (IPhyTable table : tables) {
			Table cur = table.finds(values);
			if (cur != null) {
				if (result == null) {
					result = cur;
				} else {
					result.append(cur, null);
				}
			}
		}
		
		if (opt == null || opt.indexOf('o' ) == -1) {
			String []sortFields = getAllSortedColNames();
			result.sortFields(sortFields);
		}
		
		return result;
	}
	
	public Table finds(Sequence values, String []selFields) throws IOException {
		Table result = null;
		for (IPhyTable table : tables) {
			Table cur = table.finds(values, selFields);
			if (cur != null) {
				if (result == null) {
					result = cur;
				} else {
					result.append(cur, null);
				}
			}
		}
		return result;
	}
	
	public ICursor icursor(String []fields, Expression filter, Object iname, String opt, Context ctx) {
		boolean sort = true;
		int[] sortFields = null;
		int count = tables.length;
		ArrayList list = new ArrayList(count);
		for (int i = 0; i < count; ++i) {
			ICursor cursor = tables[i].icursor(fields, filter, iname, opt, ctx);
			if (cursor != null) {
				list.add(cursor);
				if (sort) {
					if (cursor instanceof IndexCursor) {
						sortFields = ((IndexCursor)cursor).getSortFieldsIndex();
						if (sortFields == null) {
							sort = false;
						}
					}  else if (cursor instanceof IndexFCursor) {
						sortFields = ((IndexFCursor)cursor).getSortFieldsIndex();
						if (sortFields == null) {
							sort = false;
						}
					} else if (cursor instanceof Cursor) {
						//?п??ܷ???Cursor????ʱ????
						sort = false;
					} else if (cursor instanceof ConjxCursor) {
						sort = false;
					} else if (cursor instanceof MergeCursor2) {
						sortFields = ((MergeCursor2)cursor).getFields();
						if (sortFields == null) {
							sort = false;
						}
					}
				}
			}
		}

		ICursor []cursors = new ICursor[list.size()];
		list.toArray(cursors);

		if (sort) {
			return new MergeCursor(cursors, sortFields, null, ctx);
		} else {
			return new ConjxCursor(cursors);
		}
	}

	/**
	 * ȡ?????ֶ?????????????
	 * @return ?????ֶ???????
	 */
	public String[] getAllKeyColNames() {
		return tables[0].getAllKeyColNames();
	}
	
	/**
	 * ?????????ֶ?????????????
	 * @return ?????ֶ???????
	 */
	public String[] getAllSortedColNames() {
		return tables[0].getAllSortedColNames();
	}
	
	/**
	 * ?????????С?????????key?У?
	 * @return
	 */
	public String[] getAllColNames() {
		return tables[0].getAllColNames();
	}
	
	public boolean deleteIndex(String indexName) throws IOException {
		boolean result = true;
		for (IPhyTable table : tables) {
			if (!table.deleteIndex(indexName)) {
				result = false;
			}
		}
		
		return result;
	}
	
	public void createIndex(String I, String []fields, Object obj, String opt, Expression w, Context ctx) {
		for (IPhyTable table : tables) {
			table.createIndex(I, fields, obj, opt, w, ctx);
		}
	}
	
	// ȡ?ֲ?????ʽ??
	public String getDistribute() {
		return tables[0].getDistribute();
	}

	public void addColumn(String colName, Expression exp, Context ctx) {
		for (IPhyTable table : tables) {
			table.addColumn(colName, exp, ctx);
		}
	}

	public void deleteColumn(String colName) {
		for (IPhyTable table : tables) {
			table.deleteColumn(colName);
		}
	}
	
	/**
	 * ???????ֶι鲢?ֱ??????ݷ??س??α?
	 * @param ctx ??????????
	 * @return ?α?
	 */
	public ICursor merge(Context ctx) {
		String []sortFields = tables[0].getAllSortedColNames();
		if (sortFields == null || sortFields.length == 0) {
			return cursor();
		}
		
		int count = tables.length;
		ICursor []cursors = new ICursor[count];
		for (int i = 0; i < count; ++i) {
			cursors[i] = tables[i].cursor();
		}
		
		// ?????ֶ???ǰ??
		int fcount = sortFields.length;
		int []fields = new int[fcount];
		for (int i = 0; i < fcount; ++i) {
			fields[i] = i;
		}
		
		return new MergeCursor(cursors, fields, null, ctx);
	}
	

	public IPhyTable[] getTables() {
		return tables;
	}
	
	/**
	 * ʹ??Ԥ??????з??????
	 * @param exps ???????ʽ
	 * @param names ???????ʽ??????
	 * @param newExps ???ܱ???ʽ
	 * @param newNames ???ܱ???ʽ??????
	 * @param srcTable Ҫ????????
	 * @param w ????????
	 * @param hasM ?Ƿ???
	 * @param n ??????
	 * @param option
	 * @param ctx
	 * @return
	 */
	public Sequence cgroups(String []expNames, String []names, String []newExpNames, String []newNames,
			Expression w, boolean hasM, int n, String option, FileObject[] files, Context ctx) {
			int count = tables.length;
			
			//?????б??Ľ???ŵ?һ??
			Sequence result = Cuboid.cgroups(expNames, names, newExpNames, newNames, 
					(PhyTable) tables[0], w, hasM, n, option, files, ctx);
			for (int i = 1; i < count; ++i) {
				Sequence seq = Cuboid.cgroups(expNames, names, newExpNames, newNames, 
						(PhyTable) tables[i], w, hasM, n, option, files, ctx);
				result.addAll(seq);
			}
			
			//??֯???????ʽ
			count = names.length;
			Expression exps[] = new Expression[count];
			for (int i = 0; i < count; i++) {
				exps[i] = new Expression(names[i]);
			}
			
			//??֯?پۺϱ???ʽ
			Expression newExps[] = new Expression[count = newNames.length];//?????洢Ҫ?ۺϵ?ԭ?ֶ?
			for (int i = 0, len = count; i < len; i++) {
				String str = newExpNames[i];
				//??count?پۺϣ?Ҫ??Ϊ?ۼ?
				if (str.indexOf("count(") != -1) {
					str = str.replaceFirst("count", "sum");
				}
				
				//?پۺ?ʱҪ?滻һ???ֶ???
				String sub = str.substring(str.indexOf('(') + 1, str.indexOf(')'));
				str = str.replaceAll(sub, "'" + newNames[i] + "'");
				newExps[i] = new Expression(str);
			}
			return result.groups(exps, names, newExps, newNames, option, ctx);
	}

	public int getDeleteFieldIndex(Expression[] exps, String[] fields) {
		return tables[0].getDeleteFieldIndex(exps, fields);
	}

	/**
	 * ȡ?ڴ?ֱ?
	 * @return Sequence
	 */
	public Sequence getMemoryTable() {
		return memoryTable;
	}

	/**
	 * ????????????ڴ?ֱ?????????ʷ???ݺ?ʵʱ???ݻ?ϼ???
	 * @param memoryTable ???????
	 */
	public void setMemoryTable(Sequence memoryTable) {
		this.memoryTable = memoryTable;
	}

	public void append(PhyTable table) throws IOException {
		throw new RuntimeException();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy